From a13f4d8353cf6a7f612333f00282b27cfe2ce9b3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 17 Aug 2016 10:42:32 -0700 Subject: We now always build the controller in ZeroTier One, at least for desktop and server targets. Also means that ZeroTier One now requires C++11. (Still keeping C++11 out of the core in node/ though.) --- selftest.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'selftest.cpp') diff --git a/selftest.cpp b/selftest.cpp index f4232851..ab05c9ef 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -53,10 +53,6 @@ #include "osdep/PortMapper.hpp" #include "osdep/Thread.hpp" -#ifdef ZT_ENABLE_NETWORK_CONTROLLER -#include "controller/SqliteNetworkController.hpp" -#endif // ZT_ENABLE_NETWORK_CONTROLLER - #ifdef __WINDOWS__ #include #endif -- cgit v1.2.3 From 1254dece5b885d3f396c8c44b659949070694443 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 17 Aug 2016 14:19:29 -0700 Subject: Linux build fixes, and build controller. --- make-linux.mk | 8 ++++---- selftest.cpp | 13 ------------- 2 files changed, 4 insertions(+), 17 deletions(-) (limited to 'selftest.cpp') diff --git a/make-linux.mk b/make-linux.mk index d0d206a1..fe9ecad8 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -93,17 +93,17 @@ endif ifeq ($(ZT_DEBUG),1) DEFS+=-DZT_TRACE override CFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS) - override CXXFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS) + override CXXFLAGS+=-Wall -g -O -std=c++11 -pthread $(INCLUDES) $(DEFS) LDFLAGS= STRIP?=echo # The following line enables optimization for the crypto code, since # C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box! ext/lz4/lz4.o node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CFLAGS = -Wall -O2 -g -pthread $(INCLUDES) $(DEFS) else - CFLAGS?=-O3 -fstack-protector-strong + CFLAGS?=-O3 -fstack-protector override CFLAGS+=-Wall -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) - CXXFLAGS?=-O3 -fstack-protector-strong - override CXXFLAGS+=-Wall -Wno-unused-result -Wreorder -fPIE -fno-rtti -pthread $(INCLUDES) -DNDEBUG $(DEFS) + CXXFLAGS?=-O3 -fstack-protector + override CXXFLAGS+=-Wall -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS) LDFLAGS=-pie -Wl,-z,relro,-z,now STRIP?=strip STRIP+=--strip-all diff --git a/selftest.cpp b/selftest.cpp index ab05c9ef..aecccd21 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -501,19 +501,6 @@ static int testCertificate() return -1; } - std::cout << "[certificate] Testing string serialization... "; - CertificateOfMembership copyA(cA.toString()); - CertificateOfMembership copyB(cB.toString()); - if (copyA != cA) { - std::cout << "FAIL" << std::endl; - return -1; - } - if (copyB != cB) { - std::cout << "FAIL" << std::endl; - return -1; - } - std::cout << "PASS" << std::endl; - std::cout << "[certificate] Generating two certificates that should not agree..."; cA = CertificateOfMembership(10000,100,1,idA.address()); cB = CertificateOfMembership(10101,100,1,idB.address()); -- cgit v1.2.3 From a454a37a6e171f2a9101680de4c2dfda2c2246f5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 7 Nov 2016 13:27:17 -0800 Subject: Self test JSONDB. --- controller/JSONDB.cpp | 2 -- selftest.cpp | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'selftest.cpp') diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index 506fc425..6adc8a66 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -147,8 +147,6 @@ std::string JSONDB::_genPath(const std::string &n,bool create) std::vector pt(Utils::split(n.c_str(),"/","","")); if (pt.size() == 0) return std::string(); - if (pt.size() == 1) - return pt[0]; std::string p(_basePath); if (create) OSUtils::mkdir(p.c_str()); diff --git a/selftest.cpp b/selftest.cpp index aecccd21..5fcc2673 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -53,6 +53,8 @@ #include "osdep/PortMapper.hpp" #include "osdep/Thread.hpp" +#include "controller/JSONDB.hpp" + #ifdef __WINDOWS__ #include #endif @@ -807,6 +809,24 @@ static int testOther() } std::cout << "PASS (junk value to prevent optimization-out of test: " << foo << ")" << std::endl; + std::cout << "[other] Testing controller/JSONDB..."; std::cout.flush(); + { + JSONDB db1("jsondb-test"); + std::map db1data; + for(unsigned int i=0;i<256;++i) { + std::string n; + for(unsigned int j=0,k=rand() % 4;j<=k;++j) { + if (j > 0) n.push_back('/'); + char foo[24]; + Utils::snprintf(foo,sizeof(foo),"%lx",rand()); + n.append(foo); + } + db1data[n] = {{"i",i}}; + db1.put(n,db1data[n]); + } + } + std::cout << "PASS" << std::endl; + return 0; } -- cgit v1.2.3 From 5f63d5039bcca80241b12655c250a4238b936a74 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 7 Nov 2016 14:01:23 -0800 Subject: Bug fixes, self test of JSONDB disabled by default. --- controller/JSONDB.hpp | 6 ++++++ selftest.cpp | 23 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'selftest.cpp') diff --git a/controller/JSONDB.hpp b/controller/JSONDB.hpp index 61735655..a9a5e6ac 100644 --- a/controller/JSONDB.hpp +++ b/controller/JSONDB.hpp @@ -88,6 +88,9 @@ public: } } + inline bool operator==(const JSONDB &db) const { return ((_basePath == db._basePath)&&(_db == db._db)); } + inline bool operator!=(const JSONDB &db) const { return (!(*this == db)); } + private: void _reload(const std::string &p); bool _isValidObjectName(const std::string &n); @@ -98,6 +101,9 @@ private: nlohmann::json obj; uint64_t lastModifiedOnDisk; uint64_t lastCheck; + + inline bool operator==(const _E &e) const { return (obj == e.obj); } + inline bool operator!=(const _E &e) const { return (obj != e.obj); } }; std::string _basePath; diff --git a/selftest.cpp b/selftest.cpp index 5fcc2673..7ca4ac3b 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -809,10 +809,11 @@ static int testOther() } std::cout << "PASS (junk value to prevent optimization-out of test: " << foo << ")" << std::endl; + /* std::cout << "[other] Testing controller/JSONDB..."; std::cout.flush(); { - JSONDB db1("jsondb-test"); std::map db1data; + JSONDB db1("jsondb-test"); for(unsigned int i=0;i<256;++i) { std::string n; for(unsigned int j=0,k=rand() % 4;j<=k;++j) { @@ -824,8 +825,26 @@ static int testOther() db1data[n] = {{"i",i}}; db1.put(n,db1data[n]); } + for(std::map::iterator i(db1data.begin());i!=db1data.end();++i) { + i->second["foo"] = "bar"; + db1.put(i->first,i->second); + } + JSONDB db2("jsondb-test"); + if (db1 != db2) { + std::cout << " FAILED (db1!=db2 #1)" << std::endl; + return -1; + } + for(std::map::iterator i(db1data.begin());i!=db1data.end();++i) { + db1.erase(i->first); + } + db2.reload(); + if (db1 != db2) { + std::cout << " FAILED (db1!=db2 #2)" << std::endl; + return -1; + } } - std::cout << "PASS" << std::endl; + std::cout << " PASS" << std::endl; + */ return 0; } -- cgit v1.2.3 From ab4021dd0ee37af0af4137dc772911ea8ec52bb2 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 18 Nov 2016 11:09:19 -0800 Subject: Do packet MAC check before locallyValidate(), and add timing measurement in selftest. --- node/IncomingPacket.cpp | 15 ++++++++------- selftest.cpp | 12 ++++++++---- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'selftest.cpp') diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index c6346346..ee4d62c0 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -275,7 +275,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut // Continue at // VALID } - } // else continue at // VALID + } // else if alreadyAuthenticated then continue at // VALID } else { // We don't already have an identity with this address -- validate and learn it @@ -285,18 +285,19 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut return true; } + // Check packet integrity and MAC + SharedPtr newPeer(new Peer(RR,RR->identity,id)); + if (!dearmor(newPeer->key())) { + TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_path->address().toString().c_str()); + return true; + } + // Check that identity's address is valid as per the derivation function if (!id.locallyValidate()) { TRACE("dropped HELLO from %s(%s): identity invalid",id.address().toString().c_str(),_path->address().toString().c_str()); return true; } - // Check packet integrity and authentication - SharedPtr newPeer(new Peer(RR,RR->identity,id)); - if (!dearmor(newPeer->key())) { - TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_path->address().toString().c_str()); - return true; - } peer = RR->topology->addPeer(newPeer); // Continue at // VALID diff --git a/selftest.cpp b/selftest.cpp index 7ca4ac3b..9992d757 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -376,11 +376,15 @@ static int testIdentity() std::cout << "FAIL (1)" << std::endl; return -1; } - if (!id.locallyValidate()) { - std::cout << "FAIL (2)" << std::endl; - return -1; + const uint64_t vst = OSUtils::now(); + for(int k=0;k<10;++k) { + if (!id.locallyValidate()) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } } - std::cout << "PASS" << std::endl; + const uint64_t vet = OSUtils::now(); + std::cout << "PASS (" << ((double)(vet - vst) / 10.0) << "ms per validation)" << std::endl; std::cout << "[identity] Validate known-bad identity... "; std::cout.flush(); if (!id.fromString(KNOWN_BAD_IDENTITY)) { -- cgit v1.2.3 From 2ea9f516e121ea6eb344a8d180a739a1d707aecb Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 18 Nov 2016 12:59:04 -0800 Subject: Rate gate expensive validation of new identities in HELLO. --- node/Constants.hpp | 20 ++++++++++++++++++++ node/IncomingPacket.cpp | 10 +++++++++- node/InetAddress.hpp | 24 ++++++++++++++++++++++++ node/Node.cpp | 1 + node/Node.hpp | 22 ++++++++++++++++++++++ selftest.cpp | 11 +++++++++++ 6 files changed, 87 insertions(+), 1 deletion(-) (limited to 'selftest.cpp') diff --git a/node/Constants.hpp b/node/Constants.hpp index 6400e289..8803ecee 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -375,6 +375,26 @@ */ #define ZT_PEER_GENERAL_RATE_LIMIT 1000 +/** + * Don't do expensive identity validation more often than this + * + * IPv4 and IPv6 address prefixes are hashed down to 14-bit (0-16383) integers + * using the first 24 bits for IPv4 or the first 48 bits for IPv6. These are + * then rate limited to one identity validation per this often milliseconds. + */ +#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64) || defined(_M_AMD64)) +// AMD64 machines can do anywhere from one every 50ms to one every 10ms. This provides plenty of margin. +#define ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT 2000 +#else +#if (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__)) +// 32-bit Intel machines usually average about one every 100ms +#define ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT 5000 +#else +// This provides a safe margin for ARM, MIPS, etc. that usually average one every 250-400ms +#define ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT 10000 +#endif +#endif + /** * How long is a path or peer considered to have a trust relationship with us (for e.g. relay policy) since last trusted established packet? */ diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index ee4d62c0..41f3e47d 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -247,6 +247,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut if (peer->identity() != id) { // Identity is different from the one we already have -- address collision + // Check rate limits + if (!RR->node->rateGateIdentityVerification(now,_path->address())) + return true; + uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]; if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) { if (dearmor(key)) { // ensure packet is authentic, otherwise drop @@ -285,7 +289,11 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut return true; } - // Check packet integrity and MAC + // Check rate limits + if (!RR->node->rateGateIdentityVerification(now,_path->address())) + return true; + + // Check packet integrity and MAC (this is faster than locallyValidate() so do it first to filter out total crap) SharedPtr newPeer(new Peer(RR,RR->identity,id)); if (!dearmor(newPeer->key())) { TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_path->address().toString().c_str()); diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 6f070fbf..1dff710d 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -449,6 +449,30 @@ struct InetAddress : public sockaddr_storage bool isNetwork() const throw(); + /** + * @return 14-bit (0-16383) hash of this IP's first 24 or 48 bits (for V4 or V6) for rate limiting code, or 0 if non-IP + */ + inline unsigned long rateGateHash() const + { + unsigned long h = 0; + switch(ss_family) { + case AF_INET: + h = (Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr) & 0xffffff00) >> 8; + h ^= (h >> 14); + break; + case AF_INET6: { + const uint8_t *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); + h = ((unsigned long)ip[0]); h <<= 1; + h += ((unsigned long)ip[1]); h <<= 1; + h += ((unsigned long)ip[2]); h <<= 1; + h += ((unsigned long)ip[3]); h <<= 1; + h += ((unsigned long)ip[4]); h <<= 1; + h += ((unsigned long)ip[5]); + } break; + } + return (h & 0x3fff); + } + /** * @return True if address family is non-zero */ diff --git a/node/Node.cpp b/node/Node.cpp index add3117e..ec719668 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -78,6 +78,7 @@ Node::Node( memset(_expectingRepliesToBucketPtr,0,sizeof(_expectingRepliesToBucketPtr)); memset(_expectingRepliesTo,0,sizeof(_expectingRepliesTo)); + memset(_lastIdentityVerification,0,sizeof(_lastIdentityVerification)); // Use Salsa20 alone as a high-quality non-crypto PRNG { diff --git a/node/Node.hpp b/node/Node.hpp index e616da3d..ee0d6c4c 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -283,6 +283,24 @@ public: return false; } + /** + * Check whether we should do potentially expensive identity verification (rate limit) + * + * @param now Current time + * @param from Source address of packet + * @return True if within rate limits + */ + inline bool rateGateIdentityVerification(const uint64_t now,const InetAddress &from) + { + unsigned long iph = from.rateGateHash(); + printf("%s %.4lx\n",from.toString().c_str(),iph); + if ((now - _lastIdentityVerification[iph]) >= ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT) { + _lastIdentityVerification[iph] = now; + return true; + } + return false; + } + virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig); virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode); @@ -302,9 +320,13 @@ private: void *_uPtr; // _uptr (lower case) is reserved in Visual Studio :P + // For tracking packet IDs to filter out OK/ERROR replies to packets we did not send uint8_t _expectingRepliesToBucketPtr[ZT_EXPECTING_REPLIES_BUCKET_MASK1 + 1]; uint64_t _expectingRepliesTo[ZT_EXPECTING_REPLIES_BUCKET_MASK1 + 1][ZT_EXPECTING_REPLIES_BUCKET_MASK2 + 1]; + // Time of last identity verification indexed by InetAddress.rateGateHash() + uint64_t _lastIdentityVerification[16384]; + ZT_DataStoreGetFunction _dataStoreGetFunction; ZT_DataStorePutFunction _dataStorePutFunction; ZT_WirePacketSendFunction _wirePacketSendFunction; diff --git a/selftest.cpp b/selftest.cpp index 9992d757..adac2f58 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -327,6 +327,17 @@ static int testCrypto() } std::cout << "PASS" << std::endl; + std::cout << "[crypto] Benchmarking C25519 ECC key agreement... "; std::cout.flush(); + C25519::Pair bp[8]; + for(int k=0;k<8;++k) + bp[k] = C25519::generate(); + const uint64_t st = OSUtils::now(); + for(unsigned int k=0;k<50;++k) { + C25519::agree(bp[~k & 7],bp[k & 7].pub,buf1,64); + } + const uint64_t et = OSUtils::now(); + std::cout << ((double)(et - st) / 50.0) << "ms per agreement." << std::endl; + std::cout << "[crypto] Testing Ed25519 ECC signatures... "; std::cout.flush(); C25519::Pair didntSign = C25519::generate(); for(unsigned int i=0;i<10;++i) { -- cgit v1.2.3 From 902e03bccc105d96e34c938d2df5fc54f9ea66ff Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 26 Jan 2017 14:23:22 -0800 Subject: build fix --- selftest.cpp | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'selftest.cpp') diff --git a/selftest.cpp b/selftest.cpp index adac2f58..6054983d 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -49,7 +49,6 @@ #include "osdep/OSUtils.hpp" #include "osdep/Phy.hpp" #include "osdep/Http.hpp" -#include "osdep/BackgroundResolver.hpp" #include "osdep/PortMapper.hpp" #include "osdep/Thread.hpp" @@ -1012,23 +1011,6 @@ static int testPhy() return 0; } -static int testResolver() -{ - std::cout << "[resolver] Testing BackgroundResolver..."; std::cout.flush(); - - BackgroundResolver r("tcp-fallback.zerotier.com"); - r.resolveNow(); - r.wait(); - - std::vector ips(r.get()); - for(std::vector::const_iterator ip(ips.begin());ip!=ips.end();++ip) { - std::cout << ' ' << ip->toString(); - } - std::cout << std::endl; - - return 0; -} - /* static int testHttp() { @@ -1136,7 +1118,6 @@ int main(int argc,char **argv) r |= testIdentity(); r |= testCertificate(); r |= testPhy(); - r |= testResolver(); //r |= testHttp(); //*/ -- cgit v1.2.3 From 21f4a97c35c01200040deeb3051cebc923072ac5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Feb 2017 11:49:41 -0800 Subject: CSPRNG performance improvement, self test build fix. --- node/Utils.cpp | 39 ++++++++++++++++++++++----------------- selftest.cpp | 12 ++++++------ 2 files changed, 28 insertions(+), 23 deletions(-) (limited to 'selftest.cpp') diff --git a/node/Utils.cpp b/node/Utils.cpp index 247dd54a..00b0db06 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -144,6 +144,8 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes) static Mutex globalLock; static Salsa20 s20; static bool s20Initialized = false; + static uint8_t randomBuf[65536]; + static unsigned int randomPtr = sizeof(randomBuf); Mutex::Lock _l(globalLock); @@ -168,27 +170,31 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes) static HCRYPTPROV cryptProvider = NULL; - if (cryptProvider == NULL) { - if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) { - fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n"); - exit(1); - return; + for(unsigned int i=0;i= sizeof(randomBuf)) { + if (cryptProvider == NULL) { + if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) { + fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n"); + exit(1); + } + } + if (!CryptGenRandom(cryptProvider,(DWORD)sizeof(randomBuf),(BYTE *)randomBuf)) { + fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n"); + exit(1); + } + randomPtr = 0; + s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf)); } - } - if (!CryptGenRandom(cryptProvider,(DWORD)bytes,(BYTE *)buf)) { - fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n"); - exit(1); + ((uint8_t *)buf)[i] = randomBuf[randomPtr++]; } #else // not __WINDOWS__ - static char randomBuf[65536]; - static unsigned int randomPtr = sizeof(randomBuf); static int devURandomFd = -1; - if (devURandomFd <= 0) { + if (devURandomFd < 0) { devURandomFd = ::open("/dev/urandom",O_RDONLY); - if (devURandomFd <= 0) { + if (devURandomFd < 0) { fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n"); exit(1); return; @@ -201,7 +207,7 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes) if ((int)::read(devURandomFd,randomBuf,sizeof(randomBuf)) != (int)sizeof(randomBuf)) { ::close(devURandomFd); devURandomFd = ::open("/dev/urandom",O_RDONLY); - if (devURandomFd <= 0) { + if (devURandomFd < 0) { fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n"); exit(1); return; @@ -209,13 +215,12 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes) } else break; } randomPtr = 0; + s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf)); } - ((char *)buf)[i] = randomBuf[randomPtr++]; + ((uint8_t *)buf)[i] = randomBuf[randomPtr++]; } #endif // __WINDOWS__ or not - - s20.crypt12(buf,buf,bytes); } bool Utils::scopy(char *dest,unsigned int len,const char *src) diff --git a/selftest.cpp b/selftest.cpp index 6054983d..b1f4b54a 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -154,9 +154,9 @@ static int testCrypto() memset(buf3,0,sizeof(buf3)); Salsa20 s20; s20.init("12345678123456781234567812345678",256,"12345678"); - s20.encrypt20(buf1,buf2,sizeof(buf1)); + s20.crypt20(buf1,buf2,sizeof(buf1)); s20.init("12345678123456781234567812345678",256,"12345678"); - s20.decrypt20(buf2,buf3,sizeof(buf2)); + s20.crypt20(buf2,buf3,sizeof(buf2)); if (memcmp(buf1,buf3,sizeof(buf1))) { std::cout << "FAIL (encrypt/decrypt test)" << std::endl; return -1; @@ -165,7 +165,7 @@ static int testCrypto() Salsa20 s20(s20TV0Key,256,s20TV0Iv); memset(buf1,0,sizeof(buf1)); memset(buf2,0,sizeof(buf2)); - s20.encrypt20(buf1,buf2,64); + s20.crypt20(buf1,buf2,64); if (memcmp(buf2,s20TV0Ks,64)) { std::cout << "FAIL (test vector 0)" << std::endl; return -1; @@ -173,7 +173,7 @@ static int testCrypto() s20.init(s2012TV0Key,256,s2012TV0Iv); memset(buf1,0,sizeof(buf1)); memset(buf2,0,sizeof(buf2)); - s20.encrypt12(buf1,buf2,64); + s20.crypt12(buf1,buf2,64); if (memcmp(buf2,s2012TV0Ks,64)) { std::cout << "FAIL (test vector 1)" << std::endl; return -1; @@ -195,7 +195,7 @@ static int testCrypto() double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { - s20.encrypt12(bb,bb,1234567); + s20.crypt12(bb,bb,1234567); bytes += 1234567.0; } uint64_t end = OSUtils::now(); @@ -213,7 +213,7 @@ static int testCrypto() double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { - s20.encrypt20(bb,bb,1234567); + s20.crypt20(bb,bb,1234567); bytes += 1234567.0; } uint64_t end = OSUtils::now(); -- cgit v1.2.3 From 87b53d67c51fabfd208d8999be14984517d869a7 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 2 Mar 2017 10:02:29 -0800 Subject: Fix selftest build. --- selftest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'selftest.cpp') diff --git a/selftest.cpp b/selftest.cpp index b1f4b54a..8a450796 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -572,7 +572,7 @@ static int testPacket() return -1; } - a.armor(salsaKey,true); + a.armor(salsaKey,true,0); if (!a.dearmor(salsaKey)) { std::cout << "FAIL (encrypt-decrypt/verify)" << std::endl; return -1; -- cgit v1.2.3 From ec8e1178e5cfbe9cd790928dd06562af734a2d48 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 17 Mar 2017 19:16:34 -0700 Subject: Version bumps, and fix Debian so default is to build normally and .static files are used in our builds. --- RELEASE-NOTES.md | 10 +++++++++ debian/changelog | 6 +++++ debian/rules | 2 +- debian/rules.static | 16 +++++++++++++ debian/rules.wheezy | 2 +- debian/rules.wheezy.static | 11 +++++++++ ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- .../chocolatey/zerotier-one/zerotier-one.nuspec | 2 +- selftest.cpp | 26 ++++++++++++++++++++++ zerotier-one.spec | 5 ++++- 10 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 debian/rules.static create mode 100644 debian/rules.wheezy.static (limited to 'selftest.cpp') diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index d0ad47d8..b54b7ea5 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,6 +1,16 @@ ZeroTier Release Notes ====== +# 2017-03-17 -- Version 1.2.2 + +Version 1.2.2 fixes a few bugs discovered after the 1.2.0 release. These are: + + * A bug causing unreliable multicast propagation (GitHub issue #461). + * A crash in ARM binaries due to a build chain and flags problem. + * A bug in the network controller preventing members from being listed (GitHub issue #460). + +------ + # 2017-03-14 -- Version 1.2.0 Version 1.2.0 is a major milestone release representing almost nine months of work. It includes our rules engine for distributed network packet filtering and security monitoring, federated roots, and many other architectural and UI improvements and bug fixes. diff --git a/debian/changelog b/debian/changelog index 86049d04..2bfb98c7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +zerotier-one (1.2.2) unstable; urgency=medium + + * See https://github.com/zerotier/ZeroTierOne for release notes. + + -- Adam Ierymenko Fri, 17 Mar 2017 01:00:00 -0700 + zerotier-one (1.2.0) unstable; urgency=medium * See https://github.com/zerotier/ZeroTierOne for release notes. diff --git a/debian/rules b/debian/rules index 72c52955..0ef81e05 100755 --- a/debian/rules +++ b/debian/rules @@ -7,7 +7,7 @@ CXXFLAGS=-O3 -fstack-protector-strong dh $@ --with systemd override_dh_auto_build: -# make -j 2 + make -j 2 override_dh_systemd_start: dh_systemd_start --restart-after-upgrade diff --git a/debian/rules.static b/debian/rules.static new file mode 100644 index 00000000..72c52955 --- /dev/null +++ b/debian/rules.static @@ -0,0 +1,16 @@ +#!/usr/bin/make -f + +CFLAGS=-O3 -fstack-protector-strong +CXXFLAGS=-O3 -fstack-protector-strong + +%: + dh $@ --with systemd + +override_dh_auto_build: +# make -j 2 + +override_dh_systemd_start: + dh_systemd_start --restart-after-upgrade + +override_dh_installinit: + dh_installinit --name=zerotier-one -- defaults diff --git a/debian/rules.wheezy b/debian/rules.wheezy index 0165be37..55e2647a 100755 --- a/debian/rules.wheezy +++ b/debian/rules.wheezy @@ -7,5 +7,5 @@ CXXFLAGS=-O3 -fstack-protector dh $@ override_dh_auto_build: -# make -j 2 + make -j 2 diff --git a/debian/rules.wheezy.static b/debian/rules.wheezy.static new file mode 100644 index 00000000..0165be37 --- /dev/null +++ b/debian/rules.wheezy.static @@ -0,0 +1,11 @@ +#!/usr/bin/make -f + +CFLAGS=-O3 -fstack-protector +CXXFLAGS=-O3 -fstack-protector + +%: + dh $@ + +override_dh_auto_build: +# make -j 2 + diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index b9171b9f..c41b61c9 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -646,7 +646,7 @@ OVERWRITE_PERMISSIONS VERSION - 1.2.0 + 1.2.2 PROJECT_COMMENTS diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec b/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec index b8f9eb7e..03987e3a 100644 --- a/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec +++ b/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec @@ -26,7 +26,7 @@ This is a nuspec. It mostly adheres to https://docs.nuget.org/create/Nuspec-Refe - 1.2.0 + 1.2.2 diff --git a/selftest.cpp b/selftest.cpp index 8a450796..48625d53 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -582,8 +582,34 @@ static int testPacket() return 0; } +static void _testExcept(int &depth) +{ + if (depth >= 16) { + throw std::runtime_error("LOL!"); + } else { + ++depth; + _testExcept(depth); + } +} + static int testOther() { + std::cout << "[other] Testing C++ exceptions... "; std::cout.flush(); + int depth = 0; + try { + _testExcept(depth); + } catch (std::runtime_error &e) { + if (depth == 16) { + std::cout << "OK" << std::endl; + } else { + std::cout << "ERROR (depth not 16)" << std::endl; + return -1; + } + } catch ( ... ) { + std::cout << "ERROR (exception not std::runtime_error)" << std::endl; + return -1; + } + std::cout << "[other] Testing Hashtable... "; std::cout.flush(); { Hashtable ht; diff --git a/zerotier-one.spec b/zerotier-one.spec index a78af1ac..10034111 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,5 +1,5 @@ Name: zerotier-one -Version: 1.2.0 +Version: 1.2.2 Release: 1%{?dist} Summary: ZeroTier One network virtualization service @@ -145,6 +145,9 @@ esac %endif %changelog +* Fri Mar 17 2017 Adam Ierymenko - 1.2.2-0.1 +- see https://github.com/zerotier/ZeroTierOne for release notes + * Tue Mar 14 2017 Adam Ierymenko - 1.2.0-0.1 - see https://github.com/zerotier/ZeroTierOne for release notes -- cgit v1.2.3 From df48738ac96a6eab5e3baa03f6dd1fb62bdc8040 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Apr 2017 16:43:03 -0700 Subject: Enable use of NaCl for faster X64 Salsa20 implementations. Also include binary for OSX for easy build. Blazingly fast. --- ext/bin/cnacl-osx-amd64/README.md | 53 ++++++++++++ .../include/sodium/crypto_auth_hmacsha256.h | 27 ++++++ .../include/sodium/crypto_auth_hmacsha512256.h | 27 ++++++ .../sodium/crypto_box_curve25519xsalsa20poly1305.h | 44 ++++++++++ .../include/sodium/crypto_core_hsalsa20.h | 27 ++++++ .../include/sodium/crypto_core_salsa20.h | 27 ++++++ .../include/sodium/crypto_core_salsa2012.h | 27 ++++++ .../include/sodium/crypto_core_salsa208.h | 27 ++++++ .../include/sodium/crypto_hash_sha256.h | 22 +++++ .../include/sodium/crypto_hash_sha512.h | 22 +++++ .../include/sodium/crypto_hashblocks_sha256.h | 23 ++++++ .../include/sodium/crypto_hashblocks_sha512.h | 23 ++++++ .../include/sodium/crypto_onetimeauth_poly1305.h | 27 ++++++ .../include/sodium/crypto_scalarmult_curve25519.h | 27 ++++++ .../sodium/crypto_secretbox_xsalsa20poly1305.h | 31 +++++++ .../sodium/crypto_sign_edwards25519sha512batch.h | 32 ++++++++ .../include/sodium/crypto_stream_aes128ctr.h | 35 ++++++++ .../include/sodium/crypto_stream_salsa20.h | 34 ++++++++ .../include/sodium/crypto_stream_salsa2012.h | 34 ++++++++ .../include/sodium/crypto_stream_salsa208.h | 34 ++++++++ .../include/sodium/crypto_stream_xsalsa20.h | 34 ++++++++ .../cnacl-osx-amd64/include/sodium/crypto_types.h | 11 +++ .../include/sodium/crypto_verify_16.h | 21 +++++ .../include/sodium/crypto_verify_32.h | 21 +++++ make-mac.mk | 6 ++ node/Identity.cpp | 2 +- node/Node.cpp | 6 +- node/Packet.cpp | 6 +- node/Salsa20.cpp | 29 +++---- node/Salsa20.hpp | 95 ++++++++++++++++++---- node/Utils.cpp | 2 +- selftest.cpp | 12 +-- 32 files changed, 801 insertions(+), 47 deletions(-) create mode 100644 ext/bin/cnacl-osx-amd64/README.md create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha256.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha512256.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_box_curve25519xsalsa20poly1305.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_hsalsa20.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa20.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa2012.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa208.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha256.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha512.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha256.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha512.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_onetimeauth_poly1305.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_scalarmult_curve25519.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_secretbox_xsalsa20poly1305.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_sign_edwards25519sha512batch.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_aes128ctr.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa20.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa2012.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa208.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_xsalsa20.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_types.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_16.h create mode 100644 ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_32.h (limited to 'selftest.cpp') diff --git a/ext/bin/cnacl-osx-amd64/README.md b/ext/bin/cnacl-osx-amd64/README.md new file mode 100644 index 00000000..35426286 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/README.md @@ -0,0 +1,53 @@ +# cNaCl + + If you would like to be confusing, you could pronounce it sea-salt + +This is a fork NaCl by Daniel J. Bernstein and Tanja Lange. +The build has been ported to cmake so it can be cross compiled and build output is reliable. +Since it uses cmake, it could theoretically be built on windows but this has not been tested. +It does compile using mingw32. + +## How do I make this thing work? + + mkdir cbuild + cd cbuild + cmake .. + make + +## Ok now how about cross compiling? + + mkdir cbuildw32 + cd cbuildw32 + cmake -DCMAKE_TOOLCHAIN_FILE=../CMakeWindows.txt .. + make + +## Why fork? + +NaCl builds using a shell script called `./do`. This script does compiling, testing, measuring +and selection of the best implementation of each algorithm for the given machine. It also generates +the header files which will be used. + +The problems with `./do` are it's slow, it tries compiling with multiple different compiler +profiles, it's very platform independent but it doesn't run on Windows and most importantly, with +compiling, testing and measuring so tightly bound, it is impossible to cross compile for a +different operating system. + + +## How it works + +The first time you build for a new ABI, it will trigger the traditional nacl `./do` script. +What cNaCl does is parse the resulting headers from the `./do` build and create a plan so that it +can repeat roughly the same build. + +If there is already a plan for the given ABI, the build uses this plan and the build is very fast. + +Plans are stored in `./cmake/plans/` and I will be adding plans as I find new ones. + + +## What else is new? + +There is a problem with the `./do` build which prevents it from running on some ARM based machines, +this was fixed by adding a more lax method for measuring CPU speed as a fall back. + + +`#EOF#` diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha256.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha256.h new file mode 100644 index 00000000..6b5600f3 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha256.h @@ -0,0 +1,27 @@ +#ifndef crypto_auth_hmacsha256_H +#define crypto_auth_hmacsha256_H + +#define crypto_auth_hmacsha256_ref_BYTES 32 +#define crypto_auth_hmacsha256_ref_KEYBYTES 32 +#ifdef __cplusplus +#include +extern std::string crypto_auth_hmacsha256_ref(const std::string &,const std::string &); +extern void crypto_auth_hmacsha256_ref_verify(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_auth_hmacsha256_ref(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_auth_hmacsha256_ref_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_auth_hmacsha256 crypto_auth_hmacsha256_ref +#define crypto_auth_hmacsha256_verify crypto_auth_hmacsha256_ref_verify +#define crypto_auth_hmacsha256_BYTES crypto_auth_hmacsha256_ref_BYTES +#define crypto_auth_hmacsha256_KEYBYTES crypto_auth_hmacsha256_ref_KEYBYTES +#define crypto_auth_hmacsha256_IMPLEMENTATION "crypto_auth/hmacsha256/ref" +#ifndef crypto_auth_hmacsha256_ref_VERSION +#define crypto_auth_hmacsha256_ref_VERSION "-" +#endif +#define crypto_auth_hmacsha256_VERSION crypto_auth_hmacsha256_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha512256.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha512256.h new file mode 100644 index 00000000..c9bd96e4 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_auth_hmacsha512256.h @@ -0,0 +1,27 @@ +#ifndef crypto_auth_hmacsha512256_H +#define crypto_auth_hmacsha512256_H + +#define crypto_auth_hmacsha512256_ref_BYTES 32 +#define crypto_auth_hmacsha512256_ref_KEYBYTES 32 +#ifdef __cplusplus +#include +extern std::string crypto_auth_hmacsha512256_ref(const std::string &,const std::string &); +extern void crypto_auth_hmacsha512256_ref_verify(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_auth_hmacsha512256_ref(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_auth_hmacsha512256_ref_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_ref +#define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_ref_verify +#define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_ref_BYTES +#define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_ref_KEYBYTES +#define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/ref" +#ifndef crypto_auth_hmacsha512256_ref_VERSION +#define crypto_auth_hmacsha512256_ref_VERSION "-" +#endif +#define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_box_curve25519xsalsa20poly1305.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_box_curve25519xsalsa20poly1305.h new file mode 100644 index 00000000..e2c3b4cc --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_box_curve25519xsalsa20poly1305.h @@ -0,0 +1,44 @@ +#ifndef crypto_box_curve25519xsalsa20poly1305_H +#define crypto_box_curve25519xsalsa20poly1305_H + +#define crypto_box_curve25519xsalsa20poly1305_ref_PUBLICKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_ref_SECRETKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_ref_BEFORENMBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_ref_NONCEBYTES 24 +#define crypto_box_curve25519xsalsa20poly1305_ref_ZEROBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_ref_BOXZEROBYTES 16 +#ifdef __cplusplus +#include +extern std::string crypto_box_curve25519xsalsa20poly1305_ref(const std::string &,const std::string &,const std::string &,const std::string &); +extern std::string crypto_box_curve25519xsalsa20poly1305_ref_open(const std::string &,const std::string &,const std::string &,const std::string &); +extern std::string crypto_box_curve25519xsalsa20poly1305_ref_keypair(std::string *); +extern "C" { +#endif +extern int crypto_box_curve25519xsalsa20poly1305_ref(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_ref_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_ref_beforenm(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_ref_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_ref_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_ref +#define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_ref_open +#define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_ref_keypair +#define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_ref_beforenm +#define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_ref_afternm +#define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_ref_open_afternm +#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_ref_PUBLICKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_ref_SECRETKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_ref_BEFORENMBYTES +#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_ref_NONCEBYTES +#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ref_ZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_ref_BOXZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/ref" +#ifndef crypto_box_curve25519xsalsa20poly1305_ref_VERSION +#define crypto_box_curve25519xsalsa20poly1305_ref_VERSION "-" +#endif +#define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_hsalsa20.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_hsalsa20.h new file mode 100644 index 00000000..abae188e --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_hsalsa20.h @@ -0,0 +1,27 @@ +#ifndef crypto_core_hsalsa20_H +#define crypto_core_hsalsa20_H + +#define crypto_core_hsalsa20_ref_OUTPUTBYTES 32 +#define crypto_core_hsalsa20_ref_INPUTBYTES 16 +#define crypto_core_hsalsa20_ref_KEYBYTES 32 +#define crypto_core_hsalsa20_ref_CONSTBYTES 16 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_core_hsalsa20_ref(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_core_hsalsa20 crypto_core_hsalsa20_ref +#define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_ref_OUTPUTBYTES +#define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_ref_INPUTBYTES +#define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_ref_KEYBYTES +#define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_ref_CONSTBYTES +#define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/ref" +#ifndef crypto_core_hsalsa20_ref_VERSION +#define crypto_core_hsalsa20_ref_VERSION "-" +#endif +#define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa20.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa20.h new file mode 100644 index 00000000..9737b101 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa20.h @@ -0,0 +1,27 @@ +#ifndef crypto_core_salsa20_H +#define crypto_core_salsa20_H + +#define crypto_core_salsa20_ref_OUTPUTBYTES 64 +#define crypto_core_salsa20_ref_INPUTBYTES 16 +#define crypto_core_salsa20_ref_KEYBYTES 32 +#define crypto_core_salsa20_ref_CONSTBYTES 16 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_core_salsa20_ref(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_core_salsa20 crypto_core_salsa20_ref +#define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_ref_OUTPUTBYTES +#define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_ref_INPUTBYTES +#define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_ref_KEYBYTES +#define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_ref_CONSTBYTES +#define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/ref" +#ifndef crypto_core_salsa20_ref_VERSION +#define crypto_core_salsa20_ref_VERSION "-" +#endif +#define crypto_core_salsa20_VERSION crypto_core_salsa20_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa2012.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa2012.h new file mode 100644 index 00000000..137cd47f --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa2012.h @@ -0,0 +1,27 @@ +#ifndef crypto_core_salsa2012_H +#define crypto_core_salsa2012_H + +#define crypto_core_salsa2012_ref_OUTPUTBYTES 64 +#define crypto_core_salsa2012_ref_INPUTBYTES 16 +#define crypto_core_salsa2012_ref_KEYBYTES 32 +#define crypto_core_salsa2012_ref_CONSTBYTES 16 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_core_salsa2012_ref(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_core_salsa2012 crypto_core_salsa2012_ref +#define crypto_core_salsa2012_OUTPUTBYTES crypto_core_salsa2012_ref_OUTPUTBYTES +#define crypto_core_salsa2012_INPUTBYTES crypto_core_salsa2012_ref_INPUTBYTES +#define crypto_core_salsa2012_KEYBYTES crypto_core_salsa2012_ref_KEYBYTES +#define crypto_core_salsa2012_CONSTBYTES crypto_core_salsa2012_ref_CONSTBYTES +#define crypto_core_salsa2012_IMPLEMENTATION "crypto_core/salsa2012/ref" +#ifndef crypto_core_salsa2012_ref_VERSION +#define crypto_core_salsa2012_ref_VERSION "-" +#endif +#define crypto_core_salsa2012_VERSION crypto_core_salsa2012_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa208.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa208.h new file mode 100644 index 00000000..4895bbbe --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_core_salsa208.h @@ -0,0 +1,27 @@ +#ifndef crypto_core_salsa208_H +#define crypto_core_salsa208_H + +#define crypto_core_salsa208_ref_OUTPUTBYTES 64 +#define crypto_core_salsa208_ref_INPUTBYTES 16 +#define crypto_core_salsa208_ref_KEYBYTES 32 +#define crypto_core_salsa208_ref_CONSTBYTES 16 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_core_salsa208_ref(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_core_salsa208 crypto_core_salsa208_ref +#define crypto_core_salsa208_OUTPUTBYTES crypto_core_salsa208_ref_OUTPUTBYTES +#define crypto_core_salsa208_INPUTBYTES crypto_core_salsa208_ref_INPUTBYTES +#define crypto_core_salsa208_KEYBYTES crypto_core_salsa208_ref_KEYBYTES +#define crypto_core_salsa208_CONSTBYTES crypto_core_salsa208_ref_CONSTBYTES +#define crypto_core_salsa208_IMPLEMENTATION "crypto_core/salsa208/ref" +#ifndef crypto_core_salsa208_ref_VERSION +#define crypto_core_salsa208_ref_VERSION "-" +#endif +#define crypto_core_salsa208_VERSION crypto_core_salsa208_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha256.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha256.h new file mode 100644 index 00000000..20d18703 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha256.h @@ -0,0 +1,22 @@ +#ifndef crypto_hash_sha256_H +#define crypto_hash_sha256_H + +#define crypto_hash_sha256_ref_BYTES 32 +#ifdef __cplusplus +#include +extern std::string crypto_hash_sha256_ref(const std::string &); +extern "C" { +#endif +extern int crypto_hash_sha256_ref(unsigned char *,const unsigned char *,unsigned long long); +#ifdef __cplusplus +} +#endif +#define crypto_hash_sha256 crypto_hash_sha256_ref +#define crypto_hash_sha256_BYTES crypto_hash_sha256_ref_BYTES +#define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/ref" +#ifndef crypto_hash_sha256_ref_VERSION +#define crypto_hash_sha256_ref_VERSION "-" +#endif +#define crypto_hash_sha256_VERSION crypto_hash_sha256_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha512.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha512.h new file mode 100644 index 00000000..fe19d2d9 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hash_sha512.h @@ -0,0 +1,22 @@ +#ifndef crypto_hash_sha512_H +#define crypto_hash_sha512_H + +#define crypto_hash_sha512_ref_BYTES 64 +#ifdef __cplusplus +#include +extern std::string crypto_hash_sha512_ref(const std::string &); +extern "C" { +#endif +extern int crypto_hash_sha512_ref(unsigned char *,const unsigned char *,unsigned long long); +#ifdef __cplusplus +} +#endif +#define crypto_hash_sha512 crypto_hash_sha512_ref +#define crypto_hash_sha512_BYTES crypto_hash_sha512_ref_BYTES +#define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/ref" +#ifndef crypto_hash_sha512_ref_VERSION +#define crypto_hash_sha512_ref_VERSION "-" +#endif +#define crypto_hash_sha512_VERSION crypto_hash_sha512_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha256.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha256.h new file mode 100644 index 00000000..3b473e6c --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha256.h @@ -0,0 +1,23 @@ +#ifndef crypto_hashblocks_sha256_H +#define crypto_hashblocks_sha256_H + +#define crypto_hashblocks_sha256_inplace_STATEBYTES 32 +#define crypto_hashblocks_sha256_inplace_BLOCKBYTES 64 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_hashblocks_sha256_inplace(unsigned char *,const unsigned char *,unsigned long long); +#ifdef __cplusplus +} +#endif +#define crypto_hashblocks_sha256 crypto_hashblocks_sha256_inplace +#define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_inplace_STATEBYTES +#define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_inplace_BLOCKBYTES +#define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/inplace" +#ifndef crypto_hashblocks_sha256_inplace_VERSION +#define crypto_hashblocks_sha256_inplace_VERSION "-" +#endif +#define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_inplace_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha512.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha512.h new file mode 100644 index 00000000..f66edd09 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_hashblocks_sha512.h @@ -0,0 +1,23 @@ +#ifndef crypto_hashblocks_sha512_H +#define crypto_hashblocks_sha512_H + +#define crypto_hashblocks_sha512_ref_STATEBYTES 64 +#define crypto_hashblocks_sha512_ref_BLOCKBYTES 128 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_hashblocks_sha512_ref(unsigned char *,const unsigned char *,unsigned long long); +#ifdef __cplusplus +} +#endif +#define crypto_hashblocks_sha512 crypto_hashblocks_sha512_ref +#define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_ref_STATEBYTES +#define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_ref_BLOCKBYTES +#define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/ref" +#ifndef crypto_hashblocks_sha512_ref_VERSION +#define crypto_hashblocks_sha512_ref_VERSION "-" +#endif +#define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_onetimeauth_poly1305.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_onetimeauth_poly1305.h new file mode 100644 index 00000000..de08dc9f --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_onetimeauth_poly1305.h @@ -0,0 +1,27 @@ +#ifndef crypto_onetimeauth_poly1305_H +#define crypto_onetimeauth_poly1305_H + +#define crypto_onetimeauth_poly1305_53_BYTES 16 +#define crypto_onetimeauth_poly1305_53_KEYBYTES 32 +#ifdef __cplusplus +#include +extern std::string crypto_onetimeauth_poly1305_53(const std::string &,const std::string &); +extern void crypto_onetimeauth_poly1305_53_verify(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_onetimeauth_poly1305_53(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_onetimeauth_poly1305_53_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_53 +#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_53_verify +#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_53_BYTES +#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_53_KEYBYTES +#define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/53" +#ifndef crypto_onetimeauth_poly1305_53_VERSION +#define crypto_onetimeauth_poly1305_53_VERSION "-" +#endif +#define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_53_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_scalarmult_curve25519.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_scalarmult_curve25519.h new file mode 100644 index 00000000..550c4e3d --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_scalarmult_curve25519.h @@ -0,0 +1,27 @@ +#ifndef crypto_scalarmult_curve25519_H +#define crypto_scalarmult_curve25519_H + +#define crypto_scalarmult_curve25519_donna_c64_BYTES 32 +#define crypto_scalarmult_curve25519_donna_c64_SCALARBYTES 32 +#ifdef __cplusplus +#include +extern std::string crypto_scalarmult_curve25519_donna_c64(const std::string &,const std::string &); +extern std::string crypto_scalarmult_curve25519_donna_c64_base(const std::string &); +extern "C" { +#endif +extern int crypto_scalarmult_curve25519_donna_c64(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_scalarmult_curve25519_donna_c64_base(unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_donna_c64 +#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_donna_c64_base +#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_donna_c64_BYTES +#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_donna_c64_SCALARBYTES +#define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/donna_c64" +#ifndef crypto_scalarmult_curve25519_donna_c64_VERSION +#define crypto_scalarmult_curve25519_donna_c64_VERSION "-" +#endif +#define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_donna_c64_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_secretbox_xsalsa20poly1305.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_secretbox_xsalsa20poly1305.h new file mode 100644 index 00000000..c930b6f1 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_secretbox_xsalsa20poly1305.h @@ -0,0 +1,31 @@ +#ifndef crypto_secretbox_xsalsa20poly1305_H +#define crypto_secretbox_xsalsa20poly1305_H + +#define crypto_secretbox_xsalsa20poly1305_ref_KEYBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_ref_NONCEBYTES 24 +#define crypto_secretbox_xsalsa20poly1305_ref_ZEROBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_ref_BOXZEROBYTES 16 +#ifdef __cplusplus +#include +extern std::string crypto_secretbox_xsalsa20poly1305_ref(const std::string &,const std::string &,const std::string &); +extern std::string crypto_secretbox_xsalsa20poly1305_ref_open(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_secretbox_xsalsa20poly1305_ref(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_secretbox_xsalsa20poly1305_ref_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_ref +#define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_ref_open +#define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_ref_KEYBYTES +#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_ref_NONCEBYTES +#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ref_ZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_ref_BOXZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/ref" +#ifndef crypto_secretbox_xsalsa20poly1305_ref_VERSION +#define crypto_secretbox_xsalsa20poly1305_ref_VERSION "-" +#endif +#define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_sign_edwards25519sha512batch.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_sign_edwards25519sha512batch.h new file mode 100644 index 00000000..936108ef --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_sign_edwards25519sha512batch.h @@ -0,0 +1,32 @@ +#ifndef crypto_sign_edwards25519sha512batch_H +#define crypto_sign_edwards25519sha512batch_H + +#define crypto_sign_edwards25519sha512batch_ref_SECRETKEYBYTES 64 +#define crypto_sign_edwards25519sha512batch_ref_PUBLICKEYBYTES 32 +#define crypto_sign_edwards25519sha512batch_ref_BYTES 64 +#ifdef __cplusplus +#include +extern std::string crypto_sign_edwards25519sha512batch_ref(const std::string &,const std::string &); +extern std::string crypto_sign_edwards25519sha512batch_ref_open(const std::string &,const std::string &); +extern std::string crypto_sign_edwards25519sha512batch_ref_keypair(std::string *); +extern "C" { +#endif +extern int crypto_sign_edwards25519sha512batch_ref(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_edwards25519sha512batch_ref_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_edwards25519sha512batch_ref_keypair(unsigned char *,unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_sign_edwards25519sha512batch crypto_sign_edwards25519sha512batch_ref +#define crypto_sign_edwards25519sha512batch_open crypto_sign_edwards25519sha512batch_ref_open +#define crypto_sign_edwards25519sha512batch_keypair crypto_sign_edwards25519sha512batch_ref_keypair +#define crypto_sign_edwards25519sha512batch_BYTES crypto_sign_edwards25519sha512batch_ref_BYTES +#define crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_ref_PUBLICKEYBYTES +#define crypto_sign_edwards25519sha512batch_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_ref_SECRETKEYBYTES +#define crypto_sign_edwards25519sha512batch_IMPLEMENTATION "crypto_sign/edwards25519sha512batch/ref" +#ifndef crypto_sign_edwards25519sha512batch_ref_VERSION +#define crypto_sign_edwards25519sha512batch_ref_VERSION "-" +#endif +#define crypto_sign_edwards25519sha512batch_VERSION crypto_sign_edwards25519sha512batch_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_aes128ctr.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_aes128ctr.h new file mode 100644 index 00000000..76bf9137 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_aes128ctr.h @@ -0,0 +1,35 @@ +#ifndef crypto_stream_aes128ctr_H +#define crypto_stream_aes128ctr_H + +#define crypto_stream_aes128ctr_portable_KEYBYTES 16 +#define crypto_stream_aes128ctr_portable_NONCEBYTES 16 +#define crypto_stream_aes128ctr_portable_BEFORENMBYTES 1408 +#ifdef __cplusplus +#include +extern std::string crypto_stream_aes128ctr_portable(size_t,const std::string &,const std::string &); +extern std::string crypto_stream_aes128ctr_portable_xor(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_stream_aes128ctr_portable(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_aes128ctr_portable_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_aes128ctr_portable_beforenm(unsigned char *,const unsigned char *); +extern int crypto_stream_aes128ctr_portable_afternm(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_aes128ctr_portable_xor_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_stream_aes128ctr crypto_stream_aes128ctr_portable +#define crypto_stream_aes128ctr_xor crypto_stream_aes128ctr_portable_xor +#define crypto_stream_aes128ctr_beforenm crypto_stream_aes128ctr_portable_beforenm +#define crypto_stream_aes128ctr_afternm crypto_stream_aes128ctr_portable_afternm +#define crypto_stream_aes128ctr_xor_afternm crypto_stream_aes128ctr_portable_xor_afternm +#define crypto_stream_aes128ctr_KEYBYTES crypto_stream_aes128ctr_portable_KEYBYTES +#define crypto_stream_aes128ctr_NONCEBYTES crypto_stream_aes128ctr_portable_NONCEBYTES +#define crypto_stream_aes128ctr_BEFORENMBYTES crypto_stream_aes128ctr_portable_BEFORENMBYTES +#define crypto_stream_aes128ctr_IMPLEMENTATION "crypto_stream/aes128ctr/portable" +#ifndef crypto_stream_aes128ctr_portable_VERSION +#define crypto_stream_aes128ctr_portable_VERSION "-" +#endif +#define crypto_stream_aes128ctr_VERSION crypto_stream_aes128ctr_portable_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa20.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa20.h new file mode 100644 index 00000000..c96d20b4 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa20.h @@ -0,0 +1,34 @@ +#ifndef crypto_stream_salsa20_H +#define crypto_stream_salsa20_H + +#define crypto_stream_salsa20_amd64_xmm6_KEYBYTES 32 +#define crypto_stream_salsa20_amd64_xmm6_NONCEBYTES 8 +#ifdef __cplusplus +#include +extern std::string crypto_stream_salsa20_amd64_xmm6(size_t,const std::string &,const std::string &); +extern std::string crypto_stream_salsa20_amd64_xmm6_xor(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_stream_salsa20_amd64_xmm6(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa20_amd64_xmm6_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa20_amd64_xmm6_beforenm(unsigned char *,const unsigned char *); +extern int crypto_stream_salsa20_amd64_xmm6_afternm(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa20_amd64_xmm6_xor_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_stream_salsa20 crypto_stream_salsa20_amd64_xmm6 +#define crypto_stream_salsa20_xor crypto_stream_salsa20_amd64_xmm6_xor +#define crypto_stream_salsa20_beforenm crypto_stream_salsa20_amd64_xmm6_beforenm +#define crypto_stream_salsa20_afternm crypto_stream_salsa20_amd64_xmm6_afternm +#define crypto_stream_salsa20_xor_afternm crypto_stream_salsa20_amd64_xmm6_xor_afternm +#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_amd64_xmm6_KEYBYTES +#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_amd64_xmm6_NONCEBYTES +#define crypto_stream_salsa20_BEFORENMBYTES crypto_stream_salsa20_amd64_xmm6_BEFORENMBYTES +#define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/amd64_xmm6" +#ifndef crypto_stream_salsa20_amd64_xmm6_VERSION +#define crypto_stream_salsa20_amd64_xmm6_VERSION "-" +#endif +#define crypto_stream_salsa20_VERSION crypto_stream_salsa20_amd64_xmm6_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa2012.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa2012.h new file mode 100644 index 00000000..051e4e39 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa2012.h @@ -0,0 +1,34 @@ +#ifndef crypto_stream_salsa2012_H +#define crypto_stream_salsa2012_H + +#define crypto_stream_salsa2012_amd64_xmm6_KEYBYTES 32 +#define crypto_stream_salsa2012_amd64_xmm6_NONCEBYTES 8 +#ifdef __cplusplus +#include +extern std::string crypto_stream_salsa2012_amd64_xmm6(size_t,const std::string &,const std::string &); +extern std::string crypto_stream_salsa2012_amd64_xmm6_xor(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_stream_salsa2012_amd64_xmm6(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa2012_amd64_xmm6_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa2012_amd64_xmm6_beforenm(unsigned char *,const unsigned char *); +extern int crypto_stream_salsa2012_amd64_xmm6_afternm(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa2012_amd64_xmm6_xor_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_stream_salsa2012 crypto_stream_salsa2012_amd64_xmm6 +#define crypto_stream_salsa2012_xor crypto_stream_salsa2012_amd64_xmm6_xor +#define crypto_stream_salsa2012_beforenm crypto_stream_salsa2012_amd64_xmm6_beforenm +#define crypto_stream_salsa2012_afternm crypto_stream_salsa2012_amd64_xmm6_afternm +#define crypto_stream_salsa2012_xor_afternm crypto_stream_salsa2012_amd64_xmm6_xor_afternm +#define crypto_stream_salsa2012_KEYBYTES crypto_stream_salsa2012_amd64_xmm6_KEYBYTES +#define crypto_stream_salsa2012_NONCEBYTES crypto_stream_salsa2012_amd64_xmm6_NONCEBYTES +#define crypto_stream_salsa2012_BEFORENMBYTES crypto_stream_salsa2012_amd64_xmm6_BEFORENMBYTES +#define crypto_stream_salsa2012_IMPLEMENTATION "crypto_stream/salsa2012/amd64_xmm6" +#ifndef crypto_stream_salsa2012_amd64_xmm6_VERSION +#define crypto_stream_salsa2012_amd64_xmm6_VERSION "-" +#endif +#define crypto_stream_salsa2012_VERSION crypto_stream_salsa2012_amd64_xmm6_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa208.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa208.h new file mode 100644 index 00000000..4bd470c3 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_salsa208.h @@ -0,0 +1,34 @@ +#ifndef crypto_stream_salsa208_H +#define crypto_stream_salsa208_H + +#define crypto_stream_salsa208_amd64_xmm6_KEYBYTES 32 +#define crypto_stream_salsa208_amd64_xmm6_NONCEBYTES 8 +#ifdef __cplusplus +#include +extern std::string crypto_stream_salsa208_amd64_xmm6(size_t,const std::string &,const std::string &); +extern std::string crypto_stream_salsa208_amd64_xmm6_xor(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_stream_salsa208_amd64_xmm6(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa208_amd64_xmm6_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa208_amd64_xmm6_beforenm(unsigned char *,const unsigned char *); +extern int crypto_stream_salsa208_amd64_xmm6_afternm(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa208_amd64_xmm6_xor_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_stream_salsa208 crypto_stream_salsa208_amd64_xmm6 +#define crypto_stream_salsa208_xor crypto_stream_salsa208_amd64_xmm6_xor +#define crypto_stream_salsa208_beforenm crypto_stream_salsa208_amd64_xmm6_beforenm +#define crypto_stream_salsa208_afternm crypto_stream_salsa208_amd64_xmm6_afternm +#define crypto_stream_salsa208_xor_afternm crypto_stream_salsa208_amd64_xmm6_xor_afternm +#define crypto_stream_salsa208_KEYBYTES crypto_stream_salsa208_amd64_xmm6_KEYBYTES +#define crypto_stream_salsa208_NONCEBYTES crypto_stream_salsa208_amd64_xmm6_NONCEBYTES +#define crypto_stream_salsa208_BEFORENMBYTES crypto_stream_salsa208_amd64_xmm6_BEFORENMBYTES +#define crypto_stream_salsa208_IMPLEMENTATION "crypto_stream/salsa208/amd64_xmm6" +#ifndef crypto_stream_salsa208_amd64_xmm6_VERSION +#define crypto_stream_salsa208_amd64_xmm6_VERSION "-" +#endif +#define crypto_stream_salsa208_VERSION crypto_stream_salsa208_amd64_xmm6_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_xsalsa20.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_xsalsa20.h new file mode 100644 index 00000000..d75268c6 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_stream_xsalsa20.h @@ -0,0 +1,34 @@ +#ifndef crypto_stream_xsalsa20_H +#define crypto_stream_xsalsa20_H + +#define crypto_stream_xsalsa20_ref_KEYBYTES 32 +#define crypto_stream_xsalsa20_ref_NONCEBYTES 24 +#ifdef __cplusplus +#include +extern std::string crypto_stream_xsalsa20_ref(size_t,const std::string &,const std::string &); +extern std::string crypto_stream_xsalsa20_ref_xor(const std::string &,const std::string &,const std::string &); +extern "C" { +#endif +extern int crypto_stream_xsalsa20_ref(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_xsalsa20_ref_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_xsalsa20_ref_beforenm(unsigned char *,const unsigned char *); +extern int crypto_stream_xsalsa20_ref_afternm(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_xsalsa20_ref_xor_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_stream_xsalsa20 crypto_stream_xsalsa20_ref +#define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_ref_xor +#define crypto_stream_xsalsa20_beforenm crypto_stream_xsalsa20_ref_beforenm +#define crypto_stream_xsalsa20_afternm crypto_stream_xsalsa20_ref_afternm +#define crypto_stream_xsalsa20_xor_afternm crypto_stream_xsalsa20_ref_xor_afternm +#define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_ref_KEYBYTES +#define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_ref_NONCEBYTES +#define crypto_stream_xsalsa20_BEFORENMBYTES crypto_stream_xsalsa20_ref_BEFORENMBYTES +#define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/ref" +#ifndef crypto_stream_xsalsa20_ref_VERSION +#define crypto_stream_xsalsa20_ref_VERSION "-" +#endif +#define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_types.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_types.h new file mode 100644 index 00000000..b0ce9656 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_types.h @@ -0,0 +1,11 @@ +#ifndef crypto_types_h +#define crypto_types_h +typedef short crypto_int16; +typedef int crypto_int32; +typedef long long crypto_int64; +typedef signed char crypto_int8; +typedef unsigned short crypto_uint16; +typedef unsigned int crypto_uint32; +typedef unsigned long long crypto_uint64; +typedef unsigned char crypto_uint8; +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_16.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_16.h new file mode 100644 index 00000000..6bf6ca11 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_16.h @@ -0,0 +1,21 @@ +#ifndef crypto_verify_16_H +#define crypto_verify_16_H + +#define crypto_verify_16_ref_BYTES 16 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_verify_16_ref(const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_verify_16 crypto_verify_16_ref +#define crypto_verify_16_BYTES crypto_verify_16_ref_BYTES +#define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/ref" +#ifndef crypto_verify_16_ref_VERSION +#define crypto_verify_16_ref_VERSION "-" +#endif +#define crypto_verify_16_VERSION crypto_verify_16_ref_VERSION + +#endif diff --git a/ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_32.h b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_32.h new file mode 100644 index 00000000..bd5fc644 --- /dev/null +++ b/ext/bin/cnacl-osx-amd64/include/sodium/crypto_verify_32.h @@ -0,0 +1,21 @@ +#ifndef crypto_verify_32_H +#define crypto_verify_32_H + +#define crypto_verify_32_ref_BYTES 32 +#ifdef __cplusplus +#include +extern "C" { +#endif +extern int crypto_verify_32_ref(const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif +#define crypto_verify_32 crypto_verify_32_ref +#define crypto_verify_32_BYTES crypto_verify_32_ref_BYTES +#define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/ref" +#ifndef crypto_verify_32_ref_VERSION +#define crypto_verify_32_ref_VERSION "-" +#endif +#define crypto_verify_32_VERSION crypto_verify_32_ref_VERSION + +#endif diff --git a/make-mac.mk b/make-mac.mk index 8ff1b772..b71ca2fe 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -33,6 +33,12 @@ else DEFS+=-DZT_SOFTWARE_UPDATE_DEFAULT="\"download\"" endif +# Use precompiled extremely fast Salsa20/12 from "cnacl" included in ext/bin +# See https://github.com/cjdelisle/cnacl +DEFS+=-DZT_USE_LIBSODIUM +CFLAGS+=-Iext/bin/cnacl-osx-amd64/include +LIBS+=ext/bin/cnacl-osx-amd64/libnacl.a + ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER endif diff --git a/node/Identity.cpp b/node/Identity.cpp index 89fdb836..d1b21e9c 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -45,7 +45,7 @@ static inline void _computeMemoryHardHash(const void *publicKey,unsigned int pub // ordinary Salsa20 is randomly seekable. This is good for a cipher // but is not what we want for sequential memory-harndess. memset(genmem,0,ZT_IDENTITY_GEN_MEMORY); - Salsa20 s20(digest,256,(char *)digest + 32); + Salsa20 s20(digest,(char *)digest + 32); s20.crypt20((char *)genmem,(char *)genmem,64); for(unsigned long i=64;i> (32 - (c)))) #define XOR(v,w) ((v) ^ (w)) #define PLUS(v,w) ((uint32_t)((v) + (w))) @@ -66,8 +68,7 @@ static const _s20sseconsts _S20SSECONSTANTS; namespace ZeroTier { -void Salsa20::init(const void *key,unsigned int kbits,const void *iv) - throw() +void Salsa20::init(const void *key,const void *iv) { #ifdef ZT_SALSA20_SSE const uint32_t *k = (const uint32_t *)key; @@ -78,14 +79,9 @@ void Salsa20::init(const void *key,unsigned int kbits,const void *iv) _state.i[10] = k[1]; _state.i[7] = k[2]; _state.i[4] = k[3]; - if (kbits == 256) { - k += 4; - _state.i[1] = 0x3320646e; - _state.i[2] = 0x79622d32; - } else { - _state.i[1] = 0x3120646e; - _state.i[2] = 0x79622d36; - } + k += 4; + _state.i[1] = 0x3320646e; + _state.i[2] = 0x79622d32; _state.i[15] = k[0]; _state.i[12] = k[1]; _state.i[9] = k[2]; @@ -95,19 +91,14 @@ void Salsa20::init(const void *key,unsigned int kbits,const void *iv) _state.i[5] = 0; _state.i[8] = 0; #else - const char *constants; + const char *const constants = "expand 32-byte k"; const uint8_t *k = (const uint8_t *)key; _state.i[1] = U8TO32_LITTLE(k + 0); _state.i[2] = U8TO32_LITTLE(k + 4); _state.i[3] = U8TO32_LITTLE(k + 8); _state.i[4] = U8TO32_LITTLE(k + 12); - if (kbits == 256) { /* recommended */ - k += 16; - constants = "expand 32-byte k"; - } else { /* kbits == 128 */ - constants = "expand 16-byte k"; - } + k += 16; _state.i[5] = U8TO32_LITTLE(constants + 4); _state.i[6] = U8TO32_LITTLE(((const uint8_t *)iv) + 0); _state.i[7] = U8TO32_LITTLE(((const uint8_t *)iv) + 4); @@ -124,7 +115,6 @@ void Salsa20::init(const void *key,unsigned int kbits,const void *iv) } void Salsa20::crypt12(const void *in,void *out,unsigned int bytes) - throw() { uint8_t tmp[64]; const uint8_t *m = (const uint8_t *)in; @@ -624,7 +614,6 @@ void Salsa20::crypt12(const void *in,void *out,unsigned int bytes) } void Salsa20::crypt20(const void *in,void *out,unsigned int bytes) - throw() { uint8_t tmp[64]; const uint8_t *m = (const uint8_t *)in; @@ -1356,3 +1345,5 @@ void Salsa20::crypt20(const void *in,void *out,unsigned int bytes) } } // namespace ZeroTier + +#endif // !ZT_USE_LIBSODIUM diff --git a/node/Salsa20.hpp b/node/Salsa20.hpp index 6405d450..5e4c68be 100644 --- a/node/Salsa20.hpp +++ b/node/Salsa20.hpp @@ -10,10 +10,82 @@ #include #include #include +#include #include "Constants.hpp" #include "Utils.hpp" +#ifdef ZT_USE_LIBSODIUM + +#include +#include + +namespace ZeroTier { + +/** + * Salsa20 stream cipher + */ +class Salsa20 +{ +public: + Salsa20() {} + ~Salsa20() { Utils::burn(_k,sizeof(_k)); } + + /** + * @param key 256-bit (32 byte) key + * @param iv 64-bit initialization vector + */ + Salsa20(const void *key,const void *iv) + { + memcpy(_k,key,32); + memcpy(&_iv,iv,8); + } + + /** + * Initialize cipher + * + * @param key Key bits + * @param iv 64-bit initialization vector + */ + inline void init(const void *key,const void *iv) + { + memcpy(_k,key,32); + memcpy(&_iv,iv,8); + } + + /** + * Encrypt/decrypt data using Salsa20/12 + * + * @param in Input data + * @param out Output buffer + * @param bytes Length of data + */ + inline void crypt12(const void *in,void *out,unsigned int bytes) + { + crypto_stream_salsa2012_xor(reinterpret_cast(out),reinterpret_cast(in),bytes,reinterpret_cast(&_iv),reinterpret_cast(_k)); + } + + /** + * Encrypt/decrypt data using Salsa20/20 + * + * @param in Input data + * @param out Output buffer + * @param bytes Length of data + */ + inline void crypt20(const void *in,void *out,unsigned int bytes) + { + crypto_stream_salsa20_xor(reinterpret_cast(out),reinterpret_cast(in),bytes,reinterpret_cast(&_iv),reinterpret_cast(_k)); + } + +private: + uint64_t _k[4]; + uint64_t _iv; +}; + +} // namespace ZeroTier + +#else // !ZT_USE_LIBSODIUM + #if (!defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || defined(__WINDOWS__)) #define ZT_SALSA20_SSE 1 #endif @@ -30,30 +102,25 @@ namespace ZeroTier { class Salsa20 { public: - Salsa20() throw() {} - + Salsa20() {} ~Salsa20() { Utils::burn(&_state,sizeof(_state)); } /** - * @param key Key bits - * @param kbits Number of key bits: 128 or 256 (recommended) + * @param key 256-bit (32 byte) key * @param iv 64-bit initialization vector */ - Salsa20(const void *key,unsigned int kbits,const void *iv) - throw() + Salsa20(const void *key,const void *iv) { - init(key,kbits,iv); + init(key,iv); } /** * Initialize cipher * * @param key Key bits - * @param kbits Number of key bits: 128 or 256 (recommended) * @param iv 64-bit initialization vector */ - void init(const void *key,unsigned int kbits,const void *iv) - throw(); + void init(const void *key,const void *iv); /** * Encrypt/decrypt data using Salsa20/12 @@ -62,8 +129,7 @@ public: * @param out Output buffer * @param bytes Length of data */ - void crypt12(const void *in,void *out,unsigned int bytes) - throw(); + void crypt12(const void *in,void *out,unsigned int bytes); /** * Encrypt/decrypt data using Salsa20/20 @@ -72,8 +138,7 @@ public: * @param out Output buffer * @param bytes Length of data */ - void crypt20(const void *in,void *out,unsigned int bytes) - throw(); + void crypt20(const void *in,void *out,unsigned int bytes); private: union { @@ -86,4 +151,6 @@ private: } // namespace ZeroTier +#endif // ZT_USE_LIBSODIUM + #endif diff --git a/node/Utils.cpp b/node/Utils.cpp index fb448dd6..92d14d19 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -156,7 +156,7 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes) s20Key[1] = (uint64_t)buf; // address of buf s20Key[2] = (uint64_t)s20Key; // address of s20Key[] s20Key[3] = (uint64_t)&s20; // address of s20 - s20.init(s20Key,256,s20Key); + s20.init(s20Key,s20Key); } #ifdef __WINDOWS__ diff --git a/selftest.cpp b/selftest.cpp index 48625d53..fe0aa933 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -153,16 +153,16 @@ static int testCrypto() memset(buf2,0,sizeof(buf2)); memset(buf3,0,sizeof(buf3)); Salsa20 s20; - s20.init("12345678123456781234567812345678",256,"12345678"); + s20.init("12345678123456781234567812345678","12345678"); s20.crypt20(buf1,buf2,sizeof(buf1)); - s20.init("12345678123456781234567812345678",256,"12345678"); + s20.init("12345678123456781234567812345678","12345678"); s20.crypt20(buf2,buf3,sizeof(buf2)); if (memcmp(buf1,buf3,sizeof(buf1))) { std::cout << "FAIL (encrypt/decrypt test)" << std::endl; return -1; } } - Salsa20 s20(s20TV0Key,256,s20TV0Iv); + Salsa20 s20(s20TV0Key,s20TV0Iv); memset(buf1,0,sizeof(buf1)); memset(buf2,0,sizeof(buf2)); s20.crypt20(buf1,buf2,64); @@ -170,7 +170,7 @@ static int testCrypto() std::cout << "FAIL (test vector 0)" << std::endl; return -1; } - s20.init(s2012TV0Key,256,s2012TV0Iv); + s20.init(s2012TV0Key,s2012TV0Iv); memset(buf1,0,sizeof(buf1)); memset(buf2,0,sizeof(buf2)); s20.crypt12(buf1,buf2,64); @@ -191,7 +191,7 @@ static int testCrypto() unsigned char *bb = (unsigned char *)::malloc(1234567); for(unsigned int i=0;i<1234567;++i) bb[i] = (unsigned char)i; - Salsa20 s20(s20TV0Key,256,s20TV0Iv); + Salsa20 s20(s20TV0Key,s20TV0Iv); double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { @@ -209,7 +209,7 @@ static int testCrypto() unsigned char *bb = (unsigned char *)::malloc(1234567); for(unsigned int i=0;i<1234567;++i) bb[i] = (unsigned char)i; - Salsa20 s20(s20TV0Key,256,s20TV0Iv); + Salsa20 s20(s20TV0Key,s20TV0Iv); double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { -- cgit v1.2.3 From a1e94154bebe17a24d2eed43be7d866e93c061fe Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 18 Apr 2017 08:45:37 -0700 Subject: Just incorporate the X64 ASM version of Salsa20/12 for X64 platforms. This gives us (for example) 1.5gb/sec encryption on a Core i5 2.8ghz. --- ext/x64-salsa2012-asm/README.md | 6 + ext/x64-salsa2012-asm/salsa2012.h | 13 + ext/x64-salsa2012-asm/salsa2012.s | 4488 +++++++++++++++++++++++++++++++++++++ make-mac.mk | 7 + node/Packet.cpp | 65 +- selftest.cpp | 22 + 6 files changed, 4597 insertions(+), 4 deletions(-) create mode 100644 ext/x64-salsa2012-asm/README.md create mode 100644 ext/x64-salsa2012-asm/salsa2012.h create mode 100644 ext/x64-salsa2012-asm/salsa2012.s (limited to 'selftest.cpp') diff --git a/ext/x64-salsa2012-asm/README.md b/ext/x64-salsa2012-asm/README.md new file mode 100644 index 00000000..a69a1a67 --- /dev/null +++ b/ext/x64-salsa2012-asm/README.md @@ -0,0 +1,6 @@ +Blazingly fast X64 ASM implementation of Salsa20/12 +====== + +This is ripped from the [cnacl](https://github.com/cjdelisle/cnacl) source. The actual code is by Danial J. Bernstein and is in the public domain. + +This is included on Linux and Mac 64-bit builds and is significantly faster than the SSE intrinsics or C versions. It's used for packet encode/decode only since its use differs a bit from the regular Salsa20 C++ class. Specifically it lacks the ability to be called on multiple blocks, preferring instead to take a key and a single stream to encrypt and that's it. diff --git a/ext/x64-salsa2012-asm/salsa2012.h b/ext/x64-salsa2012-asm/salsa2012.h new file mode 100644 index 00000000..d47059b4 --- /dev/null +++ b/ext/x64-salsa2012-asm/salsa2012.h @@ -0,0 +1,13 @@ +#ifdef __cplusplus +extern "C" { +#endif + +// output, outlen, nonce, key (256-bit / 32-byte) +extern int zt_salsa2012_amd64_xmm6(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); + +// ciphertext, message, mlen, nonce, key +extern int zt_salsa2012_amd64_xmm6_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); + +#ifdef __cplusplus +} +#endif diff --git a/ext/x64-salsa2012-asm/salsa2012.s b/ext/x64-salsa2012-asm/salsa2012.s new file mode 100644 index 00000000..699c89ac --- /dev/null +++ b/ext/x64-salsa2012-asm/salsa2012.s @@ -0,0 +1,4488 @@ +# qhasm: enter zt_salsa2012_amd64_xmm6 +.text +.p2align 5 +.globl _zt_salsa2012_amd64_xmm6 +.globl zt_salsa2012_amd64_xmm6 +_zt_salsa2012_amd64_xmm6: +zt_salsa2012_amd64_xmm6: +mov %rsp,%r11 +and $31,%r11 +add $480,%r11 +sub %r11,%rsp + +# qhasm: r11_stack = r11_caller +# asm 1: movq r11_stack=stack64#1 +# asm 2: movq r11_stack=352(%rsp) +movq %r11,352(%rsp) + +# qhasm: r12_stack = r12_caller +# asm 1: movq r12_stack=stack64#2 +# asm 2: movq r12_stack=360(%rsp) +movq %r12,360(%rsp) + +# qhasm: r13_stack = r13_caller +# asm 1: movq r13_stack=stack64#3 +# asm 2: movq r13_stack=368(%rsp) +movq %r13,368(%rsp) + +# qhasm: r14_stack = r14_caller +# asm 1: movq r14_stack=stack64#4 +# asm 2: movq r14_stack=376(%rsp) +movq %r14,376(%rsp) + +# qhasm: r15_stack = r15_caller +# asm 1: movq r15_stack=stack64#5 +# asm 2: movq r15_stack=384(%rsp) +movq %r15,384(%rsp) + +# qhasm: rbx_stack = rbx_caller +# asm 1: movq rbx_stack=stack64#6 +# asm 2: movq rbx_stack=392(%rsp) +movq %rbx,392(%rsp) + +# qhasm: rbp_stack = rbp_caller +# asm 1: movq rbp_stack=stack64#7 +# asm 2: movq rbp_stack=400(%rsp) +movq %rbp,400(%rsp) + +# qhasm: bytes = arg2 +# asm 1: mov bytes=int64#6 +# asm 2: mov bytes=%r9 +mov %rsi,%r9 + +# qhasm: out = arg1 +# asm 1: mov out=int64#1 +# asm 2: mov out=%rdi +mov %rdi,%rdi + +# qhasm: m = out +# asm 1: mov m=int64#2 +# asm 2: mov m=%rsi +mov %rdi,%rsi + +# qhasm: iv = arg3 +# asm 1: mov iv=int64#3 +# asm 2: mov iv=%rdx +mov %rdx,%rdx + +# qhasm: k = arg4 +# asm 1: mov k=int64#8 +# asm 2: mov k=%r10 +mov %rcx,%r10 + +# qhasm: unsigned>? bytes - 0 +# asm 1: cmp $0, +jbe ._done + +# qhasm: a = 0 +# asm 1: mov $0,>a=int64#7 +# asm 2: mov $0,>a=%rax +mov $0,%rax + +# qhasm: i = bytes +# asm 1: mov i=int64#4 +# asm 2: mov i=%rcx +mov %r9,%rcx + +# qhasm: while (i) { *out++ = a; --i } +rep stosb + +# qhasm: out -= bytes +# asm 1: sub r11_stack=stack64#1 +# asm 2: movq r11_stack=352(%rsp) +movq %r11,352(%rsp) + +# qhasm: r12_stack = r12_caller +# asm 1: movq r12_stack=stack64#2 +# asm 2: movq r12_stack=360(%rsp) +movq %r12,360(%rsp) + +# qhasm: r13_stack = r13_caller +# asm 1: movq r13_stack=stack64#3 +# asm 2: movq r13_stack=368(%rsp) +movq %r13,368(%rsp) + +# qhasm: r14_stack = r14_caller +# asm 1: movq r14_stack=stack64#4 +# asm 2: movq r14_stack=376(%rsp) +movq %r14,376(%rsp) + +# qhasm: r15_stack = r15_caller +# asm 1: movq r15_stack=stack64#5 +# asm 2: movq r15_stack=384(%rsp) +movq %r15,384(%rsp) + +# qhasm: rbx_stack = rbx_caller +# asm 1: movq rbx_stack=stack64#6 +# asm 2: movq rbx_stack=392(%rsp) +movq %rbx,392(%rsp) + +# qhasm: rbp_stack = rbp_caller +# asm 1: movq rbp_stack=stack64#7 +# asm 2: movq rbp_stack=400(%rsp) +movq %rbp,400(%rsp) + +# qhasm: out = arg1 +# asm 1: mov out=int64#1 +# asm 2: mov out=%rdi +mov %rdi,%rdi + +# qhasm: m = arg2 +# asm 1: mov m=int64#2 +# asm 2: mov m=%rsi +mov %rsi,%rsi + +# qhasm: bytes = arg3 +# asm 1: mov bytes=int64#6 +# asm 2: mov bytes=%r9 +mov %rdx,%r9 + +# qhasm: iv = arg4 +# asm 1: mov iv=int64#3 +# asm 2: mov iv=%rdx +mov %rcx,%rdx + +# qhasm: k = arg5 +# asm 1: mov k=int64#8 +# asm 2: mov k=%r10 +mov %r8,%r10 + +# qhasm: unsigned>? bytes - 0 +# asm 1: cmp $0, +jbe ._done +# comment:fp stack unchanged by fallthrough + +# qhasm: start: +._start: + +# qhasm: in12 = *(uint32 *) (k + 20) +# asm 1: movl 20(in12=int64#4d +# asm 2: movl 20(in12=%ecx +movl 20(%r10),%ecx + +# qhasm: in1 = *(uint32 *) (k + 0) +# asm 1: movl 0(in1=int64#5d +# asm 2: movl 0(in1=%r8d +movl 0(%r10),%r8d + +# qhasm: in6 = *(uint32 *) (iv + 0) +# asm 1: movl 0(in6=int64#7d +# asm 2: movl 0(in6=%eax +movl 0(%rdx),%eax + +# qhasm: in11 = *(uint32 *) (k + 16) +# asm 1: movl 16(in11=int64#9d +# asm 2: movl 16(in11=%r11d +movl 16(%r10),%r11d + +# qhasm: ((uint32 *)&x1)[0] = in12 +# asm 1: movl x1=stack128#1 +# asm 2: movl x1=0(%rsp) +movl %ecx,0(%rsp) + +# qhasm: ((uint32 *)&x1)[1] = in1 +# asm 1: movl in8=int64#4 +# asm 2: mov $0,>in8=%rcx +mov $0,%rcx + +# qhasm: in13 = *(uint32 *) (k + 24) +# asm 1: movl 24(in13=int64#5d +# asm 2: movl 24(in13=%r8d +movl 24(%r10),%r8d + +# qhasm: in2 = *(uint32 *) (k + 4) +# asm 1: movl 4(in2=int64#7d +# asm 2: movl 4(in2=%eax +movl 4(%r10),%eax + +# qhasm: in7 = *(uint32 *) (iv + 4) +# asm 1: movl 4(in7=int64#3d +# asm 2: movl 4(in7=%edx +movl 4(%rdx),%edx + +# qhasm: ((uint32 *)&x2)[0] = in8 +# asm 1: movl x2=stack128#2 +# asm 2: movl x2=16(%rsp) +movl %ecx,16(%rsp) + +# qhasm: ((uint32 *)&x2)[1] = in13 +# asm 1: movl in4=int64#3d +# asm 2: movl 12(in4=%edx +movl 12(%r10),%edx + +# qhasm: in9 = 0 +# asm 1: mov $0,>in9=int64#4 +# asm 2: mov $0,>in9=%rcx +mov $0,%rcx + +# qhasm: in14 = *(uint32 *) (k + 28) +# asm 1: movl 28(in14=int64#5d +# asm 2: movl 28(in14=%r8d +movl 28(%r10),%r8d + +# qhasm: in3 = *(uint32 *) (k + 8) +# asm 1: movl 8(in3=int64#7d +# asm 2: movl 8(in3=%eax +movl 8(%r10),%eax + +# qhasm: ((uint32 *)&x3)[0] = in4 +# asm 1: movl x3=stack128#3 +# asm 2: movl x3=32(%rsp) +movl %edx,32(%rsp) + +# qhasm: ((uint32 *)&x3)[1] = in9 +# asm 1: movl in0=int64#3 +# asm 2: mov $1634760805,>in0=%rdx +mov $1634760805,%rdx + +# qhasm: in5 = 857760878 +# asm 1: mov $857760878,>in5=int64#4 +# asm 2: mov $857760878,>in5=%rcx +mov $857760878,%rcx + +# qhasm: in10 = 2036477234 +# asm 1: mov $2036477234,>in10=int64#5 +# asm 2: mov $2036477234,>in10=%r8 +mov $2036477234,%r8 + +# qhasm: in15 = 1797285236 +# asm 1: mov $1797285236,>in15=int64#7 +# asm 2: mov $1797285236,>in15=%rax +mov $1797285236,%rax + +# qhasm: ((uint32 *)&x0)[0] = in0 +# asm 1: movl x0=stack128#4 +# asm 2: movl x0=48(%rsp) +movl %edx,48(%rsp) + +# qhasm: ((uint32 *)&x0)[1] = in5 +# asm 1: movl z0=int6464#1 +# asm 2: movdqa z0=%xmm0 +movdqa 48(%rsp),%xmm0 + +# qhasm: z5 = z0[1,1,1,1] +# asm 1: pshufd $0x55,z5=int6464#2 +# asm 2: pshufd $0x55,z5=%xmm1 +pshufd $0x55,%xmm0,%xmm1 + +# qhasm: z10 = z0[2,2,2,2] +# asm 1: pshufd $0xaa,z10=int6464#3 +# asm 2: pshufd $0xaa,z10=%xmm2 +pshufd $0xaa,%xmm0,%xmm2 + +# qhasm: z15 = z0[3,3,3,3] +# asm 1: pshufd $0xff,z15=int6464#4 +# asm 2: pshufd $0xff,z15=%xmm3 +pshufd $0xff,%xmm0,%xmm3 + +# qhasm: z0 = z0[0,0,0,0] +# asm 1: pshufd $0x00,z0=int6464#1 +# asm 2: pshufd $0x00,z0=%xmm0 +pshufd $0x00,%xmm0,%xmm0 + +# qhasm: orig5 = z5 +# asm 1: movdqa orig5=stack128#5 +# asm 2: movdqa orig5=64(%rsp) +movdqa %xmm1,64(%rsp) + +# qhasm: orig10 = z10 +# asm 1: movdqa orig10=stack128#6 +# asm 2: movdqa orig10=80(%rsp) +movdqa %xmm2,80(%rsp) + +# qhasm: orig15 = z15 +# asm 1: movdqa orig15=stack128#7 +# asm 2: movdqa orig15=96(%rsp) +movdqa %xmm3,96(%rsp) + +# qhasm: orig0 = z0 +# asm 1: movdqa orig0=stack128#8 +# asm 2: movdqa orig0=112(%rsp) +movdqa %xmm0,112(%rsp) + +# qhasm: z1 = x1 +# asm 1: movdqa z1=int6464#1 +# asm 2: movdqa z1=%xmm0 +movdqa 0(%rsp),%xmm0 + +# qhasm: z6 = z1[2,2,2,2] +# asm 1: pshufd $0xaa,z6=int6464#2 +# asm 2: pshufd $0xaa,z6=%xmm1 +pshufd $0xaa,%xmm0,%xmm1 + +# qhasm: z11 = z1[3,3,3,3] +# asm 1: pshufd $0xff,z11=int6464#3 +# asm 2: pshufd $0xff,z11=%xmm2 +pshufd $0xff,%xmm0,%xmm2 + +# qhasm: z12 = z1[0,0,0,0] +# asm 1: pshufd $0x00,z12=int6464#4 +# asm 2: pshufd $0x00,z12=%xmm3 +pshufd $0x00,%xmm0,%xmm3 + +# qhasm: z1 = z1[1,1,1,1] +# asm 1: pshufd $0x55,z1=int6464#1 +# asm 2: pshufd $0x55,z1=%xmm0 +pshufd $0x55,%xmm0,%xmm0 + +# qhasm: orig6 = z6 +# asm 1: movdqa orig6=stack128#9 +# asm 2: movdqa orig6=128(%rsp) +movdqa %xmm1,128(%rsp) + +# qhasm: orig11 = z11 +# asm 1: movdqa orig11=stack128#10 +# asm 2: movdqa orig11=144(%rsp) +movdqa %xmm2,144(%rsp) + +# qhasm: orig12 = z12 +# asm 1: movdqa orig12=stack128#11 +# asm 2: movdqa orig12=160(%rsp) +movdqa %xmm3,160(%rsp) + +# qhasm: orig1 = z1 +# asm 1: movdqa orig1=stack128#12 +# asm 2: movdqa orig1=176(%rsp) +movdqa %xmm0,176(%rsp) + +# qhasm: z2 = x2 +# asm 1: movdqa z2=int6464#1 +# asm 2: movdqa z2=%xmm0 +movdqa 16(%rsp),%xmm0 + +# qhasm: z7 = z2[3,3,3,3] +# asm 1: pshufd $0xff,z7=int6464#2 +# asm 2: pshufd $0xff,z7=%xmm1 +pshufd $0xff,%xmm0,%xmm1 + +# qhasm: z13 = z2[1,1,1,1] +# asm 1: pshufd $0x55,z13=int6464#3 +# asm 2: pshufd $0x55,z13=%xmm2 +pshufd $0x55,%xmm0,%xmm2 + +# qhasm: z2 = z2[2,2,2,2] +# asm 1: pshufd $0xaa,z2=int6464#1 +# asm 2: pshufd $0xaa,z2=%xmm0 +pshufd $0xaa,%xmm0,%xmm0 + +# qhasm: orig7 = z7 +# asm 1: movdqa orig7=stack128#13 +# asm 2: movdqa orig7=192(%rsp) +movdqa %xmm1,192(%rsp) + +# qhasm: orig13 = z13 +# asm 1: movdqa orig13=stack128#14 +# asm 2: movdqa orig13=208(%rsp) +movdqa %xmm2,208(%rsp) + +# qhasm: orig2 = z2 +# asm 1: movdqa orig2=stack128#15 +# asm 2: movdqa orig2=224(%rsp) +movdqa %xmm0,224(%rsp) + +# qhasm: z3 = x3 +# asm 1: movdqa z3=int6464#1 +# asm 2: movdqa z3=%xmm0 +movdqa 32(%rsp),%xmm0 + +# qhasm: z4 = z3[0,0,0,0] +# asm 1: pshufd $0x00,z4=int6464#2 +# asm 2: pshufd $0x00,z4=%xmm1 +pshufd $0x00,%xmm0,%xmm1 + +# qhasm: z14 = z3[2,2,2,2] +# asm 1: pshufd $0xaa,z14=int6464#3 +# asm 2: pshufd $0xaa,z14=%xmm2 +pshufd $0xaa,%xmm0,%xmm2 + +# qhasm: z3 = z3[3,3,3,3] +# asm 1: pshufd $0xff,z3=int6464#1 +# asm 2: pshufd $0xff,z3=%xmm0 +pshufd $0xff,%xmm0,%xmm0 + +# qhasm: orig4 = z4 +# asm 1: movdqa orig4=stack128#16 +# asm 2: movdqa orig4=240(%rsp) +movdqa %xmm1,240(%rsp) + +# qhasm: orig14 = z14 +# asm 1: movdqa orig14=stack128#17 +# asm 2: movdqa orig14=256(%rsp) +movdqa %xmm2,256(%rsp) + +# qhasm: orig3 = z3 +# asm 1: movdqa orig3=stack128#18 +# asm 2: movdqa orig3=272(%rsp) +movdqa %xmm0,272(%rsp) + +# qhasm: bytesatleast256: +._bytesatleast256: + +# qhasm: in8 = ((uint32 *)&x2)[0] +# asm 1: movl in8=int64#3d +# asm 2: movl in8=%edx +movl 16(%rsp),%edx + +# qhasm: in9 = ((uint32 *)&x3)[1] +# asm 1: movl 4+in9=int64#4d +# asm 2: movl 4+in9=%ecx +movl 4+32(%rsp),%ecx + +# qhasm: ((uint32 *) &orig8)[0] = in8 +# asm 1: movl orig8=stack128#19 +# asm 2: movl orig8=288(%rsp) +movl %edx,288(%rsp) + +# qhasm: ((uint32 *) &orig9)[0] = in9 +# asm 1: movl orig9=stack128#20 +# asm 2: movl orig9=304(%rsp) +movl %ecx,304(%rsp) + +# qhasm: in8 += 1 +# asm 1: add $1,in9=int64#4 +# asm 2: mov in9=%rcx +mov %rdx,%rcx + +# qhasm: (uint64) in9 >>= 32 +# asm 1: shr $32,in9=int64#4 +# asm 2: mov in9=%rcx +mov %rdx,%rcx + +# qhasm: (uint64) in9 >>= 32 +# asm 1: shr $32,in9=int64#4 +# asm 2: mov in9=%rcx +mov %rdx,%rcx + +# qhasm: (uint64) in9 >>= 32 +# asm 1: shr $32,in9=int64#4 +# asm 2: mov in9=%rcx +mov %rdx,%rcx + +# qhasm: (uint64) in9 >>= 32 +# asm 1: shr $32,x2=stack128#2 +# asm 2: movl x2=16(%rsp) +movl %edx,16(%rsp) + +# qhasm: ((uint32 *)&x3)[1] = in9 +# asm 1: movl bytes_backup=stack64#8 +# asm 2: movq bytes_backup=408(%rsp) +movq %r9,408(%rsp) + +# qhasm: i = 12 +# asm 1: mov $12,>i=int64#3 +# asm 2: mov $12,>i=%rdx +mov $12,%rdx + +# qhasm: z5 = orig5 +# asm 1: movdqa z5=int6464#1 +# asm 2: movdqa z5=%xmm0 +movdqa 64(%rsp),%xmm0 + +# qhasm: z10 = orig10 +# asm 1: movdqa z10=int6464#2 +# asm 2: movdqa z10=%xmm1 +movdqa 80(%rsp),%xmm1 + +# qhasm: z15 = orig15 +# asm 1: movdqa z15=int6464#3 +# asm 2: movdqa z15=%xmm2 +movdqa 96(%rsp),%xmm2 + +# qhasm: z14 = orig14 +# asm 1: movdqa z14=int6464#4 +# asm 2: movdqa z14=%xmm3 +movdqa 256(%rsp),%xmm3 + +# qhasm: z3 = orig3 +# asm 1: movdqa z3=int6464#5 +# asm 2: movdqa z3=%xmm4 +movdqa 272(%rsp),%xmm4 + +# qhasm: z6 = orig6 +# asm 1: movdqa z6=int6464#6 +# asm 2: movdqa z6=%xmm5 +movdqa 128(%rsp),%xmm5 + +# qhasm: z11 = orig11 +# asm 1: movdqa z11=int6464#7 +# asm 2: movdqa z11=%xmm6 +movdqa 144(%rsp),%xmm6 + +# qhasm: z1 = orig1 +# asm 1: movdqa z1=int6464#8 +# asm 2: movdqa z1=%xmm7 +movdqa 176(%rsp),%xmm7 + +# qhasm: z7 = orig7 +# asm 1: movdqa z7=int6464#9 +# asm 2: movdqa z7=%xmm8 +movdqa 192(%rsp),%xmm8 + +# qhasm: z13 = orig13 +# asm 1: movdqa z13=int6464#10 +# asm 2: movdqa z13=%xmm9 +movdqa 208(%rsp),%xmm9 + +# qhasm: z2 = orig2 +# asm 1: movdqa z2=int6464#11 +# asm 2: movdqa z2=%xmm10 +movdqa 224(%rsp),%xmm10 + +# qhasm: z9 = orig9 +# asm 1: movdqa z9=int6464#12 +# asm 2: movdqa z9=%xmm11 +movdqa 304(%rsp),%xmm11 + +# qhasm: z0 = orig0 +# asm 1: movdqa z0=int6464#13 +# asm 2: movdqa z0=%xmm12 +movdqa 112(%rsp),%xmm12 + +# qhasm: z12 = orig12 +# asm 1: movdqa z12=int6464#14 +# asm 2: movdqa z12=%xmm13 +movdqa 160(%rsp),%xmm13 + +# qhasm: z4 = orig4 +# asm 1: movdqa z4=int6464#15 +# asm 2: movdqa z4=%xmm14 +movdqa 240(%rsp),%xmm14 + +# qhasm: z8 = orig8 +# asm 1: movdqa z8=int6464#16 +# asm 2: movdqa z8=%xmm15 +movdqa 288(%rsp),%xmm15 + +# qhasm: mainloop1: +._mainloop1: + +# qhasm: z10_stack = z10 +# asm 1: movdqa z10_stack=stack128#21 +# asm 2: movdqa z10_stack=320(%rsp) +movdqa %xmm1,320(%rsp) + +# qhasm: z15_stack = z15 +# asm 1: movdqa z15_stack=stack128#22 +# asm 2: movdqa z15_stack=336(%rsp) +movdqa %xmm2,336(%rsp) + +# qhasm: y4 = z12 +# asm 1: movdqa y4=int6464#2 +# asm 2: movdqa y4=%xmm1 +movdqa %xmm13,%xmm1 + +# qhasm: uint32323232 y4 += z0 +# asm 1: paddd r4=int6464#3 +# asm 2: movdqa r4=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y4 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,y9=int6464#2 +# asm 2: movdqa y9=%xmm1 +movdqa %xmm7,%xmm1 + +# qhasm: uint32323232 y9 += z5 +# asm 1: paddd r9=int6464#3 +# asm 2: movdqa r9=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y9 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,y8=int6464#2 +# asm 2: movdqa y8=%xmm1 +movdqa %xmm12,%xmm1 + +# qhasm: uint32323232 y8 += z4 +# asm 1: paddd r8=int6464#3 +# asm 2: movdqa r8=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y8 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y13=int6464#2 +# asm 2: movdqa y13=%xmm1 +movdqa %xmm0,%xmm1 + +# qhasm: uint32323232 y13 += z9 +# asm 1: paddd r13=int6464#3 +# asm 2: movdqa r13=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y13 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y12=int6464#2 +# asm 2: movdqa y12=%xmm1 +movdqa %xmm14,%xmm1 + +# qhasm: uint32323232 y12 += z8 +# asm 1: paddd r12=int6464#3 +# asm 2: movdqa r12=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y12 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y1=int6464#2 +# asm 2: movdqa y1=%xmm1 +movdqa %xmm11,%xmm1 + +# qhasm: uint32323232 y1 += z13 +# asm 1: paddd r1=int6464#3 +# asm 2: movdqa r1=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y1 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y0=int6464#2 +# asm 2: movdqa y0=%xmm1 +movdqa %xmm15,%xmm1 + +# qhasm: uint32323232 y0 += z12 +# asm 1: paddd r0=int6464#3 +# asm 2: movdqa r0=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y0 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,z10=int6464#2 +# asm 2: movdqa z10=%xmm1 +movdqa 320(%rsp),%xmm1 + +# qhasm: z0_stack = z0 +# asm 1: movdqa z0_stack=stack128#21 +# asm 2: movdqa z0_stack=320(%rsp) +movdqa %xmm12,320(%rsp) + +# qhasm: y5 = z13 +# asm 1: movdqa y5=int6464#3 +# asm 2: movdqa y5=%xmm2 +movdqa %xmm9,%xmm2 + +# qhasm: uint32323232 y5 += z1 +# asm 1: paddd r5=int6464#13 +# asm 2: movdqa r5=%xmm12 +movdqa %xmm2,%xmm12 + +# qhasm: uint32323232 y5 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,y14=int6464#3 +# asm 2: movdqa y14=%xmm2 +movdqa %xmm5,%xmm2 + +# qhasm: uint32323232 y14 += z10 +# asm 1: paddd r14=int6464#13 +# asm 2: movdqa r14=%xmm12 +movdqa %xmm2,%xmm12 + +# qhasm: uint32323232 y14 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,z15=int6464#3 +# asm 2: movdqa z15=%xmm2 +movdqa 336(%rsp),%xmm2 + +# qhasm: z5_stack = z5 +# asm 1: movdqa z5_stack=stack128#22 +# asm 2: movdqa z5_stack=336(%rsp) +movdqa %xmm0,336(%rsp) + +# qhasm: y3 = z11 +# asm 1: movdqa y3=int6464#1 +# asm 2: movdqa y3=%xmm0 +movdqa %xmm6,%xmm0 + +# qhasm: uint32323232 y3 += z15 +# asm 1: paddd r3=int6464#13 +# asm 2: movdqa r3=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y3 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,y2=int6464#1 +# asm 2: movdqa y2=%xmm0 +movdqa %xmm1,%xmm0 + +# qhasm: uint32323232 y2 += z14 +# asm 1: paddd r2=int6464#13 +# asm 2: movdqa r2=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y2 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y7=int6464#1 +# asm 2: movdqa y7=%xmm0 +movdqa %xmm2,%xmm0 + +# qhasm: uint32323232 y7 += z3 +# asm 1: paddd r7=int6464#13 +# asm 2: movdqa r7=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y7 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y6=int6464#1 +# asm 2: movdqa y6=%xmm0 +movdqa %xmm3,%xmm0 + +# qhasm: uint32323232 y6 += z2 +# asm 1: paddd r6=int6464#13 +# asm 2: movdqa r6=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y6 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y11=int6464#1 +# asm 2: movdqa y11=%xmm0 +movdqa %xmm4,%xmm0 + +# qhasm: uint32323232 y11 += z7 +# asm 1: paddd r11=int6464#13 +# asm 2: movdqa r11=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y11 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y10=int6464#1 +# asm 2: movdqa y10=%xmm0 +movdqa %xmm10,%xmm0 + +# qhasm: uint32323232 y10 += z6 +# asm 1: paddd r10=int6464#13 +# asm 2: movdqa r10=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y10 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,z0=int6464#1 +# asm 2: movdqa z0=%xmm0 +movdqa 320(%rsp),%xmm0 + +# qhasm: z10_stack = z10 +# asm 1: movdqa z10_stack=stack128#21 +# asm 2: movdqa z10_stack=320(%rsp) +movdqa %xmm1,320(%rsp) + +# qhasm: y1 = z3 +# asm 1: movdqa y1=int6464#2 +# asm 2: movdqa y1=%xmm1 +movdqa %xmm4,%xmm1 + +# qhasm: uint32323232 y1 += z0 +# asm 1: paddd r1=int6464#13 +# asm 2: movdqa r1=%xmm12 +movdqa %xmm1,%xmm12 + +# qhasm: uint32323232 y1 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,y15=int6464#2 +# asm 2: movdqa y15=%xmm1 +movdqa %xmm8,%xmm1 + +# qhasm: uint32323232 y15 += z11 +# asm 1: paddd r15=int6464#13 +# asm 2: movdqa r15=%xmm12 +movdqa %xmm1,%xmm12 + +# qhasm: uint32323232 y15 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,z5=int6464#13 +# asm 2: movdqa z5=%xmm12 +movdqa 336(%rsp),%xmm12 + +# qhasm: z15_stack = z15 +# asm 1: movdqa z15_stack=stack128#22 +# asm 2: movdqa z15_stack=336(%rsp) +movdqa %xmm2,336(%rsp) + +# qhasm: y6 = z4 +# asm 1: movdqa y6=int6464#2 +# asm 2: movdqa y6=%xmm1 +movdqa %xmm14,%xmm1 + +# qhasm: uint32323232 y6 += z5 +# asm 1: paddd r6=int6464#3 +# asm 2: movdqa r6=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y6 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,y2=int6464#2 +# asm 2: movdqa y2=%xmm1 +movdqa %xmm0,%xmm1 + +# qhasm: uint32323232 y2 += z1 +# asm 1: paddd r2=int6464#3 +# asm 2: movdqa r2=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y2 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y7=int6464#2 +# asm 2: movdqa y7=%xmm1 +movdqa %xmm12,%xmm1 + +# qhasm: uint32323232 y7 += z6 +# asm 1: paddd r7=int6464#3 +# asm 2: movdqa r7=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y7 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y3=int6464#2 +# asm 2: movdqa y3=%xmm1 +movdqa %xmm7,%xmm1 + +# qhasm: uint32323232 y3 += z2 +# asm 1: paddd r3=int6464#3 +# asm 2: movdqa r3=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y3 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y4=int6464#2 +# asm 2: movdqa y4=%xmm1 +movdqa %xmm5,%xmm1 + +# qhasm: uint32323232 y4 += z7 +# asm 1: paddd r4=int6464#3 +# asm 2: movdqa r4=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y4 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y0=int6464#2 +# asm 2: movdqa y0=%xmm1 +movdqa %xmm10,%xmm1 + +# qhasm: uint32323232 y0 += z3 +# asm 1: paddd r0=int6464#3 +# asm 2: movdqa r0=%xmm2 +movdqa %xmm1,%xmm2 + +# qhasm: uint32323232 y0 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,z10=int6464#2 +# asm 2: movdqa z10=%xmm1 +movdqa 320(%rsp),%xmm1 + +# qhasm: z0_stack = z0 +# asm 1: movdqa z0_stack=stack128#21 +# asm 2: movdqa z0_stack=320(%rsp) +movdqa %xmm0,320(%rsp) + +# qhasm: y5 = z7 +# asm 1: movdqa y5=int6464#1 +# asm 2: movdqa y5=%xmm0 +movdqa %xmm8,%xmm0 + +# qhasm: uint32323232 y5 += z4 +# asm 1: paddd r5=int6464#3 +# asm 2: movdqa r5=%xmm2 +movdqa %xmm0,%xmm2 + +# qhasm: uint32323232 y5 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,y11=int6464#1 +# asm 2: movdqa y11=%xmm0 +movdqa %xmm11,%xmm0 + +# qhasm: uint32323232 y11 += z10 +# asm 1: paddd r11=int6464#3 +# asm 2: movdqa r11=%xmm2 +movdqa %xmm0,%xmm2 + +# qhasm: uint32323232 y11 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,z15=int6464#3 +# asm 2: movdqa z15=%xmm2 +movdqa 336(%rsp),%xmm2 + +# qhasm: z5_stack = z5 +# asm 1: movdqa z5_stack=stack128#22 +# asm 2: movdqa z5_stack=336(%rsp) +movdqa %xmm12,336(%rsp) + +# qhasm: y12 = z14 +# asm 1: movdqa y12=int6464#1 +# asm 2: movdqa y12=%xmm0 +movdqa %xmm3,%xmm0 + +# qhasm: uint32323232 y12 += z15 +# asm 1: paddd r12=int6464#13 +# asm 2: movdqa r12=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y12 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,y8=int6464#1 +# asm 2: movdqa y8=%xmm0 +movdqa %xmm1,%xmm0 + +# qhasm: uint32323232 y8 += z11 +# asm 1: paddd r8=int6464#13 +# asm 2: movdqa r8=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y8 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y13=int6464#1 +# asm 2: movdqa y13=%xmm0 +movdqa %xmm2,%xmm0 + +# qhasm: uint32323232 y13 += z12 +# asm 1: paddd r13=int6464#13 +# asm 2: movdqa r13=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y13 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,y9=int6464#1 +# asm 2: movdqa y9=%xmm0 +movdqa %xmm6,%xmm0 + +# qhasm: uint32323232 y9 += z8 +# asm 1: paddd r9=int6464#13 +# asm 2: movdqa r9=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y9 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y14=int6464#1 +# asm 2: movdqa y14=%xmm0 +movdqa %xmm13,%xmm0 + +# qhasm: uint32323232 y14 += z13 +# asm 1: paddd r14=int6464#13 +# asm 2: movdqa r14=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y14 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,y10=int6464#1 +# asm 2: movdqa y10=%xmm0 +movdqa %xmm15,%xmm0 + +# qhasm: uint32323232 y10 += z9 +# asm 1: paddd r10=int6464#13 +# asm 2: movdqa r10=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y10 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,y15=int6464#1 +# asm 2: movdqa y15=%xmm0 +movdqa %xmm9,%xmm0 + +# qhasm: uint32323232 y15 += z14 +# asm 1: paddd r15=int6464#13 +# asm 2: movdqa r15=%xmm12 +movdqa %xmm0,%xmm12 + +# qhasm: uint32323232 y15 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,z0=int6464#13 +# asm 2: movdqa z0=%xmm12 +movdqa 320(%rsp),%xmm12 + +# qhasm: z5 = z5_stack +# asm 1: movdqa z5=int6464#1 +# asm 2: movdqa z5=%xmm0 +movdqa 336(%rsp),%xmm0 + +# qhasm: unsigned>? i -= 2 +# asm 1: sub $2, +ja ._mainloop1 + +# qhasm: uint32323232 z0 += orig0 +# asm 1: paddd in0=int64#3 +# asm 2: movd in0=%rdx +movd %xmm12,%rdx + +# qhasm: in1 = z1 +# asm 1: movd in1=int64#4 +# asm 2: movd in1=%rcx +movd %xmm7,%rcx + +# qhasm: in2 = z2 +# asm 1: movd in2=int64#5 +# asm 2: movd in2=%r8 +movd %xmm10,%r8 + +# qhasm: in3 = z3 +# asm 1: movd in3=int64#6 +# asm 2: movd in3=%r9 +movd %xmm4,%r9 + +# qhasm: z0 <<<= 96 +# asm 1: pshufd $0x39,in0=int64#3 +# asm 2: movd in0=%rdx +movd %xmm12,%rdx + +# qhasm: in1 = z1 +# asm 1: movd in1=int64#4 +# asm 2: movd in1=%rcx +movd %xmm7,%rcx + +# qhasm: in2 = z2 +# asm 1: movd in2=int64#5 +# asm 2: movd in2=%r8 +movd %xmm10,%r8 + +# qhasm: in3 = z3 +# asm 1: movd in3=int64#6 +# asm 2: movd in3=%r9 +movd %xmm4,%r9 + +# qhasm: z0 <<<= 96 +# asm 1: pshufd $0x39,in0=int64#3 +# asm 2: movd in0=%rdx +movd %xmm12,%rdx + +# qhasm: in1 = z1 +# asm 1: movd in1=int64#4 +# asm 2: movd in1=%rcx +movd %xmm7,%rcx + +# qhasm: in2 = z2 +# asm 1: movd in2=int64#5 +# asm 2: movd in2=%r8 +movd %xmm10,%r8 + +# qhasm: in3 = z3 +# asm 1: movd in3=int64#6 +# asm 2: movd in3=%r9 +movd %xmm4,%r9 + +# qhasm: z0 <<<= 96 +# asm 1: pshufd $0x39,in0=int64#3 +# asm 2: movd in0=%rdx +movd %xmm12,%rdx + +# qhasm: in1 = z1 +# asm 1: movd in1=int64#4 +# asm 2: movd in1=%rcx +movd %xmm7,%rcx + +# qhasm: in2 = z2 +# asm 1: movd in2=int64#5 +# asm 2: movd in2=%r8 +movd %xmm10,%r8 + +# qhasm: in3 = z3 +# asm 1: movd in3=int64#6 +# asm 2: movd in3=%r9 +movd %xmm4,%r9 + +# qhasm: (uint32) in0 ^= *(uint32 *) (m + 192) +# asm 1: xorl 192(in4=int64#3 +# asm 2: movd in4=%rdx +movd %xmm14,%rdx + +# qhasm: in5 = z5 +# asm 1: movd in5=int64#4 +# asm 2: movd in5=%rcx +movd %xmm0,%rcx + +# qhasm: in6 = z6 +# asm 1: movd in6=int64#5 +# asm 2: movd in6=%r8 +movd %xmm5,%r8 + +# qhasm: in7 = z7 +# asm 1: movd in7=int64#6 +# asm 2: movd in7=%r9 +movd %xmm8,%r9 + +# qhasm: z4 <<<= 96 +# asm 1: pshufd $0x39,in4=int64#3 +# asm 2: movd in4=%rdx +movd %xmm14,%rdx + +# qhasm: in5 = z5 +# asm 1: movd in5=int64#4 +# asm 2: movd in5=%rcx +movd %xmm0,%rcx + +# qhasm: in6 = z6 +# asm 1: movd in6=int64#5 +# asm 2: movd in6=%r8 +movd %xmm5,%r8 + +# qhasm: in7 = z7 +# asm 1: movd in7=int64#6 +# asm 2: movd in7=%r9 +movd %xmm8,%r9 + +# qhasm: z4 <<<= 96 +# asm 1: pshufd $0x39,in4=int64#3 +# asm 2: movd in4=%rdx +movd %xmm14,%rdx + +# qhasm: in5 = z5 +# asm 1: movd in5=int64#4 +# asm 2: movd in5=%rcx +movd %xmm0,%rcx + +# qhasm: in6 = z6 +# asm 1: movd in6=int64#5 +# asm 2: movd in6=%r8 +movd %xmm5,%r8 + +# qhasm: in7 = z7 +# asm 1: movd in7=int64#6 +# asm 2: movd in7=%r9 +movd %xmm8,%r9 + +# qhasm: z4 <<<= 96 +# asm 1: pshufd $0x39,in4=int64#3 +# asm 2: movd in4=%rdx +movd %xmm14,%rdx + +# qhasm: in5 = z5 +# asm 1: movd in5=int64#4 +# asm 2: movd in5=%rcx +movd %xmm0,%rcx + +# qhasm: in6 = z6 +# asm 1: movd in6=int64#5 +# asm 2: movd in6=%r8 +movd %xmm5,%r8 + +# qhasm: in7 = z7 +# asm 1: movd in7=int64#6 +# asm 2: movd in7=%r9 +movd %xmm8,%r9 + +# qhasm: (uint32) in4 ^= *(uint32 *) (m + 208) +# asm 1: xorl 208(in8=int64#3 +# asm 2: movd in8=%rdx +movd %xmm15,%rdx + +# qhasm: in9 = z9 +# asm 1: movd in9=int64#4 +# asm 2: movd in9=%rcx +movd %xmm11,%rcx + +# qhasm: in10 = z10 +# asm 1: movd in10=int64#5 +# asm 2: movd in10=%r8 +movd %xmm1,%r8 + +# qhasm: in11 = z11 +# asm 1: movd in11=int64#6 +# asm 2: movd in11=%r9 +movd %xmm6,%r9 + +# qhasm: z8 <<<= 96 +# asm 1: pshufd $0x39,in8=int64#3 +# asm 2: movd in8=%rdx +movd %xmm15,%rdx + +# qhasm: in9 = z9 +# asm 1: movd in9=int64#4 +# asm 2: movd in9=%rcx +movd %xmm11,%rcx + +# qhasm: in10 = z10 +# asm 1: movd in10=int64#5 +# asm 2: movd in10=%r8 +movd %xmm1,%r8 + +# qhasm: in11 = z11 +# asm 1: movd in11=int64#6 +# asm 2: movd in11=%r9 +movd %xmm6,%r9 + +# qhasm: z8 <<<= 96 +# asm 1: pshufd $0x39,in8=int64#3 +# asm 2: movd in8=%rdx +movd %xmm15,%rdx + +# qhasm: in9 = z9 +# asm 1: movd in9=int64#4 +# asm 2: movd in9=%rcx +movd %xmm11,%rcx + +# qhasm: in10 = z10 +# asm 1: movd in10=int64#5 +# asm 2: movd in10=%r8 +movd %xmm1,%r8 + +# qhasm: in11 = z11 +# asm 1: movd in11=int64#6 +# asm 2: movd in11=%r9 +movd %xmm6,%r9 + +# qhasm: z8 <<<= 96 +# asm 1: pshufd $0x39,in8=int64#3 +# asm 2: movd in8=%rdx +movd %xmm15,%rdx + +# qhasm: in9 = z9 +# asm 1: movd in9=int64#4 +# asm 2: movd in9=%rcx +movd %xmm11,%rcx + +# qhasm: in10 = z10 +# asm 1: movd in10=int64#5 +# asm 2: movd in10=%r8 +movd %xmm1,%r8 + +# qhasm: in11 = z11 +# asm 1: movd in11=int64#6 +# asm 2: movd in11=%r9 +movd %xmm6,%r9 + +# qhasm: (uint32) in8 ^= *(uint32 *) (m + 224) +# asm 1: xorl 224(in12=int64#3 +# asm 2: movd in12=%rdx +movd %xmm13,%rdx + +# qhasm: in13 = z13 +# asm 1: movd in13=int64#4 +# asm 2: movd in13=%rcx +movd %xmm9,%rcx + +# qhasm: in14 = z14 +# asm 1: movd in14=int64#5 +# asm 2: movd in14=%r8 +movd %xmm3,%r8 + +# qhasm: in15 = z15 +# asm 1: movd in15=int64#6 +# asm 2: movd in15=%r9 +movd %xmm2,%r9 + +# qhasm: z12 <<<= 96 +# asm 1: pshufd $0x39,in12=int64#3 +# asm 2: movd in12=%rdx +movd %xmm13,%rdx + +# qhasm: in13 = z13 +# asm 1: movd in13=int64#4 +# asm 2: movd in13=%rcx +movd %xmm9,%rcx + +# qhasm: in14 = z14 +# asm 1: movd in14=int64#5 +# asm 2: movd in14=%r8 +movd %xmm3,%r8 + +# qhasm: in15 = z15 +# asm 1: movd in15=int64#6 +# asm 2: movd in15=%r9 +movd %xmm2,%r9 + +# qhasm: z12 <<<= 96 +# asm 1: pshufd $0x39,in12=int64#3 +# asm 2: movd in12=%rdx +movd %xmm13,%rdx + +# qhasm: in13 = z13 +# asm 1: movd in13=int64#4 +# asm 2: movd in13=%rcx +movd %xmm9,%rcx + +# qhasm: in14 = z14 +# asm 1: movd in14=int64#5 +# asm 2: movd in14=%r8 +movd %xmm3,%r8 + +# qhasm: in15 = z15 +# asm 1: movd in15=int64#6 +# asm 2: movd in15=%r9 +movd %xmm2,%r9 + +# qhasm: z12 <<<= 96 +# asm 1: pshufd $0x39,in12=int64#3 +# asm 2: movd in12=%rdx +movd %xmm13,%rdx + +# qhasm: in13 = z13 +# asm 1: movd in13=int64#4 +# asm 2: movd in13=%rcx +movd %xmm9,%rcx + +# qhasm: in14 = z14 +# asm 1: movd in14=int64#5 +# asm 2: movd in14=%r8 +movd %xmm3,%r8 + +# qhasm: in15 = z15 +# asm 1: movd in15=int64#6 +# asm 2: movd in15=%r9 +movd %xmm2,%r9 + +# qhasm: (uint32) in12 ^= *(uint32 *) (m + 240) +# asm 1: xorl 240(bytes=int64#6 +# asm 2: movq bytes=%r9 +movq 408(%rsp),%r9 + +# qhasm: bytes -= 256 +# asm 1: sub $256,? bytes - 0 +# asm 1: cmp $0, +jbe ._done +# comment:fp stack unchanged by fallthrough + +# qhasm: bytesbetween1and255: +._bytesbetween1and255: + +# qhasm: unsignedctarget=int64#3 +# asm 2: mov ctarget=%rdx +mov %rdi,%rdx + +# qhasm: out = &tmp +# asm 1: leaq out=int64#1 +# asm 2: leaq out=%rdi +leaq 416(%rsp),%rdi + +# qhasm: i = bytes +# asm 1: mov i=int64#4 +# asm 2: mov i=%rcx +mov %r9,%rcx + +# qhasm: while (i) { *out++ = *m++; --i } +rep movsb + +# qhasm: out = &tmp +# asm 1: leaq out=int64#1 +# asm 2: leaq out=%rdi +leaq 416(%rsp),%rdi + +# qhasm: m = &tmp +# asm 1: leaq m=int64#2 +# asm 2: leaq m=%rsi +leaq 416(%rsp),%rsi +# comment:fp stack unchanged by fallthrough + +# qhasm: nocopy: +._nocopy: + +# qhasm: bytes_backup = bytes +# asm 1: movq bytes_backup=stack64#8 +# asm 2: movq bytes_backup=408(%rsp) +movq %r9,408(%rsp) + +# qhasm: diag0 = x0 +# asm 1: movdqa diag0=int6464#1 +# asm 2: movdqa diag0=%xmm0 +movdqa 48(%rsp),%xmm0 + +# qhasm: diag1 = x1 +# asm 1: movdqa diag1=int6464#2 +# asm 2: movdqa diag1=%xmm1 +movdqa 0(%rsp),%xmm1 + +# qhasm: diag2 = x2 +# asm 1: movdqa diag2=int6464#3 +# asm 2: movdqa diag2=%xmm2 +movdqa 16(%rsp),%xmm2 + +# qhasm: diag3 = x3 +# asm 1: movdqa diag3=int6464#4 +# asm 2: movdqa diag3=%xmm3 +movdqa 32(%rsp),%xmm3 + +# qhasm: a0 = diag1 +# asm 1: movdqa a0=int6464#5 +# asm 2: movdqa a0=%xmm4 +movdqa %xmm1,%xmm4 + +# qhasm: i = 12 +# asm 1: mov $12,>i=int64#4 +# asm 2: mov $12,>i=%rcx +mov $12,%rcx + +# qhasm: mainloop2: +._mainloop2: + +# qhasm: uint32323232 a0 += diag0 +# asm 1: paddd a1=int6464#6 +# asm 2: movdqa a1=%xmm5 +movdqa %xmm0,%xmm5 + +# qhasm: b0 = a0 +# asm 1: movdqa b0=int6464#7 +# asm 2: movdqa b0=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a0 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,a2=int6464#5 +# asm 2: movdqa a2=%xmm4 +movdqa %xmm3,%xmm4 + +# qhasm: b1 = a1 +# asm 1: movdqa b1=int6464#7 +# asm 2: movdqa b1=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a1 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,a3=int6464#6 +# asm 2: movdqa a3=%xmm5 +movdqa %xmm2,%xmm5 + +# qhasm: b2 = a2 +# asm 1: movdqa b2=int6464#7 +# asm 2: movdqa b2=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a2 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,a4=int6464#5 +# asm 2: movdqa a4=%xmm4 +movdqa %xmm3,%xmm4 + +# qhasm: b3 = a3 +# asm 1: movdqa b3=int6464#7 +# asm 2: movdqa b3=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a3 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,a5=int6464#6 +# asm 2: movdqa a5=%xmm5 +movdqa %xmm0,%xmm5 + +# qhasm: b4 = a4 +# asm 1: movdqa b4=int6464#7 +# asm 2: movdqa b4=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a4 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,a6=int6464#5 +# asm 2: movdqa a6=%xmm4 +movdqa %xmm1,%xmm4 + +# qhasm: b5 = a5 +# asm 1: movdqa b5=int6464#7 +# asm 2: movdqa b5=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a5 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,a7=int6464#6 +# asm 2: movdqa a7=%xmm5 +movdqa %xmm2,%xmm5 + +# qhasm: b6 = a6 +# asm 1: movdqa b6=int6464#7 +# asm 2: movdqa b6=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a6 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,a0=int6464#5 +# asm 2: movdqa a0=%xmm4 +movdqa %xmm1,%xmm4 + +# qhasm: b7 = a7 +# asm 1: movdqa b7=int6464#7 +# asm 2: movdqa b7=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a7 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,a1=int6464#6 +# asm 2: movdqa a1=%xmm5 +movdqa %xmm0,%xmm5 + +# qhasm: b0 = a0 +# asm 1: movdqa b0=int6464#7 +# asm 2: movdqa b0=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a0 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,a2=int6464#5 +# asm 2: movdqa a2=%xmm4 +movdqa %xmm3,%xmm4 + +# qhasm: b1 = a1 +# asm 1: movdqa b1=int6464#7 +# asm 2: movdqa b1=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a1 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,a3=int6464#6 +# asm 2: movdqa a3=%xmm5 +movdqa %xmm2,%xmm5 + +# qhasm: b2 = a2 +# asm 1: movdqa b2=int6464#7 +# asm 2: movdqa b2=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a2 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,a4=int6464#5 +# asm 2: movdqa a4=%xmm4 +movdqa %xmm3,%xmm4 + +# qhasm: b3 = a3 +# asm 1: movdqa b3=int6464#7 +# asm 2: movdqa b3=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a3 <<= 18 +# asm 1: pslld $18,>= 14 +# asm 1: psrld $14,a5=int6464#6 +# asm 2: movdqa a5=%xmm5 +movdqa %xmm0,%xmm5 + +# qhasm: b4 = a4 +# asm 1: movdqa b4=int6464#7 +# asm 2: movdqa b4=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a4 <<= 7 +# asm 1: pslld $7,>= 25 +# asm 1: psrld $25,a6=int6464#5 +# asm 2: movdqa a6=%xmm4 +movdqa %xmm1,%xmm4 + +# qhasm: b5 = a5 +# asm 1: movdqa b5=int6464#7 +# asm 2: movdqa b5=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a5 <<= 9 +# asm 1: pslld $9,>= 23 +# asm 1: psrld $23,a7=int6464#6 +# asm 2: movdqa a7=%xmm5 +movdqa %xmm2,%xmm5 + +# qhasm: b6 = a6 +# asm 1: movdqa b6=int6464#7 +# asm 2: movdqa b6=%xmm6 +movdqa %xmm4,%xmm6 + +# qhasm: uint32323232 a6 <<= 13 +# asm 1: pslld $13,>= 19 +# asm 1: psrld $19,? i -= 4 +# asm 1: sub $4,a0=int6464#5 +# asm 2: movdqa a0=%xmm4 +movdqa %xmm1,%xmm4 + +# qhasm: b7 = a7 +# asm 1: movdqa b7=int6464#7 +# asm 2: movdqa b7=%xmm6 +movdqa %xmm5,%xmm6 + +# qhasm: uint32323232 a7 <<= 18 +# asm 1: pslld $18,b0=int6464#8,>b0=int6464#8 +# asm 2: pxor >b0=%xmm7,>b0=%xmm7 +pxor %xmm7,%xmm7 + +# qhasm: uint32323232 b7 >>= 14 +# asm 1: psrld $14, +ja ._mainloop2 + +# qhasm: uint32323232 diag0 += x0 +# asm 1: paddd in0=int64#4 +# asm 2: movd in0=%rcx +movd %xmm0,%rcx + +# qhasm: in12 = diag1 +# asm 1: movd in12=int64#5 +# asm 2: movd in12=%r8 +movd %xmm1,%r8 + +# qhasm: in8 = diag2 +# asm 1: movd in8=int64#6 +# asm 2: movd in8=%r9 +movd %xmm2,%r9 + +# qhasm: in4 = diag3 +# asm 1: movd in4=int64#7 +# asm 2: movd in4=%rax +movd %xmm3,%rax + +# qhasm: diag0 <<<= 96 +# asm 1: pshufd $0x39,in5=int64#4 +# asm 2: movd in5=%rcx +movd %xmm0,%rcx + +# qhasm: in1 = diag1 +# asm 1: movd in1=int64#5 +# asm 2: movd in1=%r8 +movd %xmm1,%r8 + +# qhasm: in13 = diag2 +# asm 1: movd in13=int64#6 +# asm 2: movd in13=%r9 +movd %xmm2,%r9 + +# qhasm: in9 = diag3 +# asm 1: movd in9=int64#7 +# asm 2: movd in9=%rax +movd %xmm3,%rax + +# qhasm: diag0 <<<= 96 +# asm 1: pshufd $0x39,in10=int64#4 +# asm 2: movd in10=%rcx +movd %xmm0,%rcx + +# qhasm: in6 = diag1 +# asm 1: movd in6=int64#5 +# asm 2: movd in6=%r8 +movd %xmm1,%r8 + +# qhasm: in2 = diag2 +# asm 1: movd in2=int64#6 +# asm 2: movd in2=%r9 +movd %xmm2,%r9 + +# qhasm: in14 = diag3 +# asm 1: movd in14=int64#7 +# asm 2: movd in14=%rax +movd %xmm3,%rax + +# qhasm: diag0 <<<= 96 +# asm 1: pshufd $0x39,in15=int64#4 +# asm 2: movd in15=%rcx +movd %xmm0,%rcx + +# qhasm: in11 = diag1 +# asm 1: movd in11=int64#5 +# asm 2: movd in11=%r8 +movd %xmm1,%r8 + +# qhasm: in7 = diag2 +# asm 1: movd in7=int64#6 +# asm 2: movd in7=%r9 +movd %xmm2,%r9 + +# qhasm: in3 = diag3 +# asm 1: movd in3=int64#7 +# asm 2: movd in3=%rax +movd %xmm3,%rax + +# qhasm: (uint32) in15 ^= *(uint32 *) (m + 60) +# asm 1: xorl 60(bytes=int64#6 +# asm 2: movq bytes=%r9 +movq 408(%rsp),%r9 + +# qhasm: in8 = ((uint32 *)&x2)[0] +# asm 1: movl in8=int64#4d +# asm 2: movl in8=%ecx +movl 16(%rsp),%ecx + +# qhasm: in9 = ((uint32 *)&x3)[1] +# asm 1: movl 4+in9=int64#5d +# asm 2: movl 4+in9=%r8d +movl 4+32(%rsp),%r8d + +# qhasm: in8 += 1 +# asm 1: add $1,in9=int64#5 +# asm 2: mov in9=%r8 +mov %rcx,%r8 + +# qhasm: (uint64) in9 >>= 32 +# asm 1: shr $32,x2=stack128#2 +# asm 2: movl x2=16(%rsp) +movl %ecx,16(%rsp) + +# qhasm: ((uint32 *)&x3)[1] = in9 +# asm 1: movl ? unsigned +ja ._bytesatleast65 +# comment:fp stack unchanged by jump + +# qhasm: goto bytesatleast64 if !unsigned< +jae ._bytesatleast64 + +# qhasm: m = out +# asm 1: mov m=int64#2 +# asm 2: mov m=%rsi +mov %rdi,%rsi + +# qhasm: out = ctarget +# asm 1: mov out=int64#1 +# asm 2: mov out=%rdi +mov %rdx,%rdi + +# qhasm: i = bytes +# asm 1: mov i=int64#4 +# asm 2: mov i=%rcx +mov %r9,%rcx + +# qhasm: while (i) { *out++ = *m++; --i } +rep movsb +# comment:fp stack unchanged by fallthrough + +# qhasm: bytesatleast64: +._bytesatleast64: +# comment:fp stack unchanged by fallthrough + +# qhasm: done: +._done: + +# qhasm: r11_caller = r11_stack +# asm 1: movq r11_caller=int64#9 +# asm 2: movq r11_caller=%r11 +movq 352(%rsp),%r11 + +# qhasm: r12_caller = r12_stack +# asm 1: movq r12_caller=int64#10 +# asm 2: movq r12_caller=%r12 +movq 360(%rsp),%r12 + +# qhasm: r13_caller = r13_stack +# asm 1: movq r13_caller=int64#11 +# asm 2: movq r13_caller=%r13 +movq 368(%rsp),%r13 + +# qhasm: r14_caller = r14_stack +# asm 1: movq r14_caller=int64#12 +# asm 2: movq r14_caller=%r14 +movq 376(%rsp),%r14 + +# qhasm: r15_caller = r15_stack +# asm 1: movq r15_caller=int64#13 +# asm 2: movq r15_caller=%r15 +movq 384(%rsp),%r15 + +# qhasm: rbx_caller = rbx_stack +# asm 1: movq rbx_caller=int64#14 +# asm 2: movq rbx_caller=%rbx +movq 392(%rsp),%rbx + +# qhasm: rbp_caller = rbp_stack +# asm 1: movq rbp_caller=int64#15 +# asm 2: movq rbp_caller=%rbp +movq 400(%rsp),%rbp + +# qhasm: leave +add %r11,%rsp +xor %rax,%rax +xor %rdx,%rdx +ret + +# qhasm: bytesatleast65: +._bytesatleast65: + +# qhasm: bytes -= 64 +# asm 1: sub $64, @@ -1064,7 +1068,7 @@ const char *Packet::errorString(ErrorCode e) void Packet::armor(const void *key,bool encryptPayload,unsigned int counter) { - uint8_t mangledKey[32],macKey[32],mac[16]; + uint8_t mangledKey[32]; uint8_t *const data = reinterpret_cast(unsafeData()); // Mask least significant 3 bits of packet ID with counter to embed packet send counter for QoS use @@ -1074,23 +1078,47 @@ void Packet::armor(const void *key,bool encryptPayload,unsigned int counter) setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE); _salsa20MangleKey((const unsigned char *)key,mangledKey); + +#ifdef ZT_USE_X64_ASM_SALSA2012 + const unsigned int payloadLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0; + uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8]; + zt_salsa2012_amd64_xmm6(reinterpret_cast(keyStream),payloadLen + 64,reinterpret_cast(data + ZT_PACKET_IDX_IV),reinterpret_cast(mangledKey)); + + uint64_t *ksptr = keyStream + 8; // encryption starts after first Salsa20 block + uint8_t *dptr = data + ZT_PACKET_IDX_VERB; + unsigned int ksrem = payloadLen; + while (ksrem >= 8) { + ksrem -= 8; + *(reinterpret_cast(dptr)) ^= *(ksptr++); + dptr += 8; + } + for(unsigned int i=0;i(ksptr)[i]; + } + + uint64_t mac[2]; + Poly1305::compute(mac,data + ZT_PACKET_IDX_VERB,size() - ZT_PACKET_IDX_VERB,keyStream); + memcpy(data + ZT_PACKET_IDX_MAC,mac,8); +#else Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV); - // MAC key is always the first 32 bytes of the Salsa20 key stream - // This is the same construction DJB's NaCl library uses + uint64_t macKey[4]; s20.crypt12(ZERO_KEY,macKey,sizeof(macKey)); uint8_t *const payload = data + ZT_PACKET_IDX_VERB; const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; if (encryptPayload) s20.crypt12(payload,payload,payloadLen); + + uint64_t mac[2]; Poly1305::compute(mac,payload,payloadLen,macKey); memcpy(data + ZT_PACKET_IDX_MAC,mac,8); +#endif } bool Packet::dearmor(const void *key) { - uint8_t mangledKey[32],macKey[32],mac[16]; + uint8_t mangledKey[32]; uint8_t *const data = reinterpret_cast(unsafeData()); const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; unsigned char *const payload = data + ZT_PACKET_IDX_VERB; @@ -1098,9 +1126,37 @@ bool Packet::dearmor(const void *key) if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) { _salsa20MangleKey((const unsigned char *)key,mangledKey); + +#ifdef ZT_USE_X64_ASM_SALSA2012 + uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8]; + zt_salsa2012_amd64_xmm6(reinterpret_cast(keyStream),((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) ? (payloadLen + 64) : 64),reinterpret_cast(data + ZT_PACKET_IDX_IV),reinterpret_cast(mangledKey)); + + uint64_t mac[2]; + Poly1305::compute(mac,payload,payloadLen,keyStream); + if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) + return false; // MAC failed, packet is corrupt, modified, or is not from the sender + + if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) { + uint64_t *ksptr = keyStream + 8; // encryption starts after first Salsa20 block + uint8_t *dptr = data + ZT_PACKET_IDX_VERB; + unsigned int ksrem = payloadLen; + while (ksrem >= 8) { + ksrem -= 8; + *(reinterpret_cast(dptr)) ^= *(ksptr++); + dptr += 8; + } + for(unsigned int i=0;i(ksptr)[i]; + } + } + + return true; +#else Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV); + uint64_t macKey[4]; s20.crypt12(ZERO_KEY,macKey,sizeof(macKey)); + uint64_t mac[2]; Poly1305::compute(mac,payload,payloadLen,macKey); if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) return false; // MAC failed, packet is corrupt, modified, or is not from the sender @@ -1109,6 +1165,7 @@ bool Packet::dearmor(const void *key) s20.crypt12(payload,payload,payloadLen); return true; +#endif } else { return false; // unrecognized cipher suite } diff --git a/selftest.cpp b/selftest.cpp index fe0aa933..b7a1cc4d 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -54,6 +54,10 @@ #include "controller/JSONDB.hpp" +#ifdef ZT_USE_X64_ASM_SALSA2012 +#include "ext/x64-salsa2012-asm/salsa2012.h" +#endif + #ifdef __WINDOWS__ #include #endif @@ -204,6 +208,24 @@ static int testCrypto() ::free((void *)bb); } +#ifdef ZT_USE_X64_ASM_SALSA2012 + std::cout << "[crypto] Benchmarking Salsa20/12 fast x64 ASM... "; std::cout.flush(); + { + unsigned char *bb = (unsigned char *)::malloc(1234567); + for(unsigned int i=0;i<1234567;++i) + bb[i] = (unsigned char)i; + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for(unsigned int i=0;i<200;++i) { + zt_salsa2012_amd64_xmm6_xor(bb,bb,1234567,s20TV0Iv,s20TV0Key); + bytes += 1234567.0; + } + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1000.0)) << " MiB/second" << std::endl; + ::free((void *)bb); + } +#endif + std::cout << "[crypto] Benchmarking Salsa20/20... "; std::cout.flush(); { unsigned char *bb = (unsigned char *)::malloc(1234567); -- cgit v1.2.3 From 72bd3064a20aec9b1fcbc86bb590aca87f4eca71 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 18 Apr 2017 11:00:29 -0700 Subject: Windows build fixes, self test cleanup. --- node/Dictionary.hpp | 40 ---------- selftest.cpp | 99 ++++++------------------- windows/ZeroTierOne/ZeroTierOne.vcxproj | 8 +- windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 21 +++++- 4 files changed, 43 insertions(+), 125 deletions(-) (limited to 'selftest.cpp') diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index fa9e2883..440dae7f 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -416,46 +416,6 @@ public: return (this->get(key,tmp,2) >= 0); } - /** - * Erase a key from this dictionary - * - * Use this before add() to ensure that a key is replaced if it might - * already be present. - * - * @param key Key to erase - * @return True if key was found and erased - */ - inline bool erase(const char *key) - { - char d2[C]; - char *saveptr = (char *)0; - unsigned int d2ptr = 0; - bool found = false; - for(char *f=Utils::stok(_d,"\r\n",&saveptr);(f);f=Utils::stok((char *)0,"\r\n",&saveptr)) { - if (*f) { - const char *p = f; - const char *k = key; - while ((*k)&&(*p)) { - if (*k != *p) - break; - ++k; - ++p; - } - if (*k) { - p = f; - while (*p) - d2[d2ptr++] = *(p++); - d2[d2ptr++] = '\n'; - } else { - found = true; - } - } - } - d2[d2ptr++] = (char)0; - memcpy(_d,d2,d2ptr); - return found; - } - /** * @return Value of C template parameter */ diff --git a/selftest.cpp b/selftest.cpp index b7a1cc4d..55a469e1 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -196,7 +196,7 @@ static int testCrypto() for(unsigned int i=0;i<1234567;++i) bb[i] = (unsigned char)i; Salsa20 s20(s20TV0Key,s20TV0Iv); - double bytes = 0.0; + long double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { s20.crypt12(bb,bb,1234567); @@ -204,7 +204,7 @@ static int testCrypto() } uint64_t end = OSUtils::now(); SHA512::hash(buf1,bb,1234567); - std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1000.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; ::free((void *)bb); } @@ -221,7 +221,7 @@ static int testCrypto() bytes += 1234567.0; } uint64_t end = OSUtils::now(); - std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1000.0)) << " MiB/second" << std::endl; + std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; ::free((void *)bb); } #endif @@ -232,7 +232,7 @@ static int testCrypto() for(unsigned int i=0;i<1234567;++i) bb[i] = (unsigned char)i; Salsa20 s20(s20TV0Key,s20TV0Iv); - double bytes = 0.0; + long double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { s20.crypt20(bb,bb,1234567); @@ -240,7 +240,7 @@ static int testCrypto() } uint64_t end = OSUtils::now(); SHA512::hash(buf1,bb,1234567); - std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1000.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; ::free((void *)bb); } @@ -270,14 +270,14 @@ static int testCrypto() unsigned char *bb = (unsigned char *)::malloc(1234567); for(unsigned int i=0;i<1234567;++i) bb[i] = (unsigned char)i; - double bytes = 0.0; + long double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { Poly1305::compute(buf1,bb,1234567,poly1305TV0Key); bytes += 1234567.0; } uint64_t end = OSUtils::now(); - std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1000.0)) << " MiB/second" << std::endl; + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1000.0)) << " MiB/second" << std::endl; ::free((void *)bb); } @@ -632,6 +632,7 @@ static int testOther() return -1; } +#if 0 std::cout << "[other] Testing Hashtable... "; std::cout.flush(); { Hashtable ht; @@ -795,40 +796,28 @@ static int testOther() } } 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; - for(unsigned int i=0;i test; + Dictionary<8194> *test = new Dictionary<8194>(); char key[32][16]; char value[32][128]; + memset(key, 0, sizeof(key)); + memset(value, 0, sizeof(value)); for(unsigned int q=0;q<32;++q) { Utils::snprintf(key[q],16,"%.8lx",(unsigned long)rand()); - int r = rand() % 128; + int r = (rand() % 127) + 1; for(int x=0;xadd(key[q],value[q],r); } for(unsigned int q=0;q<1024;++q) { //int r = rand() % 128; int r = 31; char tmp[128]; - if (test.get(key[r],tmp,sizeof(tmp)) >= 0) { + if (test->get(key[r],tmp,sizeof(tmp)) >= 0) { if (strcmp(value[r],tmp)) { std::cout << "FAILED (invalid value)!" << std::endl; return -1; @@ -838,76 +827,30 @@ static int testOther() return -1; } } - for(unsigned int q=0;q<31;++q) { - char tmp[128]; - test.erase(key[q]); - if (test.get(key[q],tmp,sizeof(tmp)) >= 0) { - std::cout << "FAILED (key should have been erased)!" << std::endl; - return -1; - } - if (test.get(key[q+1],tmp,sizeof(tmp)) < 0) { - std::cout << "FAILED (key should NOT have been erased)!" << std::endl; - return -1; - } - } + delete test; } int foo = 0; volatile int *volatile bar = &foo; // force compiler not to optimize out test.get() below for(int k=0;k<200;++k) { int r = rand() % 8194; - unsigned char tmp[8194]; + unsigned char *tmp = new unsigned char[8194]; for(int q=0;q test((const char *)tmp); + Dictionary<8194> *test = new Dictionary<8194>((const char *)tmp); for(unsigned int q=0;q<100;++q) { char tmp[128]; for(unsigned int x=0;x<128;++x) tmp[x] = (char)(rand() & 0xff); tmp[127] = (char)0; char value[8194]; - *bar += test.get(tmp,value,sizeof(value)); + *bar += test->get(tmp,value,sizeof(value)); } + delete test; + delete[] tmp; } std::cout << "PASS (junk value to prevent optimization-out of test: " << foo << ")" << std::endl; - /* - std::cout << "[other] Testing controller/JSONDB..."; std::cout.flush(); - { - std::map db1data; - JSONDB db1("jsondb-test"); - for(unsigned int i=0;i<256;++i) { - std::string n; - for(unsigned int j=0,k=rand() % 4;j<=k;++j) { - if (j > 0) n.push_back('/'); - char foo[24]; - Utils::snprintf(foo,sizeof(foo),"%lx",rand()); - n.append(foo); - } - db1data[n] = {{"i",i}}; - db1.put(n,db1data[n]); - } - for(std::map::iterator i(db1data.begin());i!=db1data.end();++i) { - i->second["foo"] = "bar"; - db1.put(i->first,i->second); - } - JSONDB db2("jsondb-test"); - if (db1 != db2) { - std::cout << " FAILED (db1!=db2 #1)" << std::endl; - return -1; - } - for(std::map::iterator i(db1data.begin());i!=db1data.end();++i) { - db1.erase(i->first); - } - db2.reload(); - if (db1 != db2) { - std::cout << " FAILED (db1!=db2 #2)" << std::endl; - return -1; - } - } - std::cout << " PASS" << std::endl; - */ - return 0; } diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 84a44198..6ed95010 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -72,10 +72,7 @@ - - false - false - + @@ -88,6 +85,8 @@ + + @@ -109,6 +108,7 @@ + diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index b051b4f7..01637801 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -76,6 +76,12 @@ {ff20532b-d9a2-440d-a7b4-b49e26a9b2f8} + + {05d9cde8-03ae-4e37-b9f7-7417de98cbe9} + + + {7dc22e9c-f869-41e7-b43d-f07f5b94f6fb} + @@ -150,9 +156,6 @@ Source Files\ext\http-parser - - Source Files - Source Files\windows\ZeroTierOne @@ -246,6 +249,9 @@ Source Files\node + + Source Files + @@ -485,6 +491,15 @@ Header Files\node + + Header Files\ext\x64-salsa2012-asm + + + Header Files\controller + + + Header Files\controller + -- cgit v1.2.3 From aaf597f0205b79c0f1d8523f15c8d8aaecb63f43 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 18 Apr 2017 12:22:44 -0700 Subject: Cleanup, Windows fixes, Self test fix --- ext/x64-salsa2012-asm/salsa2012.h | 6 ++---- node/Dictionary.hpp | 18 +++++++++--------- one.cpp | 2 +- selftest.cpp | 15 ++++++--------- windows/ZeroTierOne/ZeroTierOne.vcxproj | 22 ++++++++++++++++++++-- windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 3 +++ 6 files changed, 41 insertions(+), 25 deletions(-) (limited to 'selftest.cpp') diff --git a/ext/x64-salsa2012-asm/salsa2012.h b/ext/x64-salsa2012-asm/salsa2012.h index d47059b4..d8c2e48c 100644 --- a/ext/x64-salsa2012-asm/salsa2012.h +++ b/ext/x64-salsa2012-asm/salsa2012.h @@ -2,11 +2,9 @@ extern "C" { #endif +// Generates Salsa20/12 key stream // output, outlen, nonce, key (256-bit / 32-byte) -extern int zt_salsa2012_amd64_xmm6(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); - -// ciphertext, message, mlen, nonce, key -extern int zt_salsa2012_amd64_xmm6_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int zt_salsa2012_amd64_xmm6(unsigned char *, unsigned long long, const unsigned char *, const unsigned char *); #ifdef __cplusplus } diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 440dae7f..0db13b63 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -176,12 +176,12 @@ public: j = 0; esc = false; ++p; - while ((*p != 0)&&(*p != '\r')&&(*p != '\n')) { + while ((*p != 0)&&(*p != 13)&&(*p != 10)) { if (esc) { esc = false; switch(*p) { - case 'r': dest[j++] = '\r'; break; - case 'n': dest[j++] = '\n'; break; + case 'r': dest[j++] = 13; break; + case 'n': dest[j++] = 10; break; case '0': dest[j++] = (char)0; break; case 'e': dest[j++] = '='; break; default: dest[j++] = *p; break; @@ -207,7 +207,7 @@ public: dest[j] = (char)0; return j; } else { - while ((*p)&&(*p != '\r')&&(*p != '\n')) { + while ((*p)&&(*p != 13)&&(*p != 10)) { if (++p == eof) { dest[0] = (char)0; return -1; @@ -299,7 +299,7 @@ public: unsigned int j = i; if (j > 0) { - _d[j++] = '\n'; + _d[j++] = (char)10; if (j == C) { _d[i] = (char)0; return false; @@ -326,8 +326,8 @@ public: while ( ((vlen < 0)&&(*p)) || (k < vlen) ) { switch(*p) { case 0: - case '\r': - case '\n': + case 13: + case 10: case '\\': case '=': _d[j++] = '\\'; @@ -337,8 +337,8 @@ public: } switch(*p) { case 0: _d[j++] = '0'; break; - case '\r': _d[j++] = 'r'; break; - case '\n': _d[j++] = 'n'; break; + case 13: _d[j++] = 'r'; break; + case 10: _d[j++] = 'n'; break; case '\\': _d[j++] = '\\'; break; case '=': _d[j++] = 'e'; break; } diff --git a/one.cpp b/one.cpp index edefe82e..b40e28fc 100644 --- a/one.cpp +++ b/one.cpp @@ -1257,7 +1257,7 @@ public: }; #ifdef __WINDOWS__ -int _tmain(int argc, _TCHAR* argv[]) +int __cdecl _tmain(int argc, _TCHAR* argv[]) #else int main(int argc,char **argv) #endif diff --git a/selftest.cpp b/selftest.cpp index 55a469e1..e68cf047 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -212,12 +212,10 @@ static int testCrypto() std::cout << "[crypto] Benchmarking Salsa20/12 fast x64 ASM... "; std::cout.flush(); { unsigned char *bb = (unsigned char *)::malloc(1234567); - for(unsigned int i=0;i<1234567;++i) - bb[i] = (unsigned char)i; double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { - zt_salsa2012_amd64_xmm6_xor(bb,bb,1234567,s20TV0Iv,s20TV0Key); + zt_salsa2012_amd64_xmm6(bb, 1234567, s20TV0Iv, s20TV0Key); bytes += 1234567.0; } uint64_t end = OSUtils::now(); @@ -806,20 +804,19 @@ static int testOther() memset(key, 0, sizeof(key)); memset(value, 0, sizeof(value)); for(unsigned int q=0;q<32;++q) { - Utils::snprintf(key[q],16,"%.8lx",(unsigned long)rand()); - int r = (rand() % 127) + 1; + Utils::snprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); + int r = rand() % 128; for(int x=0;xadd(key[q],value[q],r); } for(unsigned int q=0;q<1024;++q) { - //int r = rand() % 128; - int r = 31; + int r = rand() % 32; char tmp[128]; if (test->get(key[r],tmp,sizeof(tmp)) >= 0) { if (strcmp(value[r],tmp)) { - std::cout << "FAILED (invalid value)!" << std::endl; + std::cout << "FAILED (invalid value '" << value[r] << "' != '" << tmp << "')!" << std::endl; return -1; } } else { @@ -1048,7 +1045,7 @@ static int testHttp() */ #ifdef __WINDOWS__ -int _tmain(int argc, _TCHAR* argv[]) +int __cdecl _tmain(int argc, _TCHAR* argv[]) #else int main(int argc,char **argv) #endif diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 6ed95010..96de5d2b 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -72,12 +72,27 @@ - + + false + false + false + false + false + false + + + true + true + true + true + true + true + @@ -363,7 +378,7 @@ Level3 - Full + MaxSpeed true true true @@ -377,6 +392,9 @@ Speed true 4996 + Guard + false + VectorCall true diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index 01637801..cca10f97 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -252,6 +252,9 @@ Source Files + + Source Files + -- cgit v1.2.3 From a376bcc654edc5ad2fb19e3d86be18a23c882437 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 19 Apr 2017 23:49:26 +0000 Subject: ARM NEON Salsa20/12 in build and selftest. Almost 2X speedup on a Raspberry Pi. --- ext/arm32-neon-salsa2012-asm/salsa2012.h | 8 ++++++++ make-linux.mk | 13 ++++++++++++- selftest.cpp | 23 ++++++++++++++++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) (limited to 'selftest.cpp') diff --git a/ext/arm32-neon-salsa2012-asm/salsa2012.h b/ext/arm32-neon-salsa2012-asm/salsa2012.h index 7820a2e6..719b2e0c 100644 --- a/ext/arm32-neon-salsa2012-asm/salsa2012.h +++ b/ext/arm32-neon-salsa2012-asm/salsa2012.h @@ -1,6 +1,14 @@ #ifndef ZT_SALSA2012_ARM32NEON_ASM #define ZT_SALSA2012_ARM32NEON_ASM +#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) +#include +#include +#define zt_arm_has_neon() (getauxval(AT_HWCAP) & HWCAP_NEON) +#else +#define zt_arm_has_neon() (true) +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/make-linux.mk b/make-linux.mk index 2d2f023f..87d29afe 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -98,30 +98,37 @@ endif ifeq ($(CC_MACH),arm) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_SALSA2012=1 endif ifeq ($(CC_MACH),armel) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_SALSA2012=1 endif ifeq ($(CC_MACH),armhf) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_SALSA2012=1 endif ifeq ($(CC_MACH),armv6) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_SALSA2012=1 endif ifeq ($(CC_MACH),armv6zk) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_SALSA2012=1 endif ifeq ($(CC_MACH),armv6kz) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_SALSA2012=1 endif ifeq ($(CC_MACH),armv7) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_SALSA2012=1 endif ifeq ($(CC_MACH),arm64) ZT_ARCHITECTURE=4 @@ -158,11 +165,15 @@ endif # Disable software updates by default on Linux since that is normally done with package management override DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" -# Use X64 ASM Salsa20/12 on X86_64 target +# Build faster crypto on some targets ifeq ($(ZT_USE_X64_ASM_SALSA2012),1) override DEFS+=-DZT_USE_X64_ASM_SALSA2012 override OBJS+=ext/x64-salsa2012-asm/salsa2012.o endif +ifeq ($(ZT_USE_ARM32_NEON_ASM_SALSA2012),1) + override DEFS+=-DZT_USE_ARM32_NEON_ASM_SALSA2012 + override OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o +endif # Static builds, which are currently done for a number of Linux targets ifeq ($(ZT_STATIC),1) diff --git a/selftest.cpp b/selftest.cpp index e68cf047..6df2e272 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -57,6 +57,9 @@ #ifdef ZT_USE_X64_ASM_SALSA2012 #include "ext/x64-salsa2012-asm/salsa2012.h" #endif +#ifdef ZT_USE_ARM32_NEON_ASM_SALSA2012 +#include "ext/arm32-neon-salsa2012-asm/salsa2012.h" +#endif #ifdef __WINDOWS__ #include @@ -215,7 +218,7 @@ static int testCrypto() double bytes = 0.0; uint64_t start = OSUtils::now(); for(unsigned int i=0;i<200;++i) { - zt_salsa2012_amd64_xmm6(bb, 1234567, s20TV0Iv, s20TV0Key); + zt_salsa2012_amd64_xmm6(bb,1234567,s20TV0Iv,s20TV0Key); bytes += 1234567.0; } uint64_t end = OSUtils::now(); @@ -224,6 +227,24 @@ static int testCrypto() } #endif +#ifdef ZT_USE_ARM32_NEON_ASM_SALSA2012 + if (zt_arm_has_neon()) { + std::cout << "[crypto] Benchmarking Salsa20/12 fast arm32/neon ASM... "; std::cout.flush(); + { + unsigned char *bb = (unsigned char *)::malloc(1234567); + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for(unsigned int i=0;i<200;++i) { + zt_salsa2012_armneon3_xor(bb,(const unsigned char *)0,1234567,s20TV0Iv,s20TV0Key); + bytes += 1234567.0; + } + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + ::free((void *)bb); + } + } +#endif + std::cout << "[crypto] Benchmarking Salsa20/20... "; std::cout.flush(); { unsigned char *bb = (unsigned char *)::malloc(1234567); -- cgit v1.2.3 From a8ced184dc67c5cf39ce1332156c7eb80241768b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 20 Apr 2017 09:33:35 -0700 Subject: Some code cleanup and make sure any type punning is guarded with ZT_NO_TYPE_PUNNING. --- node/Packet.cpp | 60 ++++++++++++++++++++------------------------------------ node/Salsa20.cpp | 40 +++++++++++++++++-------------------- node/Salsa20.hpp | 37 ++++++++++++++++++++++++++++++++++ selftest.cpp | 2 -- 4 files changed, 76 insertions(+), 63 deletions(-) (limited to 'selftest.cpp') diff --git a/node/Packet.cpp b/node/Packet.cpp index 85b18cff..8a57dd55 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1109,38 +1109,26 @@ void Packet::armor(const void *key,bool encryptPayload,unsigned int counter) setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE); _salsa20MangleKey((const unsigned char *)key,mangledKey); - if (ZT_HAS_FAST_CRYPTO()) { - const unsigned int payloadLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0; + const unsigned int encryptLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0; uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8]; - ZT_FAST_SINGLE_PASS_SALSA2012(keyStream,payloadLen + 64,(data + ZT_PACKET_IDX_IV),mangledKey); - - uint64_t *ksptr = keyStream + 8; // encryption starts after first Salsa20 block - uint8_t *dptr = data + ZT_PACKET_IDX_VERB; - unsigned int ksrem = payloadLen; - while (ksrem >= 8) { - ksrem -= 8; - *(reinterpret_cast(dptr)) ^= *(ksptr++); - dptr += 8; - } - for(unsigned int i=0;i(ksptr)[i]; - } - + ZT_FAST_SINGLE_PASS_SALSA2012(keyStream,encryptLen + 64,(data + ZT_PACKET_IDX_IV),mangledKey); + Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast(keyStream + 8),encryptLen); uint64_t mac[2]; Poly1305::compute(mac,data + ZT_PACKET_IDX_VERB,size() - ZT_PACKET_IDX_VERB,keyStream); +#ifdef ZT_NO_TYPE_PUNNING memcpy(data + ZT_PACKET_IDX_MAC,mac,8); +#else + (*reinterpret_cast(data + ZT_PACKET_IDX_MAC)) = mac[0]; +#endif } else { Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV); - uint64_t macKey[4]; s20.crypt12(ZERO_KEY,macKey,sizeof(macKey)); - uint8_t *const payload = data + ZT_PACKET_IDX_VERB; const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; if (encryptPayload) s20.crypt12(payload,payload,payloadLen); - uint64_t mac[2]; Poly1305::compute(mac,payload,payloadLen,macKey); memcpy(data + ZT_PACKET_IDX_MAC,mac,8); @@ -1157,39 +1145,33 @@ bool Packet::dearmor(const void *key) if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) { _salsa20MangleKey((const unsigned char *)key,mangledKey); - if (ZT_HAS_FAST_CRYPTO()) { uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8]; ZT_FAST_SINGLE_PASS_SALSA2012(keyStream,((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) ? (payloadLen + 64) : 64),(data + ZT_PACKET_IDX_IV),mangledKey); - uint64_t mac[2]; Poly1305::compute(mac,payload,payloadLen,keyStream); +#ifdef ZT_NO_TYPE_PUNNING if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) - return false; // MAC failed, packet is corrupt, modified, or is not from the sender - - if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) { - uint64_t *ksptr = keyStream + 8; // encryption starts after first Salsa20 block - uint8_t *dptr = data + ZT_PACKET_IDX_VERB; - unsigned int ksrem = payloadLen; - while (ksrem >= 8) { - ksrem -= 8; - *(reinterpret_cast(dptr)) ^= *(ksptr++); - dptr += 8; - } - for(unsigned int i=0;i(ksptr)[i]; - } - } + return false; +#else + if ((*reinterpret_cast(data + ZT_PACKET_IDX_MAC)) != mac[0]) // also secure, constant time + return false; +#endif + if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) + Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast(keyStream + 8),payloadLen); } else { Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV); - uint64_t macKey[4]; s20.crypt12(ZERO_KEY,macKey,sizeof(macKey)); uint64_t mac[2]; Poly1305::compute(mac,payload,payloadLen,macKey); +#ifdef ZT_NO_TYPE_PUNNING if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) - return false; // MAC failed, packet is corrupt, modified, or is not from the sender - + return false; +#else + if ((*reinterpret_cast(data + ZT_PACKET_IDX_MAC)) != mac[0]) // also secure, constant time + return false; +#endif if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) s20.crypt12(payload,payload,payloadLen); } diff --git a/node/Salsa20.cpp b/node/Salsa20.cpp index 2a802555..1d4117e3 100644 --- a/node/Salsa20.cpp +++ b/node/Salsa20.cpp @@ -69,46 +69,42 @@ namespace ZeroTier { void Salsa20::init(const void *key,const void *iv) { #ifdef ZT_SALSA20_SSE - const uint32_t *k = (const uint32_t *)key; - + const uint32_t *const k = (const uint32_t *)key; _state.i[0] = 0x61707865; - _state.i[3] = 0x6b206574; - _state.i[13] = k[0]; - _state.i[10] = k[1]; - _state.i[7] = k[2]; - _state.i[4] = k[3]; - k += 4; _state.i[1] = 0x3320646e; _state.i[2] = 0x79622d32; - _state.i[15] = k[0]; - _state.i[12] = k[1]; - _state.i[9] = k[2]; - _state.i[6] = k[3]; - _state.i[14] = ((const uint32_t *)iv)[0]; - _state.i[11] = ((const uint32_t *)iv)[1]; + _state.i[3] = 0x6b206574; + _state.i[4] = k[3]; _state.i[5] = 0; + _state.i[6] = k[7]; + _state.i[7] = k[2]; _state.i[8] = 0; + _state.i[9] = k[6]; + _state.i[10] = k[1]; + _state.i[11] = ((const uint32_t *)iv)[1]; + _state.i[12] = k[5]; + _state.i[13] = k[0]; + _state.i[14] = ((const uint32_t *)iv)[0]; + _state.i[15] = k[4]; #else const char *const constants = "expand 32-byte k"; - const uint8_t *k = (const uint8_t *)key; - + const uint8_t *const k = (const uint8_t *)key; + _state.i[0] = U8TO32_LITTLE(constants + 0); _state.i[1] = U8TO32_LITTLE(k + 0); _state.i[2] = U8TO32_LITTLE(k + 4); _state.i[3] = U8TO32_LITTLE(k + 8); _state.i[4] = U8TO32_LITTLE(k + 12); - k += 16; _state.i[5] = U8TO32_LITTLE(constants + 4); _state.i[6] = U8TO32_LITTLE(((const uint8_t *)iv) + 0); _state.i[7] = U8TO32_LITTLE(((const uint8_t *)iv) + 4); _state.i[8] = 0; _state.i[9] = 0; _state.i[10] = U8TO32_LITTLE(constants + 8); - _state.i[11] = U8TO32_LITTLE(k + 0); - _state.i[12] = U8TO32_LITTLE(k + 4); - _state.i[13] = U8TO32_LITTLE(k + 8); - _state.i[14] = U8TO32_LITTLE(k + 12); + _state.i[11] = U8TO32_LITTLE(k + 16); + _state.i[12] = U8TO32_LITTLE(k + 20); + _state.i[13] = U8TO32_LITTLE(k + 24); + _state.i[14] = U8TO32_LITTLE(k + 28); _state.i[15] = U8TO32_LITTLE(constants + 12); - _state.i[0] = U8TO32_LITTLE(constants + 0); #endif } diff --git a/node/Salsa20.hpp b/node/Salsa20.hpp index 448c8f1a..52592602 100644 --- a/node/Salsa20.hpp +++ b/node/Salsa20.hpp @@ -34,6 +34,43 @@ public: Salsa20() {} ~Salsa20() { Utils::burn(&_state,sizeof(_state)); } + /** + * XOR d with s + * + * This is done efficiently using e.g. SSE if available. It's used when + * alternative Salsa20 implementations are used in Packet and is here + * since this is where all the SSE stuff is already included. + * + * @param d Destination to XOR + * @param s Source bytes to XOR with destination + * @param len Length of s and d + */ + static inline void memxor(uint8_t *d,const uint8_t *s,unsigned int len) + { +#ifdef ZT_SALSA20_SSE + while (len >= 16) { + _mm_storeu_si128(reinterpret_cast<__m128i *>(d),_mm_xor_si128(_mm_loadu_si128(reinterpret_cast<__m128i *>(d)),_mm_loadu_si128(reinterpret_cast(s)))); + s += 16; + d += 16; + len -= 16; + } +#else +#ifndef ZT_NO_TYPE_PUNNING + while (len >= 16) { + (*reinterpret_cast(d)) ^= (*reinterpret_cast(s)); + s += 8; + d += 8; + (*reinterpret_cast(d)) ^= (*reinterpret_cast(s)); + s += 8; + d += 8; + len -= 16; + } +#endif +#endif + while (len--) + *(d++) ^= *(s++); + } + /** * @param key 256-bit (32 byte) key * @param iv 64-bit initialization vector diff --git a/selftest.cpp b/selftest.cpp index 6df2e272..91d304a6 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -141,8 +141,6 @@ static const C25519TestVector C25519_TEST_VECTORS[ZT_NUM_C25519_TEST_VECTORS] = ////////////////////////////////////////////////////////////////////////////// -static unsigned char fuzzbuf[1048576]; - static int testCrypto() { unsigned char buf1[16384]; -- cgit v1.2.3 From cafbe44dde55e57115cc654610172556dff19bec Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 24 Apr 2017 19:16:36 -0700 Subject: Controller optimizations -- make locking more fine-grained, use true hardware concurrency, etc. --- controller/EmbeddedNetworkController.cpp | 193 ++++++++++++------------------- controller/EmbeddedNetworkController.hpp | 7 +- controller/JSONDB.cpp | 36 ++++-- controller/JSONDB.hpp | 15 +-- selftest.cpp | 2 + 5 files changed, 106 insertions(+), 147 deletions(-) (limited to 'selftest.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 597bc9c9..3b901afe 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "../include/ZeroTierOne.h" #include "../node/Constants.hpp" @@ -430,7 +431,6 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath) : _startTime(OSUtils::now()), - _threadsStarted(false), _db(dbPath), _node(node) { @@ -439,11 +439,11 @@ EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPa EmbeddedNetworkController::~EmbeddedNetworkController() { Mutex::Lock _l(_threads_m); - if (_threadsStarted) { - for(int i=0;i<(ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT*2);++i) + if (_threads.size() > 0) { + for(unsigned long i=0;i<(((unsigned long)_threads.size())*2);++i) _queue.post((_RQEntry *)0); - for(int i=0;i::iterator i(_threads.begin());i!=_threads.end();++i) + Thread::join(*i); } } @@ -465,11 +465,13 @@ void EmbeddedNetworkController::request( { Mutex::Lock _l(_threads_m); - if (!_threadsStarted) { - for(int i=0;i= 4) { const uint64_t address = Utils::hexStrToU64(path[3].c_str()); - - json member; - { - Mutex::Lock _l(_db_m); - member = _db.get("network",nwids,"member",Address(address).toString()); - } + json member(_db.get("network",nwids,"member",Address(address).toString())); if (!member.size()) return 404; - _addMemberNonPersistedFields(member,OSUtils::now()); responseBody = OSUtils::jsonDump(member); responseContentType = "application/json"; - - return 200; } else { - - Mutex::Lock _l(_db_m); - responseBody = "{"; _db.filter((std::string("network/") + nwids + "/member/"),[&responseBody](const std::string &n,const json &member) { if ((member.is_object())&&(member.size() > 0)) { @@ -540,9 +527,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( }); responseBody.push_back('}'); responseContentType = "application/json"; - - return 200; } + return 200; } // else 404 @@ -560,14 +546,11 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( } else if (path.size() == 1) { std::set networkIds; - { - Mutex::Lock _l(_db_m); - _db.filter("network/",[&networkIds](const std::string &n,const json &obj) { - if (n.length() == (16 + 8)) - networkIds.insert(n.substr(8)); - return true; // do not delete - }); - } + _db.filter("network/",[&networkIds](const std::string &n,const json &obj) { + if (n.length() == (16 + 8)) + networkIds.insert(n.substr(8)); + return true; // do not delete + }); responseBody.push_back('['); for(std::set::iterator i(networkIds.begin());i!=networkIds.end();++i) { @@ -634,11 +617,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( char addrs[24]; Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); - json member; - { - Mutex::Lock _l(_db_m); - member = _db.get("network",nwids,"member",Address(address).toString()); - } + json member(_db.get("network",nwids,"member",Address(address).toString())); json origMember(member); // for detecting changes _initMember(member); @@ -735,10 +714,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( member["lastModified"] = now; json &revj = member["revision"]; member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); - { - Mutex::Lock _l(_db_m); - _db.put("network",nwids,"member",Address(address).toString(),member); - } + _db.put("network",nwids,"member",Address(address).toString(),member); _pushMemberUpdate(now,nwid,member); } @@ -806,31 +782,26 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( } else { // POST to network ID - json network; - { - Mutex::Lock _l(_db_m); - - // Magic ID ending with ______ picks a random unused network ID - if (path[1].substr(10) == "______") { - nwid = 0; - uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL; - uint64_t nwidPostfix = 0; - for(unsigned long k=0;k<100000;++k) { // sanity limit on trials - Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix)); - uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); - if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid); - if (_db.get("network",nwids).size() <= 0) { - nwid = tryNwid; - break; - } + // Magic ID ending with ______ picks a random unused network ID + if (path[1].substr(10) == "______") { + nwid = 0; + uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL; + uint64_t nwidPostfix = 0; + for(unsigned long k=0;k<100000;++k) { // sanity limit on trials + Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix)); + uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); + if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid); + if (_db.get("network",nwids).size() <= 0) { + nwid = tryNwid; + break; } - if (!nwid) - return 503; } - - network = _db.get("network",nwids); + if (!nwid) + return 503; } + json network(_db.get("network",nwids)); + json origNetwork(network); // for detecting changes _initNetwork(network); @@ -1044,10 +1015,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json &revj = network["revision"]; network["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); network["lastModified"] = now; - { - Mutex::Lock _l(_db_m); - _db.put("network",nwids,network); - } + _db.put("network",nwids,network); // Send an update to all members of the network _db.filter((std::string("network/") + nwids + "/member/"),[this,&now,&nwid](const std::string &n,const json &obj) { @@ -1101,11 +1069,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( char nwids[24]; Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); - json network; - { - Mutex::Lock _l(_db_m); - network = _db.get("network",nwids); - } + json network(_db.get("network",nwids)); if (!network.size()) return 404; @@ -1113,8 +1077,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { const uint64_t address = Utils::hexStrToU64(path[3].c_str()); - Mutex::Lock _l(_db_m); - json member = _db.get("network",nwids,"member",Address(address).toString()); _db.erase("network",nwids,"member",Address(address).toString()); @@ -1125,8 +1087,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( return 200; } } else { - Mutex::Lock _l(_db_m); - std::string pfx("network/"); pfx.append(nwids); _db.filter(pfx,[](const std::string &n,const json &obj) { @@ -1226,7 +1186,6 @@ void EmbeddedNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTes reinterpret_cast(&(report->receivedFromRemoteAddress))->toString().c_str(), ((double)report->receivedFromLinkQuality / (double)ZT_PATH_LINK_QUALITY_MAX)); - Mutex::Lock _l(self->_db_m); self->_db.writeRaw(id,std::string(tmp)); } @@ -1252,13 +1211,8 @@ void EmbeddedNetworkController::_request( char nwids[24]; Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); - json network; - json member; - { - Mutex::Lock _l(_db_m); - network = _db.get("network",nwids); - member = _db.get("network",nwids,"member",identity.address().toString()); - } + json network(_db.get("network",nwids)); + json member(_db.get("network",nwids,"member",identity.address().toString())); if (!network.size()) { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); @@ -1403,7 +1357,6 @@ void EmbeddedNetworkController::_request( if (!authorizedBy) { if (origMember != member) { member["lastModified"] = now; - Mutex::Lock _l(_db_m); _db.put("network",nwids,"member",identity.address().toString(),member); } _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED); @@ -1759,7 +1712,6 @@ void EmbeddedNetworkController::_request( if (member != origMember) { member["lastModified"] = now; - Mutex::Lock _l(_db_m); _db.put("network",nwids,"member",identity.address().toString(),member); } @@ -1780,45 +1732,42 @@ void EmbeddedNetworkController::_getNetworkMemberInfo(uint64_t now,uint64_t nwid } } - { - Mutex::Lock _l(_db_m); - _db.filter(pfx,[&nmi,&now](const std::string &n,const json &member) { - try { - if (OSUtils::jsonBool(member["authorized"],false)) { - ++nmi.authorizedMemberCount; - - if (member.count("recentLog")) { - const json &mlog = member["recentLog"]; - if ((mlog.is_array())&&(mlog.size() > 0)) { - const json &mlog1 = mlog[0]; - if (mlog1.is_object()) { - if ((now - OSUtils::jsonInt(mlog1["ts"],0ULL)) < ZT_NETCONF_NODE_ACTIVE_THRESHOLD) - ++nmi.activeMemberCount; - } + _db.filter(pfx,[&nmi,&now](const std::string &n,const json &member) { + try { + if (OSUtils::jsonBool(member["authorized"],false)) { + ++nmi.authorizedMemberCount; + + if (member.count("recentLog")) { + const json &mlog = member["recentLog"]; + if ((mlog.is_array())&&(mlog.size() > 0)) { + const json &mlog1 = mlog[0]; + if (mlog1.is_object()) { + if ((now - OSUtils::jsonInt(mlog1["ts"],0ULL)) < ZT_NETCONF_NODE_ACTIVE_THRESHOLD) + ++nmi.activeMemberCount; } } + } - if (OSUtils::jsonBool(member["activeBridge"],false)) { - nmi.activeBridges.insert(Address(Utils::hexStrToU64(OSUtils::jsonString(member["id"],"0000000000").c_str()))); - } + if (OSUtils::jsonBool(member["activeBridge"],false)) { + nmi.activeBridges.insert(Address(Utils::hexStrToU64(OSUtils::jsonString(member["id"],"0000000000").c_str()))); + } - if (member.count("ipAssignments")) { - const json &mips = member["ipAssignments"]; - if (mips.is_array()) { - for(unsigned long i=0;i _queue; - Thread _threads[ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT]; - bool _threadsStarted; + std::vector _threads; Mutex _threads_m; std::map _nmiCache; Mutex _nmiCache_m; JSONDB _db; - Mutex _db_m; Node *const _node; std::string _path; diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index d3e76fc1..dd8e3968 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -78,22 +78,29 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) bool JSONDB::put(const std::string &n,const nlohmann::json &obj) { const bool r = writeRaw(n,OSUtils::jsonDump(obj)); - _db[n].obj = obj; + { + Mutex::Lock _l(_db_m); + _db[n].obj = obj; + } return r; } -const nlohmann::json &JSONDB::get(const std::string &n) +nlohmann::json JSONDB::get(const std::string &n) { - while (!_ready) { - Thread::sleep(250); - _ready = _reload(_basePath,std::string()); - } + { + Mutex::Lock _l(_db_m); - if (!_isValidObjectName(n)) - return _EMPTY_JSON; - std::map::iterator e(_db.find(n)); - if (e != _db.end()) - return e->second.obj; + while (!_ready) { + Thread::sleep(250); + _ready = _reload(_basePath,std::string()); + } + + if (!_isValidObjectName(n)) + return _EMPTY_JSON; + std::map::iterator e(_db.find(n)); + if (e != _db.end()) + return e->second.obj; + } std::string buf; if (_httpAddr) { @@ -110,6 +117,7 @@ const nlohmann::json &JSONDB::get(const std::string &n) } try { + Mutex::Lock _l(_db_m); _E &e2 = _db[n]; e2.obj = OSUtils::jsonParse(buf); return e2.obj; @@ -135,11 +143,15 @@ void JSONDB::erase(const std::string &n) OSUtils::rm(path.c_str()); } - _db.erase(n); + { + Mutex::Lock _l(_db_m); + _db.erase(n); + } } bool JSONDB::_reload(const std::string &p,const std::string &b) { + // Assumes _db_m is locked if (_httpAddr) { std::string body; std::map headers; diff --git a/controller/JSONDB.hpp b/controller/JSONDB.hpp index beafbaf5..2d3a5224 100644 --- a/controller/JSONDB.hpp +++ b/controller/JSONDB.hpp @@ -51,18 +51,16 @@ public: bool writeRaw(const std::string &n,const std::string &obj); bool put(const std::string &n,const nlohmann::json &obj); - inline bool put(const std::string &n1,const std::string &n2,const nlohmann::json &obj) { return this->put((n1 + "/" + n2),obj); } inline bool put(const std::string &n1,const std::string &n2,const std::string &n3,const nlohmann::json &obj) { return this->put((n1 + "/" + n2 + "/" + n3),obj); } inline bool put(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const nlohmann::json &obj) { return this->put((n1 + "/" + n2 + "/" + n3 + "/" + n4),obj); } inline bool put(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const std::string &n5,const nlohmann::json &obj) { return this->put((n1 + "/" + n2 + "/" + n3 + "/" + n4 + "/" + n5),obj); } - const nlohmann::json &get(const std::string &n); - - inline const nlohmann::json &get(const std::string &n1,const std::string &n2) { return this->get((n1 + "/" + n2)); } - inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3) { return this->get((n1 + "/" + n2 + "/" + n3)); } - inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4)); } - inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const std::string &n5) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4 + "/" + n5)); } + nlohmann::json get(const std::string &n); + inline nlohmann::json get(const std::string &n1,const std::string &n2) { return this->get((n1 + "/" + n2)); } + inline nlohmann::json get(const std::string &n1,const std::string &n2,const std::string &n3) { return this->get((n1 + "/" + n2 + "/" + n3)); } + inline nlohmann::json get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4)); } + inline nlohmann::json get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const std::string &n5) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4 + "/" + n5)); } void erase(const std::string &n); @@ -74,6 +72,8 @@ public: template inline void filter(const std::string &prefix,F func) { + Mutex::Lock _l(_db_m); + while (!_ready) { Thread::sleep(250); _ready = _reload(_basePath,std::string()); @@ -108,6 +108,7 @@ private: InetAddress _httpAddr; std::string _basePath; std::map _db; + Mutex _db_m; volatile bool _ready; }; diff --git a/selftest.cpp b/selftest.cpp index 91d304a6..33e65f2c 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "node/Constants.hpp" #include "node/Hashtable.hpp" @@ -1114,6 +1115,7 @@ int main(int argc,char **argv) */ std::cout << "[info] sizeof(void *) == " << sizeof(void *) << std::endl; + std::cout << "[info] hardware concurrency == " << std::thread::hardware_concurrency() << std::endl; std::cout << "[info] sizeof(NetworkConfig) == " << sizeof(ZeroTier::NetworkConfig) << std::endl; srand((unsigned int)time(0)); -- cgit v1.2.3 From 9e80db0fd169de19d5d343e8b6998c8ace4aeb22 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 27 Apr 2017 00:59:36 -0700 Subject: Cleanup, fix a valgrind error, stack use reduction. --- controller/EmbeddedNetworkController.cpp | 134 +- controller/EmbeddedNetworkController.hpp | 3 +- controller/JSONDB.cpp | 57 +- controller/JSONDB.hpp | 55 +- ext/json/LICENSE.MIT | 17 +- ext/json/README.md | 420 +- ext/json/json.hpp | 6976 +++++++++++++++++++----------- make-linux.mk | 9 +- node/CertificateOfOwnership.hpp | 2 + root-watcher/schema.sql | 3 +- selftest.cpp | 47 - 11 files changed, 4910 insertions(+), 2813 deletions(-) (limited to 'selftest.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index be53f2b8..a41a4a94 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. + * Copyright (C) 2011-2015 ZeroTier, Inc-> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,9 +30,9 @@ #include #include #include -#include #include #include +#include #include "../include/ZeroTierOne.h" #include "../node/Constants.hpp" @@ -1017,7 +1017,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( network["id"] = nwids; network["nwid"] = nwids; // legacy - if (network != origNetwork) { + if (true) { json &revj = network["revision"]; network["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); network["lastModified"] = now; @@ -1235,8 +1235,9 @@ void EmbeddedNetworkController::_request( } // These are always the same, but make sure they are set - member["id"] = identity.address().toString(); - member["address"] = member["id"]; + const std::string addrs(identity.address().toString()); + member["id"] = addrs; + member["address"] = addrs; member["nwid"] = nwids; // Determine whether and how member is authorized @@ -1356,8 +1357,6 @@ void EmbeddedNetworkController::_request( // If we made it this far, they are authorized. // ------------------------------------------------------------------------- - NetworkConfig nc; - uint64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; if (now > ns.mostRecentDeauthTime) { // If we recently de-authorized a member, shrink credential TTL/max delta to @@ -1371,19 +1370,21 @@ void EmbeddedNetworkController::_request( } } - nc.networkId = nwid; - nc.type = OSUtils::jsonBool(network["private"],true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; - nc.timestamp = now; - nc.credentialTimeMaxDelta = credentialtmd; - nc.revision = OSUtils::jsonInt(network["revision"],0ULL); - nc.issuedTo = identity.address(); - if (OSUtils::jsonBool(network["enableBroadcast"],true)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; - if (OSUtils::jsonBool(network["allowPassiveBridging"],false)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING; - Utils::scopy(nc.name,sizeof(nc.name),OSUtils::jsonString(network["name"],"").c_str()); - nc.multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"],32ULL); + std::auto_ptr nc(new NetworkConfig()); + + nc->networkId = nwid; + nc->type = OSUtils::jsonBool(network["private"],true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; + nc->timestamp = now; + nc->credentialTimeMaxDelta = credentialtmd; + nc->revision = OSUtils::jsonInt(network["revision"],0ULL); + nc->issuedTo = identity.address(); + if (OSUtils::jsonBool(network["enableBroadcast"],true)) nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; + if (OSUtils::jsonBool(network["allowPassiveBridging"],false)) nc->flags |= ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING; + Utils::scopy(nc->name,sizeof(nc->name),OSUtils::jsonString(network["name"],"").c_str()); + nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"],32ULL); for(std::vector
::const_iterator ab(ns.activeBridges.begin());ab!=ns.activeBridges.end();++ab) - nc.addSpecialist(*ab,ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE); + nc->addSpecialist(*ab,ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE); json &v4AssignMode = network["v4AssignMode"]; json &v6AssignMode = network["v6AssignMode"]; @@ -1399,15 +1400,15 @@ void EmbeddedNetworkController::_request( // Old versions with no rules engine support get an allow everything rule. // Since rules are enforced bidirectionally, newer versions *will* still // enforce rules on the inbound side. - nc.ruleCount = 1; - nc.rules[0].t = ZT_NETWORK_RULE_ACTION_ACCEPT; + nc->ruleCount = 1; + nc->rules[0].t = ZT_NETWORK_RULE_ACTION_ACCEPT; } else { if (rules.is_array()) { for(unsigned long i=0;i= ZT_MAX_NETWORK_RULES) + if (nc->ruleCount >= ZT_MAX_NETWORK_RULES) break; - if (_parseRule(rules[i],nc.rules[nc.ruleCount])) - ++nc.ruleCount; + if (_parseRule(rules[i],nc->rules[nc->ruleCount])) + ++nc->ruleCount; } } @@ -1451,10 +1452,10 @@ void EmbeddedNetworkController::_request( ++caprc; } } - nc.capabilities[nc.capabilityCount] = Capability((uint32_t)capId,nwid,now,1,capr,caprc); - if (nc.capabilities[nc.capabilityCount].sign(_signingId,identity.address())) - ++nc.capabilityCount; - if (nc.capabilityCount >= ZT_MAX_NETWORK_CAPABILITIES) + nc->capabilities[nc->capabilityCount] = Capability((uint32_t)capId,nwid,now,1,capr,caprc); + if (nc->capabilities[nc->capabilityCount].sign(_signingId,identity.address())) + ++nc->capabilityCount; + if (nc->capabilityCount >= ZT_MAX_NETWORK_CAPABILITIES) break; } } @@ -1485,17 +1486,17 @@ void EmbeddedNetworkController::_request( } } for(std::map< uint32_t,uint32_t >::const_iterator t(memberTagsById.begin());t!=memberTagsById.end();++t) { - if (nc.tagCount >= ZT_MAX_NETWORK_TAGS) + if (nc->tagCount >= ZT_MAX_NETWORK_TAGS) break; - nc.tags[nc.tagCount] = Tag(nwid,now,identity.address(),t->first,t->second); - if (nc.tags[nc.tagCount].sign(_signingId)) - ++nc.tagCount; + nc->tags[nc->tagCount] = Tag(nwid,now,identity.address(),t->first,t->second); + if (nc->tags[nc->tagCount].sign(_signingId)) + ++nc->tagCount; } } if (routes.is_array()) { for(unsigned long i=0;i= ZT_MAX_NETWORK_ROUTES) + if (nc->routeCount >= ZT_MAX_NETWORK_ROUTES) break; json &route = routes[i]; json &target = route["target"]; @@ -1505,11 +1506,11 @@ void EmbeddedNetworkController::_request( InetAddress v; if (via.is_string()) v.fromString(via.get()); if ((t.ss_family == AF_INET)||(t.ss_family == AF_INET6)) { - ZT_VirtualNetworkRoute *r = &(nc.routes[nc.routeCount]); + ZT_VirtualNetworkRoute *r = &(nc->routes[nc->routeCount]); *(reinterpret_cast(&(r->target))) = t; if (v.ss_family == t.ss_family) *(reinterpret_cast(&(r->via))) = v; - ++nc.routeCount; + ++nc->routeCount; } } } @@ -1518,13 +1519,13 @@ void EmbeddedNetworkController::_request( const bool noAutoAssignIps = OSUtils::jsonBool(member["noAutoAssignIps"],false); if ((v6AssignMode.is_object())&&(!noAutoAssignIps)) { - if ((OSUtils::jsonBool(v6AssignMode["rfc4193"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { - nc.staticIps[nc.staticIpCount++] = InetAddress::makeIpv6rfc4193(nwid,identity.address().toInt()); - nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; + if ((OSUtils::jsonBool(v6AssignMode["rfc4193"],false))&&(nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { + nc->staticIps[nc->staticIpCount++] = InetAddress::makeIpv6rfc4193(nwid,identity.address().toInt()); + nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; } - if ((OSUtils::jsonBool(v6AssignMode["6plane"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { - nc.staticIps[nc.staticIpCount++] = InetAddress::makeIpv66plane(nwid,identity.address().toInt()); - nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; + if ((OSUtils::jsonBool(v6AssignMode["6plane"],false))&&(nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { + nc->staticIps[nc->staticIpCount++] = InetAddress::makeIpv66plane(nwid,identity.address().toInt()); + nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; } } @@ -1542,15 +1543,15 @@ void EmbeddedNetworkController::_request( // this route, ignoring the netmask bits field of the assigned IP itself. Using that was worthless and a source // of user error / poor UX. int routedNetmaskBits = 0; - for(unsigned int rk=0;rk(&(nc.routes[rk].target))->containsAddress(ip)) ) - routedNetmaskBits = reinterpret_cast(&(nc.routes[rk].target))->netmaskBits(); + for(unsigned int rk=0;rkrouteCount;++rk) { + if ( (!nc->routes[rk].via.ss_family) && (reinterpret_cast(&(nc->routes[rk].target))->containsAddress(ip)) ) + routedNetmaskBits = reinterpret_cast(&(nc->routes[rk].target))->netmaskBits(); } if (routedNetmaskBits > 0) { - if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { + if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { ip.setPort(routedNetmaskBits); - nc.staticIps[nc.staticIpCount++] = ip; + nc->staticIps[nc->staticIpCount++] = ip; } if (ip.ss_family == AF_INET) haveManagedIpv4AutoAssignment = true; @@ -1601,9 +1602,9 @@ void EmbeddedNetworkController::_request( // Check if this IP is within a local-to-Ethernet routed network int routedNetmaskBits = 0; - for(unsigned int rk=0;rk(&(nc.routes[rk].target))->containsAddress(ip6)) ) - routedNetmaskBits = reinterpret_cast(&(nc.routes[rk].target))->netmaskBits(); + for(unsigned int rk=0;rkrouteCount;++rk) { + if ( (!nc->routes[rk].via.ss_family) && (nc->routes[rk].target.ss_family == AF_INET6) && (reinterpret_cast(&(nc->routes[rk].target))->containsAddress(ip6)) ) + routedNetmaskBits = reinterpret_cast(&(nc->routes[rk].target))->netmaskBits(); } // If it's routed, then try to claim and assign it and if successful end loop @@ -1611,8 +1612,8 @@ void EmbeddedNetworkController::_request( ipAssignments.push_back(ip6.toIpString()); member["ipAssignments"] = ipAssignments; ip6.setPort((unsigned int)routedNetmaskBits); - if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) - nc.staticIps[nc.staticIpCount++] = ip6; + if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) + nc->staticIps[nc->staticIpCount++] = ip6; haveManagedIpv6AutoAssignment = true; break; } @@ -1646,10 +1647,10 @@ void EmbeddedNetworkController::_request( // Check if this IP is within a local-to-Ethernet routed network int routedNetmaskBits = -1; - for(unsigned int rk=0;rk(&(nc.routes[rk].target))->sin_addr.s_addr)); - int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast(&(nc.routes[rk].target))->sin_port)); + for(unsigned int rk=0;rkrouteCount;++rk) { + if (nc->routes[rk].target.ss_family == AF_INET) { + uint32_t targetIp = Utils::ntoh((uint32_t)(reinterpret_cast(&(nc->routes[rk].target))->sin_addr.s_addr)); + int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast(&(nc->routes[rk].target))->sin_port)); if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) { routedNetmaskBits = targetBits; break; @@ -1662,8 +1663,8 @@ void EmbeddedNetworkController::_request( if ( (routedNetmaskBits > 0) && (!std::binary_search(ns.allocatedIps.begin(),ns.allocatedIps.end(),ip4)) ) { ipAssignments.push_back(ip4.toIpString()); member["ipAssignments"] = ipAssignments; - if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { - struct sockaddr_in *const v4ip = reinterpret_cast(&(nc.staticIps[nc.staticIpCount++])); + if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { + struct sockaddr_in *const v4ip = reinterpret_cast(&(nc->staticIps[nc->staticIpCount++])); v4ip->sin_family = AF_INET; v4ip->sin_port = Utils::hton((uint16_t)routedNetmaskBits); v4ip->sin_addr.s_addr = Utils::hton(ip); @@ -1678,17 +1679,17 @@ void EmbeddedNetworkController::_request( } // Issue a certificate of ownership for all static IPs - if (nc.staticIpCount) { - nc.certificatesOfOwnership[0] = CertificateOfOwnership(nwid,now,identity.address(),1); - for(unsigned int i=0;istaticIpCount) { + nc->certificatesOfOwnership[0] = CertificateOfOwnership(nwid,now,identity.address(),1); + for(unsigned int i=0;istaticIpCount;++i) + nc->certificatesOfOwnership[0].addThing(nc->staticIps[i]); + nc->certificatesOfOwnership[0].sign(_signingId); + nc->certificateOfOwnershipCount = 1; } CertificateOfMembership com(now,credentialtmd,nwid,identity.address()); if (com.sign(_signingId)) { - nc.com = com; + nc->com = com; } else { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR); return; @@ -1699,7 +1700,7 @@ void EmbeddedNetworkController::_request( _db.saveNetworkMember(nwid,identity.address().toInt(),member); } - _sender->ncSendConfig(nwid,requestPacketId,identity.address(),nc,metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6); + _sender->ncSendConfig(nwid,requestPacketId,identity.address(),*(nc.get()),metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6); } void EmbeddedNetworkController::_pushMemberUpdate(uint64_t now,uint64_t nwid,const nlohmann::json &member) @@ -1716,11 +1717,10 @@ void EmbeddedNetworkController::_pushMemberUpdate(uint64_t now,uint64_t nwid,con online = ( (lrt != _lastRequestTime.end()) && ((now - lrt->second) < ZT_NETWORK_AUTOCONF_DELAY) ); } if (online) { - Dictionary *metaData = new Dictionary(mdstr.c_str()); + Dictionary metaData(mdstr.c_str()); try { - this->request(nwid,InetAddress(),0,id,*metaData); + this->request(nwid,InetAddress(),0,id,metaData); } catch ( ... ) {} - delete metaData; } } } catch ( ... ) {} diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 4dada88e..8a220139 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -34,6 +34,7 @@ #include "../node/Utils.hpp" #include "../node/Address.hpp" #include "../node/InetAddress.hpp" +#include "../node/NonCopyable.hpp" #include "../osdep/OSUtils.hpp" #include "../osdep/Thread.hpp" @@ -50,7 +51,7 @@ namespace ZeroTier { class Node; -class EmbeddedNetworkController : public NetworkController +class EmbeddedNetworkController : public NetworkController,NonCopyable { public: /** diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index a2fe7f2a..01eb50cd 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -107,9 +107,64 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) } } +bool JSONDB::hasNetwork(const uint64_t networkId) const +{ + Mutex::Lock _l(_networks_m); + std::unordered_map::const_iterator i(_networks.find(networkId)); + return (i != _networks.end()); +} + +bool JSONDB::getNetwork(const uint64_t networkId,nlohmann::json &config) const +{ + Mutex::Lock _l(_networks_m); + std::unordered_map::const_iterator i(_networks.find(networkId)); + if (i == _networks.end()) + return false; + config = i->second.config; + return true; +} + +bool JSONDB::getNetworkSummaryInfo(const uint64_t networkId,NetworkSummaryInfo &ns) const +{ + Mutex::Lock _l(_networks_m); + std::unordered_map::const_iterator i(_networks.find(networkId)); + if (i == _networks.end()) + return false; + ns = i->second.summaryInfo; + return true; +} + +int JSONDB::getNetworkAndMember(const uint64_t networkId,const uint64_t nodeId,nlohmann::json &networkConfig,nlohmann::json &memberConfig,NetworkSummaryInfo &ns) const +{ + Mutex::Lock _l(_networks_m); + std::unordered_map::const_iterator i(_networks.find(networkId)); + if (i == _networks.end()) + return 0; + std::unordered_map::const_iterator j(i->second.members.find(nodeId)); + if (j == i->second.members.end()) + return 1; + networkConfig = i->second.config; + memberConfig = j->second; + ns = i->second.summaryInfo; + return 3; +} + +bool JSONDB::getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlohmann::json &memberConfig) const +{ + Mutex::Lock _l(_networks_m); + std::unordered_map::const_iterator i(_networks.find(networkId)); + if (i == _networks.end()) + return false; + std::unordered_map::const_iterator j(i->second.members.find(nodeId)); + if (j == i->second.members.end()) + return false; + memberConfig = j->second; + return true; +} + void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkConfig) { - char n[256]; + char n[64]; Utils::snprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); writeRaw(n,OSUtils::jsonDump(networkConfig)); { diff --git a/controller/JSONDB.hpp b/controller/JSONDB.hpp index f89ff6c9..8db5cc48 100644 --- a/controller/JSONDB.hpp +++ b/controller/JSONDB.hpp @@ -63,63 +63,18 @@ public: bool writeRaw(const std::string &n,const std::string &obj); - inline bool hasNetwork(const uint64_t networkId) const - { - Mutex::Lock _l(_networks_m); - std::unordered_map::const_iterator i(_networks.find(networkId)); - return (i != _networks.end()); - } + bool hasNetwork(const uint64_t networkId) const; - inline bool getNetwork(const uint64_t networkId,nlohmann::json &config) const - { - Mutex::Lock _l(_networks_m); - std::unordered_map::const_iterator i(_networks.find(networkId)); - if (i == _networks.end()) - return false; - config = i->second.config; - return true; - } + bool getNetwork(const uint64_t networkId,nlohmann::json &config) const; - inline bool getNetworkSummaryInfo(const uint64_t networkId,NetworkSummaryInfo &ns) const - { - Mutex::Lock _l(_networks_m); - std::unordered_map::const_iterator i(_networks.find(networkId)); - if (i == _networks.end()) - return false; - ns = i->second.summaryInfo; - return true; - } + bool getNetworkSummaryInfo(const uint64_t networkId,NetworkSummaryInfo &ns) const; /** * @return Bit mask: 0 == none, 1 == network only, 3 == network and member */ - inline int getNetworkAndMember(const uint64_t networkId,const uint64_t nodeId,nlohmann::json &networkConfig,nlohmann::json &memberConfig,NetworkSummaryInfo &ns) const - { - Mutex::Lock _l(_networks_m); - std::unordered_map::const_iterator i(_networks.find(networkId)); - if (i == _networks.end()) - return 0; - networkConfig = i->second.config; - ns = i->second.summaryInfo; - std::unordered_map::const_iterator j(i->second.members.find(nodeId)); - if (j == i->second.members.end()) - return 1; - memberConfig = j->second; - return 3; - } + int getNetworkAndMember(const uint64_t networkId,const uint64_t nodeId,nlohmann::json &networkConfig,nlohmann::json &memberConfig,NetworkSummaryInfo &ns) const; - inline bool getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlohmann::json &memberConfig) const - { - Mutex::Lock _l(_networks_m); - std::unordered_map::const_iterator i(_networks.find(networkId)); - if (i == _networks.end()) - return false; - std::unordered_map::const_iterator j(i->second.members.find(nodeId)); - if (j == i->second.members.end()) - return false; - memberConfig = j->second; - return true; - } + bool getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlohmann::json &memberConfig) const; void saveNetwork(const uint64_t networkId,const nlohmann::json &networkConfig); diff --git a/ext/json/LICENSE.MIT b/ext/json/LICENSE.MIT index e2ac4891..00599afe 100644 --- a/ext/json/LICENSE.MIT +++ b/ext/json/LICENSE.MIT @@ -1,14 +1,13 @@ -The library is licensed under the MIT License -: +MIT License -Copyright (c) 2013-2016 Niels Lohmann +Copyright (c) 2013-2017 Niels Lohmann -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. diff --git a/ext/json/README.md b/ext/json/README.md index 4bcbe97f..fc6dde9b 100644 --- a/ext/json/README.md +++ b/ext/json/README.md @@ -3,13 +3,34 @@ [![Build Status](https://travis-ci.org/nlohmann/json.svg?branch=master)](https://travis-ci.org/nlohmann/json) [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) [![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json) -[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/fsf5FqYe6GoX68W6) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f3732b3327e34358a0e9d1fe9f661f08)](https://www.codacy.com/app/nlohmann/json?utm_source=github.com&utm_medium=referral&utm_content=nlohmann/json&utm_campaign=Badge_Grade) +[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/nv9fOg0XVVhWmFFy) [![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) [![Github Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) [![Github Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289) +- [Design goals](#design-goals) +- [Integration](#integration) +- [Examples](#examples) + - [JSON as first-class data type](#json-as-first-class-data-type) + - [Serialization / Deserialization](#serialization--deserialization) + - [STL-like access](#stl-like-access) + - [Conversion from STL containers](#conversion-from-stl-containers) + - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch) + - [Implicit conversions](#implicit-conversions) + - [Conversions to/from arbitrary types](#arbitrary-types-conversions) + - [Binary formats (CBOR and MessagePack)](#binary-formats-cbor-and-messagepack) +- [Supported compilers](#supported-compilers) +- [License](#license) +- [Thanks](#thanks) +- [Used third-party tools](#used-third-party-tools) +- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c) +- [Notes](#notes) +- [Execute unit tests](#execute-unit-tests) + ## Design goals There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals: @@ -24,7 +45,7 @@ Other aspects were not so important to us: - **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs. -- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) may be even faster (but would consist of more files which makes the integration harder). +- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set. See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information. @@ -44,9 +65,15 @@ to the files you want to use JSON objects. That's it. Do not forget to set the n :beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`. +:warning: [Version 3.0.0](https://github.com/nlohmann/json/wiki/Road-toward-3.0.0) is currently under development. Branch `develop` is used for the ongoing work and is probably **unstable**. Please use the `master` branch for the last stable version 2.1.1. + ## Examples +Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a602f275f0359ab181221384989810604.html#a602f275f0359ab181221384989810604)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)). + +### JSON as first-class data type + Here are some examples to give you an idea how to use the class. Assume you want to create the JSON object @@ -129,6 +156,8 @@ json array_not_object = { json::array({"currency", "USD"}), json::array({"value" ### Serialization / Deserialization +#### To/from strings + You can create an object (deserialization) by appending `_json` to a string literal: ```cpp @@ -142,8 +171,14 @@ auto j2 = R"( "pi": 3.141 } )"_json; +``` + +Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. -// or explicitly +The above example can also be expressed explicitly using `json::parse()`: + +```cpp +// parse explicitly auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }"); ``` @@ -162,6 +197,8 @@ std::cout << j.dump(4) << std::endl; // } ``` +#### To/from streams (e.g. files, string streams) + You can also use streams to serialize and deserialize: ```cpp @@ -176,10 +213,37 @@ std::cout << j; std::cout << std::setw(4) << j << std::endl; ``` -These operators work for any subclasses of `std::istream` or `std::ostream`. +These operators work for any subclasses of `std::istream` or `std::ostream`. Here is the same example with files: + +```cpp +// read a JSON file +std::ifstream i("file.json"); +json j; +i >> j; + +// write prettified JSON to another file +std::ofstream o("pretty.json"); +o << std::setw(4) << j << std::endl; +``` Please note that setting the exception bit for `failbit` is inappropriate for this use case. It will result in program termination due to the `noexcept` specifier in use. +#### Read from iterator range + +You can also read JSON from an iterator range; that is, from any container accessible by iterators whose content is stored as contiguous byte sequence, for instance a `std::vector`: + +```cpp +std::vector v = {'t', 'r', 'u', 'e'}; +json j = json::parse(v.begin(), v.end()); +``` + +You may leave the iterators for the range [begin, end): + +```cpp +std::vector v = {'t', 'r', 'u', 'e'}; +json j = json::parse(v); +``` + ### STL-like access @@ -192,6 +256,9 @@ j.push_back("foo"); j.push_back(1); j.push_back(true); +// also use emplace_back +j.emplace_back(1.78); + // iterate the array for (json::iterator it = j.begin(); it != j.end(); ++it) { std::cout << *it << '\n'; @@ -207,6 +274,9 @@ const std::string tmp = j[0]; j[1] = 42; bool foo = j.at(2); +// comparison +j == "[\"foo\", 1, true]"_json; // true + // other stuff j.size(); // 3 entries j.empty(); // false @@ -221,15 +291,15 @@ j.is_object(); j.is_array(); j.is_string(); -// comparison -j == "[\"foo\", 1, true]"_json; // true - // create an object json o; o["foo"] = 23; o["bar"] = false; o["baz"] = 3.141; +// also use emplace +o.emplace("weather", "sunny"); + // special iterator member functions for objects for (json::iterator it = o.begin(); it != o.end(); ++it) { std::cout << it.key() << " : " << it.value() << "\n"; @@ -383,6 +453,252 @@ int vi = jn.get(); // etc. ``` +### Arbitrary types conversions + +Every type can be serialized in JSON, not just STL-containers and scalar types. Usually, you would do something along those lines: + +```cpp +namespace ns { + // a simple struct to model a person + struct person { + std::string name; + std::string address; + int age; + }; +} + +ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + +// convert to JSON: copy each value into the JSON object +json j; +j["name"] = p.name; +j["address"] = p.address; +j["age"] = p.age; + +// ... + +// convert from JSON: copy each value from the JSON object +ns::person p { + j["name"].get(), + j["address"].get(), + j["age"].get() +}; +``` + +It works, but that's quite a lot of boilerplate... Fortunately, there's a better way: + +```cpp +// create a person +ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60}; + +// conversion: person -> json +json j = p; + +std::cout << j << std::endl; +// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} + +// conversion: json -> person +ns::person p2 = j; + +// that's it +assert(p == p2); +``` + +#### Basic usage + +To make this work with one of your types, you only need to provide two functions: + +```cpp +using nlohmann::json; + +namespace ns { + void to_json(json& j, const person& p) { + j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}}; + } + + void from_json(const json& j, person& p) { + p.name = j.at("name").get(); + p.address = j.at("address").get(); + p.age = j.at("age").get(); + } +} // namespace ns +``` + +That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. +Likewise, when calling `get()`, the `from_json` method will be called. + +Some important things: + +* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). +* When using `get()`, `your_type` **MUST** be [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). (There is a way to bypass this requirement described later.) +* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exists, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. + +#### How do I convert third-party types? + +This requires a bit more advanced technique. But first, let's see how this conversion mechanism works: + +The library uses **JSON Serializers** to convert types to json. +The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](http://en.cppreference.com/w/cpp/language/adl)). + +It is implemented like this (simplified): + +```cpp +template +struct adl_serializer { + static void to_json(json& j, const T& value) { + // calls the "to_json" method in T's namespace + } + + static void from_json(const json& j, T& value) { + // same thing, but with the "from_json" method + } +}; +``` + +This serializer works fine when you have control over the type's namespace. However, what about `boost::optional`, or `std::filesystem::path` (C++17)? Hijacking the `boost` namespace is pretty bad, and it's illegal to add something other than template specializations to `std`... + +To solve this, you need to add a specialization of `adl_serializer` to the `nlohmann` namespace, here's an example: + +```cpp +// partial specialization (full specialization works too) +namespace nlohmann { + template + struct adl_serializer> { + static void to_json(json& j, const boost::optional& opt) { + if (opt == boost::none) { + j = nullptr; + } else { + j = *opt; // this will call adl_serializer::to_json which will + // find the free function to_json in T's namespace! + } + } + + static void from_json(const json& j, boost::optional& opt) { + if (j.is_null()) { + opt = boost::none; + } else { + opt = j.get(); // same as above, but with + // adl_serializer::from_json + } + } + }; +} +``` + +#### How can I use `get()` for non-default constructible/non-copyable types? + +There is a way, if your type is [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload: + +```cpp +struct move_only_type { + move_only_type() = delete; + move_only_type(int ii): i(ii) {} + move_only_type(const move_only_type&) = delete; + move_only_type(move_only_type&&) = default; + + int i; +}; + +namespace nlohmann { + template <> + struct adl_serializer { + // note: the return type is no longer 'void', and the method only takes + // one argument + static move_only_type from_json(const json& j) { + return {j.get()}; + } + + // Here's the catch! You must provide a to_json method! Otherwise you + // will not be able to convert move_only_type to json, since you fully + // specialized adl_serializer on that type + static void to_json(json& j, move_only_type t) { + j = t.i; + } + }; +} +``` + +#### Can I write my own serializer? (Advanced use) + +Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples. + +If you write your own serializer, you'll need to do a few things: + +* use a different `basic_json` alias than `nlohmann::json` (the last template parameter of `basic_json` is the `JSONSerializer`) +* use your `basic_json` alias (or a template parameter) in all your `to_json`/`from_json` methods +* use `nlohmann::to_json` and `nlohmann::from_json` when you need ADL + +Here is an example, without simplifications, that only accepts types with a size <= 32, and uses ADL. + +```cpp +// You should use void as a second template argument +// if you don't need compile-time checks on T +template::type> +struct less_than_32_serializer { + template + static void to_json(BasicJsonType& j, T value) { + // we want to use ADL, and call the correct to_json overload + using nlohmann::to_json; // this method is called by adl_serializer, + // this is where the magic happens + to_json(j, value); + } + + template + static void from_json(const BasicJsonType& j, T& value) { + // same thing here + using nlohmann::from_json; + from_json(j, value); + } +}; +``` + +Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention: + +```cpp +template +struct bad_serializer +{ + template + static void to_json(BasicJsonType& j, const T& value) { + // this calls BasicJsonType::json_serializer::to_json(j, value); + // if BasicJsonType::json_serializer == bad_serializer ... oops! + j = value; + } + + template + static void to_json(const BasicJsonType& j, T& value) { + // this calls BasicJsonType::json_serializer::from_json(j, value); + // if BasicJsonType::json_serializer == bad_serializer ... oops! + value = j.template get(); // oops! + } +}; +``` + +### Binary formats (CBOR and MessagePack) + +Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [CBOR](http://cbor.io) (Concise Binary Object Representation) and [MessagePack](http://msgpack.org) to efficiently encode JSON values to byte vectors and to decode such vectors. + +```cpp +// create a JSON value +json j = R"({"compact": true, "schema": 0})"_json; + +// serialize to CBOR +std::vector v_cbor = json::to_cbor(j); + +// 0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 + +// roundtrip +json j_from_cbor = json::from_cbor(v_cbor); + +// serialize to MessagePack +std::vector v_msgpack = json::to_msgpack(j); + +// 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 + +// roundtrip +json j_from_msgpack = json::from_msgpack(v_msgpack); +``` + ## Supported compilers @@ -391,6 +707,7 @@ Though it's 2016 already, the support for C++11 is still a bit sparse. Currently - GCC 4.9 - 6.0 (and possibly later) - Clang 3.4 - 3.9 (and possibly later) - Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) +- Microsoft Visual C++ 2017 / Build Tools 15.1.548.43366 (and possibly later) I would be happy to learn about other compilers/versions. @@ -423,16 +740,14 @@ The following compilers are currently used in continuous integration at [Travis] | Clang 3.7.1 | Ubuntu 14.04.4 LTS | clang version 3.7.1 (tags/RELEASE_371/final) | | Clang 3.8.0 | Ubuntu 14.04.4 LTS | clang version 3.8.0 (tags/RELEASE_380/final) | | Clang 3.8.1 | Ubuntu 14.04.4 LTS | clang version 3.8.1 (tags/RELEASE_381/final) | -| Clang Xcode 6.1 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) | -| Clang Xcode 6.2 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) | -| Clang Xcode 6.3 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn) | | Clang Xcode 6.4 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) | -| Clang Xcode 7.1 | Darwin Kernel Version 14.5.0 (OSX 10.10.5) | Apple LLVM version 7.0.0 (clang-700.1.76) | -| Clang Xcode 7.2 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.0.2 (clang-700.1.81) | | Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) | -| Clang Xcode 8.0 | Darwin Kernel Version 15.6.0 (OSX 10.11.6) | Apple LLVM version 8.0.0 (clang-800.0.38) | +| Clang Xcode 8.0 | Darwin Kernel Version 15.6.0 | Apple LLVM version 8.0.0 (clang-800.0.38) | +| Clang Xcode 8.1 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) | +| Clang Xcode 8.2 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) | +| Clang Xcode 8.3 | Darwin Kernel Version 16.5.0 (macOS 10.12.4) | Apple LLVM version 8.1.0 (clang-802.0.38) | | Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 | - +| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.1.548.43366 | ## License @@ -440,7 +755,7 @@ The following compilers are currently used in continuous integration at [Travis] The class is licensed under the [MIT License](http://opensource.org/licenses/MIT): -Copyright © 2013-2016 [Niels Lohmann](http://nlohmann.me) +Copyright © 2013-2017 [Niels Lohmann](http://nlohmann.me) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: @@ -465,7 +780,7 @@ I deeply appreciate the help of the following people. - [Eric Cornelius](https://github.com/EricMCornelius) pointed out a bug in the handling with NaN and infinity values. He also improved the performance of the string escaping. - [易思龙](https://github.com/likebeta) implemented a conversion from anonymous enums. - [kepkin](https://github.com/kepkin) patiently pushed forward the support for Microsoft Visual studio. -- [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. +- [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. In particular, he pushed forward the implementation of user-defined types. - [Caio Luppi](https://github.com/caiovlp) fixed a bug in the Unicode handling. - [dariomt](https://github.com/dariomt) fixed some typos in the examples. - [Daniel Frey](https://github.com/d-frey) cleaned up some pointers and implemented exception-safe memory allocation. @@ -493,14 +808,70 @@ I deeply appreciate the help of the following people. - [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release. - [Damien](https://github.com/dtoma) fixed one of the last conversion warnings. - [Thomas Braun](https://github.com/t-b) fixed a warning in a test case. -- [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). +- [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). He also implemented the magic behind the serialization/deserialization of user-defined types. - [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation. - [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`. - [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion. -- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable. +- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix. - [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file. - -Thanks a lot for helping out! +- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function. +- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing. +- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. +- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. +- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. +- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one. +- [Daniel599](https://github.com/Daniel599) helped to get Travis execute the tests with Clang's sanitizers. +- [Jonathan Lee](https://github.com/vjon) fixed an example in the README file. +- [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types. +- [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio. +- [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types. +- [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example. +- [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. +- [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. +- [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README. +- [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s. +- [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation. +- [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings. +- [Krzysztof Woś](https://github.com/krzysztofwos) made exceptions more visible. +- [ftillier](https://github.com/ftillier) fixed a compiler warning. +- [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped. +- [Fytch](https://github.com/Fytch) found a bug in the documentation. + +Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. + + +## Used third-party tools + +The library itself contains of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot! + +- [**American fuzzy lop**](http://lcamtuf.coredump.cx/afl/) for fuzz testing +- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows +- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code identation +- [**benchpress**](https://github.com/sbs-ableton/benchpress) to benchmark the code +- [**Catch**](https://github.com/philsquared/Catch) for the unit tests +- [**Clang**](http://clang.llvm.org) for compilation with code sanitizers +- [**Cmake**](https://cmake.org) for build automation +- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) +- [**cotire**](https://github.com/sakra/cotire) to speed of compilation +- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json) +- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json) +- [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis +- [**cxxopts**](https://github.com/jarro2783/cxxopts) to let benchpress parse command-line parameters +- [**Doxygen**](http://www.stack.nl/~dimitri/doxygen/) to generate [documentation](https://nlohmann.github.io/json/) +- [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages +- [**Github Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md) +- [**libFuzzer**](http://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz +- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library +- [**re2c**](http://re2c.org) to generate an automaton for the lexical analysis +- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](http://melpon.org/wandbox) +- [**Travis**](https://travis-ci.org) for [continuous integration](https://travis-ci.org/nlohmann/json) on Linux and macOS +- [**Valgrind**](http://valgrind.org) to check for correct memory management +- [**Wandbox**](http://melpon.org/wandbox) for [online examples](http://melpon.org/wandbox/permlink/4NEU6ZZMoM9lpIex) + + +## Projects using JSON for Modern C++ + +The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. ## Notes @@ -512,6 +883,10 @@ Thanks a lot for helping out! - Other encodings such as Latin-1, UTF-16, or UTF-32 are not supported and will yield parse errors. - [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. + - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. +- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. +- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by an `abort()` call. +- By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc7159.html) defines objects as "an unordered collection of zero or more name/value pairs". If you do want to preserve the insertion order, you can specialize the object type with containers like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map). ## Execute unit tests @@ -519,10 +894,11 @@ Thanks a lot for helping out! To compile and run the tests, you need to execute ```sh -$ make check +$ make json_unit -Ctest +$ ./test/json_unit "*" =============================================================================== -All tests passed (8905491 assertions in 36 test cases) +All tests passed (11203022 assertions in 48 test cases) ``` Alternatively, you can use [CMake](https://cmake.org) and run diff --git a/ext/json/json.hpp b/ext/json/json.hpp index 9d48e7a6..8a8b876a 100644 --- a/ext/json/json.hpp +++ b/ext/json/json.hpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.10 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -29,42 +29,39 @@ SOFTWARE. #ifndef NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP -#include // all_of, for_each, transform +#include // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform #include // array #include // assert -#include // isdigit #include // and, not, or -#include // isfinite, ldexp, signbit +#include // lconv, localeconv +#include // isfinite, labs, ldexp, signbit #include // nullptr_t, ptrdiff_t, size_t #include // int64_t, uint64_t -#include // strtod, strtof, strtold, strtoul +#include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull #include // strlen +#include // forward_list #include // function, hash, less #include // initializer_list -#include // setw #include // istream, ostream -#include // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator +#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator #include // numeric_limits #include // locale #include // map #include // addressof, allocator, allocator_traits, unique_ptr #include // accumulate #include // stringstream -#include // domain_error, invalid_argument, out_of_range #include // getline, stoi, string, to_string -#include // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference +#include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type #include // declval, forward, make_pair, move, pair, swap #include // vector // exclude unsupported compilers #if defined(__clang__) - #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) - #if CLANG_VERSION < 30400 + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) - #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - #if GCC_VERSION < 40900 + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif @@ -90,6 +87,17 @@ SOFTWARE. #define JSON_DEPRECATED #endif +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) +#else + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) +#endif + /*! @brief namespace for Niels Lohmann @see https://github.com/nlohmann @@ -98,1466 +106,2175 @@ SOFTWARE. namespace nlohmann { - /*! @brief unnamed namespace with internal helper functions -@since version 1.0.0 + +This namespace collects some functions that could not be defined inside the +@ref basic_json class. + +@since version 2.1.0 */ -namespace +namespace detail { +//////////////// +// exceptions // +//////////////// + /*! -@brief Helper to determine whether there's a key_type for T. +@brief general exception of the @ref basic_json class -Thus helper is used to tell associative containers apart from other containers -such as sequence containers. For instance, `std::map` passes the test as it -contains a `mapped_type`, whereas `std::vector` fails the test. +Extension of std::exception objects with a member @a id for exception ids. -@sa http://stackoverflow.com/a/7728728/266378 -@since version 1.0.0, overworked in version 2.0.6 +@note To have nothrow-copy-constructible exceptions, we internally use + std::runtime_error which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. + +@since version 3.0.0 */ -template -struct has_mapped_type +class exception : public std::exception { + public: + /// returns the explanatory string + virtual const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + exception(int id_, const char* what_arg) + : id(id_), m(what_arg) + {} + + static std::string name(const std::string& ename, int id) + { + return "[json.exception." + ename + "." + std::to_string(id) + "] "; + } + private: - template - static int detect(U&&); + /// an exception object as storage for error messages + std::runtime_error m; +}; - static void detect(...); +/*! +@brief exception indicating a parse error + +This excpetion is thrown by the library when a parse error occurs. Parse +errors can occur during the deserialization of JSON text as well as when +using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +@note For an input with n bytes, 1 is the index of the first character + and n+1 is the index of the terminating null byte or the end of + file. This also holds true when reading a byte vector (CBOR or + MessagePack). + +Exceptions have ids 1xx. + +name / id | example massage | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number wihtout a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.111 | parse error: bad input stream | Parsing CBOR or MessagePack from an input stream where the [`badbit` or `failbit`](http://en.cppreference.com/w/cpp/io/ios_base/iostate) is set. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xf8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. + +@since version 3.0.0 +*/ +class parse_error : public exception +{ public: - static constexpr bool value = - std::is_integral()))>::value; -}; + /*! + @brief create a parse error exception + @param[in] id the id of the exception + @param[in] byte_ the byte index where the error occured (or 0 if + the position cannot be determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id, size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id) + "parse error" + + (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id, byte_, w.c_str()); + } -} + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character + and n+1 is the index of the terminating null byte or the end of + file. This also holds true when reading a byte vector (CBOR or + MessagePack). + */ + const size_t byte; + + private: + parse_error(int id_, size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) + {} +}; /*! -@brief a class to store JSON values +@brief exception indicating errors with iterators + +Exceptions have ids 2xx. + +name / id | example massage | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compated, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + static invalid_iterator create(int id, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id) + what_arg; + return invalid_iterator(id, w.c_str()); + } -@tparam ObjectType type for JSON objects (`std::map` by default; will be used -in @ref object_t) -@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used -in @ref array_t) -@tparam StringType type for JSON strings and object keys (`std::string` by -default; will be used in @ref string_t) -@tparam BooleanType type for JSON booleans (`bool` by default; will be used -in @ref boolean_t) -@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by -default; will be used in @ref number_integer_t) -@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c -`uint64_t` by default; will be used in @ref number_unsigned_t) -@tparam NumberFloatType type for JSON floating-point numbers (`double` by -default; will be used in @ref number_float_t) -@tparam AllocatorType type of the allocator to use (`std::allocator` by -default) + private: + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) + {} +}; -@requirement The class satisfies the following concept requirements: -- Basic - - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null value. - - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): - A JSON value can be constructed from an rvalue argument. - - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): - A JSON value can be copy-constructed from an lvalue expression. - - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable): - A JSON value van be assigned from an rvalue argument. - - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable): - A JSON value can be copy-assigned from an lvalue expression. - - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible): - JSON values can be destructed. -- Layout - - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): - JSON values have - [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the class - has no virtual functions or (virtual) base classes. -- Library-wide - - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): - JSON values can be compared with `==`, see @ref - operator==(const_reference,const_reference). - - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable): - JSON values can be compared with `<`, see @ref - operator<(const_reference,const_reference). - - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable): - Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of - other compatible types, using unqualified function call @ref swap(). - - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer): - JSON values can be compared against `std::nullptr_t` objects which are used - to model the `null` value. -- Container - - [Container](http://en.cppreference.com/w/cpp/concept/Container): - JSON values can be used like STL containers and provide iterator access. - - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer); - JSON values can be used like STL containers and provide reverse iterator - access. +/*! +@brief exception indicating executing a member function with a wrong type + +Exceptions have ids 3xx. + +name / id | example massage | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + static type_error create(int id, const std::string& what_arg) + { + std::string w = exception::name("type_error", id) + what_arg; + return type_error(id, w.c_str()); + } -@invariant The member variables @a m_value and @a m_type have the following -relationship: -- If `m_type == value_t::object`, then `m_value.object != nullptr`. -- If `m_type == value_t::array`, then `m_value.array != nullptr`. -- If `m_type == value_t::string`, then `m_value.string != nullptr`. -The invariants are checked by member function assert_invariant(). + private: + type_error(int id_, const char* what_arg) + : exception(id_, what_arg) + {} +}; -@internal -@note ObjectType trick from http://stackoverflow.com/a/9860911 -@endinternal +/*! +@brief exception indicating access out of the defined range -@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange -Format](http://rfc7159.net/rfc7159) +Exceptions have ids 4xx. -@since version 1.0.0 +name / id | example massage | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -@nosubgrouping +@since version 3.0.0 */ -template < - template class ObjectType = std::map, - template class ArrayType = std::vector, - class StringType = std::string, - class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator - > -class basic_json +class out_of_range : public exception { + public: + static out_of_range create(int id, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id) + what_arg; + return out_of_range(id, w.c_str()); + } + private: - /// workaround type for MSVC - using basic_json_t = basic_json; + out_of_range(int id_, const char* what_arg) + : exception(id_, what_arg) + {} +}; - public: - // forward declarations - template class iter_impl; - template class json_reverse_iterator; - class json_pointer; +/*! +@brief exception indicating other errors - ///////////////////// - // container types // - ///////////////////// +Exceptions have ids 5xx. - /// @name container types - /// The canonic container types to use @ref basic_json like any other STL - /// container. - /// @{ +name / id | example massage | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. - /// the type of elements in a basic_json container - using value_type = basic_json; +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + static other_error create(int id, const std::string& what_arg) + { + std::string w = exception::name("other_error", id) + what_arg; + return other_error(id, w.c_str()); + } - /// the type of an element reference - using reference = value_type&; - /// the type of an element const reference - using const_reference = const value_type&; + private: + other_error(int id_, const char* what_arg) + : exception(id_, what_arg) + {} +}; - /// a type to represent differences between iterators - using difference_type = std::ptrdiff_t; - /// a type to represent container sizes - using size_type = std::size_t; - /// the allocator type - using allocator_type = AllocatorType; - /// the type of an element pointer - using pointer = typename std::allocator_traits::pointer; - /// the type of an element const pointer - using const_pointer = typename std::allocator_traits::const_pointer; +/////////////////////////// +// JSON type enumeration // +/////////////////////////// - /// an iterator for a basic_json container - using iterator = iter_impl; - /// a const iterator for a basic_json container - using const_iterator = iter_impl; - /// a reverse iterator for a basic_json container - using reverse_iterator = json_reverse_iterator; - /// a const reverse iterator for a basic_json container - using const_reverse_iterator = json_reverse_iterator; +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type - /// @} +@since version 1.0.0 +*/ +enum class value_t : uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + discarded ///< discarded by the the parser callback function +}; +/*! +@brief comparison operator for JSON types - /*! - @brief returns the allocator associated with the container - */ - static allocator_type get_allocator() +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string +- furthermore, each type is not smaller than itself + +@since version 1.0.0 +*/ +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + static constexpr std::array order = {{ + 0, // null + 3, // object + 4, // array + 5, // string + 1, // boolean + 2, // integer + 2, // unsigned + 2, // float + } + }; + + // discarded values are not comparable + if (lhs == value_t::discarded or rhs == value_t::discarded) { - return allocator_type(); + return false; } + return order[static_cast(lhs)] < + order[static_cast(rhs)]; +} - /////////////////////////// - // JSON value data types // - /////////////////////////// - /// @name JSON value data types - /// The data types to store a JSON value. These types are derived from - /// the template arguments passed to class @ref basic_json. - /// @{ +///////////// +// helpers // +///////////// - /*! - @brief a type for an object +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: - > An object is an unordered collection of zero or more name/value pairs, - > where a name is a string and a value is a string, number, boolean, null, - > object, or array. +template +using uncvref_t = typename std::remove_cv::type>::type; - To store objects in C++, a type is defined by the template parameters - described below. +/* +Implementation of two C++17 constructs: conjunction, negation. This is needed +to avoid evaluating all the traits in a condition - @tparam ObjectType the container to store objects (e.g., `std::map` or - `std::unordered_map`) - @tparam StringType the type of the keys or names (e.g., `std::string`). - The comparison function `std::less` is used to order elements - inside the container. - @tparam AllocatorType the allocator to use for objects (e.g., - `std::allocator`) +For example: not std::is_same::value and has_value_type::value +will not compile when T = void (on MSVC at least). Whereas +conjunction>, has_value_type>::value will +stop evaluating if negation<...>::value == false - #### Default type +Please note that those constructs must be used with caution, since symbols can +become very long quickly (which can slow down compilation and cause MSVC +internal compiler errors). Only use it when you have to (see example ahead). +*/ +template struct conjunction : std::true_type {}; +template struct conjunction : B1 {}; +template +struct conjunction : std::conditional, B1>::type {}; - With the default values for @a ObjectType (`std::map`), @a StringType - (`std::string`), and @a AllocatorType (`std::allocator`), the default - value for @a object_t is: +template struct negation : std::integral_constant < bool, !B::value > {}; - @code {.cpp} - std::map< - std::string, // key_type - basic_json, // value_type - std::less, // key_compare - std::allocator> // allocator_type - > - @endcode +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; - #### Behavior - The choice of @a object_t influences the behavior of the JSON class. With - the default type, objects have the following behavior: +////////////////// +// constructors // +////////////////// - - When all names are unique, objects will be interoperable in the sense - that all software implementations receiving that object will agree on - the name-value mappings. - - When the names within an object are not unique, later stored name/value - pairs overwrite previously stored name/value pairs, leaving the used - names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will - be treated as equal and both stored as `{"key": 1}`. - - Internally, name/value pairs are stored in lexicographical order of the - names. Objects will also be serialized (see @ref dump) in this order. - For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored - and serialized as `{"a": 2, "b": 1}`. - - When comparing objects, the order of the name/value pairs is irrelevant. - This makes objects interoperable in the sense that they will not be - affected by these differences. For instance, `{"b": 1, "a": 2}` and - `{"a": 2, "b": 1}` will be treated as equal. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the object's limit of nesting is not constraint explicitly. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON object. +template struct external_constructor; - #### Storage - - Objects are stored as pointers in a @ref basic_json type. That is, for any - access to object values, a pointer of type `object_t*` must be - dereferenced. +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } +}; - @sa @ref array_t -- type for an array value +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } +}; - @since version 1.0.0 +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } +}; - @note The order name/value pairs are added to the object is *not* - preserved by the library. Therefore, iterating an object may return - name/value pairs in a different order than they were originally stored. In - fact, keys will be traversed in alphabetical order as `std::map` with - `std::less` is used by default. Please note this behavior conforms to [RFC - 7159](http://rfc7159.net/rfc7159), because any order implements the - specified "unordered" nature of JSON objects. - */ - using object_t = ObjectType, - AllocatorType>>; +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; - /*! - @brief a type for an array +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } +}; - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: - > An array is an ordered sequence of zero or more values. +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_type = value_t::array; + j.m_value = arr; + j.assert_invariant(); + } - To store objects in C++, a type is defined by the template parameters - explained below. + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.assert_invariant(); + } - @tparam ArrayType container type to store arrays (e.g., `std::vector` or - `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (bool x : arr) + { + j.m_value.array->push_back(x); + } + j.assert_invariant(); + } +}; - #### Default type +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_type = value_t::object; + j.m_value = obj; + j.assert_invariant(); + } - With the default values for @a ArrayType (`std::vector`) and @a - AllocatorType (`std::allocator`), the default value for @a array_t is: + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; - @code {.cpp} - std::vector< - basic_json, // value_type - std::allocator // allocator_type - > - @endcode + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.assert_invariant(); + } +}; - #### Limits - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. +//////////////////////// +// has_/is_ functions // +//////////////////////// - In this class, the array's limit of nesting is not constraint explicitly. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON array. +/*! +@brief Helper to determine whether there's a key_type for T. - #### Storage +This helper is used to tell associative containers apart from other containers +such as sequence containers. For instance, `std::map` passes the test as it +contains a `mapped_type`, whereas `std::vector` fails the test. - Arrays are stored as pointers in a @ref basic_json type. That is, for any - access to array values, a pointer of type `array_t*` must be dereferenced. +@sa http://stackoverflow.com/a/7728728/266378 +@since version 1.0.0, overworked in version 2.0.6 +*/ +#define NLOHMANN_JSON_HAS_HELPER(type) \ + template struct has_##type { \ + private: \ + template \ + static int detect(U &&); \ + static void detect(...); \ + public: \ + static constexpr bool value = \ + std::is_integral()))>::value; \ + } - @sa @ref object_t -- type for an object value +NLOHMANN_JSON_HAS_HELPER(mapped_type); +NLOHMANN_JSON_HAS_HELPER(key_type); +NLOHMANN_JSON_HAS_HELPER(value_type); +NLOHMANN_JSON_HAS_HELPER(iterator); - @since version 1.0.0 - */ - using array_t = ArrayType>; +#undef NLOHMANN_JSON_HAS_HELPER - /*! - @brief a type for a string - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: - > A string is a sequence of zero or more Unicode characters. +template +struct is_compatible_object_type_impl : std::false_type {}; - To store objects in C++, a type is defined by the template parameter - described below. Unicode values are split by the JSON class into - byte-sized characters during deserialization. +template +struct is_compatible_object_type_impl +{ + static constexpr auto value = + std::is_constructible::value and + std::is_constructible::value; +}; - @tparam StringType the container to store strings (e.g., `std::string`). - Note this container is used for keys/names in objects, see @ref object_t. +template +struct is_compatible_object_type +{ + static auto constexpr value = is_compatible_object_type_impl < + conjunction>, + has_mapped_type, + has_key_type>::value, + typename BasicJsonType::object_t, CompatibleObjectType >::value; +}; - #### Default type +template +struct is_basic_json_nested_type +{ + static auto constexpr value = std::is_same::value or + std::is_same::value or + std::is_same::value or + std::is_same::value or + std::is_same::value; +}; - With the default values for @a StringType (`std::string`), the default - value for @a string_t is: +template +struct is_compatible_array_type +{ + static auto constexpr value = + conjunction>, + negation>, + negation>, + negation>, + has_value_type, + has_iterator>::value; +}; - @code {.cpp} - std::string - @endcode +template +struct is_compatible_integer_type_impl : std::false_type {}; - #### String comparison +template +struct is_compatible_integer_type_impl +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + std::is_constructible::value and + CompatibleLimits::is_integer and + RealLimits::is_signed == CompatibleLimits::is_signed; +}; - [RFC 7159](http://rfc7159.net/rfc7159) states: - > Software implementations are typically required to test names of object - > members for equality. Implementations that transform the textual - > representation into sequences of Unicode code units and then perform the - > comparison numerically, code unit by code unit, are interoperable in the - > sense that implementations will agree in all cases on equality or - > inequality of two strings. For example, implementations that compare - > strings with escaped characters unconverted may incorrectly find that - > `"a\\b"` and `"a\u005Cb"` are not equal. +template +struct is_compatible_integer_type +{ + static constexpr auto value = + is_compatible_integer_type_impl < + std::is_integral::value and + not std::is_same::value, + RealIntegerType, CompatibleNumberIntegerType > ::value; +}; - This implementation is interoperable as it does compare strings code unit - by code unit. - #### Storage +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json +{ + private: + // also check the return type of from_json + template::from_json( + std::declval(), std::declval()))>::value>> + static int detect(U&&); + static void detect(...); - String values are stored as pointers in a @ref basic_json type. That is, - for any access to string values, a pointer of type `string_t*` must be - dereferenced. + public: + static constexpr bool value = std::is_integral>()))>::value; +}; - @since version 1.0.0 - */ - using string_t = StringType; +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json +{ + private: + template < + typename U, + typename = enable_if_t::from_json(std::declval()))>::value >> + static int detect(U&&); + static void detect(...); - /*! - @brief a type for a boolean + public: + static constexpr bool value = std::is_integral>()))>::value; +}; - [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a - type which differentiates the two literals `true` and `false`. +// This trait checks if BasicJsonType::json_serializer::to_json exists +template +struct has_to_json +{ + private: + template::to_json( + std::declval(), std::declval()))> + static int detect(U&&); + static void detect(...); - To store objects in C++, a type is defined by the template parameter @a - BooleanType which chooses the type to use. + public: + static constexpr bool value = std::is_integral>()))>::value; +}; - #### Default type - With the default values for @a BooleanType (`bool`), the default value for - @a boolean_t is: +///////////// +// to_json // +///////////// - @code {.cpp} - bool - @endcode +template::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor::construct(j, b); +} - #### Storage +template::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor::construct(j, s); +} - Boolean values are stored directly inside a @ref basic_json type. +template::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} - @since version 1.0.0 - */ - using boolean_t = BooleanType; +template < + typename BasicJsonType, typename CompatibleNumberUnsignedType, + enable_if_t::value, int> = 0 > +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} - /*! - @brief a type for a number (integer) +template < + typename BasicJsonType, typename CompatibleNumberIntegerType, + enable_if_t::value, int> = 0 > +void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. +template::value, int> = 0> +void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); +} - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} - To store integer numbers in C++, a type is defined by the template - parameter @a NumberIntegerType which chooses the type to use. +template < + typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < + is_compatible_array_type::value or + std::is_same::value, + int > = 0 > +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} - #### Default type +template < + typename BasicJsonType, typename CompatibleObjectType, + enable_if_t::value, + int> = 0 > +void to_json(BasicJsonType& j, const CompatibleObjectType& arr) +{ + external_constructor::construct(j, arr); +} - With the default values for @a NumberIntegerType (`int64_t`), the default - value for @a number_integer_t is: +template ::value, + int> = 0> +void to_json(BasicJsonType& j, T (&arr)[N]) +{ + external_constructor::construct(j, arr); +} - @code {.cpp} - int64_t - @endcode +/////////////// +// from_json // +/////////////// + +// overloads for basic_json template parameters +template::value and + not std::is_same::value, + int> = 0> +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast( + *j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast( + *j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast( + *j.template get_ptr()); + break; + } + default: + { + JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name())); + } + } +} - #### Default behavior +template +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (not j.is_boolean()) + { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + j.type_name())); + } + b = *j.template get_ptr(); +} - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. +template +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (not j.is_string()) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + j.type_name())); + } + s = *j.template get_ptr(); +} - #### Limits +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} - When the default type is used, the maximal integer number that can be - stored is `9223372036854775807` (INT64_MAX) and the minimal integer number - that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers - that are out of range will yield over/underflow when used in a - constructor. During deserialization, too large or small integer numbers - will be automatically be stored as @ref number_unsigned_t or @ref - number_float_t. +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. +template::value, int> = 0> +void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} - As this range is a subrange of the exactly supported range [INT64_MIN, - INT64_MAX], this class's integer type is interoperable. +template +void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) +{ + if (not j.is_array()) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); + } + arr = *j.template get_ptr(); +} - #### Storage +// forward_list doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (not j.is_array()) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); + } - Integer number values are stored directly inside a @ref basic_json type. + for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) + { + l.push_front(it->template get()); + } +} - @sa @ref number_float_t -- type for number values (floating-point) +template +void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>) +{ + using std::begin; + using std::end; - @sa @ref number_unsigned_t -- type for number values (unsigned integer) + std::transform(j.begin(), j.end(), + std::inserter(arr, end(arr)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); +} - @since version 1.0.0 - */ - using number_integer_t = NumberIntegerType; +template +auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>) +-> decltype( + arr.reserve(std::declval()), + void()) +{ + using std::begin; + using std::end; - /*! - @brief a type for a number (unsigned) + arr.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(arr, end(arr)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); +} - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. +template::value and + std::is_convertible::value and + not std::is_same::value, int> = 0> +void from_json(const BasicJsonType& j, CompatibleArrayType& arr) +{ + if (not j.is_array()) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); + } - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. + from_json_array_impl(j, arr, priority_tag<1> {}); +} - To store unsigned integer numbers in C++, a type is defined by the - template parameter @a NumberUnsignedType which chooses the type to use. +template::value, int> = 0> +void from_json(const BasicJsonType& j, CompatibleObjectType& obj) +{ + if (not j.is_object()) + { + JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name())); + } - #### Default type + auto inner_object = j.template get_ptr(); + using std::begin; + using std::end; + // we could avoid the assignment, but this might require a for loop, which + // might be less efficient than the container constructor for some + // containers (would it?) + obj = CompatibleObjectType(begin(*inner_object), end(*inner_object)); +} - With the default values for @a NumberUnsignedType (`uint64_t`), the - default value for @a number_unsigned_t is: +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value, + int> = 0> +void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } + default: + { + JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name())); + } + } +} - @code {.cpp} - uint64_t - @endcode +struct to_json_fn +{ + private: + template + auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } - #### Default behavior + template + void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept + { + static_assert(sizeof(BasicJsonType) == 0, + "could not find to_json() method in T's namespace"); + } - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. + public: + template + void operator()(BasicJsonType& j, T&& val) const + noexcept(noexcept(std::declval().call(j, std::forward(val), priority_tag<1> {}))) + { + return call(j, std::forward(val), priority_tag<1> {}); + } +}; - #### Limits +struct from_json_fn +{ + private: + template + auto call(const BasicJsonType& j, T& val, priority_tag<1>) const + noexcept(noexcept(from_json(j, val))) + -> decltype(from_json(j, val), void()) + { + return from_json(j, val); + } - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. + template + void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept + { + static_assert(sizeof(BasicJsonType) == 0, + "could not find from_json() method in T's namespace"); + } - When the default type is used, the maximal integer number that can be - stored is `18446744073709551615` (UINT64_MAX) and the minimal integer - number that can be stored is `0`. Integer numbers that are out of range - will yield over/underflow when used in a constructor. During - deserialization, too large or small integer numbers will be automatically - be stored as @ref number_integer_t or @ref number_float_t. + public: + template + void operator()(const BasicJsonType& j, T& val) const + noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) + { + return call(j, val, priority_tag<1> {}); + } +}; - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; - As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. +template +constexpr T static_const::value; +} // namespace detail - #### Storage - Integer number values are stored directly inside a @ref basic_json type. +/// namespace to hold default `to_json` / `from_json` functions +namespace +{ +constexpr const auto& to_json = detail::static_const::value; +constexpr const auto& from_json = detail::static_const::value; +} - @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref number_integer_t -- type for number values (integer) - @since version 2.0.0 - */ - using number_unsigned_t = NumberUnsignedType; +/*! +@brief default JSONSerializer template argument +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer +{ /*! - @brief a type for a number (floating-point) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store floating-point numbers in C++, a type is defined by the template - parameter @a NumberFloatType which chooses the type to use. - - #### Default type - - With the default values for @a NumberFloatType (`double`), the default - value for @a number_float_t is: - - @code {.cpp} - double - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in floating-point literals will be ignored. Internally, - the value will be stored as decimal number. For instance, the C++ - floating-point literal `01.2` will be serialized to `1.2`. During - deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > This specification allows implementations to set limits on the range and - > precision of numbers accepted. Since software that implements IEEE - > 754-2008 binary64 (double precision) numbers is generally available and - > widely used, good interoperability can be achieved by implementations - > that expect no more precision or range than these provide, in the sense - > that implementations will approximate JSON numbers within the expected - > precision. - - This implementation does exactly follow this approach, as it uses double - precision floating-point numbers. Note values smaller than - `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` - will be stored as NaN internally and be serialized to `null`. - - #### Storage - - Floating-point number values are stored directly inside a @ref basic_json - type. - - @sa @ref number_integer_t -- type for number values (integer) + @brief convert a JSON value to any value type - @sa @ref number_unsigned_t -- type for number values (unsigned integer) + This function is usually called by the `get()` function of the + @ref basic_json class (either explicit or via conversion operators). - @since version 1.0.0 + @param[in] j JSON value to read from + @param[in,out] val value to write to */ - using number_float_t = NumberFloatType; - - /// @} - - - /////////////////////////// - // JSON type enumeration // - /////////////////////////// + template + static void from_json(BasicJsonType&& j, ValueType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + { + ::nlohmann::from_json(std::forward(j), val); + } /*! - @brief the JSON type enumeration + @brief convert any value type to a JSON value - This enumeration collects the different JSON types. It is internally used - to distinguish the stored values, and the functions @ref is_null(), @ref - is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref - is_number() (with @ref is_number_integer(), @ref is_number_unsigned(), and - @ref is_number_float()), @ref is_discarded(), @ref is_primitive(), and - @ref is_structured() rely on it. + This function is usually called by the constructors of the @ref basic_json + class. - @note There are three enumeration entries (number_integer, - number_unsigned, and number_float), because the library distinguishes - these three types for numbers: @ref number_unsigned_t is used for unsigned - integers, @ref number_integer_t is used for signed integers, and @ref - number_float_t is used for floating-point numbers or to approximate - integers which do not fit in the limits of their respective type. + @param[in,out] j JSON value to write to + @param[in] val value to read from + */ + template + static void to_json(BasicJsonType& j, ValueType&& val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; - @sa @ref basic_json(const value_t value_type) -- create a JSON value with - the default value for a given type - @since version 1.0.0 - */ - enum class value_t : uint8_t - { - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - discarded ///< discarded by the the parser callback function - }; +/*! +@brief a class to store JSON values + +@tparam ObjectType type for JSON objects (`std::map` by default; will be used +in @ref object_t) +@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used +in @ref array_t) +@tparam StringType type for JSON strings and object keys (`std::string` by +default; will be used in @ref string_t) +@tparam BooleanType type for JSON booleans (`bool` by default; will be used +in @ref boolean_t) +@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by +default; will be used in @ref number_integer_t) +@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c +`uint64_t` by default; will be used in @ref number_unsigned_t) +@tparam NumberFloatType type for JSON floating-point numbers (`double` by +default; will be used in @ref number_float_t) +@tparam AllocatorType type of the allocator to use (`std::allocator` by +default) +@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` +and `from_json()` (@ref adl_serializer by default) + +@requirement The class satisfies the following concept requirements: +- Basic + - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): + JSON values can be default constructed. The result will be a JSON null + value. + - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): + A JSON value can be constructed from an rvalue argument. + - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): + A JSON value can be copy-constructed from an lvalue expression. + - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable): + A JSON value van be assigned from an rvalue argument. + - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable): + A JSON value can be copy-assigned from an lvalue expression. + - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible): + JSON values can be destructed. +- Layout + - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): + JSON values have + [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): + All non-static data members are private and standard layout types, the + class has no virtual functions or (virtual) base classes. +- Library-wide + - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): + JSON values can be compared with `==`, see @ref + operator==(const_reference,const_reference). + - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable): + JSON values can be compared with `<`, see @ref + operator<(const_reference,const_reference). + - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable): + Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of + other compatible types, using unqualified function call @ref swap(). + - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer): + JSON values can be compared against `std::nullptr_t` objects which are used + to model the `null` value. +- Container + - [Container](http://en.cppreference.com/w/cpp/concept/Container): + JSON values can be used like STL containers and provide iterator access. + - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer); + JSON values can be used like STL containers and provide reverse iterator + access. +@invariant The member variables @a m_value and @a m_type have the following +relationship: +- If `m_type == value_t::object`, then `m_value.object != nullptr`. +- If `m_type == value_t::array`, then `m_value.array != nullptr`. +- If `m_type == value_t::string`, then `m_value.string != nullptr`. +The invariants are checked by member function assert_invariant(). + +@internal +@note ObjectType trick from http://stackoverflow.com/a/9860911 +@endinternal + +@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange +Format](http://rfc7159.net/rfc7159) + +@since version 1.0.0 +@nosubgrouping +*/ +template < + template class ObjectType = std::map, + template class ArrayType = std::vector, + class StringType = std::string, + class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = adl_serializer + > +class basic_json +{ private: + template friend struct detail::external_constructor; + /// workaround type for MSVC + using basic_json_t = basic_json; - /// helper for exception-safe object creation - template - static T* create(Args&& ... args) + public: + using value_t = detail::value_t; + // forward declarations + template class iter_impl; + template class json_reverse_iterator; + class json_pointer; + template + using json_serializer = JSONSerializer; + + + //////////////// + // exceptions // + //////////////// + + /// @name exceptions + /// Classes to implement user-defined exceptions. + /// @{ + + /// @copydoc detail::exception + using exception = detail::exception; + /// @copydoc detail::parse_error + using parse_error = detail::parse_error; + /// @copydoc detail::invalid_iterator + using invalid_iterator = detail::invalid_iterator; + /// @copydoc detail::type_error + using type_error = detail::type_error; + /// @copydoc detail::out_of_range + using out_of_range = detail::out_of_range; + /// @copydoc detail::other_error + using other_error = detail::other_error; + + /// @} + + + ///////////////////// + // container types // + ///////////////////// + + /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. + /// @{ + + /// the type of elements in a basic_json container + using value_type = basic_json; + + /// the type of an element reference + using reference = value_type&; + /// the type of an element const reference + using const_reference = const value_type&; + + /// a type to represent differences between iterators + using difference_type = std::ptrdiff_t; + /// a type to represent container sizes + using size_type = std::size_t; + + /// the allocator type + using allocator_type = AllocatorType; + + /// the type of an element pointer + using pointer = typename std::allocator_traits::pointer; + /// the type of an element const pointer + using const_pointer = typename std::allocator_traits::const_pointer; + + /// an iterator for a basic_json container + using iterator = iter_impl; + /// a const iterator for a basic_json container + using const_iterator = iter_impl; + /// a reverse iterator for a basic_json container + using reverse_iterator = json_reverse_iterator; + /// a const reverse iterator for a basic_json container + using const_reverse_iterator = json_reverse_iterator; + + /// @} + + + /*! + @brief returns the allocator associated with the container + */ + static allocator_type get_allocator() { - AllocatorType alloc; - auto deleter = [&](T * object) - { - alloc.deallocate(object, 1); - }; - std::unique_ptr object(alloc.allocate(1), deleter); - alloc.construct(object.get(), std::forward(args)...); - assert(object.get() != nullptr); - return object.release(); + return allocator_type(); } - //////////////////////// - // JSON value storage // - //////////////////////// - /*! - @brief a JSON value + @brief returns version information on the library - The actual storage for a JSON value of the @ref basic_json class. This - union combines the different storage types for the JSON value types - defined in @ref value_t. + This function returns a JSON object with information about the library, + including the version number and information on the platform and compiler. - JSON type | value_t type | used type - --------- | --------------- | ------------------------ - object | object | pointer to @ref object_t - array | array | pointer to @ref array_t - string | string | pointer to @ref string_t - boolean | boolean | @ref boolean_t - number | number_integer | @ref number_integer_t - number | number_unsigned | @ref number_unsigned_t - number | number_float | @ref number_float_t - null | null | *no value is stored* + @return JSON object holding version information + key | description + ----------- | --------------- + `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). + `copyright` | The copyright line for the library as string. + `name` | The name of the library as string. + `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. + `url` | The URL of the project as string. + `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). - @note Variable-length types (objects, arrays, and strings) are stored as - pointers. The size of the union should not exceed 64 bits if the default - value types are used. + @liveexample{The following code shows an example output of the `meta()` + function.,meta} - @since version 1.0.0 + @complexity Constant. + + @since 2.1.0 */ - union json_value + static basic_json meta() { - /// object (stored with pointer to save storage) - object_t* object; - /// array (stored with pointer to save storage) - array_t* array; - /// string (stored with pointer to save storage) - string_t* string; - /// boolean - boolean_t boolean; - /// number (integer) - number_integer_t number_integer; - /// number (unsigned integer) - number_unsigned_t number_unsigned; - /// number (floating-point) - number_float_t number_float; + basic_json result; - /// default constructor (for null values) - json_value() = default; - /// constructor for booleans - json_value(boolean_t v) noexcept : boolean(v) {} - /// constructor for numbers (integer) - json_value(number_integer_t v) noexcept : number_integer(v) {} - /// constructor for numbers (unsigned) - json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} - /// constructor for numbers (floating-point) - json_value(number_float_t v) noexcept : number_float(v) {} - /// constructor for empty values of a given type - json_value(value_t t) + result["copyright"] = "(C) 2013-2017 Niels Lohmann"; + result["name"] = "JSON for Modern C++"; + result["url"] = "https://github.com/nlohmann/json"; + result["version"] = { - switch (t) - { - case value_t::object: - { - object = create(); - break; - } + {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, {"patch", 1} + }; - case value_t::array: - { - array = create(); - break; - } +#ifdef _WIN32 + result["platform"] = "win32"; +#elif defined __linux__ + result["platform"] = "linux"; +#elif defined __APPLE__ + result["platform"] = "apple"; +#elif defined __unix__ + result["platform"] = "unix"; +#else + result["platform"] = "unknown"; +#endif - case value_t::string: - { - string = create(""); - break; - } +#if defined(__clang__) + result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; +#elif defined(__ICC) || defined(__INTEL_COMPILER) + result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; +#elif defined(__GNUC__) || defined(__GNUG__) + result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; +#elif defined(__HP_cc) || defined(__HP_aCC) + result["compiler"] = "hp" +#elif defined(__IBMCPP__) + result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; +#elif defined(_MSC_VER) + result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; +#elif defined(__PGI) + result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; +#elif defined(__SUNPRO_CC) + result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; +#else + result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; +#endif - case value_t::boolean: - { - boolean = boolean_t(false); - break; - } +#ifdef __cplusplus + result["compiler"]["c++"] = std::to_string(__cplusplus); +#else + result["compiler"]["c++"] = "unknown"; +#endif + return result; + } - case value_t::number_integer: - { - number_integer = number_integer_t(0); - break; - } - case value_t::number_unsigned: - { - number_unsigned = number_unsigned_t(0); - break; - } + /////////////////////////// + // JSON value data types // + /////////////////////////// - case value_t::number_float: - { - number_float = number_float_t(0.0); - break; - } + /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. + /// @{ - case value_t::null: - { - break; - } + /*! + @brief a type for an object - default: - { - if (t == value_t::null) - { - throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.0.10"); // LCOV_EXCL_LINE - } - break; - } - } - } + [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: + > An object is an unordered collection of zero or more name/value pairs, + > where a name is a string and a value is a string, number, boolean, null, + > object, or array. - /// constructor for strings - json_value(const string_t& value) - { - string = create(value); - } + To store objects in C++, a type is defined by the template parameters + described below. - /// constructor for objects - json_value(const object_t& value) - { - object = create(value); - } + @tparam ObjectType the container to store objects (e.g., `std::map` or + `std::unordered_map`) + @tparam StringType the type of the keys or names (e.g., `std::string`). + The comparison function `std::less` is used to order elements + inside the container. + @tparam AllocatorType the allocator to use for objects (e.g., + `std::allocator`) - /// constructor for arrays - json_value(const array_t& value) - { - array = create(value); - } - }; + #### Default type - /*! - @brief checks the class invariants + With the default values for @a ObjectType (`std::map`), @a StringType + (`std::string`), and @a AllocatorType (`std::allocator`), the default + value for @a object_t is: - This function asserts the class invariants. It needs to be called at the - end of every constructor to make sure that created objects respect the - invariant. Furthermore, it has to be called each time the type of a JSON - value is changed, because the invariant expresses a relationship between - @a m_type and @a m_value. - */ - void assert_invariant() const - { - assert(m_type != value_t::object or m_value.object != nullptr); - assert(m_type != value_t::array or m_value.array != nullptr); - assert(m_type != value_t::string or m_value.string != nullptr); - } + @code {.cpp} + std::map< + std::string, // key_type + basic_json, // value_type + std::less, // key_compare + std::allocator> // allocator_type + > + @endcode - public: - ////////////////////////// - // JSON parser callback // - ////////////////////////// + #### Behavior - /*! - @brief JSON callback events + The choice of @a object_t influences the behavior of the JSON class. With + the default type, objects have the following behavior: - This enumeration lists the parser events that can trigger calling a - callback function of type @ref parser_callback_t during parsing. + - When all names are unique, objects will be interoperable in the sense + that all software implementations receiving that object will agree on + the name-value mappings. + - When the names within an object are not unique, later stored name/value + pairs overwrite previously stored name/value pairs, leaving the used + names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will + be treated as equal and both stored as `{"key": 1}`. + - Internally, name/value pairs are stored in lexicographical order of the + names. Objects will also be serialized (see @ref dump) in this order. + For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored + and serialized as `{"a": 2, "b": 1}`. + - When comparing objects, the order of the name/value pairs is irrelevant. + This makes objects interoperable in the sense that they will not be + affected by these differences. For instance, `{"b": 1, "a": 2}` and + `{"a": 2, "b": 1}` will be treated as equal. - @image html callback_events.png "Example when certain parse events are triggered" + #### Limits - @since version 1.0.0 - */ - enum class parse_event_t : uint8_t - { - /// the parser read `{` and started to process a JSON object - object_start, - /// the parser read `}` and finished processing a JSON object - object_end, - /// the parser read `[` and started to process a JSON array - array_start, - /// the parser read `]` and finished processing a JSON array - array_end, - /// the parser read a key of a value in an object - key, - /// the parser finished reading a JSON value - value - }; + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the maximum depth of nesting. + + In this class, the object's limit of nesting is not constraint explicitly. + However, a maximum depth of nesting may be introduced by the compiler or + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON object. + + #### Storage + + Objects are stored as pointers in a @ref basic_json type. That is, for any + access to object values, a pointer of type `object_t*` must be + dereferenced. + + @sa @ref array_t -- type for an array value + + @since version 1.0.0 + + @note The order name/value pairs are added to the object is *not* + preserved by the library. Therefore, iterating an object may return + name/value pairs in a different order than they were originally stored. In + fact, keys will be traversed in alphabetical order as `std::map` with + `std::less` is used by default. Please note this behavior conforms to [RFC + 7159](http://rfc7159.net/rfc7159), because any order implements the + specified "unordered" nature of JSON objects. + */ + using object_t = ObjectType, + AllocatorType>>; /*! - @brief per-element parser callback type + @brief a type for an array - With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse(std::istream&, const - parser_callback_t) or @ref parse(const CharT, const parser_callback_t), - it is called on certain events (passed as @ref parse_event_t via parameter - @a event) with a set recursion depth @a depth and context JSON value - @a parsed. The return value of the callback function is a boolean - indicating whether the element that emitted the callback shall be kept or - not. + [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: + > An array is an ordered sequence of zero or more values. - We distinguish six scenarios (determined by the event type) in which the - callback function can be called. The following table describes the values - of the parameters @a depth, @a event, and @a parsed. + To store objects in C++, a type is defined by the template parameters + explained below. - parameter @a event | description | parameter @a depth | parameter @a parsed - ------------------ | ----------- | ------------------ | ------------------- - parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded - parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key - parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object - parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded - parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array - parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value + @tparam ArrayType container type to store arrays (e.g., `std::vector` or + `std::list`) + @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) - @image html callback_events.png "Example when certain parse events are triggered" + #### Default type - Discarding a value (i.e., returning `false`) has different effects - depending on the context in which function was called: + With the default values for @a ArrayType (`std::vector`) and @a + AllocatorType (`std::allocator`), the default value for @a array_t is: - - Discarded values in structured types are skipped. That is, the parser - will behave as if the discarded value was never read. - - In case a value outside a structured type is skipped, it is replaced - with `null`. This case happens if the top-level element is skipped. + @code {.cpp} + std::vector< + basic_json, // value_type + std::allocator // allocator_type + > + @endcode - @param[in] depth the depth of the recursion during parsing + #### Limits - @param[in] event an event of type parse_event_t indicating the context in - the callback function has been called + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the maximum depth of nesting. - @param[in,out] parsed the current intermediate parse result; note that - writing to this value has no effect for parse_event_t::key events + In this class, the array's limit of nesting is not constraint explicitly. + However, a maximum depth of nesting may be introduced by the compiler or + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON array. - @return Whether the JSON value which called the function during parsing - should be kept (`true`) or not (`false`). In the latter case, it is either - skipped completely or replaced by an empty discarded object. + #### Storage - @sa @ref parse(std::istream&, parser_callback_t) or - @ref parse(const CharT, const parser_callback_t) for examples + Arrays are stored as pointers in a @ref basic_json type. That is, for any + access to array values, a pointer of type `array_t*` must be dereferenced. + + @sa @ref object_t -- type for an object value @since version 1.0.0 */ - using parser_callback_t = std::function; + using array_t = ArrayType>; + /*! + @brief a type for a string - ////////////////// - // constructors // - ////////////////// + [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: + > A string is a sequence of zero or more Unicode characters. - /// @name constructors and destructors - /// Constructors of class @ref basic_json, copy/move constructor, copy - /// assignment, static functions creating objects, and the destructor. - /// @{ + To store objects in C++, a type is defined by the template parameter + described below. Unicode values are split by the JSON class into + byte-sized characters during deserialization. - /*! - @brief create an empty value with a given type + @tparam StringType the container to store strings (e.g., `std::string`). + Note this container is used for keys/names in objects, see @ref object_t. - Create an empty JSON value with a given type. The value will be default - initialized with an empty value which depends on the type: + #### Default type - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` + With the default values for @a StringType (`std::string`), the default + value for @a string_t is: - @param[in] value_type the type of the value to create + @code {.cpp} + std::string + @endcode - @complexity Constant. + #### Encoding - @throw std::bad_alloc if allocation for object, array, or string value - fails + Strings are stored in UTF-8 encoding. Therefore, functions like + `std::string::size()` or `std::string::length()` return the number of + bytes in the string rather than the number of characters or glyphs. - @liveexample{The following code shows the constructor for different @ref - value_t values,basic_json__value_t} + #### String comparison + + [RFC 7159](http://rfc7159.net/rfc7159) states: + > Software implementations are typically required to test names of object + > members for equality. Implementations that transform the textual + > representation into sequences of Unicode code units and then perform the + > comparison numerically, code unit by code unit, are interoperable in the + > sense that implementations will agree in all cases on equality or + > inequality of two strings. For example, implementations that compare + > strings with escaped characters unconverted may incorrectly find that + > `"a\\b"` and `"a\u005Cb"` are not equal. + + This implementation is interoperable as it does compare strings code unit + by code unit. + + #### Storage - @sa @ref basic_json(std::nullptr_t) -- create a `null` value - @sa @ref basic_json(boolean_t value) -- create a boolean value - @sa @ref basic_json(const string_t&) -- create a string value - @sa @ref basic_json(const object_t&) -- create a object value - @sa @ref basic_json(const array_t&) -- create a array value - @sa @ref basic_json(const number_float_t) -- create a number - (floating-point) value - @sa @ref basic_json(const number_integer_t) -- create a number (integer) - value - @sa @ref basic_json(const number_unsigned_t) -- create a number (unsigned) - value + String values are stored as pointers in a @ref basic_json type. That is, + for any access to string values, a pointer of type `string_t*` must be + dereferenced. @since version 1.0.0 */ - basic_json(const value_t value_type) - : m_type(value_type), m_value(value_type) - { - assert_invariant(); - } + using string_t = StringType; /*! - @brief create a null object + @brief a type for a boolean - Create a `null` JSON value. It either takes a null pointer as parameter - (explicitly creating `null`) or no parameter (implicitly creating `null`). - The passed null pointer itself is not read -- it is only used to choose - the right constructor. + [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a + type which differentiates the two literals `true` and `false`. - @complexity Constant. + To store objects in C++, a type is defined by the template parameter @a + BooleanType which chooses the type to use. - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. + #### Default type - @liveexample{The following code shows the constructor with and without a - null pointer parameter.,basic_json__nullptr_t} + With the default values for @a BooleanType (`bool`), the default value for + @a boolean_t is: + + @code {.cpp} + bool + @endcode + + #### Storage + + Boolean values are stored directly inside a @ref basic_json type. @since version 1.0.0 */ - basic_json(std::nullptr_t = nullptr) noexcept - : basic_json(value_t::null) - { - assert_invariant(); - } + using boolean_t = BooleanType; /*! - @brief create an object (explicit) + @brief a type for a number (integer) + + [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. - Create an object JSON value with a given content. + To store integer numbers in C++, a type is defined by the template + parameter @a NumberIntegerType which chooses the type to use. - @param[in] val a value for the object + #### Default type - @complexity Linear in the size of the passed @a val. + With the default values for @a NumberIntegerType (`int64_t`), the default + value for @a number_integer_t is: - @throw std::bad_alloc if allocation for object value fails + @code {.cpp} + int64_t + @endcode - @liveexample{The following code shows the constructor with an @ref - object_t parameter.,basic_json__object_t} + #### Default behavior - @sa @ref basic_json(const CompatibleObjectType&) -- create an object value - from a compatible STL container + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in integer literals lead to an interpretation as octal + number. Internally, the value will be stored as decimal number. For + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. - @since version 1.0.0 - */ - basic_json(const object_t& val) - : m_type(value_t::object), m_value(val) - { - assert_invariant(); - } + #### Limits - /*! - @brief create an object (implicit) + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the range and precision of numbers. - Create an object JSON value with a given content. This constructor allows - any type @a CompatibleObjectType that can be used to construct values of - type @ref object_t. + When the default type is used, the maximal integer number that can be + stored is `9223372036854775807` (INT64_MAX) and the minimal integer number + that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers + that are out of range will yield over/underflow when used in a + constructor. During deserialization, too large or small integer numbers + will be automatically be stored as @ref number_unsigned_t or @ref + number_float_t. - @tparam CompatibleObjectType An object type whose `key_type` and - `value_type` is compatible to @ref object_t. Examples include `std::map`, - `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with - a `key_type` of `std::string`, and a `value_type` from which a @ref - basic_json value can be constructed. + [RFC 7159](http://rfc7159.net/rfc7159) further states: + > Note that when such software is used, numbers that are integers and are + > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense + > that implementations will agree exactly on their numeric values. - @param[in] val a value for the object + As this range is a subrange of the exactly supported range [INT64_MIN, + INT64_MAX], this class's integer type is interoperable. - @complexity Linear in the size of the passed @a val. + #### Storage - @throw std::bad_alloc if allocation for object value fails + Integer number values are stored directly inside a @ref basic_json type. - @liveexample{The following code shows the constructor with several - compatible object type parameters.,basic_json__CompatibleObjectType} + @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref basic_json(const object_t&) -- create an object value + @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ - template::value and - std::is_constructible::value, int>::type = 0> - basic_json(const CompatibleObjectType& val) - : m_type(value_t::object) - { - using std::begin; - using std::end; - m_value.object = create(begin(val), end(val)); - assert_invariant(); - } + using number_integer_t = NumberIntegerType; /*! - @brief create an array (explicit) + @brief a type for a number (unsigned) + + [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. - Create an array JSON value with a given content. + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. - @param[in] val a value for the array + To store unsigned integer numbers in C++, a type is defined by the + template parameter @a NumberUnsignedType which chooses the type to use. - @complexity Linear in the size of the passed @a val. + #### Default type - @throw std::bad_alloc if allocation for array value fails + With the default values for @a NumberUnsignedType (`uint64_t`), the + default value for @a number_unsigned_t is: - @liveexample{The following code shows the constructor with an @ref array_t - parameter.,basic_json__array_t} + @code {.cpp} + uint64_t + @endcode - @sa @ref basic_json(const CompatibleArrayType&) -- create an array value - from a compatible STL containers + #### Default behavior - @since version 1.0.0 - */ - basic_json(const array_t& val) - : m_type(value_t::array), m_value(val) - { - assert_invariant(); - } + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in integer literals lead to an interpretation as octal + number. Internally, the value will be stored as decimal number. For + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. - /*! - @brief create an array (implicit) + #### Limits - Create an array JSON value with a given content. This constructor allows - any type @a CompatibleArrayType that can be used to construct values of - type @ref array_t. + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the range and precision of numbers. - @tparam CompatibleArrayType An object type whose `value_type` is - compatible to @ref array_t. Examples include `std::vector`, `std::deque`, - `std::list`, `std::forward_list`, `std::array`, `std::set`, - `std::unordered_set`, `std::multiset`, and `unordered_multiset` with a - `value_type` from which a @ref basic_json value can be constructed. + When the default type is used, the maximal integer number that can be + stored is `18446744073709551615` (UINT64_MAX) and the minimal integer + number that can be stored is `0`. Integer numbers that are out of range + will yield over/underflow when used in a constructor. During + deserialization, too large or small integer numbers will be automatically + be stored as @ref number_integer_t or @ref number_float_t. - @param[in] val a value for the array + [RFC 7159](http://rfc7159.net/rfc7159) further states: + > Note that when such software is used, numbers that are integers and are + > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense + > that implementations will agree exactly on their numeric values. - @complexity Linear in the size of the passed @a val. + As this range is a subrange (when considered in conjunction with the + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. - @throw std::bad_alloc if allocation for array value fails + #### Storage - @liveexample{The following code shows the constructor with several - compatible array type parameters.,basic_json__CompatibleArrayType} + Integer number values are stored directly inside a @ref basic_json type. - @sa @ref basic_json(const array_t&) -- create an array value + @sa @ref number_float_t -- type for number values (floating-point) + @sa @ref number_integer_t -- type for number values (integer) - @since version 1.0.0 + @since version 2.0.0 */ - template::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - std::is_constructible::value, int>::type = 0> - basic_json(const CompatibleArrayType& val) - : m_type(value_t::array) - { - using std::begin; - using std::end; - m_value.array = create(begin(val), end(val)); - assert_invariant(); - } + using number_unsigned_t = NumberUnsignedType; /*! - @brief create a string (explicit) + @brief a type for a number (floating-point) + + [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. - Create an string JSON value with a given content. + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. - @param[in] val a value for the string + To store floating-point numbers in C++, a type is defined by the template + parameter @a NumberFloatType which chooses the type to use. - @complexity Linear in the size of the passed @a val. + #### Default type - @throw std::bad_alloc if allocation for string value fails + With the default values for @a NumberFloatType (`double`), the default + value for @a number_float_t is: - @liveexample{The following code shows the constructor with an @ref - string_t parameter.,basic_json__string_t} + @code {.cpp} + double + @endcode - @sa @ref basic_json(const typename string_t::value_type*) -- create a - string value from a character pointer - @sa @ref basic_json(const CompatibleStringType&) -- create a string value - from a compatible string container + #### Default behavior - @since version 1.0.0 - */ - basic_json(const string_t& val) - : m_type(value_t::string), m_value(val) - { - assert_invariant(); - } + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in floating-point literals will be ignored. Internally, + the value will be stored as decimal number. For instance, the C++ + floating-point literal `01.2` will be serialized to `1.2`. During + deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. - /*! - @brief create a string (explicit) + #### Limits - Create a string JSON value with a given content. + [RFC 7159](http://rfc7159.net/rfc7159) states: + > This specification allows implementations to set limits on the range and + > precision of numbers accepted. Since software that implements IEEE + > 754-2008 binary64 (double precision) numbers is generally available and + > widely used, good interoperability can be achieved by implementations + > that expect no more precision or range than these provide, in the sense + > that implementations will approximate JSON numbers within the expected + > precision. - @param[in] val a literal value for the string + This implementation does exactly follow this approach, as it uses double + precision floating-point numbers. Note values smaller than + `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` + will be stored as NaN internally and be serialized to `null`. - @complexity Linear in the size of the passed @a val. + #### Storage - @throw std::bad_alloc if allocation for string value fails + Floating-point number values are stored directly inside a @ref basic_json + type. - @liveexample{The following code shows the constructor with string literal - parameter.,basic_json__string_t_value_type} + @sa @ref number_integer_t -- type for number values (integer) - @sa @ref basic_json(const string_t&) -- create a string value - @sa @ref basic_json(const CompatibleStringType&) -- create a string value - from a compatible string container + @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ - basic_json(const typename string_t::value_type* val) - : basic_json(string_t(val)) - { - assert_invariant(); - } + using number_float_t = NumberFloatType; - /*! - @brief create a string (implicit) + /// @} - Create a string JSON value with a given content. + private: - @param[in] val a value for the string + /// helper for exception-safe object creation + template + static T* create(Args&& ... args) + { + AllocatorType alloc; + auto deleter = [&](T * object) + { + alloc.deallocate(object, 1); + }; + std::unique_ptr object(alloc.allocate(1), deleter); + alloc.construct(object.get(), std::forward(args)...); + assert(object != nullptr); + return object.release(); + } - @tparam CompatibleStringType an string type which is compatible to @ref - string_t, for instance `std::string`. + //////////////////////// + // JSON value storage // + //////////////////////// - @complexity Linear in the size of the passed @a val. + /*! + @brief a JSON value - @throw std::bad_alloc if allocation for string value fails + The actual storage for a JSON value of the @ref basic_json class. This + union combines the different storage types for the JSON value types + defined in @ref value_t. - @liveexample{The following code shows the construction of a string value - from a compatible type.,basic_json__CompatibleStringType} + JSON type | value_t type | used type + --------- | --------------- | ------------------------ + object | object | pointer to @ref object_t + array | array | pointer to @ref array_t + string | string | pointer to @ref string_t + boolean | boolean | @ref boolean_t + number | number_integer | @ref number_integer_t + number | number_unsigned | @ref number_unsigned_t + number | number_float | @ref number_float_t + null | null | *no value is stored* - @sa @ref basic_json(const string_t&) -- create a string value - @sa @ref basic_json(const typename string_t::value_type*) -- create a - string value from a character pointer + @note Variable-length types (objects, arrays, and strings) are stored as + pointers. The size of the union should not exceed 64 bits if the default + value types are used. @since version 1.0.0 */ - template::value, int>::type = 0> - basic_json(const CompatibleStringType& val) - : basic_json(string_t(val)) + union json_value { - assert_invariant(); - } + /// object (stored with pointer to save storage) + object_t* object; + /// array (stored with pointer to save storage) + array_t* array; + /// string (stored with pointer to save storage) + string_t* string; + /// boolean + boolean_t boolean; + /// number (integer) + number_integer_t number_integer; + /// number (unsigned integer) + number_unsigned_t number_unsigned; + /// number (floating-point) + number_float_t number_float; - /*! - @brief create a boolean (explicit) + /// default constructor (for null values) + json_value() = default; + /// constructor for booleans + json_value(boolean_t v) noexcept : boolean(v) {} + /// constructor for numbers (integer) + json_value(number_integer_t v) noexcept : number_integer(v) {} + /// constructor for numbers (unsigned) + json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} + /// constructor for numbers (floating-point) + json_value(number_float_t v) noexcept : number_float(v) {} + /// constructor for empty values of a given type + json_value(value_t t) + { + switch (t) + { + case value_t::object: + { + object = create(); + break; + } - Creates a JSON boolean type from a given value. + case value_t::array: + { + array = create(); + break; + } - @param[in] val a boolean value to store + case value_t::string: + { + string = create(""); + break; + } - @complexity Constant. + case value_t::boolean: + { + boolean = boolean_t(false); + break; + } - @liveexample{The example below demonstrates boolean - values.,basic_json__boolean_t} + case value_t::number_integer: + { + number_integer = number_integer_t(0); + break; + } - @since version 1.0.0 - */ - basic_json(boolean_t val) noexcept - : m_type(value_t::boolean), m_value(val) - { - assert_invariant(); - } + case value_t::number_unsigned: + { + number_unsigned = number_unsigned_t(0); + break; + } - /*! - @brief create an integer number (explicit) + case value_t::number_float: + { + number_float = number_float_t(0.0); + break; + } - Create an integer number JSON value with a given content. + case value_t::null: + { + break; + } - @tparam T A helper type to remove this function via SFINAE in case @ref - number_integer_t is the same as `int`. In this case, this constructor - would have the same signature as @ref basic_json(const int value). Note - the helper type @a T is not visible in this constructor's interface. + default: + { + if (t == value_t::null) + { + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE + } + break; + } + } + } - @param[in] val an integer to create a JSON number from + /// constructor for strings + json_value(const string_t& value) + { + string = create(value); + } - @complexity Constant. + /// constructor for objects + json_value(const object_t& value) + { + object = create(value); + } - @liveexample{The example below shows the construction of an integer - number value.,basic_json__number_integer_t} + /// constructor for arrays + json_value(const array_t& value) + { + array = create(value); + } + }; - @sa @ref basic_json(const int) -- create a number value (integer) - @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number - value (integer) from a compatible number type + /*! + @brief checks the class invariants - @since version 1.0.0 + This function asserts the class invariants. It needs to be called at the + end of every constructor to make sure that created objects respect the + invariant. Furthermore, it has to be called each time the type of a JSON + value is changed, because the invariant expresses a relationship between + @a m_type and @a m_value. */ - template::value) and - std::is_same::value, int>::type = 0> - basic_json(const number_integer_t val) noexcept - : m_type(value_t::number_integer), m_value(val) + void assert_invariant() const { - assert_invariant(); + assert(m_type != value_t::object or m_value.object != nullptr); + assert(m_type != value_t::array or m_value.array != nullptr); + assert(m_type != value_t::string or m_value.string != nullptr); } - /*! - @brief create an integer number from an enum type (explicit) - - Create an integer number JSON value with a given content. - - @param[in] val an integer to create a JSON number from - - @note This constructor allows to pass enums directly to a constructor. As - C++ has no way of specifying the type of an anonymous enum explicitly, we - can only rely on the fact that such values implicitly convert to int. As - int may already be the same type of number_integer_t, we may need to - switch off the constructor @ref basic_json(const number_integer_t). + public: + ////////////////////////// + // JSON parser callback // + ////////////////////////// - @complexity Constant. + /*! + @brief JSON callback events - @liveexample{The example below shows the construction of an integer - number value from an anonymous enum.,basic_json__const_int} + This enumeration lists the parser events that can trigger calling a + callback function of type @ref parser_callback_t during parsing. - @sa @ref basic_json(const number_integer_t) -- create a number value - (integer) - @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number - value (integer) from a compatible number type + @image html callback_events.png "Example when certain parse events are triggered" @since version 1.0.0 */ - basic_json(const int val) noexcept - : m_type(value_t::number_integer), - m_value(static_cast(val)) + enum class parse_event_t : uint8_t { - assert_invariant(); - } + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value + }; /*! - @brief create an integer number (implicit) + @brief per-element parser callback type - Create an integer number JSON value with a given content. This constructor - allows any type @a CompatibleNumberIntegerType that can be used to - construct values of type @ref number_integer_t. + With a parser callback function, the result of parsing a JSON text can be + influenced. When passed to @ref parse(std::istream&, const + parser_callback_t) or @ref parse(const CharT, const parser_callback_t), + it is called on certain events (passed as @ref parse_event_t via parameter + @a event) with a set recursion depth @a depth and context JSON value + @a parsed. The return value of the callback function is a boolean + indicating whether the element that emitted the callback shall be kept or + not. - @tparam CompatibleNumberIntegerType An integer type which is compatible to - @ref number_integer_t. Examples include the types `int`, `int32_t`, - `long`, and `short`. + We distinguish six scenarios (determined by the event type) in which the + callback function can be called. The following table describes the values + of the parameters @a depth, @a event, and @a parsed. - @param[in] val an integer to create a JSON number from + parameter @a event | description | parameter @a depth | parameter @a parsed + ------------------ | ----------- | ------------------ | ------------------- + parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded + parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key + parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object + parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded + parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array + parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value - @complexity Constant. + @image html callback_events.png "Example when certain parse events are triggered" - @liveexample{The example below shows the construction of several integer - number values from compatible - types.,basic_json__CompatibleIntegerNumberType} + Discarding a value (i.e., returning `false`) has different effects + depending on the context in which function was called: - @sa @ref basic_json(const number_integer_t) -- create a number value - (integer) - @sa @ref basic_json(const int) -- create a number value (integer) + - Discarded values in structured types are skipped. That is, the parser + will behave as if the discarded value was never read. + - In case a value outside a structured type is skipped, it is replaced + with `null`. This case happens if the top-level element is skipped. - @since version 1.0.0 - */ - template::value and - std::numeric_limits::is_integer and - std::numeric_limits::is_signed, - CompatibleNumberIntegerType>::type = 0> - basic_json(const CompatibleNumberIntegerType val) noexcept - : m_type(value_t::number_integer), - m_value(static_cast(val)) - { - assert_invariant(); - } + @param[in] depth the depth of the recursion during parsing - /*! - @brief create an unsigned integer number (explicit) + @param[in] event an event of type parse_event_t indicating the context in + the callback function has been called - Create an unsigned integer number JSON value with a given content. + @param[in,out] parsed the current intermediate parse result; note that + writing to this value has no effect for parse_event_t::key events - @tparam T helper type to compare number_unsigned_t and unsigned int (not - visible in) the interface. + @return Whether the JSON value which called the function during parsing + should be kept (`true`) or not (`false`). In the latter case, it is either + skipped completely or replaced by an empty discarded object. - @param[in] val an integer to create a JSON number from + @sa @ref parse(std::istream&, parser_callback_t) or + @ref parse(const CharT, const parser_callback_t) for examples - @complexity Constant. + @since version 1.0.0 + */ + using parser_callback_t = std::function; - @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number - value (unsigned integer) from a compatible number type - @since version 2.0.0 - */ - template::value) and - std::is_same::value, int>::type = 0> - basic_json(const number_unsigned_t val) noexcept - : m_type(value_t::number_unsigned), m_value(val) - { - assert_invariant(); - } + ////////////////// + // constructors // + ////////////////// + + /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. + /// @{ /*! - @brief create an unsigned number (implicit) + @brief create an empty value with a given type - Create an unsigned number JSON value with a given content. This - constructor allows any type @a CompatibleNumberUnsignedType that can be - used to construct values of type @ref number_unsigned_t. + Create an empty JSON value with a given type. The value will be default + initialized with an empty value which depends on the type: - @tparam CompatibleNumberUnsignedType An integer type which is compatible - to @ref number_unsigned_t. Examples may include the types `unsigned int`, - `uint32_t`, or `unsigned short`. + Value type | initial value + ----------- | ------------- + null | `null` + boolean | `false` + string | `""` + number | `0` + object | `{}` + array | `[]` - @param[in] val an unsigned integer to create a JSON number from + @param[in] value_type the type of the value to create @complexity Constant. - @sa @ref basic_json(const number_unsigned_t) -- create a number value - (unsigned) + @liveexample{The following code shows the constructor for different @ref + value_t values,basic_json__value_t} - @since version 2.0.0 + @since version 1.0.0 */ - template::value and - std::numeric_limits::is_integer and - not std::numeric_limits::is_signed, - CompatibleNumberUnsignedType>::type = 0> - basic_json(const CompatibleNumberUnsignedType val) noexcept - : m_type(value_t::number_unsigned), - m_value(static_cast(val)) + basic_json(const value_t value_type) + : m_type(value_type), m_value(value_type) { assert_invariant(); } /*! - @brief create a floating-point number (explicit) - - Create a floating-point number JSON value with a given content. - - @param[in] val a floating-point value to create a JSON number from + @brief create a null object - @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6 - disallows NaN values: - > Numeric values that cannot be represented in the grammar below (such as - > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is created - instead. + Create a `null` JSON value. It either takes a null pointer as parameter + (explicitly creating `null`) or no parameter (implicitly creating `null`). + The passed null pointer itself is not read -- it is only used to choose + the right constructor. @complexity Constant. - @liveexample{The following example creates several floating-point - values.,basic_json__number_float_t} + @exceptionsafety No-throw guarantee: this constructor never throws + exceptions. - @sa @ref basic_json(const CompatibleNumberFloatType) -- create a number - value (floating-point) from a compatible number type + @liveexample{The following code shows the constructor with and without a + null pointer parameter.,basic_json__nullptr_t} @since version 1.0.0 */ - basic_json(const number_float_t val) noexcept - : m_type(value_t::number_float), m_value(val) + basic_json(std::nullptr_t = nullptr) noexcept + : basic_json(value_t::null) { - // replace infinity and NAN by null - if (not std::isfinite(val)) - { - m_type = value_t::null; - m_value = json_value(); - } - assert_invariant(); } /*! - @brief create an floating-point number (implicit) + @brief create a JSON value - Create an floating-point number JSON value with a given content. This - constructor allows any type @a CompatibleNumberFloatType that can be used - to construct values of type @ref number_float_t. + This is a "catch all" constructor for all compatible JSON types; that is, + types for which a `to_json()` method exsits. The constructor forwards the + parameter @a val to that method (to `json_serializer::to_json` method + with `U = uncvref_t`, to be exact). - @tparam CompatibleNumberFloatType A floating-point type which is - compatible to @ref number_float_t. Examples may include the types `float` - or `double`. + Template type @a CompatibleType includes, but is not limited to, the + following types: + - **arrays**: @ref array_t and all kinds of compatible containers such as + `std::vector`, `std::deque`, `std::list`, `std::forward_list`, + `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and + `unordered_multiset` with a `value_type` from which a @ref basic_json + value can be constructed. + - **objects**: @ref object_t and all kinds of compatible associative + containers such as `std::map`, `std::unordered_map`, `std::multimap`, + and `std::unordered_multimap` with a `key_type` compatible to + @ref string_t and a `value_type` from which a @ref basic_json value can + be constructed. + - **strings**: @ref string_t, string literals, and all compatible string + containers can be used. + - **numbers**: @ref number_integer_t, @ref number_unsigned_t, + @ref number_float_t, and all convertible number types such as `int`, + `size_t`, `int64_t`, `float` or `double` can be used. + - **boolean**: @ref boolean_t / `bool` can be used. - @param[in] val a floating-point to create a JSON number from + See the examples below. - @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6 - disallows NaN values: - > Numeric values that cannot be represented in the grammar below (such as - > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is - created instead. + @tparam CompatibleType a type such that: + - @a CompatibleType is not derived from `std::istream`, + - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move + constructors), + - @a CompatibleType is not a @ref basic_json nested type (e.g., + @ref json_pointer, @ref iterator, etc ...) + - @ref @ref json_serializer has a + `to_json(basic_json_t&, CompatibleType&&)` method - @complexity Constant. + @tparam U = `uncvref_t` - @liveexample{The example below shows the construction of several - floating-point number values from compatible - types.,basic_json__CompatibleNumberFloatType} + @param[in] val the value to be forwarded - @sa @ref basic_json(const number_float_t) -- create a number value - (floating-point) + @complexity Usually linear in the size of the passed @a val, also + depending on the implementation of the called `to_json()` + method. - @since version 1.0.0 + @throw what `json_serializer::to_json()` throws + + @liveexample{The following code shows the constructor with several + compatible types.,basic_json__CompatibleType} + + @since version 2.1.0 */ - template::value and - std::is_floating_point::value>::type> - basic_json(const CompatibleNumberFloatType val) noexcept - : basic_json(number_float_t(val)) + template, + detail::enable_if_t::value and + not std::is_same::value and + not detail::is_basic_json_nested_type< + basic_json_t, U>::value and + detail::has_to_json::value, + int> = 0> + basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer::to_json( + std::declval(), std::forward(val)))) { + JSONSerializer::to_json(*this, std::forward(val)); assert_invariant(); } @@ -1613,10 +2330,12 @@ class basic_json value_t::array and @ref value_t::object are valid); when @a type_deduction is set to `true`, this parameter has no effect - @throw std::domain_error if @a type_deduction is `false`, @a manual_type - is `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string; example: `"cannot create object from - initializer list"` + @throw type_error.301 if @a type_deduction is `false`, @a manual_type is + `value_t::object`, but @a init contains an element which is not a pair + whose first element is a string. In this case, the constructor could not + create an object. If @a type_deduction would have be `true`, an array + would have been created. See @ref object(std::initializer_list) + for an example. @complexity Linear in the size of the initializer list @a init. @@ -1654,7 +2373,7 @@ class basic_json // if object is wanted but impossible, throw an exception if (manual_type == value_t::object and not is_an_object) { - throw std::domain_error("cannot create object from initializer list"); + JSON_THROW(type_error::create(301, "cannot create object from initializer list")); } } @@ -1730,16 +2449,17 @@ class basic_json related function @ref array(std::initializer_list), there are no cases which can only be expressed by this function. That is, any initializer list @a init can also be passed to the initializer list - constructor @ref basic_json(std::initializer_list, bool, - value_t). + constructor @ref basic_json(std::initializer_list, bool, value_t). @param[in] init initializer list to create an object from (optional) @return JSON object value - @throw std::domain_error if @a init is not a pair whose first elements are - strings; thrown by - @ref basic_json(std::initializer_list, bool, value_t) + @throw type_error.301 if @a init is not a list of pairs whose first + elements are strings. In this case, no object can be created. When such a + value is passed to @ref basic_json(std::initializer_list, bool, value_t), + an array would have been created from the passed initializer list @a init. + See example below. @complexity Linear in the size of @a init. @@ -1791,10 +2511,10 @@ class basic_json The semantics depends on the different types a JSON value can have: - In case of primitive types (number, boolean, or string), @a first must be `begin()` and @a last must be `end()`. In this case, the value is - copied. Otherwise, std::out_of_range is thrown. + copied. Otherwise, invalid_iterator.204 is thrown. - In case of structured types (array, object), the constructor behaves as similar versions for `std::vector`. - - In case of a null type, std::domain_error is thrown. + - In case of a null type, invalid_iterator.206 is thrown. @tparam InputIT an input iterator type (@ref iterator or @ref const_iterator) @@ -1805,14 +2525,19 @@ class basic_json @pre Iterators @a first and @a last must be initialized. **This precondition is enforced with an assertion.** - @throw std::domain_error if iterators are not compatible; that is, do not - belong to the same JSON value; example: `"iterators are not compatible"` - @throw std::out_of_range if iterators are for a primitive type (number, - boolean, or string) where an out of range error can be detected easily; - example: `"iterators out of range"` - @throw std::bad_alloc if allocation for object, array, or string fails - @throw std::domain_error if called with a null value; example: `"cannot - use construct with iterators from null"` + @pre Range `[first, last)` is valid. Usually, this precondition cannot be + checked efficiently. Only certain edge cases are detected; see the + description of the exceptions below. + + @throw invalid_iterator.201 if iterators @a first and @a last are not + compatible (i.e., do not belong to the same JSON value). In this case, + the range `[first, last)` is undefined. + @throw invalid_iterator.204 if iterators @a first and @a last belong to a + primitive type (number, boolean, or string), but @a first does not point + to the first element any more. In this case, the range `[first, last)` is + undefined. See example code below. + @throw invalid_iterator.206 if iterators @a first and @a last belong to a + null value. In this case, the range `[first, last)` is undefined. @complexity Linear in distance between @a first and @a last. @@ -1832,7 +2557,7 @@ class basic_json // make sure iterator fits the current value if (first.m_object != last.m_object) { - throw std::domain_error("iterators are not compatible"); + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); } // copy type from first iterator @@ -1849,7 +2574,7 @@ class basic_json { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); } break; } @@ -1894,59 +2619,28 @@ class basic_json case value_t::object: { - m_value.object = create(first.m_it.object_iterator, last.m_it.object_iterator); + m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); break; } case value_t::array: { - m_value.array = create(first.m_it.array_iterator, last.m_it.array_iterator); + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); break; } default: { - throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + + first.m_object->type_name())); } } assert_invariant(); } - /*! - @brief construct a JSON value given an input stream - - @param[in,out] i stream to read a serialized JSON value from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @deprecated This constructor is deprecated and will be removed in version - 3.0.0 to unify the interface of the library. Deserialization will be - done by stream operators or by calling one of the `parse` functions, - e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls - like `json j(i);` for an input stream @a i need to be replaced by - `json j = json::parse(i);`. See the example below. - - @liveexample{The example below demonstrates constructing a JSON value from - a `std::stringstream` with and without callback - function.,basic_json__istream} - - @since version 2.0.0, deprecated in version 2.0.3, to be removed in - version 3.0.0 - */ - JSON_DEPRECATED - explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) - { - *this = parser(i, cb).parse(); - assert_invariant(); - } /////////////////////////////////////// // other constructors and destructor // @@ -1967,8 +2661,6 @@ class basic_json - The complexity is linear. - As postcondition, it holds: `other == basic_json(other)`. - @throw std::bad_alloc if allocation for object, array, or string fails. - @liveexample{The following code shows an example for the copy constructor.,basic_json__basic_json} @@ -2196,22 +2888,15 @@ class basic_json string_t dump(const int indent = -1) const { std::stringstream ss; - // fix locale problems - ss.imbue(std::locale::classic()); - - // 6, 15 or 16 digits of precision allows round-trip IEEE 754 - // string->float->string, string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - ss.precision(std::numeric_limits::digits10); + serializer s(ss); if (indent >= 0) { - dump(ss, true, static_cast(indent)); + s.dump(*this, true, static_cast(indent)); } else { - dump(ss, false, 0); + s.dump(*this, false, 0); } return ss.str(); @@ -2577,246 +3262,99 @@ class basic_json private: ////////////////// // value access // - ////////////////// - - /// get an object (explicit) - template::value and - std::is_convertible::value, int>::type = 0> - T get_impl(T*) const - { - if (is_object()) - { - return T(m_value.object->begin(), m_value.object->end()); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } - } - - /// get an object (explicit) - object_t get_impl(object_t*) const - { - if (is_object()) - { - return *(m_value.object); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } - } - - /// get an array (explicit) - template::value and - not std::is_same::value and - not std::is_arithmetic::value and - not std::is_convertible::value and - not has_mapped_type::value, int>::type = 0> - T get_impl(T*) const - { - if (is_array()) - { - T to_vector; - std::transform(m_value.array->begin(), m_value.array->end(), - std::inserter(to_vector, to_vector.end()), [](basic_json i) - { - return i.get(); - }); - return to_vector; - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get an array (explicit) - template::value and - not std::is_same::value, int>::type = 0> - std::vector get_impl(std::vector*) const - { - if (is_array()) - { - std::vector to_vector; - to_vector.reserve(m_value.array->size()); - std::transform(m_value.array->begin(), m_value.array->end(), - std::inserter(to_vector, to_vector.end()), [](basic_json i) - { - return i.get(); - }); - return to_vector; - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get an array (explicit) - template::value and - not has_mapped_type::value, int>::type = 0> - T get_impl(T*) const - { - if (is_array()) - { - return T(m_value.array->begin(), m_value.array->end()); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get an array (explicit) - array_t get_impl(array_t*) const - { - if (is_array()) - { - return *(m_value.array); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get a string (explicit) - template::value, int>::type = 0> - T get_impl(T*) const - { - if (is_string()) - { - return *m_value.string; - } - else - { - throw std::domain_error("type must be string, but is " + type_name()); - } - } - - /// get a number (explicit) - template::value, int>::type = 0> - T get_impl(T*) const - { - switch (m_type) - { - case value_t::number_integer: - { - return static_cast(m_value.number_integer); - } - - case value_t::number_unsigned: - { - return static_cast(m_value.number_unsigned); - } - - case value_t::number_float: - { - return static_cast(m_value.number_float); - } - - default: - { - throw std::domain_error("type must be number, but is " + type_name()); - } - } - } + ////////////////// /// get a boolean (explicit) - constexpr boolean_t get_impl(boolean_t*) const + boolean_t get_impl(boolean_t* /*unused*/) const { - return is_boolean() - ? m_value.boolean - : throw std::domain_error("type must be boolean, but is " + type_name()); + if (is_boolean()) + { + return m_value.boolean; + } + + JSON_THROW(type_error::create(302, "type must be boolean, but is " + type_name())); } /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t*) noexcept + object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t*) const noexcept + constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t*) noexcept + array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t*) const noexcept + constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t*) noexcept + string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t*) const noexcept + constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t*) noexcept + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept + constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t*) noexcept + number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept + constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept + number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept + constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t*) noexcept + number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { return is_number_float() ? &m_value.number_float : nullptr; } @@ -2829,7 +3367,7 @@ class basic_json @tparam ThisType will be deduced as `basic_json` or `const basic_json` - @throw std::domain_error if ReferenceType does not match underlying value + @throw type_error.303 if ReferenceType does not match underlying value type of the current JSON */ template @@ -2845,34 +3383,68 @@ class basic_json { return *ptr; } - else - { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); - } + + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + obj.type_name())); } public: - /// @name value access /// Direct access to the stored value of a JSON value. /// @{ + /*! + @brief get special-case overload + + This overloads avoids a lot of template boilerplate, it can be seen as the + identity method + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this + + @complexity Constant. + + @since version 2.1.0 + */ + template < + typename BasicJsonType, + detail::enable_if_t::type, + basic_json_t>::value, + int> = 0 > + basic_json get() const + { + return *this; + } + /*! @brief get a value (explicit) - Explicit type conversion between the JSON value and a compatible value. + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. - @tparam ValueType non-pointer type compatible to the JSON value, for - instance `int` for JSON integer numbers, `bool` for JSON booleans, or - `std::vector` types for JSON arrays + The function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + @endcode - @return copy of the JSON value, converted to type @a ValueType + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const @ref basic_json&, ValueType&)`, and + - @ref json_serializer does not have a `from_json()` method of + the form `ValueType from_json(const @ref basic_json&)` - @throw std::domain_error in case passed type @a ValueType is incompatible - to JSON; example: `"type must be object, but is null"` + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type - @complexity Linear in the size of the JSON value. + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws @liveexample{The example below shows several conversions from JSON values to other types. There a few things to note: (1) Floating-point numbers can @@ -2881,21 +3453,75 @@ class basic_json associative containers such as `std::unordered_map`.,get__ValueType_const} - @internal - The idea of using a casted null pointer to choose the correct - implementation is from . - @endinternal + @since version 2.1.0 + */ + template < + typename ValueTypeCV, + typename ValueType = detail::uncvref_t, + detail::enable_if_t < + not std::is_same::value and + detail::has_from_json::value and + not detail::has_non_default_from_json::value, + int > = 0 > + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) + { + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get(), which is why we + // still need the uncvref + static_assert(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + static_assert(std::is_default_constructible::value, + "types must be DefaultConstructible when used with get()"); - @sa @ref operator ValueType() const for implicit conversion - @sa @ref get() for pointer-member access + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + } - @since version 1.0.0 + /*! + @brief get a value (explicit); special case + + Explicit type conversion between the JSON value and a compatible value + which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + return JSONSerializer::from_json(*this); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json and + - @ref json_serializer has a `from_json()` method of the form + `ValueType from_json(const @ref basic_json&)` + + @note If @ref json_serializer has both overloads of + `from_json()`, this one is chosen. + + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @since version 2.1.0 */ - template::value, int>::type = 0> - ValueType get() const + template < + typename ValueTypeCV, + typename ValueType = detail::uncvref_t, + detail::enable_if_t::value and + detail::has_non_default_from_json::value, int> = 0 > + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) { - return get_impl(static_cast(nullptr)); + static_assert(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return JSONSerializer::from_json(*this); } /*! @@ -3025,7 +3651,7 @@ class basic_json /*! @brief get a reference value (implicit) - Implict reference access to the internally stored JSON value. No copies + Implicit reference access to the internally stored JSON value. No copies are made. @warning Writing data to the referee of the result yields an undefined @@ -3037,10 +3663,10 @@ class basic_json @return reference to the internally stored JSON value if the requested reference type @a ReferenceType fits to the JSON value; throws - std::domain_error otherwise + type_error.303 otherwise - @throw std::domain_error in case passed type @a ReferenceType is - incompatible with the stored JSON value + @throw type_error.303 in case passed type @a ReferenceType is incompatible + with the stored JSON value; see example below @complexity Constant. @@ -3083,8 +3709,9 @@ class basic_json @return copy of the JSON value, converted to type @a ValueType - @throw std::domain_error in case passed type @a ValueType is incompatible - to JSON, thrown by @ref get() const + @throw type_error.302 in case passed type @a ValueType is incompatible + to the JSON value type (e.g., the JSON value is of type boolean, but a + string is requested); see example below @complexity Linear in the size of the JSON value. @@ -3100,8 +3727,11 @@ class basic_json template < typename ValueType, typename std::enable_if < not std::is_pointer::value and not std::is_same::value -#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 +#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value +#endif +#if defined(_MSC_VER) && _MSC_VER >1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1 // fix for issue #464 + and not std::is_same::value #endif , int >::type = 0 > operator ValueType() const @@ -3131,36 +3761,40 @@ class basic_json @return reference to the element at index @a idx - @throw std::domain_error if the JSON value is not an array; example: - `"cannot use at() with string"` - @throw std::out_of_range if the index @a idx is out of range of the array; - that is, `idx >= size()`; example: `"array index 7 is out of range"` + @throw type_error.304 if the JSON value is not an array; in this case, + calling `at` with an index makes no sense. See example below. + @throw out_of_range.401 if the index @a idx is out of range of the array; + that is, `idx >= size()`. See example below. - @complexity Constant. + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. - @liveexample{The example below shows how array elements can be read and - written using `at()`.,at__size_type} + @complexity Constant. @since version 1.0.0 + + @liveexample{The example below shows how array elements can be read and + written using `at()`. It also demonstrates the different exceptions that + can be thrown.,at__size_type} */ reference at(size_type idx) { // at only works for arrays if (is_array()) { - try + JSON_TRY { return m_value.array->at(idx); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); } } @@ -3174,36 +3808,40 @@ class basic_json @return const reference to the element at index @a idx - @throw std::domain_error if the JSON value is not an array; example: - `"cannot use at() with string"` - @throw std::out_of_range if the index @a idx is out of range of the array; - that is, `idx >= size()`; example: `"array index 7 is out of range"` + @throw type_error.304 if the JSON value is not an array; in this case, + calling `at` with an index makes no sense. See example below. + @throw out_of_range.401 if the index @a idx is out of range of the array; + that is, `idx >= size()`. See example below. - @complexity Constant. + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. - @liveexample{The example below shows how array elements can be read using - `at()`.,at__size_type_const} + @complexity Constant. @since version 1.0.0 + + @liveexample{The example below shows how array elements can be read using + `at()`. It also demonstrates the different exceptions that can be thrown., + at__size_type_const} */ const_reference at(size_type idx) const { // at only works for arrays if (is_array()) { - try + JSON_TRY { return m_value.array->at(idx); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); } } @@ -3217,40 +3855,44 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if the JSON value is not an object; example: - `"cannot use at() with boolean"` - @throw std::out_of_range if the key @a key is is not stored in the object; - that is, `find(key) == end()`; example: `"key "the fast" not found"` + @throw type_error.304 if the JSON value is not an object; in this case, + calling `at` with a key makes no sense. See example below. + @throw out_of_range.403 if the key @a key is is not stored in the object; + that is, `find(key) == end()`. See example below. - @complexity Logarithmic in the size of the container. + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. - @liveexample{The example below shows how object elements can be read and - written using `at()`.,at__object_t_key_type} + @complexity Logarithmic in the size of the container. @sa @ref operator[](const typename object_t::key_type&) for unchecked access by reference @sa @ref value() for access by value with a default value @since version 1.0.0 + + @liveexample{The example below shows how object elements can be read and + written using `at()`. It also demonstrates the different exceptions that + can be thrown.,at__object_t_key_type} */ reference at(const typename object_t::key_type& key) { // at only works for objects if (is_object()) { - try + JSON_TRY { return m_value.object->at(key); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("key '" + key + "' not found"); + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); } } @@ -3264,40 +3906,44 @@ class basic_json @return const reference to the element at key @a key - @throw std::domain_error if the JSON value is not an object; example: - `"cannot use at() with boolean"` - @throw std::out_of_range if the key @a key is is not stored in the object; - that is, `find(key) == end()`; example: `"key "the fast" not found"` + @throw type_error.304 if the JSON value is not an object; in this case, + calling `at` with a key makes no sense. See example below. + @throw out_of_range.403 if the key @a key is is not stored in the object; + that is, `find(key) == end()`. See example below. - @complexity Logarithmic in the size of the container. + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. - @liveexample{The example below shows how object elements can be read using - `at()`.,at__object_t_key_type_const} + @complexity Logarithmic in the size of the container. @sa @ref operator[](const typename object_t::key_type&) for unchecked access by reference @sa @ref value() for access by value with a default value @since version 1.0.0 + + @liveexample{The example below shows how object elements can be read using + `at()`. It also demonstrates the different exceptions that can be thrown., + at__object_t_key_type_const} */ const_reference at(const typename object_t::key_type& key) const { // at only works for objects if (is_object()) { - try + JSON_TRY { return m_value.object->at(key); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("key '" + key + "' not found"); + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); } } @@ -3314,8 +3960,8 @@ class basic_json @return reference to the element at index @a idx - @throw std::domain_error if JSON is not an array or null; example: - `"cannot use operator[] with string"` + @throw type_error.305 if the JSON value is not an array or null; in that + cases, using the [] operator with an index makes no sense. @complexity Constant if @a idx is in the range of the array. Otherwise linear in `idx - size()`. @@ -3349,10 +3995,8 @@ class basic_json return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); } /*! @@ -3364,8 +4008,8 @@ class basic_json @return const reference to the element at index @a idx - @throw std::domain_error if JSON is not an array; example: `"cannot use - operator[] with null"` + @throw type_error.305 if the JSON value is not an array; in that cases, + using the [] operator with an index makes no sense. @complexity Constant. @@ -3381,10 +4025,8 @@ class basic_json { return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); } /*! @@ -3400,8 +4042,8 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: - `"cannot use operator[] with string"` + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3429,10 +4071,8 @@ class basic_json { return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); } /*! @@ -3451,8 +4091,8 @@ class basic_json @pre The element with key @a key must exist. **This precondition is enforced with an assertion.** - @throw std::domain_error if JSON is not an object; example: `"cannot use - operator[] with null"` + @throw type_error.305 if the JSON value is not an object; in that cases, + using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3473,10 +4113,8 @@ class basic_json assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); } /*! @@ -3492,8 +4130,8 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: - `"cannot use operator[] with string"` + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3527,8 +4165,8 @@ class basic_json @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object; example: `"cannot use - operator[] with null"` + @throw type_error.305 if the JSON value is not an object; in that cases, + using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3560,8 +4198,8 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: - `"cannot use operator[] with string"` + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3590,10 +4228,8 @@ class basic_json { return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); } /*! @@ -3612,8 +4248,8 @@ class basic_json @pre The element with key @a key must exist. **This precondition is enforced with an assertion.** - @throw std::domain_error if JSON is not an object; example: `"cannot use - operator[] with null"` + @throw type_error.305 if the JSON value is not an object; in that cases, + using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3635,10 +4271,8 @@ class basic_json assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); } /*! @@ -3651,7 +4285,7 @@ class basic_json @code {.cpp} try { return at(key); - } catch(std::out_of_range) { + } catch(out_of_range) { return default_value; } @endcode @@ -3674,8 +4308,8 @@ class basic_json @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object; example: `"cannot use - value() with null"` + @throw type_error.306 if the JSON value is not an objec; in that cases, + using `value()` with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3702,14 +4336,12 @@ class basic_json { return *it; } - else - { - return default_value; - } + + return default_value; } else { - throw std::domain_error("cannot use value() with " + type_name()); + JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); } } @@ -3732,7 +4364,7 @@ class basic_json @code {.cpp} try { return at(ptr); - } catch(std::out_of_range) { + } catch(out_of_range) { return default_value; } @endcode @@ -3751,8 +4383,8 @@ class basic_json @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object; example: `"cannot use - value() with null"` + @throw type_error.306 if the JSON value is not an objec; in that cases, + using `value()` with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -3771,19 +4403,17 @@ class basic_json if (is_object()) { // if pointer resolves a value, return it or use default value - try + JSON_TRY { return ptr.get_checked(this); } - catch (std::out_of_range&) + JSON_CATCH (out_of_range&) { return default_value; } } - else - { - throw std::domain_error("cannot use value() with " + type_name()); - } + + JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); } /*! @@ -3812,7 +4442,7 @@ class basic_json assertions**). @post The JSON value remains unchanged. - @throw std::out_of_range when called on `null` value + @throw invalid_iterator.214 when called on `null` value @liveexample{The following code shows an example for `front()`.,front} @@ -3855,7 +4485,8 @@ class basic_json assertions**). @post The JSON value remains unchanged. - @throw std::out_of_range when called on `null` value. + @throw invalid_iterator.214 when called on a `null` value. See example + below. @liveexample{The following code shows an example for `back()`.,back} @@ -3899,17 +4530,18 @@ class basic_json @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. - @throw std::domain_error if called on a `null` value; example: `"cannot - use erase() with null"` - @throw std::domain_error if called on an iterator which does not belong to - the current JSON value; example: `"iterator does not fit current value"` - @throw std::out_of_range if called on a primitive type with invalid + @throw type_error.307 if called on a `null` value; example: `"cannot use + erase() with null"` + @throw invalid_iterator.202 if called on an iterator which does not belong + to the current JSON value; example: `"iterator does not fit current + value"` + @throw invalid_iterator.205 if called on a primitive type with invalid iterator (i.e., any iterator which is not `begin()`); example: `"iterator out of range"` @complexity The complexity depends on the type: - objects: amortized constant - - arrays: linear in distance between pos and the end of the container + - arrays: linear in distance between @a pos and the end of the container - strings: linear in the length of the string - other types: constant @@ -3934,7 +4566,7 @@ class basic_json // make sure iterator fits the current value if (this != pos.m_object) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); } IteratorType result = end(); @@ -3949,7 +4581,7 @@ class basic_json { if (not pos.m_it.primitive_iterator.is_begin()) { - throw std::out_of_range("iterator out of range"); + JSON_THROW(invalid_iterator::create(205, "iterator out of range")); } if (is_string()) @@ -3979,7 +4611,7 @@ class basic_json default: { - throw std::domain_error("cannot use erase() with " + type_name()); + JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); } } @@ -4006,11 +4638,11 @@ class basic_json @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. - @throw std::domain_error if called on a `null` value; example: `"cannot - use erase() with null"` - @throw std::domain_error if called on iterators which does not belong to - the current JSON value; example: `"iterators do not fit current value"` - @throw std::out_of_range if called on a primitive type with invalid + @throw type_error.307 if called on a `null` value; example: `"cannot use + erase() with null"` + @throw invalid_iterator.203 if called on iterators which does not belong + to the current JSON value; example: `"iterators do not fit current value"` + @throw invalid_iterator.204 if called on a primitive type with invalid iterators (i.e., if `first != begin()` and `last != end()`); example: `"iterators out of range"` @@ -4041,7 +4673,7 @@ class basic_json // make sure iterator fits the current value if (this != first.m_object or this != last.m_object) { - throw std::domain_error("iterators do not fit current value"); + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); } IteratorType result = end(); @@ -4056,7 +4688,7 @@ class basic_json { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); } if (is_string()) @@ -4088,7 +4720,7 @@ class basic_json default: { - throw std::domain_error("cannot use erase() with " + type_name()); + JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); } } @@ -4109,7 +4741,7 @@ class basic_json @post References and iterators to the erased elements are invalidated. Other references and iterators are not affected. - @throw std::domain_error when called on a type other than JSON object; + @throw type_error.307 when called on a type other than JSON object; example: `"cannot use erase() with null"` @complexity `log(size()) + count(key)` @@ -4131,10 +4763,8 @@ class basic_json { return m_value.object->erase(key); } - else - { - throw std::domain_error("cannot use erase() with " + type_name()); - } + + JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); } /*! @@ -4144,9 +4774,9 @@ class basic_json @param[in] idx index of the element to remove - @throw std::domain_error when called on a type other than JSON array; + @throw type_error.307 when called on a type other than JSON object; example: `"cannot use erase() with null"` - @throw std::out_of_range when `idx >= size()`; example: `"array index 17 + @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 is out of range"` @complexity Linear in distance between @a idx and the end of the container. @@ -4168,14 +4798,14 @@ class basic_json { if (idx >= size()) { - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); } m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else { - throw std::domain_error("cannot use erase() with " + type_name()); + JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); } } @@ -4877,7 +5507,7 @@ class basic_json @param[in] val the value to add to the JSON array - @throw std::domain_error when called on a type other than JSON array or + @throw type_error.308 when called on a type other than JSON array or null; example: `"cannot use push_back() with number"` @complexity Amortized constant. @@ -4893,7 +5523,7 @@ class basic_json // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); } // transform null object into an array @@ -4929,7 +5559,7 @@ class basic_json // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); } // transform null object into an array @@ -4963,7 +5593,7 @@ class basic_json @param[in] val the value to add to the JSON object - @throw std::domain_error when called on a type other than JSON object or + @throw type_error.308 when called on a type other than JSON object or null; example: `"cannot use push_back() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @@ -4979,7 +5609,7 @@ class basic_json // push_back only works for null objects or objects if (not(is_null() or is_object())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); } // transform null object into an object @@ -5017,7 +5647,7 @@ class basic_json @ref push_back(const typename object_t::value_type&). Otherwise, @a init is converted to a JSON value and added using @ref push_back(basic_json&&). - @param init an initializer list + @param[in] init an initializer list @complexity Linear in the size of the initializer list @a init. @@ -5062,7 +5692,7 @@ class basic_json @param[in] args arguments to forward to a constructor of @ref basic_json @tparam Args compatible types to create a @ref basic_json object - @throw std::domain_error when called on a type other than JSON array or + @throw type_error.311 when called on a type other than JSON array or null; example: `"cannot use emplace_back() with number"` @complexity Amortized constant. @@ -5079,7 +5709,7 @@ class basic_json // emplace_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use emplace_back() with " + type_name()); + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + type_name())); } // transform null object into an array @@ -5097,8 +5727,8 @@ class basic_json /*! @brief add an object to an object if key does not exist - Inserts a new element into a JSON object constructed in-place with the given - @a args if there is no element with the key in the container. If the + Inserts a new element into a JSON object constructed in-place with the + given @a args if there is no element with the key in the container. If the function is called on a JSON null value, an empty object is created before appending the value created from @a args. @@ -5109,7 +5739,7 @@ class basic_json already-existing element if no insertion happened, and a bool denoting whether the insertion took place. - @throw std::domain_error when called on a type other than JSON object or + @throw type_error.311 when called on a type other than JSON object or null; example: `"cannot use emplace() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @@ -5127,7 +5757,7 @@ class basic_json // emplace only works for null objects or arrays if (not(is_null() or is_object())) { - throw std::domain_error("cannot use emplace() with " + type_name()); + JSON_THROW(type_error::create(311, "cannot use emplace() with " + type_name())); } // transform null object into an object @@ -5158,13 +5788,13 @@ class basic_json @param[in] val element to insert @return iterator pointing to the inserted @a val. - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error.309 if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` - @complexity Constant plus linear in the distance between pos and end of the - container. + @complexity Constant plus linear in the distance between @a pos and end of + the container. @liveexample{The example shows how `insert()` is used.,insert} @@ -5178,7 +5808,7 @@ class basic_json // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); } // insert to array and return iterator @@ -5186,10 +5816,8 @@ class basic_json result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); } /*! @@ -5213,10 +5841,10 @@ class basic_json @return iterator pointing to the first element inserted, or @a pos if `cnt==0` - @throw std::domain_error if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @complexity Linear in @a cnt plus linear in the distance between @a pos and end of the container. @@ -5233,7 +5861,7 @@ class basic_json // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); } // insert to array and return iterator @@ -5241,10 +5869,8 @@ class basic_json result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); } /*! @@ -5257,13 +5883,13 @@ class basic_json @param[in] first begin of the range of elements to insert @param[in] last end of the range of elements to insert - @throw std::domain_error if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` - @throw std::domain_error if @a first and @a last do not belong to the same - JSON value; example: `"iterators do not fit"` - @throw std::domain_error if @a first or @a last are iterators into + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + @throw invalid_iterator.211 if @a first or @a last are iterators into container for which insert is called; example: `"passed iterators may not belong to container"` @@ -5282,24 +5908,24 @@ class basic_json // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); } // check if range iterators belong to the same JSON object if (first.m_object != last.m_object) { - throw std::domain_error("iterators do not fit"); + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); } if (first.m_object == this or last.m_object == this) { - throw std::domain_error("passed iterators may not belong to container"); + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); } // insert to array and return iterator @@ -5320,10 +5946,10 @@ class basic_json the end() iterator @param[in] ilist initializer list to insert the values from - @throw std::domain_error if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @return iterator pointing to the first element inserted, or @a pos if `ilist` is empty @@ -5340,13 +5966,13 @@ class basic_json // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); } // insert to array and return iterator @@ -5355,6 +5981,52 @@ class basic_json return result; } + /*! + @brief inserts elements + + Inserts elements from range `[first, last)`. + + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.309 if called on JSON values other than objects; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if iterator @a first or @a last does does not + point to an object; example: `"iterators first and last must point to + objects"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + + @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number + of elements to insert. + + @liveexample{The example shows how `insert()` is used.,insert__range_object} + + @since version 3.0.0 + */ + void insert(const_iterator first, const_iterator last) + { + // insert only works for objects + if (not is_object()) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); + } + + // check if range iterators belong to the same JSON object + if (first.m_object != last.m_object) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + // passed iterators must belong to objects + if (not first.m_object->is_object() or not first.m_object->is_object()) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + } + /*! @brief exchanges the values @@ -5394,7 +6066,7 @@ class basic_json @param[in,out] other array to exchange the contents with - @throw std::domain_error when JSON value is not an array; example: `"cannot + @throw type_error.310 when JSON value is not an array; example: `"cannot use swap() with string"` @complexity Constant. @@ -5413,7 +6085,7 @@ class basic_json } else { - throw std::domain_error("cannot use swap() with " + type_name()); + JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); } } @@ -5427,7 +6099,7 @@ class basic_json @param[in,out] other object to exchange the contents with - @throw std::domain_error when JSON value is not an object; example: + @throw type_error.310 when JSON value is not an object; example: `"cannot use swap() with string"` @complexity Constant. @@ -5446,7 +6118,7 @@ class basic_json } else { - throw std::domain_error("cannot use swap() with " + type_name()); + JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); } } @@ -5460,7 +6132,7 @@ class basic_json @param[in,out] other string to exchange the contents with - @throw std::domain_error when JSON value is not a string; example: `"cannot + @throw type_error.310 when JSON value is not a string; example: `"cannot use swap() with boolean"` @complexity Constant. @@ -5479,13 +6151,13 @@ class basic_json } else { - throw std::domain_error("cannot use swap() with " + type_name()); + JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); } } /// @} - + public: ////////////////////////////////////////// // lexicographical comparison operators // ////////////////////////////////////////// @@ -5493,64 +6165,198 @@ class basic_json /// @name lexicographical comparison operators /// @{ - private: /*! - @brief comparison operator for JSON types + @brief comparison: equal + + Compares two JSON values for equality according to the following rules: + - Two JSON values are equal if (1) they are from the same type and (2) + their stored values are the same according to their respective + `operator==`. + - Integer and floating-point numbers are automatically converted before + comparison. Floating-point numbers are compared indirectly: two + floating-point numbers `f1` and `f2` are considered equal if neither + `f1 > f2` nor `f2 > f1` holds. Note than two NaN values are always + treated as unequal. + - Two JSON null values are equal. + + @note NaN values never compare equal to themselves or to other NaN values. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether the values @a lhs and @a rhs are equal + + @complexity Linear. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__equal} + + @since version 1.0.0 + */ + friend bool operator==(const_reference lhs, const_reference rhs) noexcept + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + { + return *lhs.m_value.array == *rhs.m_value.array; + } + case value_t::object: + { + return *lhs.m_value.object == *rhs.m_value.object; + } + case value_t::null: + { + return true; + } + case value_t::string: + { + return *lhs.m_value.string == *rhs.m_value.string; + } + case value_t::boolean: + { + return lhs.m_value.boolean == rhs.m_value.boolean; + } + case value_t::number_integer: + { + return lhs.m_value.number_integer == rhs.m_value.number_integer; + } + case value_t::number_unsigned: + { + return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; + } + case value_t::number_float: + { + return lhs.m_value.number_float == rhs.m_value.number_float; + } + default: + { + return false; + } + } + } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; + } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); + } + + return false; + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs == basic_json(rhs)); + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) == rhs); + } + + /*! + @brief comparison: not equal + + Compares two JSON values for inequality by calculating `not (lhs == rhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether the values @a lhs and @a rhs are not equal - Returns an ordering that is similar to Python: - - order: null < boolean < number < object < array < string - - furthermore, each type is not smaller than itself + @complexity Linear. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__notequal} @since version 1.0.0 */ - friend bool operator<(const value_t lhs, const value_t rhs) noexcept + friend bool operator!=(const_reference lhs, const_reference rhs) noexcept { - static constexpr std::array order = {{ - 0, // null - 3, // object - 4, // array - 5, // string - 1, // boolean - 2, // integer - 2, // unsigned - 2, // float - } - }; + return not (lhs == rhs); + } - // discarded values are not comparable - if (lhs == value_t::discarded or rhs == value_t::discarded) - { - return false; - } + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs != basic_json(rhs)); + } - return order[static_cast(lhs)] < order[static_cast(rhs)]; + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) != rhs); } - public: /*! - @brief comparison: equal + @brief comparison: less than - Compares two JSON values for equality according to the following rules: - - Two JSON values are equal if (1) they are from the same type and (2) - their stored values are the same. + Compares whether one JSON value @a lhs is less than another JSON value @a + rhs according to the following rules: + - If @a lhs and @a rhs have the same type, the values are compared using + the default `<` operator. - Integer and floating-point numbers are automatically converted before - comparison. Floating-point numbers are compared indirectly: two - floating-point numbers `f1` and `f2` are considered equal if neither - `f1 > f2` nor `f2 > f1` holds. - - Two JSON null values are equal. + comparison + - In case @a lhs and @a rhs have different types, the values are ignored + and the order of the types is considered, see + @ref operator<(const value_t, const value_t). @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are equal + @return whether @a lhs is less than @a rhs @complexity Linear. @liveexample{The example demonstrates comparing several JSON - types.,operator__equal} + types.,operator__less} @since version 1.0.0 */ - friend bool operator==(const_reference lhs, const_reference rhs) noexcept + friend bool operator<(const_reference lhs, const_reference rhs) noexcept { const auto lhs_type = lhs.type(); const auto rhs_type = rhs.type(); @@ -5561,35 +6367,35 @@ class basic_json { case value_t::array: { - return *lhs.m_value.array == *rhs.m_value.array; + return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { - return *lhs.m_value.object == *rhs.m_value.object; + return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: { - return true; + return false; } case value_t::string: { - return *lhs.m_value.string == *rhs.m_value.string; + return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: { - return lhs.m_value.boolean == rhs.m_value.boolean; + return lhs.m_value.boolean < rhs.m_value.boolean; } case value_t::number_integer: { - return lhs.m_value.number_integer == rhs.m_value.number_integer; + return lhs.m_value.number_integer < rhs.m_value.number_integer; } case value_t::number_unsigned: { - return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; + return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; } case value_t::number_float: { - return lhs.m_value.number_float == rhs.m_value.number_float; + return lhs.m_value.number_float < rhs.m_value.number_float; } default: { @@ -5599,295 +6405,786 @@ class basic_json } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { - return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; + return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); + return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); } else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); + return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; + return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) + else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; } - return false; + // We only reach this line if we cannot compare values. In that case, + // we compare types. Note we have to call the operator explicitly, + // because MSVC has problems otherwise. + return operator<(lhs_type, rhs_type); } /*! - @brief comparison: equal + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs < basic_json(rhs)); + } + + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) < rhs); + } - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `v.is_null()`. + /*! + @brief comparison: less than or equal - @param[in] v JSON value to consider - @return whether @a v is null + Compares whether one JSON value @a lhs is less than or equal to another + JSON value by calculating `not (rhs < lhs)`. - @complexity Constant. + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is less than or equal to @a rhs + + @complexity Linear. - @liveexample{The example compares several JSON types to the null pointer. - ,operator__equal__nullptr_t} + @liveexample{The example demonstrates comparing several JSON + types.,operator__greater} @since version 1.0.0 */ - friend bool operator==(const_reference v, std::nullptr_t) noexcept + friend bool operator<=(const_reference lhs, const_reference rhs) noexcept { - return v.is_null(); + return not (rhs < lhs); } /*! - @brief comparison: equal - @copydoc operator==(const_reference, std::nullptr_t) + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) */ - friend bool operator==(std::nullptr_t, const_reference v) noexcept + template::value, int>::type = 0> + friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept { - return v.is_null(); + return (lhs <= basic_json(rhs)); } /*! - @brief comparison: not equal + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) <= rhs); + } - Compares two JSON values for inequality by calculating `not (lhs == rhs)`. + /*! + @brief comparison: greater than + + Compares whether one JSON value @a lhs is greater than another + JSON value by calculating `not (lhs <= rhs)`. @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are not equal + @return whether @a lhs is greater than to @a rhs @complexity Linear. @liveexample{The example demonstrates comparing several JSON - types.,operator__notequal} + types.,operator__lessequal} @since version 1.0.0 */ - friend bool operator!=(const_reference lhs, const_reference rhs) noexcept + friend bool operator>(const_reference lhs, const_reference rhs) noexcept { - return not (lhs == rhs); + return not (lhs <= rhs); } /*! - @brief comparison: not equal + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs > basic_json(rhs)); + } + + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) > rhs); + } - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `not v.is_null()`. + /*! + @brief comparison: greater than or equal - @param[in] v JSON value to consider - @return whether @a v is not null + Compares whether one JSON value @a lhs is greater than or equal to another + JSON value by calculating `not (lhs < rhs)`. - @complexity Constant. + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is greater than or equal to @a rhs + + @complexity Linear. - @liveexample{The example compares several JSON types to the null pointer. - ,operator__notequal__nullptr_t} + @liveexample{The example demonstrates comparing several JSON + types.,operator__greaterequal} @since version 1.0.0 */ - friend bool operator!=(const_reference v, std::nullptr_t) noexcept + friend bool operator>=(const_reference lhs, const_reference rhs) noexcept { - return not v.is_null(); + return not (lhs < rhs); } /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, std::nullptr_t) + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) */ - friend bool operator!=(std::nullptr_t, const_reference v) noexcept + template::value, int>::type = 0> + friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept { - return not v.is_null(); + return (lhs >= basic_json(rhs)); } /*! - @brief comparison: less than + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) >= rhs); + } - Compares whether one JSON value @a lhs is less than another JSON value @a - rhs according to the following rules: - - If @a lhs and @a rhs have the same type, the values are compared using - the default `<` operator. - - Integer and floating-point numbers are automatically converted before - comparison - - In case @a lhs and @a rhs have different types, the values are ignored - and the order of the types is considered, see - @ref operator<(const value_t, const value_t). + /// @} - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than @a rhs - @complexity Linear. + /////////////////// + // serialization // + /////////////////// - @liveexample{The example demonstrates comparing several JSON - types.,operator__less} + /// @name serialization + /// @{ - @since version 1.0.0 + private: + /*! + @brief wrapper around the serialization functions */ - friend bool operator<(const_reference lhs, const_reference rhs) noexcept + class serializer { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); + private: + serializer(const serializer&) = delete; + serializer& operator=(const serializer&) = delete; - if (lhs_type == rhs_type) + public: + /*! + @param[in] s output stream to serialize to + */ + serializer(std::ostream& s) + : o(s), loc(std::localeconv()), + thousands_sep(!loc->thousands_sep ? '\0' : loc->thousands_sep[0]), + decimal_point(!loc->decimal_point ? '\0' : loc->decimal_point[0]) + {} + + /*! + @brief internal implementation of the serialization function + + This function is called by the public member function dump and + organizes the serialization internally. The indentation level is + propagated as additional parameter. In case of arrays and objects, the + function is called recursively. + + - strings and object keys are escaped using `escape_string()` + - integer numbers are converted implicitly via `operator<<` + - floating-point numbers are converted to a string using `"%g"` format + + @param[in] val value to serialize + @param[in] pretty_print whether the output shall be pretty-printed + @param[in] indent_step the indent level + @param[in] current_indent the current indent level (only used internally) + */ + void dump(const basic_json& val, + const bool pretty_print, + const unsigned int indent_step, + const unsigned int current_indent = 0) { - switch (lhs_type) + switch (val.m_type) { - case value_t::array: - { - return *lhs.m_value.array < *rhs.m_value.array; - } case value_t::object: { - return *lhs.m_value.object < *rhs.m_value.object; + if (val.m_value.object->empty()) + { + o.write("{}", 2); + return; + } + + if (pretty_print) + { + o.write("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (indent_string.size() < new_indent) + { + indent_string.resize(new_indent, ' '); + } + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o.write(indent_string.c_str(), static_cast(new_indent)); + o.put('\"'); + dump_escaped(i->first); + o.write("\": ", 3); + dump(i->second, true, indent_step, new_indent); + o.write(",\n", 2); + } + + // last element + assert(i != val.m_value.object->cend()); + o.write(indent_string.c_str(), static_cast(new_indent)); + o.put('\"'); + dump_escaped(i->first); + o.write("\": ", 3); + dump(i->second, true, indent_step, new_indent); + + o.put('\n'); + o.write(indent_string.c_str(), static_cast(current_indent)); + o.put('}'); + } + else + { + o.put('{'); + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o.put('\"'); + dump_escaped(i->first); + o.write("\":", 2); + dump(i->second, false, indent_step, current_indent); + o.put(','); + } + + // last element + assert(i != val.m_value.object->cend()); + o.put('\"'); + dump_escaped(i->first); + o.write("\":", 2); + dump(i->second, false, indent_step, current_indent); + + o.put('}'); + } + + return; } - case value_t::null: + + case value_t::array: { - return false; + if (val.m_value.array->empty()) + { + o.write("[]", 2); + return; + } + + if (pretty_print) + { + o.write("[\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (indent_string.size() < new_indent) + { + indent_string.resize(new_indent, ' '); + } + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) + { + o.write(indent_string.c_str(), static_cast(new_indent)); + dump(*i, true, indent_step, new_indent); + o.write(",\n", 2); + } + + // last element + assert(not val.m_value.array->empty()); + o.write(indent_string.c_str(), static_cast(new_indent)); + dump(val.m_value.array->back(), true, indent_step, new_indent); + + o.put('\n'); + o.write(indent_string.c_str(), static_cast(current_indent)); + o.put(']'); + } + else + { + o.put('['); + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) + { + dump(*i, false, indent_step, current_indent); + o.put(','); + } + + // last element + assert(not val.m_value.array->empty()); + dump(val.m_value.array->back(), false, indent_step, current_indent); + + o.put(']'); + } + + return; } + case value_t::string: { - return *lhs.m_value.string < *rhs.m_value.string; + o.put('\"'); + dump_escaped(*val.m_value.string); + o.put('\"'); + return; } + case value_t::boolean: { - return lhs.m_value.boolean < rhs.m_value.boolean; + if (val.m_value.boolean) + { + o.write("true", 4); + } + else + { + o.write("false", 5); + } + return; } + case value_t::number_integer: { - return lhs.m_value.number_integer < rhs.m_value.number_integer; + dump_integer(val.m_value.number_integer); + return; } + case value_t::number_unsigned: { - return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; + dump_integer(val.m_value.number_unsigned); + return; } + case value_t::number_float: { - return lhs.m_value.number_float < rhs.m_value.number_float; + dump_float(val.m_value.number_float); + return; } - default: + + case value_t::discarded: { - return false; + o.write("", 11); + return; + } + + case value_t::null: + { + o.write("null", 4); + return; } } } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); + + private: + /*! + @brief calculates the extra space to escape a JSON string + + @param[in] s the string to escape + @return the number of characters required to escape string @a s + + @complexity Linear in the length of string @a s. + */ + static std::size_t extra_space(const string_t& s) noexcept + { + return std::accumulate(s.begin(), s.end(), size_t{}, + [](size_t res, typename string_t::value_type c) + { + switch (c) + { + case '"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + { + // from c (1 byte) to \x (2 bytes) + return res + 1; + } + + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x0b: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + { + // from c (1 byte) to \uxxxx (6 bytes) + return res + 5; + } + + default: + { + return res; + } + } + }); } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) + + /*! + @brief dump escaped string + + Escape a string by replacing certain special characters by a sequence + of an escape character (backslash) and another character and other + control characters by a sequence of "\u" followed by a four-digit hex + representation. The escaped string is written to output stream @a o. + + @param[in] s the string to escape + + @complexity Linear in the length of string @a s. + */ + void dump_escaped(const string_t& s) const { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; + const auto space = extra_space(s); + if (space == 0) + { + o.write(s.c_str(), static_cast(s.size())); + return; + } + + // create a result string of necessary size + string_t result(s.size() + space, '\\'); + std::size_t pos = 0; + + for (const auto& c : s) + { + switch (c) + { + // quotation mark (0x22) + case '"': + { + result[pos + 1] = '"'; + pos += 2; + break; + } + + // reverse solidus (0x5c) + case '\\': + { + // nothing to change + pos += 2; + break; + } + + // backspace (0x08) + case '\b': + { + result[pos + 1] = 'b'; + pos += 2; + break; + } + + // formfeed (0x0c) + case '\f': + { + result[pos + 1] = 'f'; + pos += 2; + break; + } + + // newline (0x0a) + case '\n': + { + result[pos + 1] = 'n'; + pos += 2; + break; + } + + // carriage return (0x0d) + case '\r': + { + result[pos + 1] = 'r'; + pos += 2; + break; + } + + // horizontal tab (0x09) + case '\t': + { + result[pos + 1] = 't'; + pos += 2; + break; + } + + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x0b: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + { + // convert a number 0..15 to its hex representation + // (0..f) + static const char hexify[16] = + { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + + // print character c as \uxxxx + for (const char m : + { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] + }) + { + result[++pos] = m; + } + + ++pos; + break; + } + + default: + { + // all other characters are added as-is + result[pos++] = c; + break; + } + } + } + + assert(pos == s.size() + space); + o.write(result.c_str(), static_cast(result.size())); } - // We only reach this line if we cannot compare values. In that case, - // we compare types. Note we have to call the operator explicitly, - // because MSVC has problems otherwise. - return operator<(lhs_type, rhs_type); - } + /*! + @brief dump an integer - /*! - @brief comparison: less than or equal + Dump a given integer to output stream @a o. Works internally with + @a number_buffer. - Compares whether one JSON value @a lhs is less than or equal to another - JSON value by calculating `not (rhs < lhs)`. + @param[in] x integer number (signed or unsigned) to dump + @tparam NumberType either @a number_integer_t or @a number_unsigned_t + */ + template::value or + std::is_same::value, int> = 0> + void dump_integer(NumberType x) + { + // special case for "0" + if (x == 0) + { + o.put('0'); + return; + } - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than or equal to @a rhs + const bool is_negative = x < 0; + size_t i = 0; - @complexity Linear. + // spare 1 byte for '\0' + while (x != 0 and i < number_buffer.size() - 1) + { + const auto digit = std::labs(static_cast(x % 10)); + number_buffer[i++] = static_cast('0' + digit); + x /= 10; + } - @liveexample{The example demonstrates comparing several JSON - types.,operator__greater} + // make sure the number has been processed completely + assert(x == 0); - @since version 1.0.0 - */ - friend bool operator<=(const_reference lhs, const_reference rhs) noexcept - { - return not (rhs < lhs); - } + if (is_negative) + { + // make sure there is capacity for the '-' + assert(i < number_buffer.size() - 2); + number_buffer[i++] = '-'; + } - /*! - @brief comparison: greater than + std::reverse(number_buffer.begin(), number_buffer.begin() + i); + o.write(number_buffer.data(), static_cast(i)); + } - Compares whether one JSON value @a lhs is greater than another - JSON value by calculating `not (lhs <= rhs)`. + /*! + @brief dump a floating-point number - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than to @a rhs + Dump a given floating-point number to output stream @a o. Works + internally with @a number_buffer. - @complexity Linear. + @param[in] x floating-point number to dump + */ + void dump_float(number_float_t x) + { + // NaN / inf + if (not std::isfinite(x) or std::isnan(x)) + { + o.write("null", 4); + return; + } - @liveexample{The example demonstrates comparing several JSON - types.,operator__lessequal} + // special case for 0.0 and -0.0 + if (x == 0) + { + if (std::signbit(x)) + { + o.write("-0.0", 4); + } + else + { + o.write("0.0", 3); + } + return; + } - @since version 1.0.0 - */ - friend bool operator>(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs <= rhs); - } + // get number of digits for a text -> float -> text round-trip + static constexpr auto d = std::numeric_limits::digits10; - /*! - @brief comparison: greater than or equal + // the actual conversion + std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), + "%.*g", d, x); - Compares whether one JSON value @a lhs is greater than or equal to another - JSON value by calculating `not (lhs < rhs)`. + // negative value indicates an error + assert(len > 0); + // check if buffer was large enough + assert(static_cast(len) < number_buffer.size()); - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than or equal to @a rhs + // erase thousands separator + if (thousands_sep != '\0') + { + const auto end = std::remove(number_buffer.begin(), + number_buffer.begin() + len, + thousands_sep); + std::fill(end, number_buffer.end(), '\0'); + assert((end - number_buffer.begin()) <= len); + len = (end - number_buffer.begin()); + } - @complexity Linear. + // convert decimal point to '.' + if (decimal_point != '\0' and decimal_point != '.') + { + for (auto& c : number_buffer) + { + if (c == decimal_point) + { + c = '.'; + break; + } + } + } - @liveexample{The example demonstrates comparing several JSON - types.,operator__greaterequal} + o.write(number_buffer.data(), static_cast(len)); - @since version 1.0.0 - */ - friend bool operator>=(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs < rhs); - } + // determine if need to append ".0" + const bool value_is_int_like = std::none_of(number_buffer.begin(), + number_buffer.begin() + len + 1, + [](char c) + { + return c == '.' or c == 'e'; + }); - /// @} + if (value_is_int_like) + { + o.write(".0", 2); + } + } + private: + /// the output of the serializer + std::ostream& o; - /////////////////// - // serialization // - /////////////////// + /// a (hopefully) large enough character buffer + std::array number_buffer{{}}; - /// @name serialization - /// @{ + /// the locale + const std::lconv* loc = nullptr; + /// the locale's thousand separator character + const char thousands_sep = '\0'; + /// the locale's decimal point character + const char decimal_point = '\0'; + + /// the indentation string + string_t indent_string = string_t(512, ' '); + }; + public: /*! @brief serialize to stream @@ -5898,10 +7195,6 @@ class basic_json `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. - @note During serializaion, the locale and the precision of the output - stream @a o are changed. The original values are restored when the - function returns. - @param[in,out] o stream to serialize to @param[in] j JSON value to serialize @@ -5923,29 +7216,20 @@ class basic_json // reset width to 0 for subsequent calls to this stream o.width(0); - // fix locale problems - const auto old_locale = o.imbue(std::locale::classic()); - // set precision - - // 6, 15 or 16 digits of precision allows round-trip IEEE 754 - // string->float->string, string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - const auto old_precision = o.precision(std::numeric_limits::digits10); - // do the actual serialization - j.dump(o, pretty_print, static_cast(indentation)); - - // reset locale and precision - o.imbue(old_locale); - o.precision(old_precision); + serializer s(o); + s.dump(j, pretty_print, static_cast(indentation)); return o; } /*! @brief serialize to stream - @copydoc operator<<(std::ostream&, const basic_json&) + @deprecated This stream operator is deprecated and will be removed in a + future version of the library. Please use + @ref std::ostream& operator<<(std::ostream&, const basic_json&) + instead; that is, replace calls like `j >> o;` with `o << j;`. */ + JSON_DEPRECATED friend std::ostream& operator>>(const basic_json& j, std::ostream& o) { return o << j; @@ -5977,6 +7261,11 @@ class basic_json @return result of the deserialization + @throw parse_error.101 if a parse error occurs; example: `""unexpected end + of input; expected string literal""` + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @@ -6007,6 +7296,10 @@ class basic_json @return result of the deserialization + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @@ -6043,6 +7336,11 @@ class basic_json @return result of the deserialization + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + @throw parse_error.111 if input stream is in a bad state + @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @@ -6102,6 +7400,10 @@ class basic_json @return result of the deserialization + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @@ -6122,7 +7424,7 @@ class basic_json { // assertion to check that the iterator range is indeed contiguous, // see http://stackoverflow.com/a/35008842/266378 for more discussion - assert(std::accumulate(first, last, std::make_pair(true, 0), + assert(std::accumulate(first, last, std::pair(true, 0), [&first](std::pair res, decltype(*first) val) { res.first &= (val == *(std::next(std::addressof(*first), res.second++))); @@ -6172,6 +7474,10 @@ class basic_json @return result of the deserialization + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @@ -6192,8 +7498,22 @@ class basic_json static basic_json parse(const ContiguousContainer& c, const parser_callback_t cb = nullptr) { - // delegate the call to the iterator-range parse overload - return parse(std::begin(c), std::end(c), cb); + // delegate the call to the iterator-range parse overload + return parse(std::begin(c), std::end(c), cb); + } + + /*! + @brief deserialize from stream + @deprecated This stream operator is deprecated and will be removed in a + future version of the library. Please use + @ref std::istream& operator>>(std::istream&, basic_json&) + instead; that is, replace calls like `j << i;` with `i >> j;`. + */ + JSON_DEPRECATED + friend std::istream& operator<<(basic_json& j, std::istream& i) + { + j = parser(i).parse(); + return i; } /*! @@ -6204,7 +7524,10 @@ class basic_json @param[in,out] i input stream to read a serialized JSON value from @param[in,out] j JSON value to write the deserialized input to - @throw std::invalid_argument in case of parse errors + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + @throw parse_error.111 if input stream is in a bad state @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. @@ -6219,16 +7542,6 @@ class basic_json @since version 1.0.0 */ - friend std::istream& operator<<(basic_json& j, std::istream& i) - { - j = parser(i).parse(); - return i; - } - - /*! - @brief deserialize from stream - @copydoc operator<<(basic_json&, std::istream&) - */ friend std::istream& operator>>(std::istream& i, basic_json& j) { j = parser(i).parse(); @@ -6245,6 +7558,11 @@ class basic_json /// @{ private: + /*! + @note Some code in the switch cases has been copied, because otherwise + copilers would complain about implicit fallthrough and there is no + portable attribute to mute such warnings. + */ template static void add_to_vector(std::vector& vec, size_t bytes, const T number) { @@ -6254,24 +7572,31 @@ class basic_json { case 8: { - vec.push_back(static_cast((number >> 070) & 0xff)); - vec.push_back(static_cast((number >> 060) & 0xff)); - vec.push_back(static_cast((number >> 050) & 0xff)); - vec.push_back(static_cast((number >> 040) & 0xff)); - // intentional fall-through + vec.push_back(static_cast((static_cast(number) >> 070) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); + vec.push_back(static_cast((number >> 030) & 0xff)); + vec.push_back(static_cast((number >> 020) & 0xff)); + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; } case 4: { vec.push_back(static_cast((number >> 030) & 0xff)); vec.push_back(static_cast((number >> 020) & 0xff)); - // intentional fall-through + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; } case 2: { vec.push_back(static_cast((number >> 010) & 0xff)); - // intentional fall-through + vec.push_back(static_cast(number & 0xff)); + break; } case 1: @@ -6296,7 +7621,7 @@ class basic_json @tparam T the integral return type - @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the + @throw parse_error.110 if there are less than sizeof(T)+1 bytes in the vector @a vec to read In the for loop, the bytes from the vector are copied in reverse order into @@ -6321,13 +7646,11 @@ class basic_json template static T get_from_vector(const std::vector& vec, const size_t current_index) { - if (current_index + sizeof(T) + 1 > vec.size()) - { - throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector"); - } + // check if we can read sizeof(T) bytes starting the next index + check_length(vec.size(), sizeof(T), current_index + 1); T result; - uint8_t* ptr = reinterpret_cast(&result); + auto* ptr = reinterpret_cast(&result); for (size_t i = 0; i < sizeof(T); ++i) { *ptr++ = vec[current_index + sizeof(T) - i]; @@ -6368,32 +7691,33 @@ class basic_json if (j.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. + // signed integers and unsigned integers. Therefore, we + // used the code from the value_t::number_unsigned case + // here. if (j.m_value.number_unsigned < 128) { // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT8_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT16_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT32_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT64_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 v.push_back(0xcf); @@ -6407,25 +7731,25 @@ class basic_json // negative fixnum add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 v.push_back(0xd0); add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 v.push_back(0xd1); add_to_vector(v, 2, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 v.push_back(0xd2); add_to_vector(v, 4, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 v.push_back(0xd3); @@ -6442,25 +7766,25 @@ class basic_json // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT8_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT16_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT32_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT64_MAX) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 v.push_back(0xcf); @@ -6473,7 +7797,7 @@ class basic_json { // float 64 v.push_back(0xcb); - const uint8_t* helper = reinterpret_cast(&(j.m_value.number_float)); + const auto* helper = reinterpret_cast(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); @@ -6617,19 +7941,19 @@ class basic_json { add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT8_MAX) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { v.push_back(0x18); // one-byte uint8_t add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT16_MAX) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { v.push_back(0x19); // two-byte uint16_t add_to_vector(v, 2, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT32_MAX) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { v.push_back(0x1a); // four-byte uint32_t @@ -6644,26 +7968,26 @@ class basic_json } else { - // The conversions below encode the sign in the first byte, - // and the value is converted to a positive number. + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. const auto positive_number = -1 - j.m_value.number_integer; if (j.m_value.number_integer >= -24) { v.push_back(static_cast(0x20 + positive_number)); } - else if (positive_number <= UINT8_MAX) + else if (positive_number <= (std::numeric_limits::max)()) { // int 8 v.push_back(0x38); add_to_vector(v, 1, positive_number); } - else if (positive_number <= UINT16_MAX) + else if (positive_number <= (std::numeric_limits::max)()) { // int 16 v.push_back(0x39); add_to_vector(v, 2, positive_number); } - else if (positive_number <= UINT32_MAX) + else if (positive_number <= (std::numeric_limits::max)()) { // int 32 v.push_back(0x3a); @@ -6716,7 +8040,7 @@ class basic_json { // Double-Precision Float v.push_back(0xfb); - const uint8_t* helper = reinterpret_cast(&(j.m_value.number_float)); + const auto* helper = reinterpret_cast(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); @@ -6729,7 +8053,7 @@ class basic_json const auto N = j.m_value.string->size(); if (N <= 0x17) { - v.push_back(0x60 + N); // 1 byte for string + size + v.push_back(static_cast(0x60 + N)); // 1 byte for string + size } else if (N <= 0xff) { @@ -6765,7 +8089,7 @@ class basic_json const auto N = j.m_value.array->size(); if (N <= 0x17) { - v.push_back(0x80 + N); // 1 byte for array + size + v.push_back(static_cast(0x80 + N)); // 1 byte for array + size } else if (N <= 0xff) { @@ -6803,7 +8127,7 @@ class basic_json const auto N = j.m_value.object->size(); if (N <= 0x17) { - v.push_back(0xa0 + N); // 1 byte for object + size + v.push_back(static_cast(0xa0 + N)); // 1 byte for object + size } else if (N <= 0xff) { @@ -6850,12 +8174,12 @@ class basic_json To secure the access to the byte vector during CBOR/MessagePack deserialization, bytes are copied from the vector into buffers. This - function checks if the number of bytes to copy (@a len) does not exceed the - size @s size of the vector. Additionally, an @a offset is given from where - to start reading the bytes. + function checks if the number of bytes to copy (@a len) does not exceed + the size @s size of the vector. Additionally, an @a offset is given from + where to start reading the bytes. - This function checks whether reading the bytes is safe; that is, offset is a - valid index in the vector, offset+len + This function checks whether reading the bytes is safe; that is, offset is + a valid index in the vector, offset+len @param[in] size size of the byte vector @param[in] len number of bytes to read @@ -6872,20 +8196,81 @@ class basic_json // simple case: requested length is greater than the vector's length if (len > size or offset > size) { - throw std::out_of_range("len out of range"); + JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); } // second case: adding offset would result in overflow - if ((size > (std::numeric_limits::max() - offset))) + if ((size > ((std::numeric_limits::max)() - offset))) { - throw std::out_of_range("len+offset out of range"); + JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); } // last case: reading past the end of the vector if (len + offset > size) { - throw std::out_of_range("len+offset out of range"); + JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); + } + } + + /*! + @brief check if the next byte belongs to a string + + While parsing a map, the keys must be strings. This function checks if the + current byte is one of the start bytes for a string in MessagePack: + + - 0xa0 - 0xbf: fixstr + - 0xd9: str 8 + - 0xda: str 16 + - 0xdb: str 32 + + @param[in] v MessagePack serialization + @param[in] idx byte index in @a v to check for a string + + @throw parse_error.113 if `v[idx]` does not belong to a string + */ + static void msgpack_expect_string(const std::vector& v, size_t idx) + { + check_length(v.size(), 1, idx); + + const auto byte = v[idx]; + if ((byte >= 0xa0 and byte <= 0xbf) or (byte >= 0xd9 and byte <= 0xdb)) + { + return; + } + + std::stringstream ss; + ss << std::hex << static_cast(v[idx]); + JSON_THROW(parse_error::create(113, idx + 1, "expected a MessagePack string; last byte: 0x" + ss.str())); + } + + /*! + @brief check if the next byte belongs to a string + + While parsing a map, the keys must be strings. This function checks if the + current byte is one of the start bytes for a string in CBOR: + + - 0x60 - 0x77: fixed length + - 0x78 - 0x7b: variable length + - 0x7f: indefinity length + + @param[in] v CBOR serialization + @param[in] idx byte index in @a v to check for a string + + @throw parse_error.113 if `v[idx]` does not belong to a string + */ + static void cbor_expect_string(const std::vector& v, size_t idx) + { + check_length(v.size(), 1, idx); + + const auto byte = v[idx]; + if ((byte >= 0x60 and byte <= 0x7b) or byte == 0x7f) + { + return; } + + std::stringstream ss; + ss << std::hex << static_cast(v[idx]); + JSON_THROW(parse_error::create(113, idx + 1, "expected a CBOR string; last byte: 0x" + ss.str())); } /*! @@ -6896,32 +8281,34 @@ class basic_json @return deserialized JSON value - @throw std::invalid_argument if unsupported features from MessagePack were + @throw parse_error.110 if the given vector ends prematurely + @throw parse_error.112 if unsupported features from MessagePack were used in the given vector @a v or if the input is not valid MessagePack - @throw std::out_of_range if the given vector ends prematurely + @throw parse_error.113 if a string was expected as map key, but not found @sa https://github.com/msgpack/msgpack/blob/master/spec.md */ static basic_json from_msgpack_internal(const std::vector& v, size_t& idx) { - // make sure reading 1 byte is safe - check_length(v.size(), 1, idx); - // store and increment index const size_t current_idx = idx++; + // make sure reading 1 byte is safe + check_length(v.size(), 1, current_idx); + if (v[current_idx] <= 0xbf) { if (v[current_idx] <= 0x7f) // positive fixint { return v[current_idx]; } - else if (v[current_idx] <= 0x8f) // fixmap + if (v[current_idx] <= 0x8f) // fixmap { basic_json result = value_t::object; const size_t len = v[current_idx] & 0x0f; for (size_t i = 0; i < len; ++i) { + msgpack_expect_string(v, idx); std::string key = from_msgpack_internal(v, idx); result[key] = from_msgpack_internal(v, idx); } @@ -6972,8 +8359,8 @@ class basic_json case 0xca: // float 32 { // copy bytes in reverse order into the double variable - check_length(v.size(), sizeof(float), 1); float res; + check_length(v.size(), sizeof(float), current_idx + 1); for (size_t byte = 0; byte < sizeof(float); ++byte) { reinterpret_cast(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; @@ -6985,8 +8372,8 @@ class basic_json case 0xcb: // float 64 { // copy bytes in reverse order into the double variable - check_length(v.size(), sizeof(double), 1); double res; + check_length(v.size(), sizeof(double), current_idx + 1); for (size_t byte = 0; byte < sizeof(double); ++byte) { reinterpret_cast(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; @@ -7101,6 +8488,7 @@ class basic_json idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { + msgpack_expect_string(v, idx); std::string key = from_msgpack_internal(v, idx); result[key] = from_msgpack_internal(v, idx); } @@ -7114,6 +8502,7 @@ class basic_json idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { + msgpack_expect_string(v, idx); std::string key = from_msgpack_internal(v, idx); result[key] = from_msgpack_internal(v, idx); } @@ -7122,7 +8511,9 @@ class basic_json default: { - throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast(v[current_idx]))); + std::stringstream ss; + ss << std::hex << static_cast(v[current_idx]); + JSON_THROW(parse_error::create(112, current_idx + 1, "error reading MessagePack; last byte: 0x" + ss.str())); } } } @@ -7136,9 +8527,10 @@ class basic_json @return deserialized JSON value - @throw std::invalid_argument if unsupported features from CBOR were used in - the given vector @a v or if the input is not valid CBOR - @throw std::out_of_range if the given vector ends prematurely + @throw parse_error.110 if the given vector ends prematurely + @throw parse_error.112 if unsupported features from CBOR were + used in the given vector @a v or if the input is not valid CBOR + @throw parse_error.113 if a string was expected as map key, but not found @sa https://tools.ietf.org/html/rfc7049 */ @@ -7147,7 +8539,10 @@ class basic_json // store and increment index const size_t current_idx = idx++; - switch (v.at(current_idx)) + // make sure reading 1 byte is safe + check_length(v.size(), 1, current_idx); + + switch (v[current_idx]) { // Integer 0x00..0x17 (0..23) case 0x00: @@ -7328,7 +8723,7 @@ class basic_json case 0x7f: // UTF-8 string (indefinite length) { std::string result; - while (v.at(idx) != 0xff) + while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) { string_t s = from_cbor_internal(v, idx); result += s; @@ -7424,7 +8819,7 @@ class basic_json case 0x9f: // array (indefinite length) { basic_json result = value_t::array; - while (v.at(idx) != 0xff) + while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) { result.push_back(from_cbor_internal(v, idx)); } @@ -7463,6 +8858,7 @@ class basic_json const auto len = static_cast(v[current_idx] - 0xa0); for (size_t i = 0; i < len; ++i) { + cbor_expect_string(v, idx); std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } @@ -7476,6 +8872,7 @@ class basic_json idx += 1; // skip 1 size byte for (size_t i = 0; i < len; ++i) { + cbor_expect_string(v, idx); std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } @@ -7489,6 +8886,7 @@ class basic_json idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { + cbor_expect_string(v, idx); std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } @@ -7502,6 +8900,7 @@ class basic_json idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { + cbor_expect_string(v, idx); std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } @@ -7515,6 +8914,7 @@ class basic_json idx += 8; // skip 8 size bytes for (size_t i = 0; i < len; ++i) { + cbor_expect_string(v, idx); std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } @@ -7524,8 +8924,9 @@ class basic_json case 0xbf: // map (indefinite length) { basic_json result = value_t::object; - while (v.at(idx) != 0xff) + while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) { + cbor_expect_string(v, idx); std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } @@ -7551,7 +8952,6 @@ class basic_json case 0xf9: // Half-Precision Float (two-byte IEEE 754) { - check_length(v.size(), 2, 1); idx += 2; // skip two content bytes // code from RFC 7049, Appendix D, Figure 3: @@ -7561,6 +8961,7 @@ class basic_json // include at least decoding support for them even without such // support. An example of a small decoder for half-precision // floating-point numbers in the C language is shown in Fig. 3. + check_length(v.size(), 2, current_idx + 1); const int half = (v[current_idx + 1] << 8) + v[current_idx + 2]; const int exp = (half >> 10) & 0x1f; const int mant = half & 0x3ff; @@ -7575,16 +8976,18 @@ class basic_json } else { - val = mant == 0 ? INFINITY : NAN; + val = mant == 0 + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); } - return half & 0x8000 ? -val : val; + return (half & 0x8000) != 0 ? -val : val; } case 0xfa: // Single-Precision Float (four-byte IEEE 754) { // copy bytes in reverse order into the float variable - check_length(v.size(), sizeof(float), 1); float res; + check_length(v.size(), sizeof(float), current_idx + 1); for (size_t byte = 0; byte < sizeof(float); ++byte) { reinterpret_cast(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; @@ -7595,9 +8998,9 @@ class basic_json case 0xfb: // Double-Precision Float (eight-byte IEEE 754) { - check_length(v.size(), sizeof(double), 1); // copy bytes in reverse order into the double variable double res; + check_length(v.size(), sizeof(double), current_idx + 1); for (size_t byte = 0; byte < sizeof(double); ++byte) { reinterpret_cast(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; @@ -7608,7 +9011,9 @@ class basic_json default: // anything else (0xFF is handled inside the other types) { - throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast(v[current_idx]))); + std::stringstream ss; + ss << std::hex << static_cast(v[current_idx]); + JSON_THROW(parse_error::create(112, current_idx + 1, "error reading CBOR; last byte: 0x" + ss.str())); } } } @@ -7621,6 +9026,58 @@ class basic_json serialization format. MessagePack is a binary serialization format which aims to be more compact than JSON itself, yet more efficient to parse. + The library uses the following mapping from JSON values types to + MessagePack types according to the MessagePack specification: + + JSON value type | value/range | MessagePack type | first byte + --------------- | --------------------------------- | ---------------- | ---------- + null | `null` | nil | 0xc0 + boolean | `true` | true | 0xc3 + boolean | `false` | false | 0xc2 + number_integer | -9223372036854775808..-2147483649 | int64 | 0xd3 + number_integer | -2147483648..-32769 | int32 | 0xd2 + number_integer | -32768..-129 | int16 | 0xd1 + number_integer | -128..-33 | int8 | 0xd0 + number_integer | -32..-1 | negative fixint | 0xe0..0xff + number_integer | 0..127 | positive fixint | 0x00..0x7f + number_integer | 128..255 | uint 8 | 0xcc + number_integer | 256..65535 | uint 16 | 0xcd + number_integer | 65536..4294967295 | uint 32 | 0xce + number_integer | 4294967296..18446744073709551615 | uint 64 | 0xcf + number_unsigned | 0..127 | positive fixint | 0x00..0x7f + number_unsigned | 128..255 | uint 8 | 0xcc + number_unsigned | 256..65535 | uint 16 | 0xcd + number_unsigned | 65536..4294967295 | uint 32 | 0xce + number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xcf + number_float | *any value* | float 64 | 0xcb + string | *length*: 0..31 | fixstr | 0xa0..0xbf + string | *length*: 32..255 | str 8 | 0xd9 + string | *length*: 256..65535 | str 16 | 0xda + string | *length*: 65536..4294967295 | str 32 | 0xdb + array | *size*: 0..15 | fixarray | 0x90..0x9f + array | *size*: 16..65535 | array 16 | 0xdc + array | *size*: 65536..4294967295 | array 32 | 0xdd + object | *size*: 0..15 | fix map | 0x80..0x8f + object | *size*: 16..65535 | map 16 | 0xde + object | *size*: 65536..4294967295 | map 32 | 0xdf + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a MessagePack value. + + @note The following values can **not** be converted to a MessagePack value: + - strings with more than 4294967295 bytes + - arrays with more than 4294967295 elements + - objects with more than 4294967295 elements + + @note The following MessagePack types are not used in the conversion: + - bin 8 - bin 32 (0xc4..0xc6) + - ext 8 - ext 32 (0xc7..0xc9) + - float 32 (0xca) + - fixext 1 - fixext 16 (0xd4..0xd8) + + @note Any MessagePack output created @ref to_msgpack can be successfully + parsed by @ref from_msgpack. + @param[in] j JSON value to serialize @return MessagePack serialization as byte vector @@ -7630,9 +9087,11 @@ class basic_json vector in MessagePack format.,to_msgpack} @sa http://msgpack.org - @sa @ref from_msgpack(const std::vector&) for the analogous - deserialization + @sa @ref from_msgpack(const std::vector&, const size_t) for the + analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format + + @since version 2.0.9 */ static std::vector to_msgpack(const basic_json& j) { @@ -7647,12 +9106,54 @@ class basic_json Deserializes a given byte vector @a v to a JSON value using the MessagePack serialization format. + The library maps MessagePack types to JSON value types as follows: + + MessagePack type | JSON value type | first byte + ---------------- | --------------- | ---------- + positive fixint | number_unsigned | 0x00..0x7f + fixmap | object | 0x80..0x8f + fixarray | array | 0x90..0x9f + fixstr | string | 0xa0..0xbf + nil | `null` | 0xc0 + false | `false` | 0xc2 + true | `true` | 0xc3 + float 32 | number_float | 0xca + float 64 | number_float | 0xcb + uint 8 | number_unsigned | 0xcc + uint 16 | number_unsigned | 0xcd + uint 32 | number_unsigned | 0xce + uint 64 | number_unsigned | 0xcf + int 8 | number_integer | 0xd0 + int 16 | number_integer | 0xd1 + int 32 | number_integer | 0xd2 + int 64 | number_integer | 0xd3 + str 8 | string | 0xd9 + str 16 | string | 0xda + str 32 | string | 0xdb + array 16 | array | 0xdc + array 32 | array | 0xdd + map 16 | object | 0xde + map 32 | object | 0xdf + negative fixint | number_integer | 0xe0-0xff + + @warning The mapping is **incomplete** in the sense that not all + MessagePack types can be converted to a JSON value. The following + MessagePack types are not supported and will yield parse errors: + - bin 8 - bin 32 (0xc4..0xc6) + - ext 8 - ext 32 (0xc7..0xc9) + - fixext 1 - fixext 16 (0xd4..0xd8) + + @note Any MessagePack output created @ref to_msgpack can be successfully + parsed by @ref from_msgpack. + @param[in] v a byte vector in MessagePack format + @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value - @throw std::invalid_argument if unsupported features from MessagePack were + @throw parse_error.110 if the given vector ends prematurely + @throw parse_error.112 if unsupported features from MessagePack were used in the given vector @a v or if the input is not valid MessagePack - @throw std::out_of_range if the given vector ends prematurely + @throw parse_error.113 if a string was expected as map key, but not found @complexity Linear in the size of the byte vector @a v. @@ -7661,11 +9162,15 @@ class basic_json @sa http://msgpack.org @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(const std::vector&) for the related CBOR format + @sa @ref from_cbor(const std::vector&, const size_t) for the + related CBOR format + + @since version 2.0.9, parameter @a start_index since 2.1.1 */ - static basic_json from_msgpack(const std::vector& v) + static basic_json from_msgpack(const std::vector& v, + const size_t start_index = 0) { - size_t i = 0; + size_t i = start_index; return from_msgpack_internal(v, i); } @@ -7677,6 +9182,65 @@ class basic_json serialization format which aims to be more compact than JSON itself, yet more efficient to parse. + The library uses the following mapping from JSON values types to + CBOR types according to the CBOR specification (RFC 7049): + + JSON value type | value/range | CBOR type | first byte + --------------- | ------------------------------------------ | ---------------------------------- | --------------- + null | `null` | Null | 0xf6 + boolean | `true` | True | 0xf5 + boolean | `false` | False | 0xf4 + number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3b + number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3a + number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 + number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 + number_integer | -24..-1 | Negative integer | 0x20..0x37 + number_integer | 0..23 | Integer | 0x00..0x17 + number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 + number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 + number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a + number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b + number_unsigned | 0..23 | Integer | 0x00..0x17 + number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 + number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 + number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a + number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b + number_float | *any value* | Double-Precision Float | 0xfb + string | *length*: 0..23 | UTF-8 string | 0x60..0x77 + string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 + string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 + string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7a + string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7b + array | *size*: 0..23 | array | 0x80..0x97 + array | *size*: 23..255 | array (1 byte follow) | 0x98 + array | *size*: 256..65535 | array (2 bytes follow) | 0x99 + array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9a + array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9b + object | *size*: 0..23 | map | 0xa0..0xb7 + object | *size*: 23..255 | map (1 byte follow) | 0xb8 + object | *size*: 256..65535 | map (2 bytes follow) | 0xb9 + object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xba + object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xbb + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a CBOR value. + + @note The following CBOR types are not used in the conversion: + - byte strings (0x40..0x5f) + - UTF-8 strings terminated by "break" (0x7f) + - arrays terminated by "break" (0x9f) + - maps terminated by "break" (0xbf) + - date/time (0xc0..0xc1) + - bignum (0xc2..0xc3) + - decimal fraction (0xc4) + - bigfloat (0xc5) + - tagged items (0xc6..0xd4, 0xd8..0xdb) + - expected conversions (0xd5..0xd7) + - simple values (0xe0..0xf3, 0xf8) + - undefined (0xf7) + - half and single-precision floats (0xf9-0xfa) + - break (0xff) + @param[in] j JSON value to serialize @return MessagePack serialization as byte vector @@ -7686,9 +9250,11 @@ class basic_json vector in CBOR format.,to_cbor} @sa http://cbor.io - @sa @ref from_cbor(const std::vector&) for the analogous - deserialization + @sa @ref from_cbor(const std::vector&, const size_t) for the + analogous deserialization @sa @ref to_msgpack(const basic_json& for the related MessagePack format + + @since version 2.0.9 */ static std::vector to_cbor(const basic_json& j) { @@ -7703,12 +9269,74 @@ class basic_json Deserializes a given byte vector @a v to a JSON value using the CBOR (Concise Binary Object Representation) serialization format. + The library maps CBOR types to JSON value types as follows: + + CBOR type | JSON value type | first byte + ---------------------- | --------------- | ---------- + Integer | number_unsigned | 0x00..0x17 + Unsigned integer | number_unsigned | 0x18 + Unsigned integer | number_unsigned | 0x19 + Unsigned integer | number_unsigned | 0x1a + Unsigned integer | number_unsigned | 0x1b + Negative integer | number_integer | 0x20..0x37 + Negative integer | number_integer | 0x38 + Negative integer | number_integer | 0x39 + Negative integer | number_integer | 0x3a + Negative integer | number_integer | 0x3b + Negative integer | number_integer | 0x40..0x57 + UTF-8 string | string | 0x60..0x77 + UTF-8 string | string | 0x78 + UTF-8 string | string | 0x79 + UTF-8 string | string | 0x7a + UTF-8 string | string | 0x7b + UTF-8 string | string | 0x7f + array | array | 0x80..0x97 + array | array | 0x98 + array | array | 0x99 + array | array | 0x9a + array | array | 0x9b + array | array | 0x9f + map | object | 0xa0..0xb7 + map | object | 0xb8 + map | object | 0xb9 + map | object | 0xba + map | object | 0xbb + map | object | 0xbf + False | `false` | 0xf4 + True | `true` | 0xf5 + Nill | `null` | 0xf6 + Half-Precision Float | number_float | 0xf9 + Single-Precision Float | number_float | 0xfa + Double-Precision Float | number_float | 0xfb + + @warning The mapping is **incomplete** in the sense that not all CBOR + types can be converted to a JSON value. The following CBOR types + are not supported and will yield parse errors (parse_error.112): + - byte strings (0x40..0x5f) + - date/time (0xc0..0xc1) + - bignum (0xc2..0xc3) + - decimal fraction (0xc4) + - bigfloat (0xc5) + - tagged items (0xc6..0xd4, 0xd8..0xdb) + - expected conversions (0xd5..0xd7) + - simple values (0xe0..0xf3, 0xf8) + - undefined (0xf7) + + @warning CBOR allows map keys of any type, whereas JSON only allows + strings as keys in object values. Therefore, CBOR maps with keys + other than UTF-8 strings are rejected (parse_error.113). + + @note Any CBOR output created @ref to_cbor can be successfully parsed by + @ref from_cbor. + @param[in] v a byte vector in CBOR format + @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value - @throw std::invalid_argument if unsupported features from CBOR were used in - the given vector @a v or if the input is not valid MessagePack - @throw std::out_of_range if the given vector ends prematurely + @throw parse_error.110 if the given vector ends prematurely + @throw parse_error.112 if unsupported features from CBOR were + used in the given vector @a v or if the input is not valid CBOR + @throw parse_error.113 if a string was expected as map key, but not found @complexity Linear in the size of the byte vector @a v. @@ -7717,375 +9345,63 @@ class basic_json @sa http://cbor.io @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(const std::vector&) for the related - MessagePack format - */ - static basic_json from_cbor(const std::vector& v) - { - size_t i = 0; - return from_cbor_internal(v, i); - } - - /// @} - - private: - /////////////////////////// - // convenience functions // - /////////////////////////// - - /*! - @brief return the type as string - - Returns the type name as string to be used in error messages - usually to - indicate that a function was called on a wrong JSON type. - - @return basically a string representation of a the @a m_type member - - @complexity Constant. - - @since version 1.0.0 - */ - std::string type_name() const - { - switch (m_type) - { - case value_t::null: - return "null"; - case value_t::object: - return "object"; - case value_t::array: - return "array"; - case value_t::string: - return "string"; - case value_t::boolean: - return "boolean"; - case value_t::discarded: - return "discarded"; - default: - return "number"; - } - } - - /*! - @brief calculates the extra space to escape a JSON string - - @param[in] s the string to escape - @return the number of characters required to escape string @a s - - @complexity Linear in the length of string @a s. - */ - static std::size_t extra_space(const string_t& s) noexcept - { - return std::accumulate(s.begin(), s.end(), size_t{}, - [](size_t res, typename string_t::value_type c) - { - switch (c) - { - case '"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - { - // from c (1 byte) to \x (2 bytes) - return res + 1; - } - - default: - { - if (c >= 0x00 and c <= 0x1f) - { - // from c (1 byte) to \uxxxx (6 bytes) - return res + 5; - } - else - { - return res; - } - } - } - }); - } - - /*! - @brief escape a string - - Escape a string by replacing certain special characters by a sequence of - an escape character (backslash) and another character and other control - characters by a sequence of "\u" followed by a four-digit hex - representation. - - @param[in] s the string to escape - @return the escaped string - - @complexity Linear in the length of string @a s. - */ - static string_t escape_string(const string_t& s) - { - const auto space = extra_space(s); - if (space == 0) - { - return s; - } - - // create a result string of necessary size - string_t result(s.size() + space, '\\'); - std::size_t pos = 0; - - for (const auto& c : s) - { - switch (c) - { - // quotation mark (0x22) - case '"': - { - result[pos + 1] = '"'; - pos += 2; - break; - } - - // reverse solidus (0x5c) - case '\\': - { - // nothing to change - pos += 2; - break; - } - - // backspace (0x08) - case '\b': - { - result[pos + 1] = 'b'; - pos += 2; - break; - } - - // formfeed (0x0c) - case '\f': - { - result[pos + 1] = 'f'; - pos += 2; - break; - } - - // newline (0x0a) - case '\n': - { - result[pos + 1] = 'n'; - pos += 2; - break; - } - - // carriage return (0x0d) - case '\r': - { - result[pos + 1] = 'r'; - pos += 2; - break; - } - - // horizontal tab (0x09) - case '\t': - { - result[pos + 1] = 't'; - pos += 2; - break; - } - - default: - { - if (c >= 0x00 and c <= 0x1f) - { - // convert a number 0..15 to its hex representation - // (0..f) - static const char hexify[16] = - { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - // print character c as \uxxxx - for (const char m : - { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] - }) - { - result[++pos] = m; - } - - ++pos; - } - else - { - // all other characters are added as-is - result[pos++] = c; - } - break; - } - } - } - - return result; - } - - /*! - @brief internal implementation of the serialization function - - This function is called by the public member function dump and organizes - the serialization internally. The indentation level is propagated as - additional parameter. In case of arrays and objects, the function is - called recursively. Note that - - - strings and object keys are escaped using `escape_string()` - - integer numbers are converted implicitly via `operator<<` - - floating-point numbers are converted to a string using `"%g"` format - - @param[out] o stream to write to - @param[in] pretty_print whether the output shall be pretty-printed - @param[in] indent_step the indent level - @param[in] current_indent the current indent level (only used internally) - */ - void dump(std::ostream& o, - const bool pretty_print, - const unsigned int indent_step, - const unsigned int current_indent = 0) const - { - // variable to hold indentation for recursive calls - unsigned int new_indent = current_indent; - - switch (m_type) - { - case value_t::object: - { - if (m_value.object->empty()) - { - o << "{}"; - return; - } - - o << "{"; - - // increase indentation - if (pretty_print) - { - new_indent += indent_step; - o << "\n"; - } - - for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i) - { - if (i != m_value.object->cbegin()) - { - o << (pretty_print ? ",\n" : ","); - } - o << string_t(new_indent, ' ') << "\"" - << escape_string(i->first) << "\":" - << (pretty_print ? " " : ""); - i->second.dump(o, pretty_print, indent_step, new_indent); - } - - // decrease indentation - if (pretty_print) - { - new_indent -= indent_step; - o << "\n"; - } - - o << string_t(new_indent, ' ') + "}"; - return; - } - - case value_t::array: - { - if (m_value.array->empty()) - { - o << "[]"; - return; - } - - o << "["; - - // increase indentation - if (pretty_print) - { - new_indent += indent_step; - o << "\n"; - } - - for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i) - { - if (i != m_value.array->cbegin()) - { - o << (pretty_print ? ",\n" : ","); - } - o << string_t(new_indent, ' '); - i->dump(o, pretty_print, indent_step, new_indent); - } + @sa @ref from_msgpack(const std::vector&, const size_t) for the + related MessagePack format - // decrease indentation - if (pretty_print) - { - new_indent -= indent_step; - o << "\n"; - } + @since version 2.0.9, parameter @a start_index since 2.1.1 + */ + static basic_json from_cbor(const std::vector& v, + const size_t start_index = 0) + { + size_t i = start_index; + return from_cbor_internal(v, i); + } - o << string_t(new_indent, ' ') << "]"; - return; - } + /// @} - case value_t::string: - { - o << string_t("\"") << escape_string(*m_value.string) << "\""; - return; - } + /////////////////////////// + // convenience functions // + /////////////////////////// - case value_t::boolean: - { - o << (m_value.boolean ? "true" : "false"); - return; - } + /*! + @brief return the type as string - case value_t::number_integer: - { - o << m_value.number_integer; - return; - } + Returns the type name as string to be used in error messages - usually to + indicate that a function was called on a wrong JSON type. - case value_t::number_unsigned: - { - o << m_value.number_unsigned; - return; - } + @return basically a string representation of a the @a m_type member - case value_t::number_float: - { - if (m_value.number_float == 0) - { - // special case for zero to get "0.0"/"-0.0" - o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0"); - } - else - { - o << m_value.number_float; - } - return; - } + @complexity Constant. - case value_t::discarded: - { - o << ""; - return; - } + @liveexample{The following code exemplifies `type_name()` for all JSON + types.,type_name} - case value_t::null: + @since version 1.0.0, public since 2.1.0 + */ + std::string type_name() const + { + { + switch (m_type) { - o << "null"; - return; + case value_t::null: + return "null"; + case value_t::object: + return "object"; + case value_t::array: + return "array"; + case value_t::string: + return "string"; + case value_t::boolean: + return "boolean"; + case value_t::discarded: + return "discarded"; + default: + return "number"; } } } + private: ////////////////////// // member variables // @@ -8115,6 +9431,11 @@ class basic_json class primitive_iterator_t { public: + + difference_type get_value() const noexcept + { + return m_it; + } /// set iterator to a defined beginning void set_begin() noexcept { @@ -8139,16 +9460,89 @@ class basic_json return (m_it == end_value); } - /// return reference to the value to change and compare - operator difference_type& () noexcept + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { - return m_it; + return lhs.m_it == rhs.m_it; } - /// return value to compare - constexpr operator difference_type () const noexcept + friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { - return m_it; + return !(lhs == rhs); + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it <= rhs.m_it; + } + + friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it > rhs.m_it; + } + + friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it >= rhs.m_it; + } + + primitive_iterator_t operator+(difference_type i) + { + auto result = *this; + result += i; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it) + { + return os << it.m_it; + } + + primitive_iterator_t& operator++() + { + ++m_it; + return *this; + } + + primitive_iterator_t operator++(int) + { + auto result = *this; + m_it++; + return result; + } + + primitive_iterator_t& operator--() + { + --m_it; + return *this; + } + + primitive_iterator_t operator--(int) + { + auto result = *this; + m_it--; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) + { + m_it -= n; + return *this; } private: @@ -8500,7 +9894,7 @@ class basic_json case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + JSON_THROW(invalid_iterator::create(214, "cannot get value")); } default: @@ -8509,10 +9903,8 @@ class basic_json { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); } } } @@ -8545,10 +9937,8 @@ class basic_json { return m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); } } } @@ -8648,7 +10038,7 @@ class basic_json // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); } assert(m_object != nullptr); @@ -8690,7 +10080,7 @@ class basic_json // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); } assert(m_object != nullptr); @@ -8699,7 +10089,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot compare order of object iterators"); + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); } case basic_json::value_t::array: @@ -8753,7 +10143,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); } case basic_json::value_t::array: @@ -8815,7 +10205,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); } case basic_json::value_t::array: @@ -8842,7 +10232,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator[] for object iterators"); + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); } case basic_json::value_t::array: @@ -8852,19 +10242,17 @@ class basic_json case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + JSON_THROW(invalid_iterator::create(214, "cannot get value")); } default: { - if (m_it.primitive_iterator == -n) + if (m_it.primitive_iterator.get_value() == -n) { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); } } } @@ -8881,10 +10269,8 @@ class basic_json { return m_it.object_iterator->first; } - else - { - throw std::domain_error("cannot use key() for non-object iterators"); - } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); } /*! @@ -9039,7 +10425,9 @@ class basic_json literal_false, ///< the `false` literal literal_null, ///< the `null` literal value_string, ///< a string -- use get_string() for actual value - value_number, ///< a number -- use get_number() for actual value + value_unsigned, ///< an unsigned integer -- use get_number() for actual value + value_integer, ///< a signed integer -- use get_number() for actual value + value_float, ///< an floating point number -- use get_number() for actual value begin_array, ///< the character for array begin `[` begin_object, ///< the character for object begin `{` end_array, ///< the character for array end `]` @@ -9062,14 +10450,17 @@ class basic_json m_limit = m_content + len; } - /// a lexer from an input stream + /*! + @brief a lexer from an input stream + @throw parse_error.111 if input stream is in a bad state + */ explicit lexer(std::istream& s) : m_stream(&s), m_line_buffer() { // immediately abort if stream is erroneous if (s.fail()) { - throw std::invalid_argument("stream error"); + JSON_THROW(parse_error::create(111, 0, "bad input stream")); } // fill buffer @@ -9103,17 +10494,17 @@ class basic_json @return string representation of the code point; the length of the result string is between 1 and 4 characters. - @throw std::out_of_range if code point is > 0x10ffff; example: `"code - points above 0x10FFFF are invalid"` - @throw std::invalid_argument if the low surrogate is invalid; example: + @throw parse_error.102 if the low surrogate is invalid; example: `""missing or wrong low surrogate""` + @throw parse_error.103 if code point is > 0x10ffff; example: `"code + points above 0x10FFFF are invalid"` @complexity Constant. @see */ - static string_t to_unicode(const std::size_t codepoint1, - const std::size_t codepoint2 = 0) + string_t to_unicode(const std::size_t codepoint1, + const std::size_t codepoint2 = 0) const { // calculate the code point from the given code points std::size_t codepoint = codepoint1; @@ -9136,7 +10527,7 @@ class basic_json } else { - throw std::invalid_argument("missing or wrong low surrogate"); + JSON_THROW(parse_error::create(102, get_position(), "missing or wrong low surrogate")); } } @@ -9150,27 +10541,27 @@ class basic_json else if (codepoint <= 0x7ff) { // 2-byte characters: 110xxxxx 10xxxxxx - result.append(1, static_cast(0xC0 | ((codepoint >> 6) & 0x1F))); + result.append(1, static_cast(0xC0 | (codepoint >> 6))); result.append(1, static_cast(0x80 | (codepoint & 0x3F))); } else if (codepoint <= 0xffff) { // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - result.append(1, static_cast(0xE0 | ((codepoint >> 12) & 0x0F))); + result.append(1, static_cast(0xE0 | (codepoint >> 12))); result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); result.append(1, static_cast(0x80 | (codepoint & 0x3F))); } else if (codepoint <= 0x10ffff) { // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - result.append(1, static_cast(0xF0 | ((codepoint >> 18) & 0x07))); + result.append(1, static_cast(0xF0 | (codepoint >> 18))); result.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); result.append(1, static_cast(0x80 | (codepoint & 0x3F))); } else { - throw std::out_of_range("code points above 0x10FFFF are invalid"); + JSON_THROW(parse_error::create(103, get_position(), "code points above 0x10FFFF are invalid")); } return result; @@ -9191,7 +10582,9 @@ class basic_json return "null literal"; case token_type::value_string: return "string literal"; - case token_type::value_number: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: + case lexer::token_type::value_float: return "number literal"; case token_type::begin_array: return "'['"; @@ -9233,10 +10626,9 @@ class basic_json Proof (by contradiction): Assume a finite input. To loop forever, the loop must never hit code with a `break` statement. The only code - snippets without a `break` statement are the continue statements for - whitespace and byte-order-marks. To loop forever, the input must be an - infinite sequence of whitespace or byte-order-marks. This contradicts - the assumption of finite input, q.e.d. + snippets without a `break` statement is the continue statement for + whitespace. To loop forever, the input must be an infinite sequence + whitespace. This contradicts the assumption of finite input, q.e.d. */ token_type scan() { @@ -9428,6 +10820,7 @@ basic_json_parser_6: goto basic_json_parser_6; } { + position += static_cast((m_cursor - m_start)); continue; } basic_json_parser_9: @@ -9464,37 +10857,47 @@ basic_json_parser_12: } if (yych <= '0') { - goto basic_json_parser_13; + goto basic_json_parser_43; } if (yych <= '9') { - goto basic_json_parser_15; + goto basic_json_parser_45; } goto basic_json_parser_5; basic_json_parser_13: yyaccept = 1; yych = *(m_marker = ++m_cursor); - if (yych <= 'D') + if (yych <= '9') { if (yych == '.') { - goto basic_json_parser_43; + goto basic_json_parser_47; + } + if (yych >= '0') + { + goto basic_json_parser_48; } } else { if (yych <= 'E') { - goto basic_json_parser_44; + if (yych >= 'E') + { + goto basic_json_parser_51; + } } - if (yych == 'e') + else { - goto basic_json_parser_44; + if (yych == 'e') + { + goto basic_json_parser_51; + } } } basic_json_parser_14: { - last_token_type = token_type::value_number; + last_token_type = token_type::value_unsigned; break; } basic_json_parser_15: @@ -9513,7 +10916,7 @@ basic_json_parser_15: { if (yych == '.') { - goto basic_json_parser_43; + goto basic_json_parser_47; } goto basic_json_parser_14; } @@ -9521,11 +10924,11 @@ basic_json_parser_15: { if (yych <= 'E') { - goto basic_json_parser_44; + goto basic_json_parser_51; } if (yych == 'e') { - goto basic_json_parser_44; + goto basic_json_parser_51; } goto basic_json_parser_14; } @@ -9552,7 +10955,7 @@ basic_json_parser_23: yych = *(m_marker = ++m_cursor); if (yych == 'a') { - goto basic_json_parser_45; + goto basic_json_parser_52; } goto basic_json_parser_5; basic_json_parser_24: @@ -9560,7 +10963,7 @@ basic_json_parser_24: yych = *(m_marker = ++m_cursor); if (yych == 'u') { - goto basic_json_parser_46; + goto basic_json_parser_53; } goto basic_json_parser_5; basic_json_parser_25: @@ -9568,7 +10971,7 @@ basic_json_parser_25: yych = *(m_marker = ++m_cursor); if (yych == 'r') { - goto basic_json_parser_47; + goto basic_json_parser_54; } goto basic_json_parser_5; basic_json_parser_26: @@ -9650,13 +11053,27 @@ basic_json_parser_31: } basic_json_parser_32: m_cursor = m_marker; - if (yyaccept == 0) + if (yyaccept <= 1) { - goto basic_json_parser_5; + if (yyaccept == 0) + { + goto basic_json_parser_5; + } + else + { + goto basic_json_parser_14; + } } else { - goto basic_json_parser_14; + if (yyaccept == 2) + { + goto basic_json_parser_44; + } + else + { + goto basic_json_parser_58; + } } basic_json_parser_33: ++m_cursor; @@ -9737,7 +11154,7 @@ basic_json_parser_35: } if (yych <= 'u') { - goto basic_json_parser_48; + goto basic_json_parser_55; } goto basic_json_parser_32; } @@ -9836,43 +11253,138 @@ basic_json_parser_41: } if (yych <= 0xBF) { - goto basic_json_parser_38; + goto basic_json_parser_38; + } + goto basic_json_parser_32; +basic_json_parser_42: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0x8F) + { + goto basic_json_parser_38; + } + goto basic_json_parser_32; +basic_json_parser_43: + yyaccept = 2; + yych = *(m_marker = ++m_cursor); + if (yych <= '9') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + if (yych >= '0') + { + goto basic_json_parser_48; + } + } + else + { + if (yych <= 'E') + { + if (yych >= 'E') + { + goto basic_json_parser_51; + } + } + else + { + if (yych == 'e') + { + goto basic_json_parser_51; + } + } + } +basic_json_parser_44: + { + last_token_type = token_type::value_integer; + break; + } +basic_json_parser_45: + yyaccept = 2; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + fill_line_buffer(3); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '9') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + if (yych <= '/') + { + goto basic_json_parser_44; + } + goto basic_json_parser_45; + } + else + { + if (yych <= 'E') + { + if (yych <= 'D') + { + goto basic_json_parser_44; + } + goto basic_json_parser_51; + } + else + { + if (yych == 'e') + { + goto basic_json_parser_51; + } + goto basic_json_parser_44; + } + } +basic_json_parser_47: + yych = *++m_cursor; + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_56; } goto basic_json_parser_32; -basic_json_parser_42: +basic_json_parser_48: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0x8F) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_43: - yych = *++m_cursor; if (yych <= '/') { - goto basic_json_parser_32; + goto basic_json_parser_50; } if (yych <= '9') { - goto basic_json_parser_49; + goto basic_json_parser_48; } - goto basic_json_parser_32; -basic_json_parser_44: +basic_json_parser_50: + { + last_token_type = token_type::parse_error; + break; + } +basic_json_parser_51: yych = *++m_cursor; if (yych <= ',') { if (yych == '+') { - goto basic_json_parser_51; + goto basic_json_parser_59; } goto basic_json_parser_32; } @@ -9880,7 +11392,7 @@ basic_json_parser_44: { if (yych <= '-') { - goto basic_json_parser_51; + goto basic_json_parser_59; } if (yych <= '/') { @@ -9888,32 +11400,32 @@ basic_json_parser_44: } if (yych <= '9') { - goto basic_json_parser_52; + goto basic_json_parser_60; } goto basic_json_parser_32; } -basic_json_parser_45: +basic_json_parser_52: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_54; + goto basic_json_parser_62; } goto basic_json_parser_32; -basic_json_parser_46: +basic_json_parser_53: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_55; + goto basic_json_parser_63; } goto basic_json_parser_32; -basic_json_parser_47: +basic_json_parser_54: yych = *++m_cursor; if (yych == 'u') { - goto basic_json_parser_56; + goto basic_json_parser_64; } goto basic_json_parser_32; -basic_json_parser_48: +basic_json_parser_55: ++m_cursor; if (m_limit <= m_cursor) { @@ -9928,7 +11440,7 @@ basic_json_parser_48: } if (yych <= '9') { - goto basic_json_parser_57; + goto basic_json_parser_65; } goto basic_json_parser_32; } @@ -9936,7 +11448,7 @@ basic_json_parser_48: { if (yych <= 'F') { - goto basic_json_parser_57; + goto basic_json_parser_65; } if (yych <= '`') { @@ -9944,12 +11456,12 @@ basic_json_parser_48: } if (yych <= 'f') { - goto basic_json_parser_57; + goto basic_json_parser_65; } goto basic_json_parser_32; } -basic_json_parser_49: - yyaccept = 1; +basic_json_parser_56: + yyaccept = 3; m_marker = ++m_cursor; if ((m_limit - m_cursor) < 3) { @@ -9960,27 +11472,30 @@ basic_json_parser_49: { if (yych <= '/') { - goto basic_json_parser_14; + goto basic_json_parser_58; } if (yych <= '9') { - goto basic_json_parser_49; + goto basic_json_parser_56; } - goto basic_json_parser_14; } else { if (yych <= 'E') { - goto basic_json_parser_44; + goto basic_json_parser_51; } if (yych == 'e') { - goto basic_json_parser_44; + goto basic_json_parser_51; } - goto basic_json_parser_14; } -basic_json_parser_51: +basic_json_parser_58: + { + last_token_type = token_type::value_float; + break; + } +basic_json_parser_59: yych = *++m_cursor; if (yych <= '/') { @@ -9990,7 +11505,7 @@ basic_json_parser_51: { goto basic_json_parser_32; } -basic_json_parser_52: +basic_json_parser_60: ++m_cursor; if (m_limit <= m_cursor) { @@ -9999,35 +11514,35 @@ basic_json_parser_52: yych = *m_cursor; if (yych <= '/') { - goto basic_json_parser_14; + goto basic_json_parser_58; } if (yych <= '9') { - goto basic_json_parser_52; + goto basic_json_parser_60; } - goto basic_json_parser_14; -basic_json_parser_54: + goto basic_json_parser_58; +basic_json_parser_62: yych = *++m_cursor; if (yych == 's') { - goto basic_json_parser_58; + goto basic_json_parser_66; } goto basic_json_parser_32; -basic_json_parser_55: +basic_json_parser_63: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_59; + goto basic_json_parser_67; } goto basic_json_parser_32; -basic_json_parser_56: +basic_json_parser_64: yych = *++m_cursor; if (yych == 'e') { - goto basic_json_parser_61; + goto basic_json_parser_69; } goto basic_json_parser_32; -basic_json_parser_57: +basic_json_parser_65: ++m_cursor; if (m_limit <= m_cursor) { @@ -10042,7 +11557,7 @@ basic_json_parser_57: } if (yych <= '9') { - goto basic_json_parser_63; + goto basic_json_parser_71; } goto basic_json_parser_32; } @@ -10050,7 +11565,7 @@ basic_json_parser_57: { if (yych <= 'F') { - goto basic_json_parser_63; + goto basic_json_parser_71; } if (yych <= '`') { @@ -10058,30 +11573,30 @@ basic_json_parser_57: } if (yych <= 'f') { - goto basic_json_parser_63; + goto basic_json_parser_71; } goto basic_json_parser_32; } -basic_json_parser_58: +basic_json_parser_66: yych = *++m_cursor; if (yych == 'e') { - goto basic_json_parser_64; + goto basic_json_parser_72; } goto basic_json_parser_32; -basic_json_parser_59: +basic_json_parser_67: ++m_cursor; { last_token_type = token_type::literal_null; break; } -basic_json_parser_61: +basic_json_parser_69: ++m_cursor; { last_token_type = token_type::literal_true; break; } -basic_json_parser_63: +basic_json_parser_71: ++m_cursor; if (m_limit <= m_cursor) { @@ -10096,7 +11611,7 @@ basic_json_parser_63: } if (yych <= '9') { - goto basic_json_parser_66; + goto basic_json_parser_74; } goto basic_json_parser_32; } @@ -10104,7 +11619,7 @@ basic_json_parser_63: { if (yych <= 'F') { - goto basic_json_parser_66; + goto basic_json_parser_74; } if (yych <= '`') { @@ -10112,17 +11627,17 @@ basic_json_parser_63: } if (yych <= 'f') { - goto basic_json_parser_66; + goto basic_json_parser_74; } goto basic_json_parser_32; } -basic_json_parser_64: +basic_json_parser_72: ++m_cursor; { last_token_type = token_type::literal_false; break; } -basic_json_parser_66: +basic_json_parser_74: ++m_cursor; if (m_limit <= m_cursor) { @@ -10161,6 +11676,7 @@ basic_json_parser_66: } + position += static_cast((m_cursor - m_start)); return last_token_type; } @@ -10209,7 +11725,7 @@ basic_json_parser_66: assert(m_marker == nullptr or m_marker <= m_limit); // number of processed characters (p) - const size_t num_processed_chars = static_cast(m_start - m_content); + const auto num_processed_chars = static_cast(m_start - m_content); // offset for m_marker wrt. to m_start const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; // number of unprocessed characters (u) @@ -10219,7 +11735,7 @@ basic_json_parser_66: if (m_stream == nullptr or m_stream->eof()) { // m_start may or may not be pointing into m_line_buffer at - // this point. We trust the standand library to do the right + // this point. We trust the standard library to do the right // thing. See http://stackoverflow.com/q/28142011/266378 m_line_buffer.assign(m_start, m_limit); @@ -10237,6 +11753,13 @@ basic_json_parser_66: m_line_buffer.erase(0, num_processed_chars); // read next line from input stream m_line_buffer_tmp.clear(); + + // check if stream is still good + if (m_stream->fail()) + { + JSON_THROW(parse_error::create(111, 0, "bad input stream")); + } + std::getline(*m_stream, m_line_buffer_tmp, '\n'); // add line with newline symbol to the line buffer @@ -10307,7 +11830,7 @@ basic_json_parser_66: m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This can be rephrased to m_cursor - m_start - 2 > x. With the precondition, we x <= 0, meaning that the loop condition holds - indefinitly if i is always decreased. However, observe that the value + indefinitely if i is always decreased. However, observe that the value of i is strictly increasing with each iteration, as it is incremented by 1 in the iteration expression and never decremented inside the loop body. Hence, the loop condition will eventually be false which @@ -10316,7 +11839,8 @@ basic_json_parser_66: @return string value of current token without opening and closing quotes - @throw std::out_of_range if to_unicode fails + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails */ string_t get_string() const { @@ -10402,7 +11926,7 @@ basic_json_parser_66: // make sure there is a subsequent unicode if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u') { - throw std::invalid_argument("missing low surrogate"); + JSON_THROW(parse_error::create(102, get_position(), "missing low surrogate")); } // get code yyyy from uxxxx\uyyyy @@ -10415,7 +11939,7 @@ basic_json_parser_66: else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF) { // we found a lone low surrogate - throw std::invalid_argument("missing high surrogate"); + JSON_THROW(parse_error::create(102, get_position(), "missing high surrogate")); } else { @@ -10433,186 +11957,245 @@ basic_json_parser_66: return result; } - /*! - @brief parse floating point number - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + /*! + @brief parse string into a built-in arithmetic type as if the current + locale is POSIX. - @param[in,out] endptr recieves a pointer to the first character after - the number + @note in floating-point case strtod may parse past the token's end - + this is not an error - @return the floating point number + @note any leading blanks are not handled */ - long double str_to_float_t(long double* /* type */, char** endptr) const + struct strtonum { - return std::strtold(reinterpret_cast(m_start), endptr); - } + public: + strtonum(const char* start, const char* end) + : m_start(start), m_end(end) + {} - /*! - @brief parse floating point number + /*! + @return true iff parsed successfully as number of type T - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + @param[in,out] val shall contain parsed value, or undefined value + if could not parse + */ + template::value>::type> + bool to(T& val) const + { + return parse(val, std::is_integral()); + } - @param[in,out] endptr recieves a pointer to the first character after - the number + private: + const char* const m_start = nullptr; + const char* const m_end = nullptr; - @return the floating point number - */ - double str_to_float_t(double* /* type */, char** endptr) const - { - return std::strtod(reinterpret_cast(m_start), endptr); - } + // floating-point conversion - /*! - @brief parse floating point number + // overloaded wrappers for strtod/strtof/strtold + // that will be called from parse + static void strtof(float& f, const char* str, char** endptr) + { + f = std::strtof(str, endptr); + } - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + static void strtof(double& f, const char* str, char** endptr) + { + f = std::strtod(str, endptr); + } - @param[in,out] endptr recieves a pointer to the first character after - the number + static void strtof(long double& f, const char* str, char** endptr) + { + f = std::strtold(str, endptr); + } - @return the floating point number - */ - float str_to_float_t(float* /* type */, char** endptr) const - { - return std::strtof(reinterpret_cast(m_start), endptr); - } + template + bool parse(T& value, /*is_integral=*/std::false_type) const + { + // replace decimal separator with locale-specific version, + // when necessary; data will point to either the original + // string, or buf, or tempstr containing the fixed string. + std::string tempstr; + std::array buf; + const size_t len = static_cast(m_end - m_start); - /*! - @brief return number value for number tokens + // lexer will reject empty numbers + assert(len > 0); - This function translates the last token into the most appropriate - number type (either integer, unsigned integer or floating point), - which is passed back to the caller via the result parameter. + // since dealing with strtod family of functions, we're + // getting the decimal point char from the C locale facilities + // instead of C++'s numpunct facet of the current std::locale + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; - This function parses the integer component up to the radix point or - exponent while collecting information about the 'floating point - representation', which it stores in the result parameter. If there is - no radix point or exponent, and the number can fit into a @ref - number_integer_t or @ref number_unsigned_t then it sets the result - parameter accordingly. + const char* data = m_start; - If the number is a floating point number the number is then parsed - using @a std:strtod (or @a std:strtof or @a std::strtold). + if (decimal_point_char != '.') + { + const size_t ds_pos = static_cast(std::find(m_start, m_end, '.') - m_start); - @param[out] result @ref basic_json object to receive the number, or - NAN if the conversion read past the current token. The latter case - needs to be treated by the caller function. - */ - void get_number(basic_json& result) const - { - assert(m_start != nullptr); + if (ds_pos != len) + { + // copy the data into the local buffer or tempstr, if + // buffer is too small; replace decimal separator, and + // update data to point to the modified bytes + if ((len + 1) < buf.size()) + { + std::copy(m_start, m_end, buf.begin()); + buf[len] = 0; + buf[ds_pos] = decimal_point_char; + data = buf.data(); + } + else + { + tempstr.assign(m_start, m_end); + tempstr[ds_pos] = decimal_point_char; + data = tempstr.c_str(); + } + } + } + + char* endptr = nullptr; + value = 0; + // this calls appropriate overload depending on T + strtof(value, data, &endptr); - const lexer::lexer_char_t* curptr = m_start; + // parsing was successful iff strtof parsed exactly the number + // of characters determined by the lexer (len) + const bool ok = (endptr == (data + len)); - // accumulate the integer conversion result (unsigned for now) - number_unsigned_t value = 0; + if (ok and (value == static_cast(0.0)) and (*data == '-')) + { + // some implementations forget to negate the zero + value = -0.0; + } - // maximum absolute value of the relevant integer type - number_unsigned_t max; + return ok; + } - // temporarily store the type to avoid unecessary bitfield access - value_t type; + // integral conversion - // look for sign - if (*curptr == '-') + signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const { - type = value_t::number_integer; - max = static_cast((std::numeric_limits::max)()) + 1; - curptr++; + return std::strtoll(m_start, endptr, 10); } - else + + unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const + { + return std::strtoull(m_start, endptr, 10); + } + + template + bool parse(T& value, /*is_integral=*/std::true_type) const { - type = value_t::number_unsigned; - max = static_cast((std::numeric_limits::max)()); + char* endptr = nullptr; + errno = 0; // these are thread-local + const auto x = parse_integral(&endptr, std::is_signed()); + + // called right overload? + static_assert(std::is_signed() == std::is_signed(), ""); + + value = static_cast(x); + + return (x == static_cast(value)) // x fits into destination T + and (x < 0) == (value < 0) // preserved sign + //and ((x != 0) or is_integral()) // strto[u]ll did nto fail + and (errno == 0) // strto[u]ll did not overflow + and (m_start < m_end) // token was not empty + and (endptr == m_end); // parsed entire token exactly } + }; + + /*! + @brief return number value for number tokens + + This function translates the last token into the most appropriate + number type (either integer, unsigned integer or floating point), + which is passed back to the caller via the result parameter. + + integral numbers that don't fit into the the range of the respective + type are parsed as number_float_t + + floating-point values do not satisfy std::isfinite predicate + are converted to value_t::null + + throws if the entire string [m_start .. m_cursor) cannot be + interpreted as a number + + @param[out] result @ref basic_json object to receive the number. + @param[in] token the type of the number token + */ + bool get_number(basic_json& result, const token_type token) const + { + assert(m_start != nullptr); + assert(m_start < m_cursor); + assert((token == token_type::value_unsigned) or + (token == token_type::value_integer) or + (token == token_type::value_float)); - // count the significant figures - for (; curptr < m_cursor; curptr++) + strtonum num_converter(reinterpret_cast(m_start), + reinterpret_cast(m_cursor)); + + switch (token) { - // quickly skip tests if a digit - if (*curptr < '0' || *curptr > '9') + case lexer::token_type::value_unsigned: { - if (*curptr == '.') + number_unsigned_t val; + if (num_converter.to(val)) { - // don't count '.' but change to float - type = value_t::number_float; - continue; + // parsing successful + result.m_type = value_t::number_unsigned; + result.m_value = val; + return true; } - // assume exponent (if not then will fail parse): change to - // float, stop counting and record exponent details - type = value_t::number_float; break; } - // skip if definitely not an integer - if (type != value_t::number_float) + case lexer::token_type::value_integer: { - auto digit = static_cast(*curptr - '0'); - - // overflow if value * 10 + digit > max, move terms around - // to avoid overflow in intermediate values - if (value > (max - digit) / 10) - { - // overflow - type = value_t::number_float; - } - else + number_integer_t val; + if (num_converter.to(val)) { - // no overflow - value = value * 10 + digit; + // parsing successful + result.m_type = value_t::number_integer; + result.m_value = val; + return true; } + break; } - } - - // save the value (if not a float) - if (type == value_t::number_unsigned) - { - result.m_value.number_unsigned = value; - } - else if (type == value_t::number_integer) - { - // invariant: if we parsed a '-', the absolute value is between - // 0 (we allow -0) and max == -INT64_MIN - assert(value >= 0); - assert(value <= max); - if (value == max) - { - // we cannot simply negate value (== max == -INT64_MIN), - // see https://github.com/nlohmann/json/issues/389 - result.m_value.number_integer = static_cast(INT64_MIN); - } - else + default: { - // all other values can be negated safely - result.m_value.number_integer = -static_cast(value); + break; } } - else + + // parse float (either explicitly or because a previous conversion + // failed) + number_float_t val; + if (num_converter.to(val)) { - // parse with strtod - result.m_value.number_float = str_to_float_t(static_cast(nullptr), NULL); + // parsing successful + result.m_type = value_t::number_float; + result.m_value = val; - // replace infinity and NAN by null + // throw in case of infinity or NAN if (not std::isfinite(result.m_value.number_float)) { - type = value_t::null; - result.m_value = basic_json::json_value(); + JSON_THROW(out_of_range::create(406, "number overflow parsing '" + get_token_string() + "'")); } + + return true; } - // save the type - result.m_type = type; + // couldn't parse number in any format + return false; + } + + constexpr size_t get_position() const + { + return position; } private: @@ -10634,6 +12217,8 @@ basic_json_parser_66: const lexer_char_t* m_limit = nullptr; /// the last token type token_type last_token_type = token_type::end_of_input; + /// current position in the input (read bytes) + size_t position = 0; }; /*! @@ -10650,7 +12235,10 @@ basic_json_parser_66: m_lexer(reinterpret_cast(buff), std::strlen(buff)) {} - /// a parser reading from an input stream + /*! + @brief a parser reading from an input stream + @throw parse_error.111 if input stream is in a bad state + */ parser(std::istream& is, const parser_callback_t cb = nullptr) : callback(cb), m_lexer(is) {} @@ -10666,7 +12254,12 @@ basic_json_parser_66: static_cast(std::distance(first, last))) {} - /// public parser interface + /*! + @brief public parser interface + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ basic_json parse() { // read first token @@ -10683,7 +12276,12 @@ basic_json_parser_66: } private: - /// the actual parser + /*! + @brief the actual parser + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ basic_json parse_internal(bool keep) { auto result = basic_json(value_t::discarded); @@ -10856,9 +12454,11 @@ basic_json_parser_66: break; } - case lexer::token_type::value_number: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: + case lexer::token_type::value_float: { - m_lexer.get_number(result); + m_lexer.get_number(result, last_token); get_token(); break; } @@ -10884,6 +12484,9 @@ basic_json_parser_66: return last_token; } + /*! + @throw parse_error.101 if expected token did not occur + */ void expect(typename lexer::token_type t) const { if (t != last_token) @@ -10893,10 +12496,13 @@ basic_json_parser_66: "'") : lexer::token_type_name(last_token)); error_msg += "; expected " + lexer::token_type_name(t); - throw std::invalid_argument(error_msg); + JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg)); } } + /*! + @throw parse_error.101 if unexpected token occurred + */ void unexpect(typename lexer::token_type t) const { if (t == last_token) @@ -10905,7 +12511,7 @@ basic_json_parser_66: error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + "'") : lexer::token_type_name(last_token)); - throw std::invalid_argument(error_msg); + JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg)); } } @@ -10948,12 +12554,12 @@ basic_json_parser_66: empty string is assumed which references the whole JSON value - @throw std::domain_error if reference token is nonempty and does not - begin with a slash (`/`); example: `"JSON pointer must be empty or - begin with /"` - @throw std::domain_error if a tilde (`~`) is not followed by `0` - (representing `~`) or `1` (representing `/`); example: `"escape error: - ~ must be followed with 0 or 1"` + @throw parse_error.107 if the given JSON pointer @a s is nonempty and + does not begin with a slash (`/`); see example below + + @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s + is not followed by `0` (representing `~`) or `1` (representing `/`); + see example below @liveexample{The example shows the construction several valid JSON pointers as well as the exceptional behavior.,json_pointer} @@ -10996,12 +12602,15 @@ basic_json_parser_66: } private: - /// remove and return last reference pointer + /*! + @brief remove and return last reference pointer + @throw out_of_range.405 if JSON pointer has no parent + */ std::string pop_back() { if (is_root()) { - throw std::domain_error("JSON pointer has no parent"); + JSON_THROW(out_of_range::create(405, "JSON pointer has no parent")); } auto last = reference_tokens.back(); @@ -11019,7 +12628,7 @@ basic_json_parser_66: { if (is_root()) { - throw std::domain_error("JSON pointer has no parent"); + JSON_THROW(out_of_range::create(405, "JSON pointer has no parent")); } json_pointer result = *this; @@ -11031,6 +12640,9 @@ basic_json_parser_66: @brief create and return a reference to the pointed to value @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened */ reference get_and_create(reference j) const { @@ -11067,7 +12679,14 @@ basic_json_parser_66: case value_t::array: { // create an entry in the array - result = &result->operator[](static_cast(std::stoi(reference_token))); + JSON_TRY + { + result = &result->operator[](static_cast(std::stoi(reference_token))); + } + JSON_CATCH (std::invalid_argument&) + { + JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } break; } @@ -11080,7 +12699,7 @@ basic_json_parser_66: */ default: { - throw std::domain_error("invalid value to unflatten"); + JSON_THROW(type_error::create(313, "invalid value to unflatten")); } } } @@ -11103,9 +12722,9 @@ basic_json_parser_66: @complexity Linear in the length of the JSON pointer. - @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved */ reference get_unchecked(pointer ptr) const { @@ -11119,7 +12738,7 @@ basic_json_parser_66: reference_token.end(), [](const char x) { - return std::isdigit(x); + return (x >= '0' and x <= '9'); }); // change value to array for numbers or "-" or to object @@ -11148,25 +12767,32 @@ basic_json_parser_66: // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } if (reference_token == "-") { - // explicityly treat "-" as index beyond the end + // explicitly treat "-" as index beyond the end ptr = &ptr->operator[](ptr->m_value.array->size()); } else { // convert array index to number; unchecked access - ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); + JSON_TRY + { + ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); + } + JSON_CATCH (std::invalid_argument&) + { + JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } } break; } default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); } } } @@ -11174,6 +12800,12 @@ basic_json_parser_66: return *ptr; } + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ reference get_checked(pointer ptr) const { for (const auto& reference_token : reference_tokens) @@ -11192,25 +12824,32 @@ basic_json_parser_66: if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(out_of_range::create(402, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } // note: at performs range check - ptr = &ptr->at(static_cast(std::stoi(reference_token))); + JSON_TRY + { + ptr = &ptr->at(static_cast(std::stoi(reference_token))); + } + JSON_CATCH (std::invalid_argument&) + { + JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } break; } default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); } } } @@ -11225,6 +12864,11 @@ basic_json_parser_66: @return const reference to the JSON value pointed to by the JSON pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved */ const_reference get_unchecked(const_pointer ptr) const { @@ -11244,25 +12888,32 @@ basic_json_parser_66: if (reference_token == "-") { // "-" cannot be used for const access - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(out_of_range::create(402, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } // use unchecked array access - ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); + JSON_TRY + { + ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); + } + JSON_CATCH (std::invalid_argument&) + { + JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } break; } default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); } } } @@ -11270,6 +12921,12 @@ basic_json_parser_66: return *ptr; } + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ const_reference get_checked(const_pointer ptr) const { for (const auto& reference_token : reference_tokens) @@ -11288,25 +12945,32 @@ basic_json_parser_66: if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(out_of_range::create(402, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } // note: at performs range check - ptr = &ptr->at(static_cast(std::stoi(reference_token))); + JSON_TRY + { + ptr = &ptr->at(static_cast(std::stoi(reference_token))); + } + JSON_CATCH (std::invalid_argument&) + { + JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } break; } default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); } } } @@ -11314,7 +12978,15 @@ basic_json_parser_66: return *ptr; } - /// split the string input to reference tokens + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ static std::vector split(const std::string& reference_string) { std::vector result; @@ -11328,7 +13000,7 @@ basic_json_parser_66: // check if nonempty reference string begins with slash if (reference_string[0] != '/') { - throw std::domain_error("JSON pointer must be empty or begin with '/'"); + JSON_THROW(parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'")); } // extract the reference tokens: @@ -11336,7 +13008,7 @@ basic_json_parser_66: // - start: position after the previous slash for ( // search for the first slash after the first character - size_t slash = reference_string.find_first_of("/", 1), + size_t slash = reference_string.find_first_of('/', 1), // set the beginning of the first reference token start = 1; // we can stop if start == string::npos+1 = 0 @@ -11345,16 +13017,16 @@ basic_json_parser_66: // (will eventually be 0 if slash == std::string::npos) start = slash + 1, // find next slash - slash = reference_string.find_first_of("/", start)) + slash = reference_string.find_first_of('/', start)) { // use the text between the beginning of the reference token // (start) and the last slash (slash). auto reference_token = reference_string.substr(start, slash - start); // check reference tokens are properly escaped - for (size_t pos = reference_token.find_first_of("~"); + for (size_t pos = reference_token.find_first_of('~'); pos != std::string::npos; - pos = reference_token.find_first_of("~", pos + 1)) + pos = reference_token.find_first_of('~', pos + 1)) { assert(reference_token[pos] == '~'); @@ -11363,7 +13035,7 @@ basic_json_parser_66: (reference_token[pos + 1] != '0' and reference_token[pos + 1] != '1')) { - throw std::domain_error("escape error: '~' must be followed with '0' or '1'"); + JSON_THROW(parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); } } @@ -11375,7 +13047,6 @@ basic_json_parser_66: return result; } - private: /*! @brief replace all occurrences of a substring by another string @@ -11384,7 +13055,8 @@ basic_json_parser_66: @param[in] f the substring to replace with @a t @param[in] t the string to replace @a f - @pre The search string @a f must not be empty. + @pre The search string @a f must not be empty. **This precondition is + enforced with an assertion.** @since version 2.0.0 */ @@ -11484,12 +13156,17 @@ basic_json_parser_66: @param[in] value flattened JSON @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened */ static basic_json unflatten(const basic_json& value) { if (not value.is_object()) { - throw std::domain_error("only objects can be unflattened"); + JSON_THROW(type_error::create(314, "only objects can be unflattened")); } basic_json result; @@ -11499,7 +13176,7 @@ basic_json_parser_66: { if (not element.second.is_primitive()) { - throw std::domain_error("values in object must be primitive"); + JSON_THROW(type_error::create(315, "values in object must be primitive")); } // assign value to reference pointed to by JSON pointer; Note @@ -11513,7 +13190,18 @@ basic_json_parser_66: return result; } - private: + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return lhs.reference_tokens == rhs.reference_tokens; + } + + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return !(lhs == rhs); + } + /// the reference tokens std::vector reference_tokens {}; }; @@ -11550,9 +13238,9 @@ basic_json_parser_66: @complexity Constant. - @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved @liveexample{The behavior is shown in the example.,operatorjson_pointer} @@ -11577,9 +13265,10 @@ basic_json_parser_66: @complexity Constant. - @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} @@ -11600,15 +13289,30 @@ basic_json_parser_66: @return reference to the element pointed to by @a ptr - @complexity Constant. + @throw parse_error.106 if an array index in the passed JSON pointer @a ptr + begins with '0'. See example below. - @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw parse_error.109 if an array index in the passed JSON pointer @a ptr + is not a number. See example below. - @liveexample{The behavior is shown in the example.,at_json_pointer} + @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr + is out of range. See example below. + + @throw out_of_range.402 if the array index '-' is used in the passed JSON + pointer @a ptr. As `at` provides checked access (and no elements are + implicitly inserted), the index '-' is always invalid. See example below. + + @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. + See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. @since version 2.0.0 + + @liveexample{The behavior is shown in the example.,at_json_pointer} */ reference at(const json_pointer& ptr) { @@ -11625,15 +13329,30 @@ basic_json_parser_66: @return reference to the element pointed to by @a ptr - @complexity Constant. + @throw parse_error.106 if an array index in the passed JSON pointer @a ptr + begins with '0'. See example below. - @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw parse_error.109 if an array index in the passed JSON pointer @a ptr + is not a number. See example below. - @liveexample{The behavior is shown in the example.,at_json_pointer_const} + @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr + is out of range. See example below. + + @throw out_of_range.402 if the array index '-' is used in the passed JSON + pointer @a ptr. As `at` provides checked access (and no elements are + implicitly inserted), the index '-' is always invalid. See example below. + + @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. + See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. @since version 2.0.0 + + @liveexample{The behavior is shown in the example.,at_json_pointer_const} */ const_reference at(const json_pointer& ptr) const { @@ -11648,7 +13367,7 @@ basic_json_parser_66: primitive. The original JSON value can be restored using the @ref unflatten() function. - @return an object that maps JSON pointers to primitve values + @return an object that maps JSON pointers to primitive values @note Empty objects and arrays are flattened to `null` and will not be reconstructed correctly by the @ref unflatten() function. @@ -11689,6 +13408,9 @@ basic_json_parser_66: @complexity Linear in the size the JSON value. + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitve + @liveexample{The following code shows how a flattened JSON object is unflattened into the original nested JSON object.,unflatten} @@ -11715,7 +13437,7 @@ basic_json_parser_66: [JSON Patch](http://jsonpatch.com) defines a JSON document structure for expressing a sequence of operations to apply to a JSON) document. With - this funcion, a JSON Patch is applied to the current JSON value by + this function, a JSON Patch is applied to the current JSON value by executing all operations from the patch. @param[in] json_patch JSON patch document @@ -11726,12 +13448,23 @@ basic_json_parser_66: any case, the original value is not changed: the patch is applied to a copy of the value. - @throw std::out_of_range if a JSON pointer inside the patch could not - be resolved successfully in the current JSON value; example: `"key baz - not found"` - @throw invalid_argument if the JSON patch is malformed (e.g., mandatory + @throw parse_error.104 if the JSON patch does not consist of an array of + objects + + @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory attributes are missing); example: `"operation add must have member path"` + @throw out_of_range.401 if an array index is out of range. + + @throw out_of_range.403 if a JSON pointer inside the patch could not be + resolved successfully in the current JSON value; example: `"key baz not + found"` + + @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", + "move") + + @throw other_error.501 if "test" operation was unsuccessful + @complexity Linear in the size of the JSON value and the length of the JSON patch. As usually only a fraction of the JSON value is affected by the patch, the complexity can usually be neglected. @@ -11754,7 +13487,7 @@ basic_json_parser_66: // the valid JSON Patch operations enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - const auto get_op = [](const std::string op) + const auto get_op = [](const std::string & op) { if (op == "add") { @@ -11828,7 +13561,7 @@ basic_json_parser_66: if (static_cast(idx) > parent.size()) { // avoid undefined behavior - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); } else { @@ -11866,7 +13599,7 @@ basic_json_parser_66: } else { - throw std::out_of_range("key '" + last_path + "' not found"); + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); } } else if (parent.is_array()) @@ -11876,14 +13609,13 @@ basic_json_parser_66: } }; - // type check + // type check: top level value must be an array if (not json_patch.is_array()) { - // a JSON patch must be an array of objects - throw std::invalid_argument("JSON patch must be an array of objects"); + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); } - // iterate and apply th eoperations + // iterate and apply the operations for (const auto& val : json_patch) { // wrapper to get a value for an operation @@ -11900,23 +13632,23 @@ basic_json_parser_66: // check if desired value is present if (it == val.m_value.object->end()) { - throw std::invalid_argument(error_msg + " must have member '" + member + "'"); + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); } // check if result is of type string if (string_type and not it->second.is_string()) { - throw std::invalid_argument(error_msg + " must have string member '" + member + "'"); + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); } // no error: return value return it->second; }; - // type check + // type check: every element of the array must be an object if (not val.is_object()) { - throw std::invalid_argument("JSON patch must be an array of objects"); + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); } // collect mandatory members @@ -11975,13 +13707,13 @@ basic_json_parser_66: case patch_operations::test: { bool success = false; - try + JSON_TRY { // check if "value" matches the one at "path" // the "path" location must exist - use at() success = (result.at(ptr) == get_value("test", "value", false)); } - catch (std::out_of_range&) + JSON_CATCH (out_of_range&) { // ignore out of range errors: success remains false } @@ -11989,7 +13721,7 @@ basic_json_parser_66: // throw an exception if test fails if (not success) { - throw std::domain_error("unsuccessful: " + val.dump()); + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); } break; @@ -11999,7 +13731,7 @@ basic_json_parser_66: { // op must be "add", "remove", "replace", "move", "copy", or // "test" - throw std::invalid_argument("operation value '" + op + "' is invalid"); + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); } } } @@ -12022,8 +13754,8 @@ basic_json_parser_66: @note Currently, only `remove`, `add`, and `replace` operations are generated. - @param[in] source JSON value to copare from - @param[in] target JSON value to copare against + @param[in] source JSON value to compare from + @param[in] target JSON value to compare against @param[in] path helper value to create JSON pointers @return a JSON patch to convert the @a source to @a target @@ -12174,7 +13906,6 @@ basic_json_parser_66: /// @} }; - ///////////// // presets // ///////////// @@ -12188,7 +13919,7 @@ uses the standard template types. @since version 1.0.0 */ using json = basic_json<>; -} +} // namespace nlohmann /////////////////////// @@ -12229,7 +13960,23 @@ struct hash return h(j.dump()); } }; -} + +/// specialization for std::less +template <> +struct less<::nlohmann::detail::value_t> +{ + /*! + @brief compare two value_t enum values + @since version 3.0.0 + */ + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept + { + return nlohmann::detail::operator<(lhs, rhs); + } +}; + +} // namespace std /*! @brief user-defined string literal for JSON values @@ -12271,5 +14018,14 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) #pragma GCC diagnostic pop #endif +#if defined(__clang__) + #pragma GCC diagnostic pop +#endif + +// clean up +#undef JSON_CATCH +#undef JSON_THROW +#undef JSON_TRY +#undef JSON_DEPRECATED #endif diff --git a/make-linux.mk b/make-linux.mk index 811d4a6e..5fb489bb 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -8,7 +8,7 @@ ifeq ($(origin CXX),default) endif INCLUDES?= -DEFS?=-D_FORTIFY_SOURCE=2 +DEFS?= LDLIBS?= DESTDIR?= @@ -55,14 +55,15 @@ endif ifeq ($(ZT_DEBUG),1) override DEFS+=-DZT_TRACE - override CFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS) - override CXXFLAGS+=-Wall -g -O -std=c++11 -pthread $(INCLUDES) $(DEFS) + override CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS) + override CXXFLAGS+=-Wall -g -std=c++11 -pthread $(INCLUDES) $(DEFS) override LDFLAGS+= STRIP?=echo # The following line enables optimization for the crypto code, since # C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box! -node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CFLAGS = -Wall -O2 -g -pthread $(INCLUDES) $(DEFS) +node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -g -pthread $(INCLUDES) $(DEFS) else + override DEFS+=-D_FORTIFY_SOURCE=2 CFLAGS?=-O3 -fstack-protector override CFLAGS+=-Wall -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) CXXFLAGS?=-O3 -fstack-protector diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index 93be64dd..f01da38e 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -72,6 +72,8 @@ public: _thingCount(0), _issuedTo(issuedTo) { + memset(_thingTypes,0,sizeof(_thingTypes)); + memset(_thingValues,0,sizeof(_thingValues)); } inline uint64_t networkId() const { return _networkId; } diff --git a/root-watcher/schema.sql b/root-watcher/schema.sql index bdb3a1cf..ade0fa3e 100644 --- a/root-watcher/schema.sql +++ b/root-watcher/schema.sql @@ -1,7 +1,6 @@ /* Schema for ZeroTier root watcher log database */ -/* If you cluster this DB using any PG clustering scheme that uses logs, you must remove UNLOGGED here! */ -CREATE UNLOGGED TABLE "Peer" +CREATE TABLE "Peer" ( "ztAddress" BIGINT NOT NULL, "timestamp" BIGINT NOT NULL, diff --git a/selftest.cpp b/selftest.cpp index 33e65f2c..e23afd6e 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -49,7 +49,6 @@ #include "osdep/OSUtils.hpp" #include "osdep/Phy.hpp" -#include "osdep/Http.hpp" #include "osdep/PortMapper.hpp" #include "osdep/Thread.hpp" @@ -1019,51 +1018,6 @@ static int testPhy() return 0; } -/* -static int testHttp() -{ - std::map requestHeaders,responseHeaders; - std::string responseBody; - - InetAddress downloadZerotierDotCom; - std::vector rr(OSUtils::resolve("download.zerotier.com")); - if (rr.empty()) { - std::cout << "[http] Resolve of download.zerotier.com failed, skipping." << std::endl; - return 0; - } else { - for(std::vector::iterator r(rr.begin());r!=rr.end();++r) { - std::cout << "[http] download.zerotier.com: " << r->toString() << std::endl; - if (r->isV4()) - downloadZerotierDotCom = *r; - } - } - downloadZerotierDotCom.setPort(80); - - std::cout << "[http] GET http://download.zerotier.com/dev/1k @" << downloadZerotierDotCom.toString() << " ... "; std::cout.flush(); - requestHeaders["Host"] = "download.zerotier.com"; - unsigned int sc = Http::GET(1024 * 1024 * 16,60000,reinterpret_cast(&downloadZerotierDotCom),"/dev/1k",requestHeaders,responseHeaders,responseBody); - std::cout << sc << " " << responseBody.length() << " bytes "; - if (sc == 0) - std::cout << "ERROR: " << responseBody << std::endl; - else std::cout << "DONE" << std::endl; - - std::cout << "[http] GET http://download.zerotier.com/dev/4m @" << downloadZerotierDotCom.toString() << " ... "; std::cout.flush(); - requestHeaders["Host"] = "download.zerotier.com"; - sc = Http::GET(1024 * 1024 * 16,60000,reinterpret_cast(&downloadZerotierDotCom),"/dev/4m",requestHeaders,responseHeaders,responseBody); - std::cout << sc << " " << responseBody.length() << " bytes "; - if (sc == 0) - std::cout << "ERROR: " << responseBody << std::endl; - else std::cout << "DONE" << std::endl; - - downloadZerotierDotCom = InetAddress("1.0.0.1/1234"); - std::cout << "[http] GET @" << downloadZerotierDotCom.toString() << " ... "; std::cout.flush(); - sc = Http::GET(1024 * 1024 * 16,2500,reinterpret_cast(&downloadZerotierDotCom),"/dev/4m",requestHeaders,responseHeaders,responseBody); - std::cout << sc << " (should be 0, time out)" << std::endl; - - return 0; -} -*/ - #ifdef __WINDOWS__ int __cdecl _tmain(int argc, _TCHAR* argv[]) #else @@ -1127,7 +1081,6 @@ int main(int argc,char **argv) r |= testIdentity(); r |= testCertificate(); r |= testPhy(); - //r |= testHttp(); //*/ if (r) -- cgit v1.2.3 From 1b68d6dbdc5540e1b26b4ea35d019dde746af79e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 27 Apr 2017 20:47:25 -0700 Subject: License header update. --- include/ZeroTierOne.h | 10 +++++++++- node/Address.hpp | 10 +++++++++- node/Array.hpp | 10 +++++++++- node/AtomicCounter.hpp | 10 +++++++++- node/Buffer.hpp | 10 +++++++++- node/C25519.cpp | 4 +--- node/C25519.hpp | 10 +++++++++- node/Capability.cpp | 10 +++++++++- node/Capability.hpp | 10 +++++++++- node/CertificateOfMembership.cpp | 10 +++++++++- node/CertificateOfMembership.hpp | 10 +++++++++- node/CertificateOfOwnership.cpp | 10 +++++++++- node/CertificateOfOwnership.hpp | 10 +++++++++- node/CertificateOfRepresentation.hpp | 10 +++++++++- node/Cluster.cpp | 10 +++++++++- node/Cluster.hpp | 10 +++++++++- node/Constants.hpp | 10 +++++++++- node/Credential.hpp | 10 +++++++++- node/Dictionary.hpp | 10 +++++++++- node/Hashtable.hpp | 10 +++++++++- node/Identity.cpp | 10 +++++++++- node/Identity.hpp | 10 +++++++++- node/IncomingPacket.cpp | 10 +++++++++- node/IncomingPacket.hpp | 10 +++++++++- node/InetAddress.cpp | 10 +++++++++- node/InetAddress.hpp | 10 +++++++++- node/MAC.hpp | 10 +++++++++- node/Membership.cpp | 10 +++++++++- node/Membership.hpp | 10 +++++++++- node/MulticastGroup.hpp | 10 +++++++++- node/Multicaster.cpp | 10 +++++++++- node/Multicaster.hpp | 10 +++++++++- node/Mutex.hpp | 10 +++++++++- node/Network.cpp | 10 +++++++++- node/Network.hpp | 10 +++++++++- node/NetworkConfig.cpp | 10 +++++++++- node/NetworkConfig.hpp | 10 +++++++++- node/NetworkController.hpp | 10 +++++++++- node/Node.cpp | 10 +++++++++- node/Node.hpp | 10 +++++++++- node/NonCopyable.hpp | 10 +++++++++- node/OutboundMulticast.cpp | 10 +++++++++- node/OutboundMulticast.hpp | 10 +++++++++- node/Packet.cpp | 10 +++++++++- node/Packet.hpp | 10 +++++++++- node/Path.cpp | 10 +++++++++- node/Path.hpp | 10 +++++++++- node/Peer.cpp | 10 +++++++++- node/Peer.hpp | 10 +++++++++- node/Poly1305.hpp | 10 +++++++++- node/Revocation.cpp | 10 +++++++++- node/Revocation.hpp | 10 +++++++++- node/RuntimeEnvironment.hpp | 10 +++++++++- node/SHA512.cpp | 35 +++++++---------------------------- node/SHA512.hpp | 10 +++++++++- node/SelfAwareness.cpp | 10 +++++++++- node/SelfAwareness.hpp | 10 +++++++++- node/SharedPtr.hpp | 10 +++++++++- node/Switch.cpp | 10 +++++++++- node/Switch.hpp | 10 +++++++++- node/Tag.cpp | 10 +++++++++- node/Tag.hpp | 10 +++++++++- node/Topology.cpp | 10 +++++++++- node/Topology.hpp | 10 +++++++++- node/Utils.cpp | 10 +++++++++- node/Utils.hpp | 10 +++++++++- node/World.hpp | 10 +++++++++- one.cpp | 10 +++++++++- osdep/Arp.cpp | 10 +++++++++- osdep/Arp.hpp | 10 +++++++++- osdep/BSDEthernetTap.cpp | 10 +++++++++- osdep/BSDEthernetTap.hpp | 10 +++++++++- osdep/Binder.hpp | 10 +++++++++- osdep/BlockingQueue.hpp | 10 +++++++++- osdep/Http.cpp | 10 +++++++++- osdep/Http.hpp | 10 +++++++++- osdep/LinuxEthernetTap.cpp | 10 +++++++++- osdep/LinuxEthernetTap.hpp | 10 +++++++++- osdep/ManagedRoute.cpp | 10 +++++++++- osdep/ManagedRoute.hpp | 26 ++++++++++++++++++++++++++ osdep/NeighborDiscovery.cpp | 10 +++++++++- osdep/NeighborDiscovery.hpp | 10 +++++++++- osdep/OSUtils.cpp | 10 +++++++++- osdep/OSUtils.hpp | 10 +++++++++- osdep/OSXEthernetTap.cpp | 10 +++++++++- osdep/OSXEthernetTap.hpp | 10 +++++++++- osdep/Phy.hpp | 10 +++++++++- osdep/PortMapper.cpp | 10 +++++++++- osdep/PortMapper.hpp | 10 +++++++++- osdep/TestEthernetTap.hpp | 10 +++++++++- osdep/Thread.hpp | 10 +++++++++- osdep/WindowsEthernetTap.cpp | 10 +++++++++- osdep/WindowsEthernetTap.hpp | 10 +++++++++- selftest.cpp | 10 +++++++++- service/ClusterDefinition.hpp | 10 +++++++++- service/ClusterGeoIpService.cpp | 10 +++++++++- service/ClusterGeoIpService.hpp | 10 +++++++++- service/OneService.cpp | 10 +++++++++- service/OneService.hpp | 10 +++++++++- service/SoftwareUpdater.cpp | 10 +++++++++- service/SoftwareUpdater.hpp | 10 +++++++++- version.h | 10 +++++++++- 102 files changed, 925 insertions(+), 130 deletions(-) (limited to 'selftest.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 747e1855..20707a1d 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ /* diff --git a/node/Address.hpp b/node/Address.hpp index 4a5883b0..9d2d1734 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_ADDRESS_HPP diff --git a/node/Array.hpp b/node/Array.hpp index 19b29eb3..5c616475 100644 --- a/node/Array.hpp +++ b/node/Array.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_ARRAY_HPP diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp index a0f29baa..e1864db8 100644 --- a/node/AtomicCounter.hpp +++ b/node/AtomicCounter.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_ATOMICCOUNTER_HPP diff --git a/node/Buffer.hpp b/node/Buffer.hpp index 37f39e7b..ae242c73 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_BUFFER_HPP diff --git a/node/C25519.cpp b/node/C25519.cpp index e9ffecc1..a78e0466 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -1,5 +1,3 @@ -// Code taken from NaCl by D. J. Bernstein and others - /* Matthew Dempsky Public domain. @@ -7,7 +5,7 @@ Derived from public domain code by D. J. Bernstein. */ // Modified very slightly for ZeroTier One by Adam Ierymenko -// (no functional changes) +// This code remains in the public domain. #include #include diff --git a/node/C25519.hpp b/node/C25519.hpp index b19d9693..da9ba665 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_C25519_HPP diff --git a/node/Capability.cpp b/node/Capability.cpp index c178e566..0e02025a 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Capability.hpp" diff --git a/node/Capability.hpp b/node/Capability.hpp index 454723ac..8d4b9085 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CAPABILITY_HPP diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 9bf70216..a5445e42 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "CertificateOfMembership.hpp" diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index dfccb138..739d5390 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index 2bd181e0..31d0ae18 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "CertificateOfOwnership.hpp" diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index f01da38e..95039a2d 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP diff --git a/node/CertificateOfRepresentation.hpp b/node/CertificateOfRepresentation.hpp index 710ee577..92a71bc0 100644 --- a/node/CertificateOfRepresentation.hpp +++ b/node/CertificateOfRepresentation.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CERTIFICATEOFREPRESENTATION_HPP diff --git a/node/Cluster.cpp b/node/Cluster.cpp index 54206f99..4d2dea76 100644 --- a/node/Cluster.cpp +++ b/node/Cluster.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_ENABLE_CLUSTER diff --git a/node/Cluster.hpp b/node/Cluster.hpp index 08e32a99..74b091f5 100644 --- a/node/Cluster.hpp +++ b/node/Cluster.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CLUSTER_HPP diff --git a/node/Constants.hpp b/node/Constants.hpp index 93184efa..d3c87491 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CONSTANTS_HPP diff --git a/node/Credential.hpp b/node/Credential.hpp index 0ae2a0a8..bc81919b 100644 --- a/node/Credential.hpp +++ b/node/Credential.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CREDENTIAL_HPP diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 0db13b63..e212e453 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_DICTIONARY_HPP diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index 66f2990a..c46ed68f 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_HASHTABLE_HPP diff --git a/node/Identity.cpp b/node/Identity.cpp index d1b21e9c..ba77aa47 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Identity.hpp b/node/Identity.hpp index e4522732..b1c7d6f4 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_IDENTITY_HPP diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 303160ec..126da53c 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 3d4a2e05..43a1ea10 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_INCOMINGPACKET_HPP diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 7d22eeae..62bb8145 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index c37fa621..0975a9cf 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_INETADDRESS_HPP diff --git a/node/MAC.hpp b/node/MAC.hpp index 95623f12..e7717d99 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_MAC_HPP diff --git a/node/Membership.cpp b/node/Membership.cpp index 2d0471f1..466f9021 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Membership.hpp b/node/Membership.hpp index 0bc8f335..5e4475da 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_MEMBERSHIP_HPP diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index be4e8084..4240db67 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_MULTICASTGROUP_HPP diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 8e534b5e..52213364 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index f646a5be..2186e9c3 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_MULTICASTER_HPP diff --git a/node/Mutex.hpp b/node/Mutex.hpp index d451ede0..6f1d3471 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_MUTEX_HPP diff --git a/node/Network.cpp b/node/Network.cpp index b7f25f7f..ee0f8611 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Network.hpp b/node/Network.hpp index faef0fed..cce6c41f 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_NETWORK_HPP diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index fe7393e8..9effe529 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 85c24090..7bae6a91 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_NETWORKCONFIG_HPP diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp index 0634f435..63d44a46 100644 --- a/node/NetworkController.hpp +++ b/node/NetworkController.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_NETWORKCONFIGMASTER_HPP diff --git a/node/Node.cpp b/node/Node.cpp index ccbe9411..5848d953 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Node.hpp b/node/Node.hpp index d25a619b..95587161 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_NODE_HPP diff --git a/node/NonCopyable.hpp b/node/NonCopyable.hpp index 6d4daa86..25c71b1c 100644 --- a/node/NonCopyable.hpp +++ b/node/NonCopyable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_NONCOPYABLE_HPP__ diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 285bfa5d..a2341ffd 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Constants.hpp" diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 0ecf113f..0c988804 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_OUTBOUNDMULTICAST_HPP diff --git a/node/Packet.cpp b/node/Packet.cpp index 8a57dd55..d60a3a34 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Packet.hpp b/node/Packet.hpp index 8ad2c0f9..1de679e7 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_N_PACKET_HPP diff --git a/node/Path.cpp b/node/Path.cpp index 7366b56f..a5fe1aa7 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Path.hpp" diff --git a/node/Path.hpp b/node/Path.hpp index aef628d4..32bceae0 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_PATH_HPP diff --git a/node/Peer.cpp b/node/Peer.cpp index 2e9f6a2b..01905833 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "../version.h" diff --git a/node/Peer.hpp b/node/Peer.hpp index b9d85404..9b57f23e 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_PEER_HPP diff --git a/node/Poly1305.hpp b/node/Poly1305.hpp index 62d57546..ff709983 100644 --- a/node/Poly1305.hpp +++ b/node/Poly1305.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_POLY1305_HPP diff --git a/node/Revocation.cpp b/node/Revocation.cpp index bab5653c..026058da 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Revocation.hpp" diff --git a/node/Revocation.hpp b/node/Revocation.hpp index e5e013bd..e8f5d00d 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_REVOCATION_HPP diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 7ba1c989..d8e1d699 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_RUNTIMEENVIRONMENT_HPP diff --git a/node/SHA512.cpp b/node/SHA512.cpp index 76737d37..c8d81dd1 100644 --- a/node/SHA512.cpp +++ b/node/SHA512.cpp @@ -1,20 +1,11 @@ +// Code taken from NaCl by D. J. Bernstein and others +// Public domain + /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +20080913 +D. J. Bernstein +Public domain. +*/ #include #include @@ -25,18 +16,6 @@ namespace ZeroTier { -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -// Code taken from NaCl by D. J. Bernstein and others -// Public domain - -/* -20080913 -D. J. Bernstein -Public domain. -*/ - #define uint64 uint64_t #ifdef ZT_NO_TYPE_PUNNING diff --git a/node/SHA512.hpp b/node/SHA512.hpp index 639a7dfd..584f8e11 100644 --- a/node/SHA512.hpp +++ b/node/SHA512.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_SHA512_HPP diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index cba84cdc..c5daddc3 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index c1db0c84..63c416bf 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_SELFAWARENESS_HPP diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index 1dd3b43d..09010f67 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_SHAREDPTR_HPP diff --git a/node/Switch.cpp b/node/Switch.cpp index 56299a9a..211b706a 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Switch.hpp b/node/Switch.hpp index ff350934..9793dd45 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_N_SWITCH_HPP diff --git a/node/Tag.cpp b/node/Tag.cpp index 3f924da1..39b17f2a 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Tag.hpp" diff --git a/node/Tag.hpp b/node/Tag.hpp index 1f7f6835..746ade26 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_TAG_HPP diff --git a/node/Topology.cpp b/node/Topology.cpp index a1d37332..80f4ed4e 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Constants.hpp" diff --git a/node/Topology.hpp b/node/Topology.hpp index d29c424e..d06ba94b 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_TOPOLOGY_HPP diff --git a/node/Utils.cpp b/node/Utils.cpp index 9ce1bf05..d69e5335 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/node/Utils.hpp b/node/Utils.hpp index ceb29d7e..25a90055 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_UTILS_HPP diff --git a/node/World.hpp b/node/World.hpp index 6e835bec..003d70e3 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_WORLD_HPP diff --git a/one.cpp b/one.cpp index b40e28fc..1f38361f 100644 --- a/one.cpp +++ b/one.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/Arp.cpp b/osdep/Arp.cpp index fcc122f0..c06f459b 100644 --- a/osdep/Arp.cpp +++ b/osdep/Arp.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/Arp.hpp b/osdep/Arp.hpp index 5f0d199a..e26fcdb3 100644 --- a/osdep/Arp.hpp +++ b/osdep/Arp.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_ARP_HPP diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index 62fabc48..87a9aece 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index 8c6314db..3cb9c10e 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_BSDETHERNETTAP_HPP diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 9829f170..ee832825 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_BINDER_HPP diff --git a/osdep/BlockingQueue.hpp b/osdep/BlockingQueue.hpp index 6172f4da..34abcb67 100644 --- a/osdep/BlockingQueue.hpp +++ b/osdep/BlockingQueue.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_BLOCKINGQUEUE_HPP diff --git a/osdep/Http.cpp b/osdep/Http.cpp index 064ccd0c..d2540071 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/Http.hpp b/osdep/Http.hpp index e7d4d03e..3f98d760 100644 --- a/osdep/Http.hpp +++ b/osdep/Http.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_HTTP_HPP diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index f74efc0a..2d3891e3 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index a2a00a79..ab9d2370 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_LINUXETHERNETTAP_HPP diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 3a020d61..fca1c290 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "../node/Constants.hpp" diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index fd77a79a..849bddf5 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -1,3 +1,29 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + #ifndef ZT_MANAGEDROUTE_HPP #define ZT_MANAGEDROUTE_HPP diff --git a/osdep/NeighborDiscovery.cpp b/osdep/NeighborDiscovery.cpp index 4f636310..cd8b9b91 100644 --- a/osdep/NeighborDiscovery.cpp +++ b/osdep/NeighborDiscovery.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "NeighborDiscovery.hpp" diff --git a/osdep/NeighborDiscovery.hpp b/osdep/NeighborDiscovery.hpp index 47831bda..2e7a68ba 100644 --- a/osdep/NeighborDiscovery.hpp +++ b/osdep/NeighborDiscovery.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_NEIGHBORDISCOVERY_HPP diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index fd5efed0..b7fce982 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index b84d5d2d..4b9ee893 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_OSUTILS_HPP diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index f70908b8..53c9ba98 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/OSXEthernetTap.hpp b/osdep/OSXEthernetTap.hpp index 5a96c210..ed7f39c3 100644 --- a/osdep/OSXEthernetTap.hpp +++ b/osdep/OSXEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_OSXETHERNETTAP_HPP diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index eab8a317..01a339e9 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_PHY_HPP diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index d3a19384..99286172 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/PortMapper.hpp b/osdep/PortMapper.hpp index 0b8d15fc..61015a09 100644 --- a/osdep/PortMapper.hpp +++ b/osdep/PortMapper.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/TestEthernetTap.hpp b/osdep/TestEthernetTap.hpp index 6c044a94..afd89541 100644 --- a/osdep/TestEthernetTap.hpp +++ b/osdep/TestEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_TESTETHERNETTAP_HPP diff --git a/osdep/Thread.hpp b/osdep/Thread.hpp index 5423a8ab..a2f0919f 100644 --- a/osdep/Thread.hpp +++ b/osdep/Thread.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_THREAD_HPP diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 79b9d35e..c37c7410 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index f2cf73f3..a3c1c0c3 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_WINDOWSETHERNETTAP_HPP diff --git a/selftest.cpp b/selftest.cpp index e23afd6e..209fe203 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/service/ClusterDefinition.hpp b/service/ClusterDefinition.hpp index dda1a8c8..9947e46b 100644 --- a/service/ClusterDefinition.hpp +++ b/service/ClusterDefinition.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CLUSTERDEFINITION_HPP diff --git a/service/ClusterGeoIpService.cpp b/service/ClusterGeoIpService.cpp index 89015c51..2dcc9179 100644 --- a/service/ClusterGeoIpService.cpp +++ b/service/ClusterGeoIpService.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_ENABLE_CLUSTER diff --git a/service/ClusterGeoIpService.hpp b/service/ClusterGeoIpService.hpp index ff2fcdb8..380f944f 100644 --- a/service/ClusterGeoIpService.hpp +++ b/service/ClusterGeoIpService.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CLUSTERGEOIPSERVICE_HPP diff --git a/service/OneService.cpp b/service/OneService.cpp index 988e723d..9f9cec0a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/service/OneService.hpp b/service/OneService.hpp index 3390f2ac..f52cd40e 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_ONESERVICE_HPP diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 7ec377cc..d94beab5 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index 4bb0ef51..ff3e36df 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_SOFTWAREUPDATER_HPP diff --git a/version.h b/version.h index c51bfee2..b3b2fc81 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef _ZT_VERSION_H -- cgit v1.2.3 From d297d8fe2eccf8ca001d28a950152fc3bec992b5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 May 2017 21:21:56 -0700 Subject: Musl fix --- make-linux.mk | 8 ++++---- osdep/OSUtils.hpp | 30 +++++++----------------------- selftest.cpp | 1 + 3 files changed, 12 insertions(+), 27 deletions(-) (limited to 'selftest.cpp') diff --git a/make-linux.mk b/make-linux.mk index cdfb52ba..eb77326e 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -66,9 +66,9 @@ node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 - else override DEFS+=-D_FORTIFY_SOURCE=2 CFLAGS?=-O3 -fstack-protector - override CFLAGS+=-Wall -Wno-deprecated -Werror -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) + override CFLAGS+=-Wall -Wno-deprecated -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) CXXFLAGS?=-O3 -fstack-protector - override CXXFLAGS+=-Wall -Wno-deprecated -Werror -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS) + override CXXFLAGS+=-Wall -Wno-deprecated -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS) override LDFLAGS+=-pie -Wl,-z,relro,-z,now STRIP?=strip STRIP+=--strip-all @@ -211,10 +211,10 @@ endif all: one #ext/x64-salsa2012-asm/salsa2012.o: -# $(CC) $(CFLAGS) -c ext/x64-salsa2012-asm/salsa2012.s -o ext/x64-salsa2012-asm/salsa2012.o +# $(CC) -c ext/x64-salsa2012-asm/salsa2012.s -o ext/x64-salsa2012-asm/salsa2012.o #ext/arm32-neon-salsa2012-asm/salsa2012.o: -# $(CC) $(CFLAGS) -c ext/arm32-neon-salsa2012-asm/salsa2012.s -o ext/arm32-neon-salsa2012-asm/salsa2012.o +# $(CC) -c ext/arm32-neon-salsa2012-asm/salsa2012.s -o ext/arm32-neon-salsa2012-asm/salsa2012.o one: $(CORE_OBJS) $(ONE_OBJS) one.o $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LDLIBS) diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 4b9ee893..dff7df86 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -51,6 +51,9 @@ #include #include #include +#ifdef __LINUX__ +#include +#endif #endif #include "../ext/json/json.hpp" @@ -185,7 +188,6 @@ public: * @return Current time in milliseconds since epoch */ static inline uint64_t now() - throw() { #ifdef __WINDOWS__ FILETIME ft; @@ -198,33 +200,15 @@ public: return ( ((tmp.QuadPart - 116444736000000000ULL) / 10000L) + st.wMilliseconds ); #else struct timeval tv; +#ifdef __LINUX__ + syscall(SYS_gettimeofday,&tv,0); /* fix for musl libc broken gettimeofday bug */ +#else gettimeofday(&tv,(struct timezone *)0); +#endif return ( (1000ULL * (uint64_t)tv.tv_sec) + (uint64_t)(tv.tv_usec / 1000) ); #endif }; - /** - * @return Current time in seconds since epoch, to the highest available resolution - */ - static inline double nowf() - throw() - { -#ifdef __WINDOWS__ - FILETIME ft; - SYSTEMTIME st; - ULARGE_INTEGER tmp; - GetSystemTime(&st); - SystemTimeToFileTime(&st,&ft); - tmp.LowPart = ft.dwLowDateTime; - tmp.HighPart = ft.dwHighDateTime; - return (((double)(tmp.QuadPart - 116444736000000000ULL)) / 10000000.0); -#else - struct timeval tv; - gettimeofday(&tv,(struct timezone *)0); - return ( ((double)tv.tv_sec) + (((double)tv.tv_usec) / 1000000.0) ); -#endif - } - /** * Read the full contents of a file into a string buffer * diff --git a/selftest.cpp b/selftest.cpp index 209fe203..759f39c1 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -1077,6 +1077,7 @@ int main(int argc,char **argv) */ std::cout << "[info] sizeof(void *) == " << sizeof(void *) << std::endl; + std::cout << "[info] OSUtils::now() == " << OSUtils::now() << std::endl; std::cout << "[info] hardware concurrency == " << std::thread::hardware_concurrency() << std::endl; std::cout << "[info] sizeof(NetworkConfig) == " << sizeof(ZeroTier::NetworkConfig) << std::endl; -- cgit v1.2.3 From ceee56af51231e849a3aecfdd6fddebbb47fe9d0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 May 2017 21:36:25 -0700 Subject: Fix for small stacks. --- selftest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'selftest.cpp') diff --git a/selftest.cpp b/selftest.cpp index 759f39c1..8175d708 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -151,8 +151,8 @@ static const C25519TestVector C25519_TEST_VECTORS[ZT_NUM_C25519_TEST_VECTORS] = static int testCrypto() { - unsigned char buf1[16384]; - unsigned char buf2[sizeof(buf1)],buf3[sizeof(buf1)]; + static unsigned char buf1[16384]; + static unsigned char buf2[sizeof(buf1)],buf3[sizeof(buf1)]; for(int i=0;i<3;++i) { Utils::getSecureRandom(buf1,64); -- cgit v1.2.3 From 355cce3938a815feba1085569263ae0225cebfa6 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 27 Jun 2017 11:31:29 -0700 Subject: Rename Utils::snprintf due to it being a #define on one platform. --- attic/DBM.cpp | 243 ------------------------------- attic/DBM.hpp | 168 --------------------- controller/EmbeddedNetworkController.cpp | 26 ++-- controller/JSONDB.cpp | 10 +- node/Address.hpp | 4 +- node/Dictionary.hpp | 4 +- node/InetAddress.cpp | 8 +- node/MAC.hpp | 2 +- node/MulticastGroup.hpp | 2 +- node/Network.cpp | 4 +- node/NetworkConfig.cpp | 2 +- node/Node.cpp | 2 +- node/Utils.cpp | 5 +- node/Utils.hpp | 3 +- one.cpp | 20 +-- osdep/BSDEthernetTap.cpp | 16 +- osdep/Http.cpp | 4 +- osdep/LinuxEthernetTap.cpp | 10 +- osdep/OSUtils.cpp | 6 +- osdep/OSXEthernetTap.cpp | 14 +- osdep/PortMapper.cpp | 4 +- osdep/WindowsEthernetTap.cpp | 10 +- selftest.cpp | 2 +- service/ClusterDefinition.hpp | 2 +- service/OneService.cpp | 62 ++++---- service/SoftwareUpdater.cpp | 2 +- 26 files changed, 111 insertions(+), 524 deletions(-) delete mode 100644 attic/DBM.cpp delete mode 100644 attic/DBM.hpp (limited to 'selftest.cpp') diff --git a/attic/DBM.cpp b/attic/DBM.cpp deleted file mode 100644 index 54f017e0..00000000 --- a/attic/DBM.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#include "DBM.hpp" - -#include "../version.h" - -#include "../node/Salsa20.hpp" -#include "../node/Poly1305.hpp" -#include "../node/SHA512.hpp" - -#include "../osdep/OSUtils.hpp" - -#define ZT_STORED_OBJECT_TYPE__CLUSTER_NODE_STATUS (ZT_STORED_OBJECT__MAX_TYPE_ID + 1) -#define ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION (ZT_STORED_OBJECT__MAX_TYPE_ID + 2) - -namespace ZeroTier { - -// We generate the cluster ID from our address and version info since this is -// not at all designed to allow interoperation between versions (or endians) -// in the same cluster. -static inline uint64_t _mkClusterId(const Address &myAddress) -{ - uint64_t x = ZEROTIER_ONE_VERSION_MAJOR; - x <<= 8; - x += ZEROTIER_ONE_VERSION_MINOR; - x <<= 8; - x += ZEROTIER_ONE_VERSION_REVISION; - x <<= 40; - x ^= myAddress.toInt(); -#if __BYTE_ORDER == __BIG_ENDIAN - ++x; -#endif; - return x; -} - -void DBM::onUpdate(uint64_t from,const _MapKey &k,const _MapValue &v,uint64_t rev) -{ - char p[4096]; - char tmp[ZT_DBM_MAX_VALUE_SIZE]; - if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p))) { - // Reduce unnecessary disk writes - FILE *f = fopen(p,"r"); - if (f) { - long n = (long)fread(tmp,1,sizeof(tmp),f); - fclose(f); - if ((n == (long)v.len)&&(!memcmp(v.data,tmp,n))) - return; - } - - // Write to disk if file has changed or was not already present - f = fopen(p,"w"); - if (f) { - if (fwrite(data,len,1,f) != 1) - fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p); - fclose(f); - if (type == ZT_STORED_OBJECT_IDENTITY_SECRET) - OSUtils::lockDownFile(p,false); - } else { - fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p); - } - } -} - -void DBM::onDelete(uint64_t from,const _MapKey &k) -{ - char p[4096]; - if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p))) - OSUtils::rm(p); -} - -DBM::_vsdm_cryptor::_vsdm_cryptor(const Identity &secretIdentity) -{ - uint8_t s512[64]; - SHA512::hash(h512,secretIdentity.privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); - memcpy(_key,s512,sizeof(_key)); -} - -void DBM::_vsdm_cryptor::encrypt(void *d,unsigned long l) -{ - if (l >= 24) { // sanity check - uint8_t key[32]; - uint8_t authKey[32]; - uint8_t auth[16]; - - uint8_t *const iv = reinterpret_cast(d) + (l - 16); - Utils::getSecureRandom(iv,16); - memcpy(key,_key,32); - for(unsigned long i=0;i<8;++i) - _key[i] ^= iv[i]; - - Salsa20 s20(key,iv + 8); - memset(authKey,0,32); - s20.crypt12(authKey,authKey,32); - s20.crypt12(d,d,l - 24); - - Poly1305::compute(auth,d,l - 24,authKey); - memcpy(reinterpret_cast(d) + (l - 24),auth,8); - } -} - -bool DBM::_vsdm_cryptor::decrypt(void *d,unsigned long l) -{ - if (l >= 24) { // sanity check - uint8_t key[32]; - uint8_t authKey[32]; - uint8_t auth[16]; - - uint8_t *const iv = reinterpret_cast(d) + (l - 16); - memcpy(key,_key,32); - for(unsigned long i=0;i<8;++i) - _key[i] ^= iv[i]; - - Salsa20 s20(key,iv + 8); - memset(authKey,0,32); - s20.crypt12(authKey,authKey,32); - - Poly1305::compute(auth,d,l - 24,authKey); - if (!Utils::secureEq(reinterpret_cast(d) + (l - 24),auth,8)) - return false; - - s20.crypt12(d,d,l - 24); - - return true; - } - return false; -} - -DBM::DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node) : - _basePath(basePath), - _node(node), - _startTime(OSUtils::now()), - _m(_mkClusterId(secretIdentity.address()),clusterMemberId,false,_vsdm_cryptor(secretIdentity),_vsdm_watcher(this)) -{ -} - -DBM::~DBM() -{ -} - -void DBM::put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len) -{ - char p[4096]; - if (_m.put(_MapKey(key,(uint16_t)type),Value(OSUtils::now(),(uint16_t)len,data))) { - if (_persistentPath(type,key,p,sizeof(p))) { - FILE *f = fopen(p,"w"); - if (f) { - if (fwrite(data,len,1,f) != 1) - fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p); - fclose(f); - if (type == ZT_STORED_OBJECT_IDENTITY_SECRET) - OSUtils::lockDownFile(p,false); - } else { - fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p); - } - } - } -} - -bool DBM::get(const ZT_StoredObjectType type,const uint64_t key,Value &value) -{ - char p[4096]; - if (_m.get(_MapKey(key,(uint16_t)type),value)) - return true; - if (_persistentPath(type,key,p,sizeof(p))) { - FILE *f = fopen(p,"r"); - if (f) { - long n = (long)fread(value.data,1,sizeof(value.data),f); - value.len = (n > 0) ? (uint16_t)n : (uint16_t)0; - fclose(f); - value.ts = OSUtils::getLastModified(p); - _m.put(_MapKey(key,(uint16_t)type),value); - return true; - } - } - return false; -} - -void DBM::del(const ZT_StoredObjectType type,const uint64_t key) -{ - char p[4096]; - _m.del(_MapKey(key,(uint16_t)type)); - if (_persistentPath(type,key,p,sizeof(p))) - OSUtils::rm(p); -} - -void DBM::clean() -{ -} - -bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen) -{ - switch(type) { - case ZT_STORED_OBJECT_IDENTITY_PUBLIC: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.public",_basePath.c_str()); - return true; - case ZT_STORED_OBJECT_IDENTITY_SECRET: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.secret",_basePath.c_str()); - return true; - case ZT_STORED_OBJECT_IDENTITY: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "iddb.d" ZT_PATH_SEPARATOR_S "%.10llx",_basePath.c_str(),key); - return true; - case ZT_STORED_OBJECT_NETWORK_CONFIG: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_basePath.c_str(),key); - return true; - case ZT_STORED_OBJECT_PLANET: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "planet",_basePath.c_str()); - return true; - case ZT_STORED_OBJECT_MOON: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon",_basePath.c_str(),key); - return true; - case (ZT_StoredObjectType)ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "cluster",_basePath.c_str()); - return true; - default: - return false; - } -} - -} // namespace ZeroTier diff --git a/attic/DBM.hpp b/attic/DBM.hpp deleted file mode 100644 index c6d5b8c0..00000000 --- a/attic/DBM.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_DBM_HPP___ -#define ZT_DBM_HPP___ - -#include -#include -#include -#include - -#include - -#include "../node/Constants.hpp" -#include "../node/Mutex.hpp" -#include "../node/Utils.hpp" -#include "../node/Identity.hpp" -#include "../node/Peer.hpp" - -#include "../ext/vsdm/vsdm.hpp" - -// The Peer is the largest structure we persist here -#define ZT_DBM_MAX_VALUE_SIZE sizeof(Peer) - -namespace ZeroTier { - -class Node; -class DBM; - -class DBM -{ -public: - ZT_PACKED_STRUCT(struct Value - { - Value(const uint64_t t,const uint16_t l,const void *d) : - ts(t), - l(l) - { - memcpy(data,d,l); - } - uint64_t ts; - uint16_t len; - uint8_t data[ZT_DBM_MAX_VALUE_SIZE]; - }); - -private: - ZT_PACKED_STRUCT(struct _MapKey - { - _MapKey() : obj(0),type(0) {} - _MapKey(const uint16_t t,const uint64_t o) : obj(o),type(t) {} - uint64_t obj; - uint16_t type; - inline bool operator==(const _MapKey &k) const { return ((obj == k.obj)&&(type == k.type)); } - }); - struct _MapHasher - { - inline std::size_t operator()(const _MapKey &k) const { return (std::size_t)((k.obj ^ (k.obj >> 32)) + (uint64_t)k.type); } - }; - - void onUpdate(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev); - void onDelete(uint64_t from,const _MapKey &k); - - class _vsdm_watcher - { - public: - _vsdm_watcher(DBM *p) : _parent(p) {} - inline void add(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); } - inline void update(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); } - inline void del(uint64_t from,const _MapKey &k) { _parent->onDelete(from,k); } - private: - DBM *_parent; - }; - class _vsdm_serializer - { - public: - static inline unsigned long objectSize(const _MapKey &k) { return 10; } - static inline unsigned long objectSize(const Value &v) { return (10 + v.len); } - static inline const char *objectData(const _MapKey &k) { return reinterpret_cast(&k); } - static inline const char *objectData(const Value &v) { return reinterpret_cast(&v); } - static inline bool objectDeserialize(const char *d,unsigned long l,_MapKey &k) - { - if (l == 10) { - memcpy(&k,d,10); - return true; - } - return false; - } - static inline bool objectDeserialize(const char *d,unsigned long l,Value &v) - { - if ((l >= 10)&&(l <= (10 + ZT_DBM_MAX_VALUE_SIZE))) { - memcpy(&v,d,l); - return true; - } - return false; - } - }; - class _vsdm_cryptor - { - public: - _vsdm_cryptor(const Identity &secretIdentity); - static inline unsigned long overhead() { return 24; } - void encrypt(void *d,unsigned long l); - bool decrypt(void *d,unsigned long l); - uint8_t _key[32]; - }; - - typedef vsdm< _MapKey,Value,16384,_vsdm_watcher,_vsdm_serializer,_vsdm_cryptor,_MapHasher > _Map; - - friend class _Map; - -public: - ZT_PACKED_STRUCT(struct ClusterPeerStatus - { - uint64_t startTime; - uint64_t currentTime; - uint64_t clusterPeersConnected; - uint64_t ztPeersConnected; - uint16_t platform; - uint16_t arch; - }); - - DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node); - - ~DBM(); - - void put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len); - - bool get(const ZT_StoredObjectType type,const uint64_t key,Value &value); - - void del(const ZT_StoredObjectType type,const uint64_t key); - - void clean(); - -private: - bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen); - - const std::string _basePath; - Node *const _node; - uint64_t _startTime; - _Map _m; -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index e2eaa788..85c759e7 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -122,12 +122,12 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: r["type"] = "MATCH_MAC_SOURCE"; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_MAC_DEST: r["type"] = "MATCH_MAC_DEST"; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: @@ -179,7 +179,7 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: r["type"] = "MATCH_CHARACTERISTICS"; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); r["mask"] = tmp; break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: @@ -514,7 +514,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( _db.eachMember(nwid,[&responseBody](uint64_t networkId,uint64_t nodeId,const json &member) { if ((member.is_object())&&(member.size() > 0)) { char tmp[128]; - Utils::snprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); responseBody.append(tmp); } }); @@ -548,7 +548,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( for(std::vector::const_iterator i(networkIds.begin());i!=networkIds.end();++i) { if (responseBody.length() > 1) responseBody.push_back(','); - Utils::snprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); + Utils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); responseBody.append(tmp); } responseBody.push_back(']'); @@ -562,7 +562,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( // Controller status char tmp[4096]; - Utils::snprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); + Utils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); responseBody = tmp; responseContentType = "application/json"; return 200; @@ -603,14 +603,14 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if ((path.size() >= 2)&&(path[1].length() == 16)) { uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); char nwids[24]; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); if (path.size() >= 3) { if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { uint64_t address = Utils::hexStrToU64(path[3].c_str()); char addrs[24]; - Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); + Utils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); json member; _db.getNetworkMember(nwid,address,member); @@ -748,7 +748,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (!nwid) return 503; } - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); json network; _db.getNetwork(nwid,network); @@ -995,7 +995,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( _queue.post(qe); char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"{\"clock\":%llu,\"ping\":%s}",(unsigned long long)now,OSUtils::jsonDump(b).c_str()); + Utils::ztsnprintf(tmp,sizeof(tmp),"{\"clock\":%llu,\"ping\":%s}",(unsigned long long)now,OSUtils::jsonDump(b).c_str()); responseBody = tmp; responseContentType = "application/json"; @@ -1083,7 +1083,7 @@ void EmbeddedNetworkController::threadMain() auto ms = this->_memberStatus.find(_MemberStatusKey(networkId,nodeId)); if (ms != _memberStatus.end()) lrt = ms->second.lastRequestTime; - Utils::snprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", + Utils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", (first) ? "" : ",", (unsigned long long)networkId, (unsigned long long)nodeId, @@ -1093,7 +1093,7 @@ void EmbeddedNetworkController::threadMain() }); } char tmp2[256]; - Utils::snprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); + Utils::ztsnprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); pong.append(tmp2); _db.writeRaw("pong",pong); } @@ -1126,7 +1126,7 @@ void EmbeddedNetworkController::_request( ms.lastRequestTime = now; } - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); if (!_db.getNetworkAndMember(nwid,identity.address().toInt(),network,member,ns)) { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); return; diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index e0dd1742..acf23700 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -94,7 +94,7 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) std::string body; std::map reqHeaders; char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); reqHeaders["Content-Length"] = tmp; reqHeaders["Content-Type"] = "application/json"; const unsigned int sc = Http::PUT(0,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),(unsigned long)obj.length(),headers,body); @@ -164,7 +164,7 @@ bool JSONDB::getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlo void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkConfig) { char n[64]; - Utils::snprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); writeRaw(n,OSUtils::jsonDump(networkConfig)); { Mutex::Lock _l(_networks_m); @@ -176,7 +176,7 @@ void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkC void JSONDB::saveNetworkMember(const uint64_t networkId,const uint64_t nodeId,const nlohmann::json &memberConfig) { char n[256]; - Utils::snprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); writeRaw(n,OSUtils::jsonDump(memberConfig)); { Mutex::Lock _l(_networks_m); @@ -202,7 +202,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) } char n[256]; - Utils::snprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); if (_httpAddr) { // Deletion is currently done by Central in harnessed mode @@ -229,7 +229,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) nlohmann::json JSONDB::eraseNetworkMember(const uint64_t networkId,const uint64_t nodeId,bool recomputeSummaryInfo) { char n[256]; - Utils::snprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); if (_httpAddr) { // Deletion is currently done by the caller in Central harnessed mode diff --git a/node/Address.hpp b/node/Address.hpp index 9d2d1734..98e32858 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -144,7 +144,7 @@ public: inline std::string toString() const { char buf[16]; - Utils::snprintf(buf,sizeof(buf),"%.10llx",(unsigned long long)_a); + Utils::ztsnprintf(buf,sizeof(buf),"%.10llx",(unsigned long long)_a); return std::string(buf); }; @@ -154,7 +154,7 @@ public: */ inline void toString(char *buf,unsigned int len) const { - Utils::snprintf(buf,len,"%.10llx",(unsigned long long)_a); + Utils::ztsnprintf(buf,len,"%.10llx",(unsigned long long)_a); } /** diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 4413d628..0b000f13 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -391,7 +391,7 @@ public: inline bool add(const char *key,uint64_t value) { char tmp[32]; - Utils::snprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value); + Utils::ztsnprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value); return this->add(key,tmp,-1); } @@ -401,7 +401,7 @@ public: inline bool add(const char *key,const Address &a) { char tmp[32]; - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt()); return this->add(key,tmp,-1); } diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 0fbb2d68..17d7c72e 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -152,7 +152,7 @@ std::string InetAddress::toString() const char buf[128]; switch(ss_family) { case AF_INET: - Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d", + Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d", (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], @@ -161,7 +161,7 @@ std::string InetAddress::toString() const ); return std::string(buf); case AF_INET6: - Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", + Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), @@ -190,7 +190,7 @@ std::string InetAddress::toIpString() const char buf[128]; switch(ss_family) { case AF_INET: - Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d", + Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d", (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], @@ -198,7 +198,7 @@ std::string InetAddress::toIpString() const ); return std::string(buf); case AF_INET6: - Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", + Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), diff --git a/node/MAC.hpp b/node/MAC.hpp index e7717d99..db50aeb1 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -178,7 +178,7 @@ public: */ inline void toString(char *buf,unsigned int len) const { - Utils::snprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]); + Utils::ztsnprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]); } /** diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 4240db67..7cbec2e0 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -100,7 +100,7 @@ public: inline std::string toString() const { char buf[64]; - Utils::snprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi); + Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi); return std::string(buf); } diff --git a/node/Network.cpp b/node/Network.cpp index 12deeeb7..8c6f2ce8 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -51,7 +51,7 @@ namespace ZeroTier { namespace { #ifdef ZT_RULES_ENGINE_DEBUGGING -#define FILTER_TRACE(f,...) { Utils::snprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } +#define FILTER_TRACE(f,...) { Utils::ztsnprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } static const char *_rtn(const ZT_VirtualNetworkRuleType rt) { switch(rt) { @@ -1261,7 +1261,7 @@ void Network::requestConfiguration(void *tPtr) nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP; nconf->type = ZT_NETWORK_TYPE_PUBLIC; - Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); + Utils::ztsnprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); this->setConfiguration(tPtr,*nconf,false); delete nconf; diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index c39f6cab..65101c3a 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -94,7 +94,7 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (ets.length() > 0) ets.push_back(','); char tmp2[16]; - Utils::snprintf(tmp2,sizeof(tmp2),"%x",et); + Utils::ztsnprintf(tmp2,sizeof(tmp2),"%x",et); ets.append(tmp2); } et = 0; diff --git a/node/Node.cpp b/node/Node.cpp index 39325b65..ab49e63b 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -742,7 +742,7 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...) va_end(ap); tmp2[sizeof(tmp2)-1] = (char)0; - Utils::snprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2); + Utils::ztsnprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2); postEvent((void *)0,ZT_EVENT_TRACE,tmp1); } #endif // ZT_TRACE diff --git a/node/Utils.cpp b/node/Utils.cpp index d69e5335..d2321e16 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -244,8 +244,7 @@ bool Utils::scopy(char *dest,unsigned int len,const char *src) return true; } -unsigned int Utils::snprintf(char *buf,unsigned int len,const char *fmt,...) - throw(std::length_error) +unsigned int Utils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) { va_list ap; @@ -256,7 +255,7 @@ unsigned int Utils::snprintf(char *buf,unsigned int len,const char *fmt,...) if ((n >= (int)len)||(n < 0)) { if (len) buf[len - 1] = (char)0; - throw std::length_error("buf[] overflow in Utils::snprintf"); + throw std::length_error("buf[] overflow"); } return (unsigned int)n; diff --git a/node/Utils.hpp b/node/Utils.hpp index 25a90055..212ef247 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -244,8 +244,7 @@ public: * @param ... Format arguments * @throws std::length_error buf[] too short (buf[] will still be left null-terminated) */ - static unsigned int snprintf(char *buf,unsigned int len,const char *fmt,...) - throw(std::length_error); + static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...); /** * Count the number of bits set in an integer diff --git a/one.cpp b/one.cpp index 93504cfb..cbf09121 100644 --- a/one.cpp +++ b/one.cpp @@ -260,9 +260,9 @@ static int cli(int argc,char **argv) if (hd) { char p[4096]; #ifdef __APPLE__ - Utils::snprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); + Utils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); #else - Utils::snprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); + Utils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); #endif OSUtils::readFile(p,authToken); } @@ -278,7 +278,7 @@ static int cli(int argc,char **argv) InetAddress addr; { char addrtmp[256]; - Utils::snprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); + Utils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); addr = InetAddress(addrtmp); } @@ -366,7 +366,7 @@ static int cli(int argc,char **argv) std::string addr = path["address"]; const uint64_t now = OSUtils::now(); const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0; - Utils::snprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); bestPath = tmp; break; } @@ -378,7 +378,7 @@ static int cli(int argc,char **argv) int64_t vmin = p["versionMinor"]; int64_t vrev = p["versionRev"]; if (vmaj >= 0) { - Utils::snprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); + Utils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); } else { ver[0] = '-'; ver[1] = (char)0; @@ -527,9 +527,9 @@ static int cli(int argc,char **argv) const uint64_t seed = Utils::hexStrToU64(arg2.c_str()); if ((worldId)&&(seed)) { char jsons[1024]; - Utils::snprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); + Utils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); char cl[128]; - Utils::snprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -579,11 +579,11 @@ static int cli(int argc,char **argv) if (eqidx != std::string::npos) { if ((arg2.substr(0,eqidx) == "allowManaged")||(arg2.substr(0,eqidx) == "allowGlobal")||(arg2.substr(0,eqidx) == "allowDefault")) { char jsons[1024]; - Utils::snprintf(jsons,sizeof(jsons),"{\"%s\":%s}", + Utils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}", arg2.substr(0,eqidx).c_str(), (((arg2.substr(eqidx,2) == "=t")||(arg2.substr(eqidx,2) == "=1")) ? "true" : "false")); char cl[128]; - Utils::snprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -864,7 +864,7 @@ static int idtool(int argc,char **argv) Buffer wbuf; w.serialize(wbuf); char fn[128]; - Utils::snprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); + Utils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); OSUtils::writeFile(fn,wbuf.data(),wbuf.size()); printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S,fn,(unsigned long long)now); } diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index 5bb5fbd1..f07f9e5a 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -114,8 +114,8 @@ BSDEthernetTap::BSDEthernetTap( std::vector devFiles(OSUtils::listDirectory("/dev")); for(int i=9993;i<(9993+128);++i) { - Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) { long cpid = (long)vfork(); if (cpid == 0) { @@ -152,8 +152,8 @@ BSDEthernetTap::BSDEthernetTap( /* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */ for(int i=0;i<64;++i) { - Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); _fd = ::open(devpath,O_RDWR); if (_fd > 0) { _dev = tmpdevname; @@ -171,9 +171,9 @@ BSDEthernetTap::BSDEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); + Utils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); + Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); long cpid = (long)vfork(); if (cpid == 0) { ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); @@ -385,7 +385,7 @@ void BSDEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%u",mtu); + Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0); _exit(-1); } else if (cpid > 0) { diff --git a/osdep/Http.cpp b/osdep/Http.cpp index f1d3bfe2..3c556f44 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -244,10 +244,10 @@ unsigned int Http::_do( try { char tmp[1024]; - Utils::snprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); handler.writeBuf.append(tmp); for(std::map::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) { - Utils::snprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); handler.writeBuf.append(tmp); } handler.writeBuf.append("\r\n"); diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index ccaa92ef..fc5199f1 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -97,7 +97,7 @@ LinuxEthernetTap::LinuxEthernetTap( char procpath[128],nwids[32]; struct stat sbuf; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally @@ -134,7 +134,7 @@ LinuxEthernetTap::LinuxEthernetTap( std::map::const_iterator gdmEntry = globalDeviceMap.find(nwids); if (gdmEntry != globalDeviceMap.end()) { Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),gdmEntry->second.c_str()); - Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); recalledDevice = (stat(procpath,&sbuf) != 0); } @@ -142,8 +142,8 @@ LinuxEthernetTap::LinuxEthernetTap( #ifdef __SYNOLOGY__ int devno = 50; do { - Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); - Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + Utils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); + Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist #else char devno = 0; @@ -158,7 +158,7 @@ LinuxEthernetTap::LinuxEthernetTap( _base32_5_to_8(reinterpret_cast(tmp2) + 5,tmp3 + 10); tmp3[15] = (char)0; memcpy(ifr.ifr_name,tmp3,16); - Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); #endif } diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 53e8bb97..bf0dc04d 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -134,7 +134,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) if (date.QuadPart > 0) { date.QuadPart -= adjust.QuadPart; if ((uint64_t)((date.QuadPart / 10000000) * 1000) < olderThan) { - Utils::snprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); + Utils::ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); if (DeleteFileA(tmp)) ++cleaned; } @@ -157,7 +157,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) break; if (dptr) { if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) { - Utils::snprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); if (stat(tmp,&st) == 0) { uint64_t mt = (uint64_t)(st.st_mtime); if ((mt > 0)&&((mt * 1000) < olderThan)) { @@ -446,7 +446,7 @@ std::string OSUtils::jsonString(const nlohmann::json &jv,const char *dfl) return jv; } else if (jv.is_number()) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); + Utils::ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); return tmp; } else if (jv.is_boolean()) { return ((bool)jv ? std::string("1") : std::string("0")); diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index f5e1c43f..e082408e 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -336,7 +336,7 @@ OSXEthernetTap::OSXEthernetTap( char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; struct stat stattmp; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _gl(globalTapCreateLock); @@ -391,13 +391,13 @@ OSXEthernetTap::OSXEthernetTap( // Open the first unused tap device if we didn't recall a previous one. if (!recalledDevice) { for(int i=0;i<64;++i) { - Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i); + Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",i); if (stat(devpath,&stattmp)) throw std::runtime_error("no more TAP devices available"); _fd = ::open(devpath,O_RDWR); if (_fd > 0) { char foo[16]; - Utils::snprintf(foo,sizeof(foo),"zt%d",i); + Utils::ztsnprintf(foo,sizeof(foo),"zt%d",i); _dev = foo; break; } @@ -413,9 +413,9 @@ OSXEthernetTap::OSXEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); + Utils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); + Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); long cpid = (long)vfork(); if (cpid == 0) { ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); @@ -636,7 +636,7 @@ void OSXEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%u",mtu); + Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0); _exit(-1); } else if (cpid > 0) { diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index 99286172..df868e7a 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -205,7 +205,7 @@ public: memset(externalip,0,sizeof(externalip)); memset(&urls,0,sizeof(urls)); memset(&data,0,sizeof(data)); - Utils::snprintf(inport,sizeof(inport),"%d",localPort); + Utils::ztsnprintf(inport,sizeof(inport),"%d",localPort); if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { #ifdef ZT_PORTMAPPER_TRACE @@ -220,7 +220,7 @@ public: int tryPort = (int)localPort + tries; if (tryPort >= 65535) tryPort = (tryPort - 65535) + 1025; - Utils::snprintf(outport,sizeof(outport),"%u",tryPort); + Utils::ztsnprintf(outport,sizeof(outport),"%u",tryPort); // First check and see if this port is already mapped to the // same unique name. If so, keep this mapping and don't try diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index c5d82d8e..b96ad791 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -484,7 +484,7 @@ WindowsEthernetTap::WindowsEthernetTap( char tag[24]; // We "tag" registry entries with the network ID to identify persistent devices - Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); + Utils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); Mutex::Lock _l(_systemTapInitLock); @@ -601,10 +601,10 @@ WindowsEthernetTap::WindowsEthernetTap( if (_netCfgInstanceId.length() > 0) { char tmps[64]; - unsigned int tmpsl = Utils::snprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; + unsigned int tmpsl = Utils::ztsnprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl); - tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu); + tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MTU",REG_SZ,tmps,tmpsl); DWORD tmp = 0; @@ -879,7 +879,7 @@ void WindowsEthernetTap::setMtu(unsigned int mtu) HKEY nwAdapters; if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) == ERROR_SUCCESS) { char tmps[64]; - unsigned int tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu); + unsigned int tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl); RegCloseKey(nwAdapters); } @@ -902,7 +902,7 @@ void WindowsEthernetTap::threadMain() HANDLE wait4[3]; OVERLAPPED tapOvlRead,tapOvlWrite; - Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); + Utils::ztsnprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); try { while (_run) { diff --git a/selftest.cpp b/selftest.cpp index 8175d708..ff171aa3 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -831,7 +831,7 @@ static int testOther() memset(key, 0, sizeof(key)); memset(value, 0, sizeof(value)); for(unsigned int q=0;q<32;++q) { - Utils::snprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); + Utils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); int r = rand() % 128; for(int x=0;x lines(OSUtils::split(cf.c_str(),"\r\n","","")); for(std::vector::iterator l(lines.begin());l!=lines.end();++l) { diff --git a/service/OneService.cpp b/service/OneService.cpp index 644454bc..993fb116 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -210,10 +210,10 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc, case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break; } - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); nj["id"] = tmp; nj["nwid"] = tmp; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); nj["mac"] = tmp; nj["name"] = nc->name; nj["status"] = nstatus; @@ -260,12 +260,12 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; } - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",peer->address); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",peer->address); pj["address"] = tmp; pj["versionMajor"] = peer->versionMajor; pj["versionMinor"] = peer->versionMinor; pj["versionRev"] = peer->versionRev; - Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); + Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); pj["version"] = tmp; pj["latency"] = peer->latency; pj["role"] = prole; @@ -289,7 +289,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) static void _moonToJson(nlohmann::json &mj,const World &world) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",world.id()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id()); mj["id"] = tmp; mj["timestamp"] = world.timestamp(); mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size()); @@ -687,7 +687,7 @@ public: // Save primary port to a file so CLIs and GUIs can learn it easily char portstr[64]; - Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]); + Utils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]); OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr)); // Attempt to bind to a secondary port chosen from our ZeroTier address. @@ -725,7 +725,7 @@ public: } if (_ports[2]) { char uniqueName[64]; - Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + Utils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); _portMapper = new PortMapper(_ports[2],uniqueName); } } @@ -1069,7 +1069,7 @@ public: n->second.settings = settings; char nlcpath[4096]; - Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); + Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); FILE *out = fopen(nlcpath,"w"); if (out) { fprintf(out,"allowManaged=%d\n",(int)n->second.settings.allowManaged); @@ -1188,7 +1188,7 @@ public: ZT_NodeStatus status; _node->status(&status); - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",status.address); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",status.address); res["address"] = tmp; res["publicIdentity"] = status.publicIdentity; res["online"] = (bool)(status.online != 0); @@ -1197,7 +1197,7 @@ public: res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; - Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); res["version"] = tmp; res["clock"] = OSUtils::now(); @@ -1373,7 +1373,7 @@ public: if ((scode != 200)&&(seed != 0)) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",id); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id); res["id"] = tmp; res["roots"] = json::array(); res["timestamp"] = 0; @@ -1617,7 +1617,7 @@ public: std::string h = controllerDbHttpHost; _controllerDbPath.append(h); char dbp[128]; - Utils::snprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort); + Utils::ztsnprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort); _controllerDbPath.push_back(':'); _controllerDbPath.append(dbp); if (controllerDbHttpPath.is_string()) { @@ -1711,7 +1711,7 @@ public: if (syncRoutes) { char tapdev[64]; #ifdef __WINDOWS__ - Utils::snprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); + Utils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); #else Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str()); #endif @@ -1933,24 +1933,24 @@ public: bool secure = false; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); secure = true; break; case ZT_STATE_OBJECT_PEER_IDENTITY: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); secure = true; break; case ZT_STATE_OBJECT_PLANET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; default: p[0] = (char)0; @@ -2022,7 +2022,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -2235,7 +2235,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -2402,7 +2402,7 @@ public: if (!n.tap) { try { char friendlyName[128]; - Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); + Utils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); n.tap = new EthernetTap( _homePath.c_str(), @@ -2416,7 +2416,7 @@ public: *nuptr = (void *)&n; char nlcpath[256]; - Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); std::string nlcbuf; if (OSUtils::readFile(nlcpath,nlcbuf)) { Dictionary<4096> nc; @@ -2502,7 +2502,7 @@ public: #endif if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) { char nlcpath[256]; - Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); OSUtils::rm(nlcpath); } } else { @@ -2554,22 +2554,22 @@ public: char p[4096]; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); break; case ZT_STATE_OBJECT_PEER_IDENTITY: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_PLANET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; default: return -1; @@ -2765,7 +2765,7 @@ public: default: scodestr = "Error"; break; } - Utils::snprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", + Utils::ztsnprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", scode, scodestr, contentType.c_str(), diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index d94beab5..e0519827 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -284,7 +284,7 @@ bool SoftwareUpdater::check(const uint64_t now) if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { _lastCheckTime = now; char tmp[512]; - const unsigned int len = Utils::snprintf(tmp,sizeof(tmp), + const unsigned int len = Utils::ztsnprintf(tmp,sizeof(tmp), "%c{\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "\":%d," -- cgit v1.2.3 From d2415dee00914ab3fd7016758f4184d46bb407a5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 6 Jul 2017 16:11:11 -0700 Subject: Cleanup. --- controller/EmbeddedNetworkController.cpp | 104 +++++++++-------- controller/JSONDB.cpp | 14 +-- node/Address.hpp | 15 +-- node/CertificateOfMembership.cpp | 7 +- node/Dictionary.hpp | 6 +- node/Identity.cpp | 26 +++-- node/Identity.hpp | 18 +-- node/InetAddress.cpp | 195 ++++++++++++++----------------- node/InetAddress.hpp | 94 ++++++--------- node/MAC.hpp | 83 +++---------- node/MulticastGroup.hpp | 12 -- node/Network.cpp | 14 ++- node/NetworkConfig.cpp | 12 +- node/Node.cpp | 51 ++------ node/Node.hpp | 4 - node/RuntimeEnvironment.hpp | 10 +- node/Topology.cpp | 8 +- node/Utils.cpp | 114 ++++-------------- node/Utils.hpp | 182 +++++++++++++++++++++-------- one.cpp | 55 +++++---- osdep/BSDEthernetTap.cpp | 19 +-- osdep/Http.cpp | 4 +- osdep/LinuxEthernetTap.cpp | 33 +++--- osdep/ManagedRoute.cpp | 11 +- osdep/OSUtils.cpp | 28 ++++- osdep/OSUtils.hpp | 15 ++- osdep/OSXEthernetTap.cpp | 20 ++-- osdep/PortMapper.cpp | 4 +- osdep/WindowsEthernetTap.cpp | 10 +- selftest.cpp | 31 +++-- service/OneService.cpp | 94 +++++++-------- service/SoftwareUpdater.cpp | 5 +- 32 files changed, 620 insertions(+), 678 deletions(-) (limited to 'selftest.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 85c759e7..b57a37e8 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -76,19 +76,19 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_ACTION_TEE: r["type"] = "ACTION_TEE"; - r["address"] = Address(rule.v.fwd.address).toString(); + r["address"] = Address(rule.v.fwd.address).toString(tmp); r["flags"] = (unsigned int)rule.v.fwd.flags; r["length"] = (unsigned int)rule.v.fwd.length; break; case ZT_NETWORK_RULE_ACTION_WATCH: r["type"] = "ACTION_WATCH"; - r["address"] = Address(rule.v.fwd.address).toString(); + r["address"] = Address(rule.v.fwd.address).toString(tmp); r["flags"] = (unsigned int)rule.v.fwd.flags; r["length"] = (unsigned int)rule.v.fwd.length; break; case ZT_NETWORK_RULE_ACTION_REDIRECT: r["type"] = "ACTION_REDIRECT"; - r["address"] = Address(rule.v.fwd.address).toString(); + r["address"] = Address(rule.v.fwd.address).toString(tmp); r["flags"] = (unsigned int)rule.v.fwd.flags; break; case ZT_NETWORK_RULE_ACTION_BREAK: @@ -102,11 +102,11 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) switch(rt) { case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(); + r["zt"] = Address(rule.v.zt).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(); + r["zt"] = Address(rule.v.zt).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_VLAN_ID: r["type"] = "MATCH_VLAN_ID"; @@ -122,29 +122,29 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: r["type"] = "MATCH_MAC_SOURCE"; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_MAC_DEST: r["type"] = "MATCH_MAC_DEST"; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: r["type"] = "MATCH_IPV4_SOURCE"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); + r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IPV4_DEST: r["type"] = "MATCH_IPV4_DEST"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); + r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: r["type"] = "MATCH_IPV6_SOURCE"; - r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); + r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IPV6_DEST: r["type"] = "MATCH_IPV6_DEST"; - r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); + r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IP_TOS: r["type"] = "MATCH_IP_TOS"; @@ -179,7 +179,7 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: r["type"] = "MATCH_CHARACTERISTICS"; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); r["mask"] = tmp; break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: @@ -312,28 +312,28 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) return true; } else if (t == "MATCH_IPV4_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE; - InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0").c_str()); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV4_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST; - InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0").c_str()); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV6_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; - InetAddress ip(OSUtils::jsonString(r["ip"],"::0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IPV6_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; - InetAddress ip(OSUtils::jsonString(r["ip"],"::0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; @@ -514,7 +514,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( _db.eachMember(nwid,[&responseBody](uint64_t networkId,uint64_t nodeId,const json &member) { if ((member.is_object())&&(member.size() > 0)) { char tmp[128]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); responseBody.append(tmp); } }); @@ -548,7 +548,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( for(std::vector::const_iterator i(networkIds.begin());i!=networkIds.end();++i) { if (responseBody.length() > 1) responseBody.push_back(','); - Utils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); responseBody.append(tmp); } responseBody.push_back(']'); @@ -562,7 +562,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( // Controller status char tmp[4096]; - Utils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); responseBody = tmp; responseContentType = "application/json"; return 200; @@ -603,14 +603,14 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if ((path.size() >= 2)&&(path[1].length() == 16)) { uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); char nwids[24]; - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); if (path.size() >= 3) { if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { uint64_t address = Utils::hexStrToU64(path[3].c_str()); char addrs[24]; - Utils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); + OSUtils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); json member; _db.getNetworkMember(nwid,address,member); @@ -655,9 +655,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json mipa(json::array()); for(unsigned long i=0;i()); + InetAddress t(target.get().c_str()); InetAddress v; - if (via.is_string()) v.fromString(via.get()); + if (via.is_string()) v.fromString(via.get().c_str()); if ( ((t.ss_family == AF_INET)||(t.ss_family == AF_INET6)) && (t.netmaskBitsValid()) ) { json tmp; - tmp["target"] = t.toString(); + char tmp2[64]; + tmp["target"] = t.toString(tmp2); if (v.ss_family == t.ss_family) - tmp["via"] = v.toIpString(); + tmp["via"] = v.toIpString(tmp2); else tmp["via"] = json(); nrts.push_back(tmp); } @@ -840,12 +842,13 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( for(unsigned long i=0;i_memberStatus.find(_MemberStatusKey(networkId,nodeId)); if (ms != _memberStatus.end()) lrt = ms->second.lastRequestTime; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", (first) ? "" : ",", (unsigned long long)networkId, (unsigned long long)nodeId, @@ -1093,7 +1096,7 @@ void EmbeddedNetworkController::threadMain() }); } char tmp2[256]; - Utils::ztsnprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); + OSUtils::ztsnprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); pong.append(tmp2); _db.writeRaw("pong",pong); } @@ -1126,7 +1129,7 @@ void EmbeddedNetworkController::_request( ms.lastRequestTime = now; } - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); if (!_db.getNetworkAndMember(nwid,identity.address().toInt(),network,member,ns)) { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); return; @@ -1152,13 +1155,15 @@ void EmbeddedNetworkController::_request( } } else { // If we do not yet know this member's identity, learn it. - member["identity"] = identity.toString(false); + char idtmp[1024]; + member["identity"] = identity.toString(false,idtmp); } } // These are always the same, but make sure they are set { - const std::string addrs(identity.address().toString()); + char tmpid[128]; + const std::string addrs(identity.address().toString(tmpid)); member["id"] = addrs; member["address"] = addrs; member["nwid"] = nwids; @@ -1264,8 +1269,9 @@ void EmbeddedNetworkController::_request( if (fromAddr) ms.physicalAddr = fromAddr; + char tmpip[64]; if (ms.physicalAddr) - member["physicalAddr"] = ms.physicalAddr.toString(); + member["physicalAddr"] = ms.physicalAddr.toString(tmpip); } } } else { @@ -1427,9 +1433,9 @@ void EmbeddedNetworkController::_request( json &target = route["target"]; json &via = route["via"]; if (target.is_string()) { - const InetAddress t(target.get()); + const InetAddress t(target.get().c_str()); InetAddress v; - if (via.is_string()) v.fromString(via.get()); + if (via.is_string()) v.fromString(via.get().c_str()); if ((t.ss_family == AF_INET)||(t.ss_family == AF_INET6)) { ZT_VirtualNetworkRoute *r = &(nc->routes[nc->routeCount]); *(reinterpret_cast(&(r->target))) = t; @@ -1462,7 +1468,7 @@ void EmbeddedNetworkController::_request( if (!ipAssignments[i].is_string()) continue; std::string ips = ipAssignments[i]; - InetAddress ip(ips); + InetAddress ip(ips.c_str()); // IP assignments are only pushed if there is a corresponding local route. We also now get the netmask bits from // this route, ignoring the netmask bits field of the assigned IP itself. Using that was worthless and a source @@ -1492,8 +1498,8 @@ void EmbeddedNetworkController::_request( for(unsigned long p=0;((p 0) && (!std::binary_search(ns.allocatedIps.begin(),ns.allocatedIps.end(),ip6)) ) { - ipAssignments.push_back(ip6.toIpString()); + char tmpip[64]; + ipAssignments.push_back(ip6.toIpString(tmpip)); member["ipAssignments"] = ipAssignments; ip6.setPort((unsigned int)routedNetmaskBits); if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) @@ -1552,8 +1559,8 @@ void EmbeddedNetworkController::_request( for(unsigned long p=0;((p(&ipRangeStartIA)->sin_addr.s_addr)); uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEndIA)->sin_addr.s_addr)); @@ -1586,7 +1593,8 @@ void EmbeddedNetworkController::_request( // If it's routed, then try to claim and assign it and if successful end loop const InetAddress ip4(Utils::hton(ip),0); if ( (routedNetmaskBits > 0) && (!std::binary_search(ns.allocatedIps.begin(),ns.allocatedIps.end(),ip4)) ) { - ipAssignments.push_back(ip4.toIpString()); + char tmpip[64]; + ipAssignments.push_back(ip4.toIpString(tmpip)); member["ipAssignments"] = ipAssignments; if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { struct sockaddr_in *const v4ip = reinterpret_cast(&(nc->staticIps[nc->staticIpCount++])); diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index acf23700..97a217a1 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -39,7 +39,7 @@ JSONDB::JSONDB(const std::string &basePath) : std::size_t hnsep = hn.find_last_of(':'); if (hnsep != std::string::npos) hn[hnsep] = '/'; - _httpAddr.fromString(hn); + _httpAddr.fromString(hn.c_str()); if (hnend != std::string::npos) _basePath = _basePath.substr(7 + hnend); if (_basePath.length() == 0) @@ -94,7 +94,7 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) std::string body; std::map reqHeaders; char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); reqHeaders["Content-Length"] = tmp; reqHeaders["Content-Type"] = "application/json"; const unsigned int sc = Http::PUT(0,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),(unsigned long)obj.length(),headers,body); @@ -164,7 +164,7 @@ bool JSONDB::getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlo void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkConfig) { char n[64]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); writeRaw(n,OSUtils::jsonDump(networkConfig)); { Mutex::Lock _l(_networks_m); @@ -176,7 +176,7 @@ void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkC void JSONDB::saveNetworkMember(const uint64_t networkId,const uint64_t nodeId,const nlohmann::json &memberConfig) { char n[256]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); writeRaw(n,OSUtils::jsonDump(memberConfig)); { Mutex::Lock _l(_networks_m); @@ -202,7 +202,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) } char n[256]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); if (_httpAddr) { // Deletion is currently done by Central in harnessed mode @@ -229,7 +229,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) nlohmann::json JSONDB::eraseNetworkMember(const uint64_t networkId,const uint64_t nodeId,bool recomputeSummaryInfo) { char n[256]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); if (_httpAddr) { // Deletion is currently done by the caller in Central harnessed mode @@ -314,7 +314,7 @@ void JSONDB::threadMain() const nlohmann::json &mips = member["ipAssignments"]; if (mips.is_array()) { for(unsigned long i=0;iadd(key,tmp,-1); + return this->add(key,Utils::hex(value,tmp),-1); } /** @@ -401,8 +400,7 @@ public: inline bool add(const char *key,const Address &a) { char tmp[32]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt()); - return this->add(key,tmp,-1); + return this->add(key,Utils::hex(a.toInt(),tmp),-1); } /** diff --git a/node/Identity.cpp b/node/Identity.cpp index ba77aa47..3b00b4c0 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -136,19 +136,23 @@ bool Identity::locallyValidate() const (digest[63] == addrb[4])); } -std::string Identity::toString(bool includePrivate) const +char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const { - std::string r; - - r.append(_address.toString()); - r.append(":0:"); // 0 == ZT_OBJECT_TYPE_IDENTITY - r.append(Utils::hex(_publicKey.data,(unsigned int)_publicKey.size())); + char *p = buf; + Utils::hex10(_address.toInt(),p); + p += 10; + *(p++) = ':'; + *(p++) = '0'; + *(p++) = ':'; + Utils::hex(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,p); + p += ZT_C25519_PUBLIC_KEY_LEN * 2; if ((_privateKey)&&(includePrivate)) { - r.push_back(':'); - r.append(Utils::hex(_privateKey->data,(unsigned int)_privateKey->size())); + *(p++) = ':'; + Utils::hex(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN,p); + p += ZT_C25519_PRIVATE_KEY_LEN * 2; } - - return r; + *(p++) = (char)0; + return buf; } bool Identity::fromString(const char *str) @@ -157,7 +161,7 @@ bool Identity::fromString(const char *str) return false; char *saveptr = (char *)0; - char tmp[1024]; + char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH]; if (!Utils::scopy(tmp,sizeof(tmp),str)) return false; diff --git a/node/Identity.hpp b/node/Identity.hpp index 79e17f4d..5804b9f8 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -29,7 +29,6 @@ #include #include -#include #include "Constants.hpp" #include "Array.hpp" @@ -39,6 +38,8 @@ #include "Buffer.hpp" #include "SHA512.hpp" +#define ZT_IDENTITY_STRING_BUFFER_LENGTH 384 + namespace ZeroTier { /** @@ -66,16 +67,7 @@ public: { } - Identity(const char *str) - throw(std::invalid_argument) : - _privateKey((C25519::Private *)0) - { - if (!fromString(str)) - throw std::invalid_argument(std::string("invalid string-serialized identity: ") + str); - } - - Identity(const std::string &str) - throw(std::invalid_argument) : + Identity(const char *str) : _privateKey((C25519::Private *)0) { if (!fromString(str)) @@ -277,9 +269,10 @@ public: * Serialize to a more human-friendly string * * @param includePrivate If true, include private key (if it exists) + * @param buf Buffer to store string * @return ASCII string representation of identity */ - std::string toString(bool includePrivate) const; + char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const; /** * Deserialize a human-friendly string @@ -291,7 +284,6 @@ public: * @return True if deserialization appears successful */ bool fromString(const char *str); - inline bool fromString(const std::string &str) { return fromString(str.c_str()); } /** * @return C25519 public key diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 17d7c72e..f7585bdb 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -5,7 +5,7 @@ * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * (at your oion) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -40,7 +40,6 @@ const InetAddress InetAddress::LO4((const void *)("\x7f\x00\x00\x01"),4,0); const InetAddress InetAddress::LO6((const void *)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"),16,0); InetAddress::IpScope InetAddress::ipScope() const - throw() { switch(ss_family) { @@ -111,27 +110,7 @@ InetAddress::IpScope InetAddress::ipScope() const return IP_SCOPE_NONE; } -void InetAddress::set(const std::string &ip,unsigned int port) - throw() -{ - memset(this,0,sizeof(InetAddress)); - if (ip.find(':') != std::string::npos) { - struct sockaddr_in6 *sin6 = reinterpret_cast(this); - ss_family = AF_INET6; - sin6->sin6_port = Utils::hton((uint16_t)port); - if (inet_pton(AF_INET6,ip.c_str(),(void *)&(sin6->sin6_addr.s6_addr)) <= 0) - memset(this,0,sizeof(InetAddress)); - } else if (ip.find('.') != std::string::npos) { - struct sockaddr_in *sin = reinterpret_cast(this); - ss_family = AF_INET; - sin->sin_port = Utils::hton((uint16_t)port); - if (inet_pton(AF_INET,ip.c_str(),(void *)&(sin->sin_addr.s_addr)) <= 0) - memset(this,0,sizeof(InetAddress)); - } -} - void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) - throw() { memset(this,0,sizeof(InetAddress)); if (ipLen == 4) { @@ -147,90 +126,98 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) } } -std::string InetAddress::toString() const +char *InetAddress::toString(char buf[64]) const { - char buf[128]; - switch(ss_family) { - case AF_INET: - Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d", - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[3], - (int)Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin_port)) - ); - return std::string(buf); - case AF_INET6: - Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[3]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[4]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[5]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[6]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[7]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[8]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[9]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[10]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[11]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[12]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[13]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[14]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[15]), - (int)Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin6_port)) - ); - return std::string(buf); + char *p = toIpString(buf); + if (*p) { + while (*p) ++p; + *(p++) = '/'; + Utils::decimal(port(),p); } - return std::string(); + return buf; } -std::string InetAddress::toIpString() const +char *InetAddress::toIpString(char buf[64]) const { - char buf[128]; switch(ss_family) { - case AF_INET: - Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d", - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[3] - ); - return std::string(buf); - case AF_INET6: - Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[3]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[4]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[5]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[6]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[7]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[8]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[9]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[10]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[11]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[12]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[13]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[14]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[15]) - ); - return std::string(buf); + case AF_INET: { + const uint8_t *a = reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)); + char *p = buf; + for(int i=0;;++i) { + Utils::decimal((unsigned long)a[i],p); + if (i != 3) { + while (*p) ++p; + *(p++) = '.'; + } else break; + } + } break; + + case AF_INET6: { + uint16_t a[8]; + memcpy(a,reinterpret_cast(this)->sin6_addr.s6_addr,16); + char *p = buf; + for(int i=0;i<8;++i) { + Utils::hex(Utils::ntoh(a[i]),p); + p[4] = (i == 7) ? (char)0 : ':'; + p += 5; + } + } break; + + default: + buf[0] = (char)0; + break; } - return std::string(); + return buf; } -void InetAddress::fromString(const std::string &ipSlashPort) +bool InetAddress::fromString(const char *ipSlashPort) { - const std::size_t slashAt = ipSlashPort.find('/'); - if (slashAt == std::string::npos) { - set(ipSlashPort,0); + char buf[64]; + + memset(this,0,sizeof(InetAddress)); + + if (!*ipSlashPort) + return true; + if (!Utils::scopy(buf,sizeof(buf),ipSlashPort)) + return false; + + char *portAt = buf; + while ((*portAt)&&(*portAt != '/')) + ++portAt; + unsigned int port = 0; + if (*portAt) { + *(portAt++) = (char)0; + port = Utils::strToUInt(portAt) & 0xffff; + } + + if (strchr(buf,':')) { + uint16_t a[8]; + unsigned int b = 0; + char *saveptr = (char *)0; + for(char *s=Utils::stok(buf,":",&saveptr);((s)&&(b<8));s=Utils::stok((char *)0,":",&saveptr)) + a[b++] = Utils::hton((uint16_t)(Utils::hexStrToUInt(s) & 0xffff)); + + struct sockaddr_in6 *const in6 = reinterpret_cast(this); + in6->sin6_family = AF_INET6; + memcpy(in6->sin6_addr.s6_addr,a,16); + in6->sin6_port = Utils::hton((uint16_t)port); + + return true; + } else if (strchr(buf,'.')) { + uint8_t a[4]; + unsigned int b = 0; + char *saveptr = (char *)0; + for(char *s=Utils::stok(buf,".",&saveptr);((s)&&(b<4));s=Utils::stok((char *)0,".",&saveptr)) + a[b++] = (uint8_t)(Utils::strToUInt(s) & 0xff); + + struct sockaddr_in *const in = reinterpret_cast(this); + in->sin_family = AF_INET; + memcpy(&(in->sin_addr.s_addr),a,4); + in->sin_port = Utils::hton((uint16_t)port); + + return true; } else { - long p = strtol(ipSlashPort.substr(slashAt+1).c_str(),(char **)0,10); - if ((p > 0)&&(p <= 0xffff)) - set(ipSlashPort.substr(0,slashAt),(unsigned int)p); - else set(ipSlashPort.substr(0,slashAt),0); + return false; } } @@ -244,14 +231,13 @@ InetAddress InetAddress::netmask() const case AF_INET6: { uint64_t nm[2]; const unsigned int bits = netmaskBits(); - if(bits) { - nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); - nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); - } - else { - nm[0] = 0; - nm[1] = 0; - } + if(bits) { + nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); + nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); + } else { + nm[0] = 0; + nm[1] = 0; + } memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); } break; } @@ -338,7 +324,6 @@ bool InetAddress::containsAddress(const InetAddress &addr) const } bool InetAddress::isNetwork() const - throw() { switch(ss_family) { case AF_INET: { @@ -371,7 +356,6 @@ bool InetAddress::isNetwork() const } bool InetAddress::operator==(const InetAddress &a) const - throw() { if (ss_family == a.ss_family) { switch(ss_family) { @@ -395,7 +379,6 @@ bool InetAddress::operator==(const InetAddress &a) const } bool InetAddress::operator<(const InetAddress &a) const - throw() { if (ss_family < a.ss_family) return true; diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 4cb9a4dc..dd055084 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -31,8 +31,6 @@ #include #include -#include - #include "Constants.hpp" #include "../include/ZeroTierOne.h" #include "Utils.hpp" @@ -85,25 +83,22 @@ struct InetAddress : public sockaddr_storage IP_SCOPE_PRIVATE = 7 // 10.x.x.x, 192.168.x.x, etc. }; - InetAddress() throw() { memset(this,0,sizeof(InetAddress)); } - InetAddress(const InetAddress &a) throw() { memcpy(this,&a,sizeof(InetAddress)); } - InetAddress(const InetAddress *a) throw() { memcpy(this,a,sizeof(InetAddress)); } - InetAddress(const struct sockaddr_storage &ss) throw() { *this = ss; } - InetAddress(const struct sockaddr_storage *ss) throw() { *this = ss; } - InetAddress(const struct sockaddr &sa) throw() { *this = sa; } - InetAddress(const struct sockaddr *sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in &sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in *sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in6 &sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in6 *sa) throw() { *this = sa; } - InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) throw() { this->set(ipBytes,ipLen,port); } - InetAddress(const uint32_t ipv4,unsigned int port) throw() { this->set(&ipv4,4,port); } - InetAddress(const std::string &ip,unsigned int port) throw() { this->set(ip,port); } - InetAddress(const std::string &ipSlashPort) throw() { this->fromString(ipSlashPort); } - InetAddress(const char *ipSlashPort) throw() { this->fromString(std::string(ipSlashPort)); } + InetAddress() { memset(this,0,sizeof(InetAddress)); } + InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); } + InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); } + InetAddress(const struct sockaddr_storage &ss) { *this = ss; } + InetAddress(const struct sockaddr_storage *ss) { *this = ss; } + InetAddress(const struct sockaddr &sa) { *this = sa; } + InetAddress(const struct sockaddr *sa) { *this = sa; } + InetAddress(const struct sockaddr_in &sa) { *this = sa; } + InetAddress(const struct sockaddr_in *sa) { *this = sa; } + InetAddress(const struct sockaddr_in6 &sa) { *this = sa; } + InetAddress(const struct sockaddr_in6 *sa) { *this = sa; } + InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); } + InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); } + InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); } inline InetAddress &operator=(const InetAddress &a) - throw() { if (&a != this) memcpy(this,&a,sizeof(InetAddress)); @@ -111,7 +106,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const InetAddress *a) - throw() { if (a != this) memcpy(this,a,sizeof(InetAddress)); @@ -119,7 +113,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_storage &ss) - throw() { if (reinterpret_cast(&ss) != this) memcpy(this,&ss,sizeof(InetAddress)); @@ -127,7 +120,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_storage *ss) - throw() { if (reinterpret_cast(ss) != this) memcpy(this,ss,sizeof(InetAddress)); @@ -135,7 +127,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in &sa) - throw() { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -145,7 +136,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in *sa) - throw() { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -155,7 +145,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in6 &sa) - throw() { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -165,7 +154,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in6 *sa) - throw() { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -175,7 +163,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr &sa) - throw() { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -192,7 +179,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr *sa) - throw() { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -211,17 +197,7 @@ struct InetAddress : public sockaddr_storage /** * @return IP scope classification (e.g. loopback, link-local, private, global) */ - IpScope ipScope() const - throw(); - - /** - * Set from a string-format IP and a port - * - * @param ip IP address in V4 or V6 ASCII notation - * @param port Port or 0 for none - */ - void set(const std::string &ip,unsigned int port) - throw(); + IpScope ipScope() const; /** * Set from a raw IP and port number @@ -230,8 +206,7 @@ struct InetAddress : public sockaddr_storage * @param ipLen Length of IP address: 4 or 16 * @param port Port number or 0 for none */ - void set(const void *ipBytes,unsigned int ipLen,unsigned int port) - throw(); + void set(const void *ipBytes,unsigned int ipLen,unsigned int port); /** * Set the port component @@ -272,23 +247,23 @@ struct InetAddress : public sockaddr_storage /** * @return ASCII IP/port format representation */ - std::string toString() const; + char *toString(char buf[64]) const; /** * @return IP portion only, in ASCII string format */ - std::string toIpString() const; + char *toIpString(char buf[64]) const; /** - * @param ipSlashPort ASCII IP/port format notation + * @param ipSlashPort IP/port (port is optional, will be 0 if not included) + * @return True if address appeared to be valid */ - void fromString(const std::string &ipSlashPort); + bool fromString(const char *ipSlashPort); /** * @return Port or 0 if no port component defined */ inline unsigned int port() const - throw() { switch(ss_family) { case AF_INET: return Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin_port)); @@ -306,7 +281,7 @@ struct InetAddress : public sockaddr_storage * * @return Netmask bits */ - inline unsigned int netmaskBits() const throw() { return port(); } + inline unsigned int netmaskBits() const { return port(); } /** * @return True if netmask bits is valid for the address type @@ -329,7 +304,7 @@ struct InetAddress : public sockaddr_storage * * @return Gateway metric */ - inline unsigned int metric() const throw() { return port(); } + inline unsigned int metric() const { return port(); } /** * Construct a full netmask as an InetAddress @@ -376,12 +351,12 @@ struct InetAddress : public sockaddr_storage /** * @return True if this is an IPv4 address */ - inline bool isV4() const throw() { return (ss_family == AF_INET); } + inline bool isV4() const { return (ss_family == AF_INET); } /** * @return True if this is an IPv6 address */ - inline bool isV6() const throw() { return (ss_family == AF_INET6); } + inline bool isV6() const { return (ss_family == AF_INET6); } /** * @return pointer to raw address bytes or NULL if not available @@ -454,7 +429,7 @@ struct InetAddress : public sockaddr_storage /** * Set to null/zero */ - inline void zero() throw() { memset(this,0,sizeof(InetAddress)); } + inline void zero() { memset(this,0,sizeof(InetAddress)); } /** * Check whether this is a network/route rather than an IP assignment @@ -464,8 +439,7 @@ struct InetAddress : public sockaddr_storage * * @return True if everything after netmask bits is zero */ - bool isNetwork() const - throw(); + bool isNetwork() const; /** * @return 14-bit (0-16383) hash of this IP's first 24 or 48 bits (for V4 or V6) for rate limiting code, or 0 if non-IP @@ -494,7 +468,7 @@ struct InetAddress : public sockaddr_storage /** * @return True if address family is non-zero */ - inline operator bool() const throw() { return (ss_family != 0); } + inline operator bool() const { return (ss_family != 0); } template inline void serialize(Buffer &b) const @@ -552,12 +526,12 @@ struct InetAddress : public sockaddr_storage return (p - startAt); } - bool operator==(const InetAddress &a) const throw(); - bool operator<(const InetAddress &a) const throw(); - inline bool operator!=(const InetAddress &a) const throw() { return !(*this == a); } - inline bool operator>(const InetAddress &a) const throw() { return (a < *this); } - inline bool operator<=(const InetAddress &a) const throw() { return !(a < *this); } - inline bool operator>=(const InetAddress &a) const throw() { return !(*this < a); } + bool operator==(const InetAddress &a) const; + bool operator<(const InetAddress &a) const; + inline bool operator!=(const InetAddress &a) const { return !(*this == a); } + inline bool operator>(const InetAddress &a) const { return (a < *this); } + inline bool operator<=(const InetAddress &a) const { return !(a < *this); } + inline bool operator>=(const InetAddress &a) const { return !(*this < a); } /** * @param mac MAC address seed diff --git a/node/MAC.hpp b/node/MAC.hpp index db50aeb1..52388d59 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -44,30 +44,24 @@ namespace ZeroTier { class MAC { public: - MAC() throw() : _m(0ULL) {} - MAC(const MAC &m) throw() : _m(m._m) {} + MAC() : _m(0ULL) {} + MAC(const MAC &m) : _m(m._m) {} - MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) throw() : + MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) : _m( ((((uint64_t)a) & 0xffULL) << 40) | ((((uint64_t)b) & 0xffULL) << 32) | ((((uint64_t)c) & 0xffULL) << 24) | ((((uint64_t)d) & 0xffULL) << 16) | ((((uint64_t)e) & 0xffULL) << 8) | (((uint64_t)f) & 0xffULL) ) {} - - MAC(const char *s) throw() { fromString(s); } - MAC(const std::string &s) throw() { fromString(s.c_str()); } - - MAC(const void *bits,unsigned int len) throw() { setTo(bits,len); } - - MAC(const Address &ztaddr,uint64_t nwid) throw() { fromAddress(ztaddr,nwid); } - - MAC(const uint64_t m) throw() : _m(m & 0xffffffffffffULL) {} + MAC(const void *bits,unsigned int len) { setTo(bits,len); } + MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); } + MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {} /** * @return MAC in 64-bit integer */ - inline uint64_t toInt() const throw() { return _m; } + inline uint64_t toInt() const { return _m; } /** * Set MAC to zero @@ -77,14 +71,13 @@ public: /** * @return True if MAC is non-zero */ - inline operator bool() const throw() { return (_m != 0ULL); } + inline operator bool() const { return (_m != 0ULL); } /** * @param bits Raw MAC in big-endian byte order * @param len Length, must be >= 6 or result is zero */ inline void setTo(const void *bits,unsigned int len) - throw() { if (len < 6) { _m = 0ULL; @@ -104,7 +97,6 @@ public: * @param len Length of buffer, must be >= 6 or nothing is copied */ inline void copyTo(void *buf,unsigned int len) const - throw() { if (len < 6) return; @@ -124,7 +116,6 @@ public: */ template inline void appendTo(Buffer &b) const - throw(std::out_of_range) { unsigned char *p = (unsigned char *)b.appendField(6); *(p++) = (unsigned char)((_m >> 40) & 0xff); @@ -138,48 +129,17 @@ public: /** * @return True if this is broadcast (all 0xff) */ - inline bool isBroadcast() const throw() { return (_m == 0xffffffffffffULL); } + inline bool isBroadcast() const { return (_m == 0xffffffffffffULL); } /** * @return True if this is a multicast MAC */ - inline bool isMulticast() const throw() { return ((_m & 0x010000000000ULL) != 0ULL); } + inline bool isMulticast() const { return ((_m & 0x010000000000ULL) != 0ULL); } /** * @param True if this is a locally-administered MAC */ - inline bool isLocallyAdministered() const throw() { return ((_m & 0x020000000000ULL) != 0ULL); } - - /** - * @param s Hex MAC, with or without : delimiters - */ - inline void fromString(const char *s) - { - char tmp[8]; - for(int i=0;i<6;++i) - tmp[i] = (char)0; - Utils::unhex(s,tmp,6); - setTo(tmp,6); - } - - /** - * @return MAC address in standard :-delimited hex format - */ - inline std::string toString() const - { - char tmp[24]; - toString(tmp,sizeof(tmp)); - return std::string(tmp); - } - - /** - * @param buf Buffer to contain human-readable MAC - * @param len Length of buffer - */ - inline void toString(char *buf,unsigned int len) const - { - Utils::ztsnprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]); - } + inline bool isLocallyAdministered() const { return ((_m & 0x020000000000ULL) != 0ULL); } /** * Set this MAC to a MAC derived from an address and a network ID @@ -188,7 +148,6 @@ public: * @param nwid 64-bit network ID */ inline void fromAddress(const Address &ztaddr,uint64_t nwid) - throw() { uint64_t m = ((uint64_t)firstOctetForNetwork(nwid)) << 40; m |= ztaddr.toInt(); // a is 40 bits @@ -208,7 +167,6 @@ public: * @param nwid Network ID */ inline Address toAddress(uint64_t nwid) const - throw() { uint64_t a = _m & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address a ^= ((nwid >> 8) & 0xff) << 32; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it @@ -224,7 +182,6 @@ public: * @return First octet of MAC for this network */ static inline unsigned char firstOctetForNetwork(uint64_t nwid) - throw() { unsigned char a = ((unsigned char)(nwid & 0xfe) | 0x02); // locally administered, not multicast, from LSB of network ID return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular virtualization engines... seems de-facto standard on Linux @@ -239,29 +196,27 @@ public: /** * @return 6, which is the number of bytes in a MAC, for container compliance */ - inline unsigned int size() const throw() { return 6; } + inline unsigned int size() const { return 6; } - inline unsigned long hashCode() const throw() { return (unsigned long)_m; } + inline unsigned long hashCode() const { return (unsigned long)_m; } inline MAC &operator=(const MAC &m) - throw() { _m = m._m; return *this; } inline MAC &operator=(const uint64_t m) - throw() { _m = m; return *this; } - inline bool operator==(const MAC &m) const throw() { return (_m == m._m); } - inline bool operator!=(const MAC &m) const throw() { return (_m != m._m); } - inline bool operator<(const MAC &m) const throw() { return (_m < m._m); } - inline bool operator<=(const MAC &m) const throw() { return (_m <= m._m); } - inline bool operator>(const MAC &m) const throw() { return (_m > m._m); } - inline bool operator>=(const MAC &m) const throw() { return (_m >= m._m); } + inline bool operator==(const MAC &m) const { return (_m == m._m); } + inline bool operator!=(const MAC &m) const { return (_m != m._m); } + inline bool operator<(const MAC &m) const { return (_m < m._m); } + inline bool operator<=(const MAC &m) const { return (_m <= m._m); } + inline bool operator>(const MAC &m) const { return (_m > m._m); } + inline bool operator>=(const MAC &m) const { return (_m >= m._m); } private: uint64_t _m; diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 7cbec2e0..f56c675b 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -29,8 +29,6 @@ #include -#include - #include "MAC.hpp" #include "InetAddress.hpp" @@ -94,16 +92,6 @@ public: return MulticastGroup(); } - /** - * @return Human readable string representing this group (MAC/ADI in hex) - */ - inline std::string toString() const - { - char buf[64]; - Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi); - return std::string(buf); - } - /** * @return Multicast address */ diff --git a/node/Network.cpp b/node/Network.cpp index bccc0397..f2b6771b 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -51,7 +51,7 @@ namespace ZeroTier { namespace { #ifdef ZT_RULES_ENGINE_DEBUGGING -#define FILTER_TRACE(f,...) { Utils::ztsnprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } +#define FILTER_TRACE(f,...) { snprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } static const char *_rtn(const ZT_VirtualNetworkRuleType rt) { switch(rt) { @@ -1257,7 +1257,17 @@ void Network::requestConfiguration(void *tPtr) nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP; nconf->type = ZT_NETWORK_TYPE_PUBLIC; - Utils::ztsnprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); + + nconf->name[0] = 'a'; + nconf->name[1] = 'd'; + nconf->name[2] = 'h'; + nconf->name[3] = 'o'; + nconf->name[4] = 'c'; + nconf->name[5] = '-'; + Utils::hex((uint16_t)startPortRange,nconf->name + 6); + nconf->name[10] = '-'; + Utils::hex((uint16_t)endPortRange,nconf->name + 11); + nconf->name[15] = (char)0; this->setConfiguration(tPtr,*nconf,false); delete nconf; diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 65101c3a..e5929923 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -64,7 +64,8 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (this->staticIps[i].ss_family == AF_INET) { if (v4s.length() > 0) v4s.push_back(','); - v4s.append(this->staticIps[i].toString()); + char buf[64]; + v4s.append(this->staticIps[i].toString(buf)); } } if (v4s.length() > 0) { @@ -75,7 +76,8 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (this->staticIps[i].ss_family == AF_INET6) { if (v6s.length() > 0) v6s.push_back(','); - v6s.append(this->staticIps[i].toString()); + char buf[64]; + v6s.append(this->staticIps[i].toString(buf)); } } if (v6s.length() > 0) { @@ -94,8 +96,7 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (ets.length() > 0) ets.push_back(','); char tmp2[16]; - Utils::ztsnprintf(tmp2,sizeof(tmp2),"%x",et); - ets.append(tmp2); + ets.append(Utils::hex((uint16_t)et,tmp2)); } et = 0; } @@ -114,7 +115,8 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if ((this->specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) { if (ab.length() > 0) ab.push_back(','); - ab.append(Address(this->specialists[i]).toString().c_str()); + char tmp2[16]; + ab.append(Address(this->specialists[i]).toString(tmp2)); } } if (ab.length() > 0) { diff --git a/node/Node.cpp b/node/Node.cpp index 4b598f61..e28accee 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -82,8 +82,8 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 if (n > 0) { tmp[n] = (char)0; if (RR->identity.fromString(tmp)) { - RR->publicIdentityStr = RR->identity.toString(false); - RR->secretIdentityStr = RR->identity.toString(true); + RR->identity.toString(false,RR->publicIdentityStr); + RR->identity.toString(true,RR->secretIdentityStr); } else { n = -1; } @@ -92,10 +92,10 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; if (n <= 0) { RR->identity.generate(); - RR->publicIdentityStr = RR->identity.toString(false); - RR->secretIdentityStr = RR->identity.toString(true); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr.data(),(unsigned int)RR->secretIdentityStr.length()); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length()); + RR->identity.toString(false,RR->publicIdentityStr); + RR->identity.toString(true,RR->secretIdentityStr); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr)); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } else { n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { @@ -104,7 +104,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 n = -1; } if (n <= 0) - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length()); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } try { @@ -386,8 +386,8 @@ uint64_t Node::address() const void Node::status(ZT_NodeStatus *status) const { status->address = RR->identity.address().toInt(); - status->publicIdentity = RR->publicIdentityStr.c_str(); - status->secretIdentity = RR->secretIdentityStr.c_str(); + status->publicIdentity = RR->publicIdentityStr; + status->secretIdentity = RR->secretIdentityStr; status->online = _online ? 1 : 0; } @@ -544,39 +544,6 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast(&remoteAddress)) != 0) : true); } -#ifdef ZT_TRACE -void Node::postTrace(const char *module,unsigned int line,const char *fmt,...) -{ - static Mutex traceLock; - - va_list ap; - char tmp1[1024],tmp2[1024],tmp3[256]; - - Mutex::Lock _l(traceLock); - - time_t now = (time_t)(_now / 1000ULL); -#ifdef __WINDOWS__ - ctime_s(tmp3,sizeof(tmp3),&now); - char *nowstr = tmp3; -#else - char *nowstr = ctime_r(&now,tmp3); -#endif - unsigned long nowstrlen = (unsigned long)strlen(nowstr); - if (nowstr[nowstrlen-1] == '\n') - nowstr[--nowstrlen] = (char)0; - if (nowstr[nowstrlen-1] == '\r') - nowstr[--nowstrlen] = (char)0; - - va_start(ap,fmt); - vsnprintf(tmp2,sizeof(tmp2),fmt,ap); - va_end(ap); - tmp2[sizeof(tmp2)-1] = (char)0; - - Utils::ztsnprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2); - postEvent((void *)0,ZT_EVENT_TRACE,tmp1); -} -#endif // ZT_TRACE - uint64_t Node::prng() { // https://en.wikipedia.org/wiki/Xorshift#xorshift.2B diff --git a/node/Node.hpp b/node/Node.hpp index 55491b06..40903f7c 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -195,10 +195,6 @@ public: inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,(int)len); } inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,(const void *)0,-1); } -#ifdef ZT_TRACE - void postTrace(const char *module,unsigned int line,const char *fmt,...); -#endif - bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress); inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 99afe25d..94b96d34 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -27,7 +27,7 @@ #ifndef ZT_RUNTIMEENVIRONMENT_HPP #define ZT_RUNTIMEENVIRONMENT_HPP -#include +#include #include "Constants.hpp" #include "Utils.hpp" @@ -60,11 +60,13 @@ public: ,sa((SelfAwareness *)0) { Utils::getSecureRandom(&instanceId,sizeof(instanceId)); + memset(publicIdentityStr,0,sizeof(publicIdentityStr)); + memset(secretIdentityStr,0,sizeof(secretIdentityStr)); } ~RuntimeEnvironment() { - Utils::burn(reinterpret_cast(const_cast(secretIdentityStr.data())),(unsigned int)secretIdentityStr.length()); + Utils::burn(secretIdentityStr,sizeof(secretIdentityStr)); } /** @@ -77,8 +79,8 @@ public: // This node's identity Identity identity; - std::string publicIdentityStr; - std::string secretIdentityStr; + char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH]; + char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH]; // This is set externally to an instance of this base class NetworkController *localNetworkController; diff --git a/node/Topology.cpp b/node/Topology.cpp index 809bc7e7..e7bbdfae 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -91,12 +91,8 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : SharedPtr Topology::addPeer(void *tPtr,const SharedPtr &peer) { #ifdef ZT_TRACE - if ((!peer)||(peer->address() == RR->identity.address())) { - if (!peer) - fprintf(stderr,"FATAL BUG: addPeer() caught attempt to add NULL peer" ZT_EOL_S); - else fprintf(stderr,"FATAL BUG: addPeer() caught attempt to add peer for self" ZT_EOL_S); - abort(); - } + if ((!peer)||(peer->address() == RR->identity.address())) + return SharedPtr(); #endif SharedPtr np; diff --git a/node/Utils.cpp b/node/Utils.cpp index d2321e16..a3a4c3c3 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -55,90 +55,35 @@ namespace ZeroTier { const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; -// Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers. -static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len) -{ - volatile uint8_t *const end = ptr + len; - while (ptr != end) *(ptr++) = (uint8_t)0; -} -static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn; -void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); } - -std::string Utils::hex(const void *data,unsigned int len) +static unsigned long _Utils_itoa(unsigned long n,char *s) { - std::string r; - r.reserve(len * 2); - for(unsigned int i=0;i> 4]); - r.push_back(HEXCHARS[((const unsigned char *)data)[i] & 0x0f]); - } - return r; + if (n == 0) + return 0; + unsigned long pos = _Utils_itoa(n / 10,s); + if (pos >= 22) // sanity check, should be impossible + pos = 22; + s[pos] = '0' + (char)(n % 10); + return pos + 1; } - -std::string Utils::unhex(const char *hex,unsigned int maxlen) +char *Utils::decimal(unsigned long n,char s[24]) { - int n = 1; - unsigned char c,b = 0; - const char *eof = hex + maxlen; - std::string r; - - if (!maxlen) - return r; - - while ((c = (unsigned char)*(hex++))) { - if ((c >= 48)&&(c <= 57)) { // 0..9 - if ((n ^= 1)) - r.push_back((char)(b | (c - 48))); - else b = (c - 48) << 4; - } else if ((c >= 65)&&(c <= 70)) { // A..F - if ((n ^= 1)) - r.push_back((char)(b | (c - (65 - 10)))); - else b = (c - (65 - 10)) << 4; - } else if ((c >= 97)&&(c <= 102)) { // a..f - if ((n ^= 1)) - r.push_back((char)(b | (c - (97 - 10)))); - else b = (c - (97 - 10)) << 4; - } - if (hex == eof) - break; + if (n == 0) { + s[0] = '0'; + s[1] = (char)0; + return s; } - - return r; + s[_Utils_itoa(n,s)] = (char)0; + return s; } -unsigned int Utils::unhex(const char *hex,unsigned int maxlen,void *buf,unsigned int len) +// Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers. +static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len) { - int n = 1; - unsigned char c,b = 0; - unsigned int l = 0; - const char *eof = hex + maxlen; - - if (!maxlen) - return 0; - - while ((c = (unsigned char)*(hex++))) { - if ((c >= 48)&&(c <= 57)) { // 0..9 - if ((n ^= 1)) { - if (l >= len) break; - ((unsigned char *)buf)[l++] = (b | (c - 48)); - } else b = (c - 48) << 4; - } else if ((c >= 65)&&(c <= 70)) { // A..F - if ((n ^= 1)) { - if (l >= len) break; - ((unsigned char *)buf)[l++] = (b | (c - (65 - 10))); - } else b = (c - (65 - 10)) << 4; - } else if ((c >= 97)&&(c <= 102)) { // a..f - if ((n ^= 1)) { - if (l >= len) break; - ((unsigned char *)buf)[l++] = (b | (c - (97 - 10))); - } else b = (c - (97 - 10)) << 4; - } - if (hex == eof) - break; - } - - return l; + volatile uint8_t *const end = ptr + len; + while (ptr != end) *(ptr++) = (uint8_t)0; } +static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn; +void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); } void Utils::getSecureRandom(void *buf,unsigned int bytes) { @@ -244,21 +189,4 @@ bool Utils::scopy(char *dest,unsigned int len,const char *src) return true; } -unsigned int Utils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) -{ - va_list ap; - - va_start(ap,fmt); - int n = (int)vsnprintf(buf,len,fmt,ap); - va_end(ap); - - if ((n >= (int)len)||(n < 0)) { - if (len) - buf[len - 1] = (char)0; - throw std::length_error("buf[] overflow"); - } - - return (unsigned int)n; -} - } // namespace ZeroTier diff --git a/node/Utils.hpp b/node/Utils.hpp index 212ef247..5a5e9f39 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -70,42 +70,144 @@ public: static void burn(void *ptr,unsigned int len); /** - * Convert binary data to hexadecimal - * - * @param data Data to convert to hex - * @param len Length of data - * @return Hexadecimal string + * @param n Number to convert + * @param s Buffer, at least 24 bytes in size + * @return String containing 'n' in base 10 form */ - static std::string hex(const void *data,unsigned int len); - static inline std::string hex(const std::string &data) { return hex(data.data(),(unsigned int)data.length()); } + static char *decimal(unsigned long n,char s[24]); - /** - * Convert hexadecimal to binary data - * - * This ignores all non-hex characters, just stepping over them and - * continuing. Upper and lower case are supported for letters a-f. - * - * @param hex Hexadecimal ASCII code (non-hex chars are ignored, stops at zero or maxlen) - * @param maxlen Maximum length of hex string buffer - * @return Binary data - */ - static std::string unhex(const char *hex,unsigned int maxlen); - static inline std::string unhex(const std::string &hex) { return unhex(hex.c_str(),(unsigned int)hex.length()); } + static inline char *hex(uint64_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 60) & 0xf]; + s[1] = HEXCHARS[(i >> 56) & 0xf]; + s[2] = HEXCHARS[(i >> 52) & 0xf]; + s[3] = HEXCHARS[(i >> 48) & 0xf]; + s[4] = HEXCHARS[(i >> 44) & 0xf]; + s[5] = HEXCHARS[(i >> 40) & 0xf]; + s[6] = HEXCHARS[(i >> 36) & 0xf]; + s[7] = HEXCHARS[(i >> 32) & 0xf]; + s[8] = HEXCHARS[(i >> 28) & 0xf]; + s[9] = HEXCHARS[(i >> 24) & 0xf]; + s[10] = HEXCHARS[(i >> 20) & 0xf]; + s[11] = HEXCHARS[(i >> 16) & 0xf]; + s[12] = HEXCHARS[(i >> 12) & 0xf]; + s[13] = HEXCHARS[(i >> 8) & 0xf]; + s[14] = HEXCHARS[(i >> 4) & 0xf]; + s[15] = HEXCHARS[i & 0xf]; + s[16] = (char)0; + return s; + } - /** - * Convert hexadecimal to binary data - * - * This ignores all non-hex characters, just stepping over them and - * continuing. Upper and lower case are supported for letters a-f. - * - * @param hex Hexadecimal ASCII - * @param maxlen Maximum length of hex string buffer - * @param buf Buffer to fill - * @param len Length of buffer - * @return Number of characters actually written - */ - static unsigned int unhex(const char *hex,unsigned int maxlen,void *buf,unsigned int len); - static inline unsigned int unhex(const std::string &hex,void *buf,unsigned int len) { return unhex(hex.c_str(),(unsigned int)hex.length(),buf,len); } + static inline char *hex10(uint64_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 36) & 0xf]; + s[1] = HEXCHARS[(i >> 32) & 0xf]; + s[2] = HEXCHARS[(i >> 28) & 0xf]; + s[3] = HEXCHARS[(i >> 24) & 0xf]; + s[4] = HEXCHARS[(i >> 20) & 0xf]; + s[5] = HEXCHARS[(i >> 16) & 0xf]; + s[6] = HEXCHARS[(i >> 12) & 0xf]; + s[7] = HEXCHARS[(i >> 8) & 0xf]; + s[8] = HEXCHARS[(i >> 4) & 0xf]; + s[9] = HEXCHARS[i & 0xf]; + s[10] = (char)0; + return s; + } + + static inline char *hex(uint16_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 12) & 0xf]; + s[1] = HEXCHARS[(i >> 8) & 0xf]; + s[2] = HEXCHARS[(i >> 4) & 0xf]; + s[3] = HEXCHARS[i & 0xf]; + s[4] = (char)0; + return s; + } + + static inline char *hex(uint8_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 4) & 0xf]; + s[1] = HEXCHARS[i & 0xf]; + s[2] = (char)0; + return s; + } + + static inline char *hex(const void *d,unsigned int l,char *s) + { + char *save = s; + for(unsigned int i=0;i(d)[i]; + *(s++) = HEXCHARS[(b >> 4) & 0xf]; + *(s++) = HEXCHARS[b & 0xf]; + } + *s = (char)0; + return save; + } + + static inline unsigned int unhex(const char *h,void *buf,unsigned int buflen) + { + unsigned int l = 0; + while (l < buflen) { + uint8_t hc = (uint8_t)*(h++); + if (!hc) break; + + uint8_t c = 0; + if ((hc >= 48)&&(hc <= 57)) + c = hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c = hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c = hc - 55; + + hc = (uint8_t)*(h++); + if (!hc) break; + + c <<= 4; + if ((hc >= 48)&&(hc <= 57)) + c |= hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c |= hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c |= hc - 55; + + reinterpret_cast(buf)[l++] = c; + } + return l; + } + + static inline unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen) + { + unsigned int l = 0; + const char *hend = h + hlen; + while (l < buflen) { + if (h == hend) break; + uint8_t hc = (uint8_t)*(h++); + if (!hc) break; + + uint8_t c = 0; + if ((hc >= 48)&&(hc <= 57)) + c = hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c = hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c = hc - 55; + + if (h == hend) break; + hc = (uint8_t)*(h++); + if (!hc) break; + + c <<= 4; + if ((hc >= 48)&&(hc <= 57)) + c |= hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c |= hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c |= hc - 55; + + reinterpret_cast(buf)[l++] = c; + } + return l; + } /** * Generate secure random bytes @@ -232,20 +334,6 @@ public: */ static bool scopy(char *dest,unsigned int len,const char *src); - /** - * Variant of snprintf that is portable and throws an exception - * - * This just wraps the local implementation whatever it's called, while - * performing a few other checks and adding exceptions for overflow. - * - * @param buf Buffer to write to - * @param len Length of buffer in bytes - * @param fmt Format string - * @param ... Format arguments - * @throws std::length_error buf[] too short (buf[] will still be left null-terminated) - */ - static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...); - /** * Count the number of bits set in an integer * diff --git a/one.cpp b/one.cpp index cbf09121..b1a19e8c 100644 --- a/one.cpp +++ b/one.cpp @@ -260,9 +260,9 @@ static int cli(int argc,char **argv) if (hd) { char p[4096]; #ifdef __APPLE__ - Utils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); + OSUtils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); #else - Utils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); + OSUtils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); #endif OSUtils::readFile(p,authToken); } @@ -278,7 +278,7 @@ static int cli(int argc,char **argv) InetAddress addr; { char addrtmp[256]; - Utils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); + OSUtils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); addr = InetAddress(addrtmp); } @@ -366,7 +366,7 @@ static int cli(int argc,char **argv) std::string addr = path["address"]; const uint64_t now = OSUtils::now(); const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); bestPath = tmp; break; } @@ -378,7 +378,7 @@ static int cli(int argc,char **argv) int64_t vmin = p["versionMinor"]; int64_t vrev = p["versionRev"]; if (vmaj >= 0) { - Utils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); + OSUtils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); } else { ver[0] = '-'; ver[1] = (char)0; @@ -527,9 +527,9 @@ static int cli(int argc,char **argv) const uint64_t seed = Utils::hexStrToU64(arg2.c_str()); if ((worldId)&&(seed)) { char jsons[1024]; - Utils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); + OSUtils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); char cl[128]; - Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + OSUtils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -579,11 +579,11 @@ static int cli(int argc,char **argv) if (eqidx != std::string::npos) { if ((arg2.substr(0,eqidx) == "allowManaged")||(arg2.substr(0,eqidx) == "allowGlobal")||(arg2.substr(0,eqidx) == "allowDefault")) { char jsons[1024]; - Utils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}", + OSUtils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}", arg2.substr(0,eqidx).c_str(), (((arg2.substr(eqidx,2) == "=t")||(arg2.substr(eqidx,2) == "=1")) ? "true" : "false")); char cl[128]; - Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + OSUtils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -648,7 +648,7 @@ static Identity getIdFromArg(char *arg) } else { // identity is to be read from a file std::string idser; if (OSUtils::readFile(arg,idser)) { - if (id.fromString(idser)) + if (id.fromString(idser.c_str())) return id; } } @@ -689,14 +689,15 @@ static int idtool(int argc,char **argv) } } - std::string idser = id.toString(true); + char idtmp[1024]; + std::string idser = id.toString(true,idtmp); if (argc >= 3) { if (!OSUtils::writeFile(argv[2],idser)) { fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[2]); return 1; } else printf("%s written" ZT_EOL_S,argv[2]); if (argc >= 4) { - idser = id.toString(false); + idser = id.toString(false,idtmp); if (!OSUtils::writeFile(argv[3],idser)) { fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[3]); return 1; @@ -731,7 +732,8 @@ static int idtool(int argc,char **argv) return 1; } - printf("%s",id.toString(false).c_str()); + char idtmp[1024]; + printf("%s",id.toString(false,idtmp)); } else if (!strcmp(argv[1],"sign")) { if (argc < 4) { idtoolPrintHelp(stdout,argv[0]); @@ -755,7 +757,8 @@ static int idtool(int argc,char **argv) return 1; } C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length()); - printf("%s",Utils::hex(signature.data,(unsigned int)signature.size()).c_str()); + char hexbuf[1024]; + printf("%s",Utils::hex(signature.data,(unsigned int)signature.size(),hexbuf)); } else if (!strcmp(argv[1],"verify")) { if (argc < 4) { idtoolPrintHelp(stdout,argv[0]); @@ -774,7 +777,8 @@ static int idtool(int argc,char **argv) return 1; } - std::string signature(Utils::unhex(argv[4])); + char buf[4096]; + std::string signature(buf,Utils::unhex(argv[4],buf,(unsigned int)sizeof(buf))); if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),(unsigned int)inf.length(),signature.data(),(unsigned int)signature.length()))) { printf("%s signature valid" ZT_EOL_S,argv[3]); } else { @@ -793,14 +797,15 @@ static int idtool(int argc,char **argv) C25519::Pair kp(C25519::generate()); + char idtmp[4096]; nlohmann::json mj; mj["objtype"] = "world"; mj["worldType"] = "moon"; - mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,(unsigned int)kp.pub.size()); - mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,(unsigned int)kp.priv.size()); - mj["id"] = id.address().toString(); + mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,(unsigned int)kp.pub.size(),idtmp); + mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,(unsigned int)kp.priv.size(),idtmp); + mj["id"] = id.address().toString(idtmp); nlohmann::json seedj; - seedj["identity"] = id.toString(false); + seedj["identity"] = id.toString(false,idtmp); seedj["stableEndpoints"] = nlohmann::json::array(); (mj["roots"] = nlohmann::json::array()).push_back(seedj); std::string mjd(OSUtils::jsonDump(mj)); @@ -836,9 +841,9 @@ static int idtool(int argc,char **argv) C25519::Pair signingKey; C25519::Public updatesMustBeSignedBy; - Utils::unhex(OSUtils::jsonString(mj["signingKey"],""),signingKey.pub.data,(unsigned int)signingKey.pub.size()); - Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],""),signingKey.priv.data,(unsigned int)signingKey.priv.size()); - Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],""),updatesMustBeSignedBy.data,(unsigned int)updatesMustBeSignedBy.size()); + Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,(unsigned int)signingKey.pub.size()); + Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,(unsigned int)signingKey.priv.size()); + Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,(unsigned int)updatesMustBeSignedBy.size()); std::vector roots; nlohmann::json &rootsj = mj["roots"]; @@ -847,11 +852,11 @@ static int idtool(int argc,char **argv) nlohmann::json &r = rootsj[i]; if (r.is_object()) { roots.push_back(World::Root()); - roots.back().identity = Identity(OSUtils::jsonString(r["identity"],"")); + roots.back().identity = Identity(OSUtils::jsonString(r["identity"],"").c_str()); nlohmann::json &stableEndpointsj = r["stableEndpoints"]; if (stableEndpointsj.is_array()) { for(unsigned long k=0;k<(unsigned long)stableEndpointsj.size();++k) - roots.back().stableEndpoints.push_back(InetAddress(OSUtils::jsonString(stableEndpointsj[k],""))); + roots.back().stableEndpoints.push_back(InetAddress(OSUtils::jsonString(stableEndpointsj[k],"").c_str())); std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end()); } } @@ -864,7 +869,7 @@ static int idtool(int argc,char **argv) Buffer wbuf; w.serialize(wbuf); char fn[128]; - Utils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); + OSUtils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); OSUtils::writeFile(fn,wbuf.data(),wbuf.size()); printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S,fn,(unsigned long long)now); } diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index f07f9e5a..8e57d605 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -114,8 +114,8 @@ BSDEthernetTap::BSDEthernetTap( std::vector devFiles(OSUtils::listDirectory("/dev")); for(int i=9993;i<(9993+128);++i) { - Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) { long cpid = (long)vfork(); if (cpid == 0) { @@ -152,8 +152,8 @@ BSDEthernetTap::BSDEthernetTap( /* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */ for(int i=0;i<64;++i) { - Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); _fd = ::open(devpath,O_RDWR); if (_fd > 0) { _dev = tmpdevname; @@ -171,9 +171,9 @@ BSDEthernetTap::BSDEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); + OSUtils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); + OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); + OSUtils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); long cpid = (long)vfork(); if (cpid == 0) { ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); @@ -256,7 +256,8 @@ bool BSDEthernetTap::addIp(const InetAddress &ip) long cpid = (long)vfork(); if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); + char tmp[128]; + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString(tmp),"alias",(const char *)0); ::_exit(-1); } else if (cpid > 0) { int exitcode = -1; @@ -385,7 +386,7 @@ void BSDEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0); _exit(-1); } else if (cpid > 0) { diff --git a/osdep/Http.cpp b/osdep/Http.cpp index 3c556f44..d6d0238c 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -244,10 +244,10 @@ unsigned int Http::_do( try { char tmp[1024]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); handler.writeBuf.append(tmp); for(std::map::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) { - Utils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); handler.writeBuf.append(tmp); } handler.writeBuf.append("\r\n"); diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index fc5199f1..c8f9ef9d 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -97,7 +97,7 @@ LinuxEthernetTap::LinuxEthernetTap( char procpath[128],nwids[32]; struct stat sbuf; - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally @@ -134,7 +134,7 @@ LinuxEthernetTap::LinuxEthernetTap( std::map::const_iterator gdmEntry = globalDeviceMap.find(nwids); if (gdmEntry != globalDeviceMap.end()) { Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),gdmEntry->second.c_str()); - Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); recalledDevice = (stat(procpath,&sbuf) != 0); } @@ -142,8 +142,8 @@ LinuxEthernetTap::LinuxEthernetTap( #ifdef __SYNOLOGY__ int devno = 50; do { - Utils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); - Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + OSUtils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); + OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist #else char devno = 0; @@ -158,7 +158,7 @@ LinuxEthernetTap::LinuxEthernetTap( _base32_5_to_8(reinterpret_cast(tmp2) + 5,tmp3 + 10); tmp3[15] = (char)0; memcpy(ifr.ifr_name,tmp3,16); - Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); #endif } @@ -264,7 +264,8 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip) if (cpid == 0) { OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); - ::execlp("ip","ip","addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0); + char iptmp[128]; + ::execlp("ip","ip","addr","del",ip.toString(iptmp),"dev",_dev.c_str(),(const char *)0); ::_exit(-1); } else { int exitcode = -1; @@ -296,25 +297,28 @@ bool LinuxEthernetTap::addIpSyn(std::vector ips) // Assemble and write contents of ifcfg-dev file for(int i=0; i<(int)ips.size(); i++) { if (ips[i].isV4()) { + char iptmp[64],iptmp2[64]; std::string numstr4 = ip4_tot > 1 ? std::to_string(ip4) : ""; - cfg_contents += "\nIPADDR"+numstr4+"="+ips[i].toIpString() - + "\nNETMASK"+numstr4+"="+ips[i].netmask().toIpString()+"\n"; + cfg_contents += "\nIPADDR"+numstr4+"="+ips[i].toIpString(iptmp) + + "\nNETMASK"+numstr4+"="+ips[i].netmask().toIpString(iptmp2)+"\n"; ip4++; } else { + char iptmp[64],iptmp2[64]; std::string numstr6 = ip6_tot > 1 ? std::to_string(ip6) : ""; - cfg_contents += "\nIPV6ADDR"+numstr6+"="+ips[i].toIpString() - + "\nNETMASK"+numstr6+"="+ips[i].netmask().toIpString()+"\n"; + cfg_contents += "\nIPV6ADDR"+numstr6+"="+ips[i].toIpString(iptmp) + + "\nNETMASK"+numstr6+"="+ips[i].netmask().toIpString(iptmp2)+"\n"; ip6++; } } OSUtils::writeFile(filepath.c_str(), cfg_contents.c_str(), cfg_contents.length()); // Finaly, add IPs for(int i=0; i<(int)ips.size(); i++){ + char iptmp[128],iptmp2[128[; if (ips[i].isV4()) - ::execlp("ip","ip","addr","add",ips[i].toString().c_str(),"broadcast",ips[i].broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ips[i].toString(iptmp),"broadcast",ips[i].broadcast().toIpString(iptmp2),"dev",_dev.c_str(),(const char *)0); else - ::execlp("ip","ip","addr","add",ips[i].toString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ips[i].toString(iptmp),"dev",_dev.c_str(),(const char *)0); } ::_exit(-1); } else if (cpid > 0) { @@ -345,10 +349,11 @@ bool LinuxEthernetTap::addIp(const InetAddress &ip) if (cpid == 0) { OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); + char iptmp[128],iptmp2[128]; if (ip.isV4()) { - ::execlp("ip","ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ip.toString(iptmp),"broadcast",ip.broadcast().toIpString(iptmp2),"dev",_dev.c_str(),(const char *)0); } else { - ::execlp("ip","ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ip.toString(iptmp),"dev",_dev.c_str(),(const char *)0); } ::_exit(-1); } else if (cpid > 0) { diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index fca1c290..3a0b8a7e 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -246,7 +246,6 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains) static void _routeCmd(const char *op,const InetAddress &target,const InetAddress &via,const char *ifscope,const char *localInterface) { - //printf("route %s %s %s %s %s\n",op,target.toString().c_str(),(via) ? via.toString().c_str() : "(null)",(ifscope) ? ifscope : "(null)",(localInterface) ? localInterface : "(null)"); long p = (long)fork(); if (p > 0) { int exitcode = -1; @@ -254,17 +253,19 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress } else if (p == 0) { ::close(STDOUT_FILENO); ::close(STDERR_FILENO); + char ttmp[64]; + char iptmp[64]; if (via) { if ((ifscope)&&(ifscope[0])) { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),via.toIpString().c_str(),(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0); } else { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),via.toIpString().c_str(),(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0); } } else if ((localInterface)&&(localInterface[0])) { if ((ifscope)&&(ifscope[0])) { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),"-interface",localInterface,(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0); } else { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),"-interface",localInterface,(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0); } } ::_exit(-1); diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 06508e77..882b8255 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -57,6 +57,23 @@ namespace ZeroTier { +unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) +{ + va_list ap; + + va_start(ap,fmt); + int n = (int)vsnprintf(buf,len,fmt,ap); + va_end(ap); + + if ((n >= (int)len)||(n < 0)) { + if (len) + buf[len - 1] = (char)0; + throw std::length_error("buf[] overflow"); + } + + return (unsigned int)n; +} + #ifdef __UNIX_LIKE__ bool OSUtils::redirectUnixOutputs(const char *stdoutPath,const char *stderrPath) throw() @@ -134,7 +151,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) if (date.QuadPart > 0) { date.QuadPart -= adjust.QuadPart; if ((uint64_t)((date.QuadPart / 10000000) * 1000) < olderThan) { - Utils::ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); + ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); if (DeleteFileA(tmp)) ++cleaned; } @@ -157,7 +174,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) break; if (dptr) { if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) { - Utils::ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); + ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); if (stat(tmp,&st) == 0) { uint64_t mt = (uint64_t)(st.st_mtime); if ((mt > 0)&&((mt * 1000) < olderThan)) { @@ -464,7 +481,7 @@ std::string OSUtils::jsonString(const nlohmann::json &jv,const char *dfl) return jv; } else if (jv.is_number()) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); + ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); return tmp; } else if (jv.is_boolean()) { return ((bool)jv ? std::string("1") : std::string("0")); @@ -477,9 +494,10 @@ std::string OSUtils::jsonBinFromHex(const nlohmann::json &jv) { std::string s(jsonString(jv,"")); if (s.length() > 0) { - char *buf = new char[(s.length() / 2) + 1]; + unsigned int buflen = (s.length() / 2) + 1; + char *buf = new char[buflen]; try { - unsigned int l = Utils::unhex(s,buf,(unsigned int)s.length()); + unsigned int l = Utils::unhex(s.c_str(),buf,buflen); std::string b(buf,l); delete [] buf; return b; diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index dff7df86..d6f32822 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -66,6 +65,20 @@ namespace ZeroTier { class OSUtils { public: + /** + * Variant of snprintf that is portable and throws an exception + * + * This just wraps the local implementation whatever it's called, while + * performing a few other checks and adding exceptions for overflow. + * + * @param buf Buffer to write to + * @param len Length of buffer in bytes + * @param fmt Format string + * @param ... Format arguments + * @throws std::length_error buf[] too short (buf[] will still be left null-terminated) + */ + static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...); + #ifdef __UNIX_LIKE__ /** * Close STDOUT_FILENO and STDERR_FILENO and replace them with output to given path diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index e082408e..b43d34c0 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -336,7 +336,7 @@ OSXEthernetTap::OSXEthernetTap( char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; struct stat stattmp; - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _gl(globalTapCreateLock); @@ -391,13 +391,13 @@ OSXEthernetTap::OSXEthernetTap( // Open the first unused tap device if we didn't recall a previous one. if (!recalledDevice) { for(int i=0;i<64;++i) { - Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",i); + OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",i); if (stat(devpath,&stattmp)) throw std::runtime_error("no more TAP devices available"); _fd = ::open(devpath,O_RDWR); if (_fd > 0) { char foo[16]; - Utils::ztsnprintf(foo,sizeof(foo),"zt%d",i); + OSUtils::ztsnprintf(foo,sizeof(foo),"zt%d",i); _dev = foo; break; } @@ -413,9 +413,9 @@ OSXEthernetTap::OSXEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); + OSUtils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); + OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); + OSUtils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); long cpid = (long)vfork(); if (cpid == 0) { ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); @@ -499,7 +499,8 @@ bool OSXEthernetTap::addIp(const InetAddress &ip) long cpid = (long)vfork(); if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toString().c_str(),"alias",(const char *)0); + char tmp[128]; + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toString(tmp),"alias",(const char *)0); ::_exit(-1); } else if (cpid > 0) { int exitcode = -1; @@ -519,7 +520,8 @@ bool OSXEthernetTap::removeIp(const InetAddress &ip) if (*i == ip) { long cpid = (long)vfork(); if (cpid == 0) { - execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toIpString().c_str(),"-alias",(const char *)0); + char tmp[128]; + execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toIpString(tmp),"-alias",(const char *)0); _exit(-1); } else if (cpid > 0) { int exitcode = -1; @@ -636,7 +638,7 @@ void OSXEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0); _exit(-1); } else if (cpid > 0) { diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index df868e7a..b1990486 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -205,7 +205,7 @@ public: memset(externalip,0,sizeof(externalip)); memset(&urls,0,sizeof(urls)); memset(&data,0,sizeof(data)); - Utils::ztsnprintf(inport,sizeof(inport),"%d",localPort); + OSUtils::ztsnprintf(inport,sizeof(inport),"%d",localPort); if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { #ifdef ZT_PORTMAPPER_TRACE @@ -220,7 +220,7 @@ public: int tryPort = (int)localPort + tries; if (tryPort >= 65535) tryPort = (tryPort - 65535) + 1025; - Utils::ztsnprintf(outport,sizeof(outport),"%u",tryPort); + OSUtils::ztsnprintf(outport,sizeof(outport),"%u",tryPort); // First check and see if this port is already mapped to the // same unique name. If so, keep this mapping and don't try diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index b96ad791..5344268f 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -484,7 +484,7 @@ WindowsEthernetTap::WindowsEthernetTap( char tag[24]; // We "tag" registry entries with the network ID to identify persistent devices - Utils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); + OSUtils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); Mutex::Lock _l(_systemTapInitLock); @@ -601,10 +601,10 @@ WindowsEthernetTap::WindowsEthernetTap( if (_netCfgInstanceId.length() > 0) { char tmps[64]; - unsigned int tmpsl = Utils::ztsnprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; + unsigned int tmpsl = OSUtils::ztsnprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl); - tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); + tmpsl = OSUtils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MTU",REG_SZ,tmps,tmpsl); DWORD tmp = 0; @@ -879,7 +879,7 @@ void WindowsEthernetTap::setMtu(unsigned int mtu) HKEY nwAdapters; if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) == ERROR_SUCCESS) { char tmps[64]; - unsigned int tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); + unsigned int tmpsl = OSUtils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl); RegCloseKey(nwAdapters); } @@ -902,7 +902,7 @@ void WindowsEthernetTap::threadMain() HANDLE wait4[3]; OVERLAPPED tapOvlRead,tapOvlWrite; - Utils::ztsnprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); + OSUtils::ztsnprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); try { while (_run) { diff --git a/selftest.cpp b/selftest.cpp index ff171aa3..e6705700 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -153,10 +153,11 @@ static int testCrypto() { static unsigned char buf1[16384]; static unsigned char buf2[sizeof(buf1)],buf3[sizeof(buf1)]; + static char hexbuf[1024]; for(int i=0;i<3;++i) { Utils::getSecureRandom(buf1,64); - std::cout << "[crypto] getSecureRandom: " << Utils::hex(buf1,64) << std::endl; + std::cout << "[crypto] getSecureRandom: " << Utils::hex(buf1,64,hexbuf) << std::endl; } std::cout << "[crypto] Testing Salsa20... "; std::cout.flush(); @@ -213,7 +214,7 @@ static int testCrypto() } uint64_t end = OSUtils::now(); SHA512::hash(buf1,bb,1234567); - std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl; ::free((void *)bb); } @@ -265,7 +266,7 @@ static int testCrypto() } uint64_t end = OSUtils::now(); SHA512::hash(buf1,bb,1234567); - std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl; ::free((void *)bb); } @@ -427,6 +428,7 @@ static int testIdentity() { Identity id; Buffer<512> buf; + char buf2[1024]; std::cout << "[identity] Validate known-good identity... "; std::cout.flush(); if (!id.fromString(KNOWN_GOOD_IDENTITY)) { @@ -459,7 +461,7 @@ static int testIdentity() uint64_t genstart = OSUtils::now(); id.generate(); uint64_t genend = OSUtils::now(); - std::cout << "(took " << (genend - genstart) << "ms): " << id.toString(true) << std::endl; + std::cout << "(took " << (genend - genstart) << "ms): " << id.toString(true,buf2) << std::endl; std::cout << "[identity] Locally validate identity: "; if (id.locallyValidate()) { std::cout << "PASS" << std::endl; @@ -499,7 +501,7 @@ static int testIdentity() { Identity id2; - id2.fromString(id.toString(true).c_str()); + id2.fromString(id.toString(true,buf2)); std::cout << "[identity] Serialize and deserialize (ASCII w/private): "; if ((id == id2)&&(id2.locallyValidate())) { std::cout << "PASS" << std::endl; @@ -511,7 +513,7 @@ static int testIdentity() { Identity id2; - id2.fromString(id.toString(false).c_str()); + id2.fromString(id.toString(false,buf2)); std::cout << "[identity] Serialize and deserialize (ASCII no private): "; if ((id == id2)&&(id2.locallyValidate())) { std::cout << "PASS" << std::endl; @@ -526,16 +528,18 @@ static int testIdentity() static int testCertificate() { + char buf[4096]; + Identity authority; std::cout << "[certificate] Generating identity to act as authority... "; std::cout.flush(); authority.generate(); - std::cout << authority.address().toString() << std::endl; + std::cout << authority.address().toString(buf) << std::endl; Identity idA,idB; std::cout << "[certificate] Generating identities A and B... "; std::cout.flush(); idA.generate(); idB.generate(); - std::cout << idA.address().toString() << ", " << idB.address().toString() << std::endl; + std::cout << idA.address().toString(buf) << ", " << idB.address().toString(buf) << std::endl; std::cout << "[certificate] Generating certificates A and B..."; CertificateOfMembership cA(10000,100,1,idA.address()); @@ -641,6 +645,8 @@ static void _testExcept(int &depth) static int testOther() { + char buf[1024]; + std::cout << "[other] Testing C++ exceptions... "; std::cout.flush(); int depth = 0; try { @@ -657,6 +663,13 @@ static int testOther() return -1; } + std::cout << "[other] Testing InetAddress encode/decode..."; std::cout.flush(); + std::cout << " " << InetAddress("127.0.0.1/9993").toString(buf); + std::cout << " " << InetAddress("feed:dead:babe:dead:beef:f00d:1234:5678/12345").toString(buf); + std::cout << " " << InetAddress("0/9993").toString(buf); + std::cout << " " << InetAddress("").toString(buf); + std::cout << std::endl; + #if 0 std::cout << "[other] Testing Hashtable... "; std::cout.flush(); { @@ -831,7 +844,7 @@ static int testOther() memset(key, 0, sizeof(key)); memset(value, 0, sizeof(value)); for(unsigned int q=0;q<32;++q) { - Utils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); + OSUtils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); int r = rand() % 128; for(int x=0;xnwid); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); nj["id"] = tmp; nj["nwid"] = tmp; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); nj["mac"] = tmp; nj["name"] = nc->name; nj["status"] = nstatus; @@ -223,16 +223,16 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc, nlohmann::json aa = nlohmann::json::array(); for(unsigned int i=0;iassignedAddressCount;++i) { - aa.push_back(reinterpret_cast(&(nc->assignedAddresses[i]))->toString()); + aa.push_back(reinterpret_cast(&(nc->assignedAddresses[i]))->toString(tmp)); } nj["assignedAddresses"] = aa; nlohmann::json ra = nlohmann::json::array(); for(unsigned int i=0;irouteCount;++i) { nlohmann::json rj; - rj["target"] = reinterpret_cast(&(nc->routes[i].target))->toString(); + rj["target"] = reinterpret_cast(&(nc->routes[i].target))->toString(tmp); if (nc->routes[i].via.ss_family == nc->routes[i].target.ss_family) - rj["via"] = reinterpret_cast(&(nc->routes[i].via))->toIpString(); + rj["via"] = reinterpret_cast(&(nc->routes[i].via))->toIpString(tmp); else rj["via"] = nlohmann::json(); rj["flags"] = (int)nc->routes[i].flags; rj["metric"] = (int)nc->routes[i].metric; @@ -252,12 +252,12 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; } - Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",peer->address); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",peer->address); pj["address"] = tmp; pj["versionMajor"] = peer->versionMajor; pj["versionMinor"] = peer->versionMinor; pj["versionRev"] = peer->versionRev; - Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); pj["version"] = tmp; pj["latency"] = peer->latency; pj["role"] = prole; @@ -265,7 +265,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) nlohmann::json pa = nlohmann::json::array(); for(unsigned int i=0;ipathCount;++i) { nlohmann::json j; - j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(); + j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(tmp); j["lastSend"] = peer->paths[i].lastSend; j["lastReceive"] = peer->paths[i].lastReceive; j["trustedPathId"] = peer->paths[i].trustedPathId; @@ -280,19 +280,19 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) static void _moonToJson(nlohmann::json &mj,const World &world) { - char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id()); + char tmp[4096]; + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id()); mj["id"] = tmp; mj["timestamp"] = world.timestamp(); - mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size()); - mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,(unsigned int)world.updatesMustBeSignedBy().size()); + mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size(),tmp); + mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,(unsigned int)world.updatesMustBeSignedBy().size(),tmp); nlohmann::json ra = nlohmann::json::array(); for(std::vector::const_iterator r(world.roots().begin());r!=world.roots().end();++r) { nlohmann::json rj; - rj["identity"] = r->identity.toString(false); + rj["identity"] = r->identity.toString(false,tmp); nlohmann::json eps = nlohmann::json::array(); for(std::vector::const_iterator a(r->stableEndpoints.begin());a!=r->stableEndpoints.end();++a) - eps.push_back(a->toString()); + eps.push_back(a->toString(tmp)); rj["stableEndpoints"] = eps; ra.push_back(rj); } @@ -613,7 +613,7 @@ public: json &physical = _localConfig["physical"]; if (physical.is_object()) { for(json::iterator phy(physical.begin());phy!=physical.end();++phy) { - InetAddress net(OSUtils::jsonString(phy.key(),"")); + InetAddress net(OSUtils::jsonString(phy.key(),"").c_str()); if (net) { if (phy.value().is_object()) { uint64_t tpid; @@ -674,7 +674,7 @@ public: // Save primary port to a file so CLIs and GUIs can learn it easily char portstr[64]; - Utils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]); + OSUtils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]); OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr)); // Attempt to bind to a secondary port chosen from our ZeroTier address. @@ -712,7 +712,7 @@ public: } if (_ports[2]) { char uniqueName[64]; - Utils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + OSUtils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); _portMapper = new PortMapper(_ports[2],uniqueName); } } @@ -982,7 +982,7 @@ public: n->second.settings = settings; char nlcpath[4096]; - Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); + OSUtils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); FILE *out = fopen(nlcpath,"w"); if (out) { fprintf(out,"allowManaged=%d\n",(int)n->second.settings.allowManaged); @@ -1101,7 +1101,7 @@ public: ZT_NodeStatus status; _node->status(&status); - Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",status.address); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",status.address); res["address"] = tmp; res["publicIdentity"] = status.publicIdentity; res["online"] = (bool)(status.online != 0); @@ -1110,7 +1110,7 @@ public: res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; - Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); res["version"] = tmp; res["clock"] = OSUtils::now(); @@ -1257,7 +1257,7 @@ public: if ((scode != 200)&&(seed != 0)) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id); res["id"] = tmp; res["roots"] = json::array(); res["timestamp"] = 0; @@ -1395,7 +1395,7 @@ public: json &tryAddrs = v.value()["try"]; if (tryAddrs.is_array()) { for(unsigned long i=0;i 0)) { if (phy.value().is_object()) { if (OSUtils::jsonBool(phy.value()["blacklist"],false)) { @@ -1477,7 +1477,7 @@ public: json &amf = settings["allowManagementFrom"]; if (amf.is_array()) { for(unsigned long i=0;i newManagedIps; @@ -1565,7 +1567,7 @@ public: for(std::vector::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) { if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) { if (!n.tap->removeIp(*ip)) - fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString().c_str()); + fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf)); } } #ifdef __SYNOLOGY__ @@ -1575,7 +1577,7 @@ public: for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) { if (!n.tap->addIp(*ip)) - fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString().c_str()); + fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf)); } } #endif @@ -1585,7 +1587,7 @@ public: if (syncRoutes) { char tapdev[64]; #ifdef __WINDOWS__ - Utils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); + OSUtils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); #else Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str()); #endif @@ -1670,7 +1672,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -1851,7 +1853,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -1919,7 +1921,7 @@ public: if (!n.tap) { try { char friendlyName[128]; - Utils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); + OSUtils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); n.tap = new EthernetTap( _homePath.c_str(), @@ -1933,7 +1935,7 @@ public: *nuptr = (void *)&n; char nlcpath[256]; - Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + OSUtils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); std::string nlcbuf; if (OSUtils::readFile(nlcpath,nlcbuf)) { Dictionary<4096> nc; @@ -1954,7 +1956,7 @@ public: while (true) { size_t nextPos = addresses.find(',', pos); std::string address = addresses.substr(pos, (nextPos == std::string::npos ? addresses.size() : nextPos) - pos); - n.settings.allowManagedWhitelist.push_back(InetAddress(address)); + n.settings.allowManagedWhitelist.push_back(InetAddress(address.c_str())); if (nextPos == std::string::npos) break; pos = nextPos + 1; } @@ -2019,7 +2021,7 @@ public: #endif if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) { char nlcpath[256]; - Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + OSUtils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); OSUtils::rm(nlcpath); } } else { @@ -2068,20 +2070,20 @@ public: switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); secure = true; break; case ZT_STATE_OBJECT_PLANET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); secure = true; break; default: @@ -2121,19 +2123,19 @@ public: char p[4096]; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_PLANET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; default: return -1; @@ -2322,7 +2324,7 @@ public: default: scodestr = "Error"; break; } - Utils::ztsnprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", + OSUtils::ztsnprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", scode, scodestr, contentType.c_str(), diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index e0519827..b4bf03ec 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -284,7 +284,7 @@ bool SoftwareUpdater::check(const uint64_t now) if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { _lastCheckTime = now; char tmp[512]; - const unsigned int len = Utils::ztsnprintf(tmp,sizeof(tmp), + const unsigned int len = OSUtils::ztsnprintf(tmp,sizeof(tmp), "%c{\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "\":%d," @@ -321,7 +321,8 @@ bool SoftwareUpdater::check(const uint64_t now) // (1) Check the hash itself to make sure the image is basically okay uint8_t sha512[ZT_SHA512_DIGEST_LEN]; SHA512::hash(sha512,_download.data(),(unsigned int)_download.length()); - if (Utils::hex(sha512,ZT_SHA512_DIGEST_LEN) == OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"")) { + char hexbuf[(ZT_SHA512_DIGEST_LEN * 2) + 2]; + if (OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"") == Utils::hex(sha512,ZT_SHA512_DIGEST_LEN,hexbuf)) { // (2) Check signature by signing authority const std::string sig(OSUtils::jsonBinFromHex(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE])); if (Identity(ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY).verify(_download.data(),(unsigned int)_download.length(),sig.data(),(unsigned int)sig.length())) { -- cgit v1.2.3 From 6fc70f7c16da968a63e69798bbc73ada442cfd2a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 7 Jul 2017 06:50:40 -0700 Subject: More cleanup, Linux build fixes. --- node/C25519.cpp | 290 +++---------------------------------------------- node/Poly1305.cpp | 1 - node/SharedPtr.hpp | 55 +++------- node/Utils.hpp | 22 +++- osdep/Binder.hpp | 4 +- osdep/ManagedRoute.cpp | 9 +- selftest.cpp | 2 +- 7 files changed, 59 insertions(+), 324 deletions(-) (limited to 'selftest.cpp') diff --git a/node/C25519.cpp b/node/C25519.cpp index a78e0466..f35a88c2 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -268,9 +268,7 @@ static void recip(unsigned int out[32],const unsigned int z[32]) /* 2^255 - 21 */ mult(out,t1,z11); } -static inline int crypto_scalarmult(unsigned char *q, - const unsigned char *n, - const unsigned char *p) +static inline int crypto_scalarmult(unsigned char *q,const unsigned char *n,const unsigned char *p) { unsigned int work[96]; unsigned char e[32]; @@ -288,12 +286,24 @@ static inline int crypto_scalarmult(unsigned char *q, return 0; } -static const unsigned char base[32] = {9}; - -static inline int crypto_scalarmult_base(unsigned char *q, - const unsigned char *n) +//static const unsigned char base[32] = {9}; +static inline int crypto_scalarmult_base(unsigned char *q,const unsigned char *n) { - return crypto_scalarmult(q,n,base); + //return crypto_scalarmult(q,n,base); + unsigned int work[96]; + unsigned char e[32]; + unsigned int i; + for (i = 0;i < 32;++i) e[i] = n[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + for (i = 0;i < 32;++i) work[i] = 9; + mainloop(work,e); + recip(work + 32,work + 32); + mult(work + 64,work,work + 32); + freeze(work + 64); + for (i = 0;i < 32;++i) q[i] = work[64 + i]; + return 0; } ////////////////////////////////////////////////////////////////////////////// @@ -413,20 +423,6 @@ static inline void fe25519_pack(unsigned char r[32], const fe25519 *x) r[i] = y.v[i]; } -#if 0 -static int fe25519_iszero(const fe25519 *x) -{ - int i; - int r; - fe25519 t = *x; - fe25519_freeze(&t); - r = equal(t.v[0],0); - for(i=1;i<32;i++) - r &= equal(t.v[i],0); - return r; -} -#endif - static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) { int i; @@ -745,14 +741,6 @@ static inline void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) barrett_reduce(r, t); } -#if 0 -static void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]) -{ - int i; - for(i=0;i<16;i++) r->v[i] = x[i]; -} -#endif - static inline void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) { int i; @@ -761,56 +749,12 @@ static inline void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) barrett_reduce(r, t); } -#if 0 -static void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x) -{ - int i; - for(i=0;i<16;i++) - r->v[i] = x->v[i]; - for(i=0;i<16;i++) - r->v[16+i] = 0; -} -#endif - static inline void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) { int i; for(i=0;i<32;i++) r[i] = x->v[i]; } -#if 0 -static int sc25519_iszero_vartime(const sc25519 *x) -{ - int i; - for(i=0;i<32;i++) - if(x->v[i] != 0) return 0; - return 1; -} -#endif - -#if 0 -static int sc25519_isshort_vartime(const sc25519 *x) -{ - int i; - for(i=31;i>15;i--) - if(x->v[i] != 0) return 0; - return 1; -} -#endif - -#if 0 -static int sc25519_lt_vartime(const sc25519 *x, const sc25519 *y) -{ - int i; - for(i=31;i>=0;i--) - { - if(x->v[i] < y->v[i]) return 1; - if(x->v[i] > y->v[i]) return 0; - } - return 0; -} -#endif - static inline void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) { int i, carry; @@ -824,21 +768,6 @@ static inline void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) reduce_add_sub(r); } -#if 0 -static void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y) -{ - crypto_uint32 b = 0; - crypto_uint32 t; - int i; - for(i=0;i<32;i++) - { - t = x->v[i] - y->v[i] - b; - r->v[i] = t & 255; - b = (t >> 8) & 1; - } -} -#endif - static inline void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) { int i,j,carry; @@ -860,15 +789,6 @@ static inline void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) barrett_reduce(r, t); } -#if 0 -static void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y) -{ - sc25519 t; - sc25519_from_shortsc(&t, y); - sc25519_mul(r, x, &t); -} -#endif - static inline void sc25519_window3(signed char r[85], const sc25519 *s) { char carry; @@ -906,45 +826,6 @@ static inline void sc25519_window3(signed char r[85], const sc25519 *s) r[84] += carry; } -#if 0 -static void sc25519_window5(signed char r[51], const sc25519 *s) -{ - char carry; - int i; - for(i=0;i<6;i++) - { - r[8*i+0] = s->v[5*i+0] & 31; - r[8*i+1] = (s->v[5*i+0] >> 5) & 31; - r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; - r[8*i+2] = (s->v[5*i+1] >> 2) & 31; - r[8*i+3] = (s->v[5*i+1] >> 7) & 31; - r[8*i+3] ^= (s->v[5*i+2] << 1) & 31; - r[8*i+4] = (s->v[5*i+2] >> 4) & 31; - r[8*i+4] ^= (s->v[5*i+3] << 4) & 31; - r[8*i+5] = (s->v[5*i+3] >> 1) & 31; - r[8*i+6] = (s->v[5*i+3] >> 6) & 31; - r[8*i+6] ^= (s->v[5*i+4] << 2) & 31; - r[8*i+7] = (s->v[5*i+4] >> 3) & 31; - } - r[8*i+0] = s->v[5*i+0] & 31; - r[8*i+1] = (s->v[5*i+0] >> 5) & 31; - r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; - r[8*i+2] = (s->v[5*i+1] >> 2) & 31; - - /* Making it signed */ - carry = 0; - for(i=0;i<50;i++) - { - r[i] += carry; - r[i+1] += r[i] >> 5; - r[i] &= 31; - carry = r[i] >> 4; - r[i] -= carry<<5; - } - r[50] += carry; -} -#endif - static inline void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) { int i; @@ -2052,16 +1933,6 @@ static inline void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) r[31] ^= fe25519_getparity(&tx) << 7; } -#if 0 -static int ge25519_isneutral_vartime(const ge25519_p3 *p) -{ - int ret = 1; - if(!fe25519_iszero(&p->x)) ret = 0; - if(!fe25519_iseq_vartime(&p->y, &p->z)) ret = 0; - return ret; -} -#endif - /* computes [s1]p1 + [s2]p2 */ static void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) { @@ -2137,131 +2008,6 @@ static inline void get_hram(unsigned char *hram, const unsigned char *sm, const SHA512::hash(hram,playground,(unsigned int)smlen); } -// This is the original sign and verify code -- the versions in sign() and -// verify() below the fold are slightly modified in terms of how they behave -// in relation to the message, but the algorithms are the same. - -#if 0 -int crypto_sign_keypair( - unsigned char *pk, - unsigned char *sk - ) -{ - sc25519 scsk; - ge25519 gepk; - unsigned char extsk[64]; - int i; - - randombytes(sk, 32); - crypto_hash_sha512(extsk, sk, 32); - extsk[0] &= 248; - extsk[31] &= 127; - extsk[31] |= 64; - - sc25519_from32bytes(&scsk,extsk); - - ge25519_scalarmult_base(&gepk, &scsk); - ge25519_pack(pk, &gepk); - for(i=0;i<32;i++) - sk[32 + i] = pk[i]; - return 0; -} - -static int crypto_sign( - unsigned char *sm,unsigned long long *smlen, - const unsigned char *m,unsigned long long mlen, - const unsigned char *sk - ) -{ - sc25519 sck, scs, scsk; - ge25519 ger; - unsigned char r[32]; - unsigned char s[32]; - unsigned char extsk[64]; - unsigned long long i; - unsigned char hmg[crypto_hash_sha512_BYTES]; - unsigned char hram[crypto_hash_sha512_BYTES]; - - crypto_hash_sha512(extsk, sk, 32); - extsk[0] &= 248; - extsk[31] &= 127; - extsk[31] |= 64; - - *smlen = mlen+64; - for(i=0;i diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index 09010f67..af66545f 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -33,41 +33,19 @@ namespace ZeroTier { /** - * Simple reference counted pointer + * Simple zero-overhead introspective reference counted pointer * * This is an introspective shared pointer. Classes that need to be reference * counted must list this as a 'friend' and must have a private instance of - * AtomicCounter called __refCount. They should also have private destructors, - * since only this class should delete them. - * - * Because this is introspective, it is safe to apply to a naked pointer - * multiple times provided there is always at least one holding SharedPtr. - * - * Once C++11 is ubiquitous, this and a few other things like Thread might get - * torn out for their standard equivalents. + * AtomicCounter called __refCount. */ template class SharedPtr { public: - SharedPtr() - throw() : - _ptr((T *)0) - { - } - - SharedPtr(T *obj) - throw() : - _ptr(obj) - { - ++obj->__refCount; - } - - SharedPtr(const SharedPtr &sp) - throw() : - _ptr(sp._getAndInc()) - { - } + SharedPtr() : _ptr((T *)0) {} + SharedPtr(T *obj) : _ptr(obj) { ++obj->__refCount; } + SharedPtr(const SharedPtr &sp) : _ptr(sp._getAndInc()) {} ~SharedPtr() { @@ -110,21 +88,20 @@ public: * @param with Pointer to swap with */ inline void swap(SharedPtr &with) - throw() { T *tmp = _ptr; _ptr = with._ptr; with._ptr = tmp; } - inline operator bool() const throw() { return (_ptr != (T *)0); } - inline T &operator*() const throw() { return *_ptr; } - inline T *operator->() const throw() { return _ptr; } + inline operator bool() const { return (_ptr != (T *)0); } + inline T &operator*() const { return *_ptr; } + inline T *operator->() const { return _ptr; } /** * @return Raw pointer to held object */ - inline T *ptr() const throw() { return _ptr; } + inline T *ptr() const { return _ptr; } /** * Set this pointer to NULL @@ -162,22 +139,20 @@ public: } } - inline bool operator==(const SharedPtr &sp) const throw() { return (_ptr == sp._ptr); } - inline bool operator!=(const SharedPtr &sp) const throw() { return (_ptr != sp._ptr); } - inline bool operator>(const SharedPtr &sp) const throw() { return (_ptr > sp._ptr); } - inline bool operator<(const SharedPtr &sp) const throw() { return (_ptr < sp._ptr); } - inline bool operator>=(const SharedPtr &sp) const throw() { return (_ptr >= sp._ptr); } - inline bool operator<=(const SharedPtr &sp) const throw() { return (_ptr <= sp._ptr); } + inline bool operator==(const SharedPtr &sp) const { return (_ptr == sp._ptr); } + inline bool operator!=(const SharedPtr &sp) const { return (_ptr != sp._ptr); } + inline bool operator>(const SharedPtr &sp) const { return (_ptr > sp._ptr); } + inline bool operator<(const SharedPtr &sp) const { return (_ptr < sp._ptr); } + inline bool operator>=(const SharedPtr &sp) const { return (_ptr >= sp._ptr); } + inline bool operator<=(const SharedPtr &sp) const { return (_ptr <= sp._ptr); } private: inline T *_getAndInc() const - throw() { if (_ptr) ++_ptr->__refCount; return _ptr; } - T *_ptr; }; diff --git a/node/Utils.hpp b/node/Utils.hpp index a5b5f7b5..1139c9f1 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -76,7 +76,7 @@ public: */ static char *decimal(unsigned long n,char s[24]); - static inline char *hex(uint64_t i,char *const s) + static inline char *hex(uint64_t i,char s[17]) { s[0] = HEXCHARS[(i >> 60) & 0xf]; s[1] = HEXCHARS[(i >> 56) & 0xf]; @@ -98,7 +98,7 @@ public: return s; } - static inline char *hex10(uint64_t i,char *const s) + static inline char *hex10(uint64_t i,char s[11]) { s[0] = HEXCHARS[(i >> 36) & 0xf]; s[1] = HEXCHARS[(i >> 32) & 0xf]; @@ -114,7 +114,21 @@ public: return s; } - static inline char *hex(uint16_t i,char *const s) + static inline char *hex(uint32_t i,char s[9]) + { + s[0] = HEXCHARS[(i >> 28) & 0xf]; + s[1] = HEXCHARS[(i >> 24) & 0xf]; + s[2] = HEXCHARS[(i >> 20) & 0xf]; + s[3] = HEXCHARS[(i >> 16) & 0xf]; + s[4] = HEXCHARS[(i >> 12) & 0xf]; + s[5] = HEXCHARS[(i >> 8) & 0xf]; + s[6] = HEXCHARS[(i >> 4) & 0xf]; + s[7] = HEXCHARS[i & 0xf]; + s[8] = (char)0; + return s; + } + + static inline char *hex(uint16_t i,char s[5]) { s[0] = HEXCHARS[(i >> 12) & 0xf]; s[1] = HEXCHARS[(i >> 8) & 0xf]; @@ -124,7 +138,7 @@ public: return s; } - static inline char *hex(uint8_t i,char *const s) + static inline char *hex(uint8_t i,char s[3]) { s[0] = HEXCHARS[(i >> 4) & 0xf]; s[1] = HEXCHARS[i & 0xf]; diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index f956a67e..126dba28 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -176,7 +176,7 @@ public: const unsigned long pid = (unsigned long)getpid(); // Get all device names - Utils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); + OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); FILE *procf = fopen(fn,"r"); if (procf) { while (fgets(tmp,sizeof(tmp),procf)) { @@ -192,7 +192,7 @@ public: } // Get IPv6 addresses (and any device names we don't already know) - Utils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); + OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); procf = fopen(fn,"r"); if (procf) { while (fgets(tmp,sizeof(tmp),procf)) { diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 3a0b8a7e..5b5bf541 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -286,12 +286,13 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress } else if (p == 0) { ::close(STDOUT_FILENO); ::close(STDERR_FILENO); + char ipbuf[64],ipbuf2[64]; if (via) { - ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString().c_str(),"via",via.toIpString().c_str(),(const char *)0); - ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString().c_str(),"via",via.toIpString().c_str(),(const char *)0); + ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"via",via.toIpString(ipbuf2),(const char *)0); + ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"via",via.toIpString(ipbuf2),(const char *)0); } else if ((localInterface)&&(localInterface[0])) { - ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString().c_str(),"dev",localInterface,(const char *)0); - ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString().c_str(),"dev",localInterface,(const char *)0); + ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"dev",localInterface,(const char *)0); + ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"dev",localInterface,(const char *)0); } ::_exit(-1); } diff --git a/selftest.cpp b/selftest.cpp index e6705700..882422bc 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -844,7 +844,7 @@ static int testOther() memset(key, 0, sizeof(key)); memset(value, 0, sizeof(value)); for(unsigned int q=0;q<32;++q) { - OSUtils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); + Utils::hex((uint32_t)((rand() % 1000) + (q * 1000)),key[q]); int r = rand() % 128; for(int x=0;x Date: Thu, 13 Jul 2017 15:08:57 -0700 Subject: More tracing stuff. --- include/ZeroTierOne.h | 59 ++++++++++++++++++++++ node/Identity.cpp | 32 ++++++++---- node/Node.cpp | 13 ++--- node/Trace.cpp | 129 +++++++++++++------------------------------------ node/Trace.hpp | 4 ++ node/Utils.hpp | 18 +++---- osdep/Binder.hpp | 89 +++++++++++++++++++++++----------- selftest.cpp | 40 ++++++--------- service/OneService.cpp | 11 +++-- 9 files changed, 216 insertions(+), 179 deletions(-) (limited to 'selftest.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index f7681768..e4c39fbc 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -257,6 +257,65 @@ extern "C" { */ #define ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN 0x0000000000000001ULL +// Fields in remote trace dictionaries +#define ZT_REMOTE_TRACE_FIELD__EVENT "E" +#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "pid" +#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "pv" +#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "ptpid" +#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_APPROVED "ptpok" +#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "phops" +#define ZT_REMOTE_TRACE_FIELD__OLD_REMOTE_PHYADDR "oldrphy" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "rzt" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "rphy" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "lzt" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "lphy" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "ls" +#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "ipsc" +#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "nwid" +#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "seth" +#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "deth" +#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "et" +#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlan" +#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "fl" +#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "fd" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "crtype" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "crid" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "crts" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "crinfo" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "criss" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET "crrevt" +#define ZT_REMOTE_TRACE_FIELD__REASON "reason" + +// Event types in remote traces +#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE 0x1000 +#define ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT 0x1001 +#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH 0x1002 +#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH 0x1003 +#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED 0x1004 +#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE 0x1005 +#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID 0x1006 +#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO 0x1006 +#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED 0x2000 +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED 0x2001 +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED 0x2002 +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED 0x2003 +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED 0x2004 + +// Event types in remote traces in hex string form +#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000" +#define ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT_S "1001" +#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1002" +#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1003" +#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1004" +#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1005" +#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1006" +#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006" +#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S "2000" +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S "2001" +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S "2002" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004" + /****************************************************************************/ /* Structures and other types */ /****************************************************************************/ diff --git a/node/Identity.cpp b/node/Identity.cpp index dba27d1c..a972d60d 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -157,44 +157,58 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_ bool Identity::fromString(const char *str) { - if (!str) + if (!str) { + _address.zero(); return false; - - char *saveptr = (char *)0; + } char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH]; - if (!Utils::scopy(tmp,sizeof(tmp),str)) + if (!Utils::scopy(tmp,sizeof(tmp),str)) { + _address.zero(); return false; + } delete _privateKey; _privateKey = (C25519::Private *)0; int fno = 0; + char *saveptr = (char *)0; for(char *f=Utils::stok(tmp,":",&saveptr);(f);f=Utils::stok((char *)0,":",&saveptr)) { switch(fno++) { case 0: _address = Address(Utils::hexStrToU64(f)); - if (_address.isReserved()) + if (_address.isReserved()) { + _address.zero(); return false; + } break; case 1: - if ((f[0] != '0')||(f[1])) + if ((f[0] != '0')||(f[1])) { + _address.zero(); return false; + } break; case 2: - if (Utils::unhex(f,_publicKey.data,(unsigned int)_publicKey.size()) != _publicKey.size()) + if (Utils::unhex(f,_publicKey.data,(unsigned int)_publicKey.size()) != _publicKey.size()) { + _address.zero(); return false; + } break; case 3: _privateKey = new C25519::Private(); - if (Utils::unhex(f,_privateKey->data,(unsigned int)_privateKey->size()) != _privateKey->size()) + if (Utils::unhex(f,_privateKey->data,(unsigned int)_privateKey->size()) != _privateKey->size()) { + _address.zero(); return false; + } break; default: + _address.zero(); return false; } } - if (fno < 3) + if (fno < 3) { + _address.zero(); return false; + } return true; } diff --git a/node/Node.cpp b/node/Node.cpp index 073af4bd..ff3acfc2 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -78,7 +78,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0; - char tmp[1024]; + char tmp[2048]; int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; @@ -92,21 +92,18 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 if (n <= 0) { RR->identity.generate(); - idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; RR->identity.toString(false,RR->publicIdentityStr); RR->identity.toString(true,RR->secretIdentityStr); + idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr)); stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } else { idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); - if (n > 0) { - tmp[n] = (char)0; - if (RR->publicIdentityStr != tmp) - n = -1; + if ((n > 0)&&(n < sizeof(RR->publicIdentityStr))&&(n < sizeof(tmp))) { + if (memcmp(tmp,RR->publicIdentityStr,n)) + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } - if (n <= 0) - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } try { diff --git a/node/Trace.cpp b/node/Trace.cpp index dc5ecf19..21d06228 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -39,101 +39,6 @@ namespace ZeroTier { -// Defining ZT_TRACE causes debug tracing messages to be dumped to stderr -#ifdef ZT_TRACE - -static const char *packetVerbString(Packet::Verb v) -{ - switch(v) { - case Packet::VERB_NOP: return "NOP"; - case Packet::VERB_HELLO: return "HELLO"; - case Packet::VERB_ERROR: return "ERROR"; - case Packet::VERB_OK: return "OK"; - case Packet::VERB_WHOIS: return "WHOIS"; - case Packet::VERB_RENDEZVOUS: return "RENDEZVOUS"; - case Packet::VERB_FRAME: return "FRAME"; - case Packet::VERB_EXT_FRAME: return "EXT_FRAME"; - case Packet::VERB_ECHO: return "ECHO"; - case Packet::VERB_MULTICAST_LIKE: return "MULTICAST_LIKE"; - case Packet::VERB_NETWORK_CREDENTIALS: return "NETWORK_CREDENTIALS"; - case Packet::VERB_NETWORK_CONFIG_REQUEST: return "NETWORK_CONFIG_REQUEST"; - case Packet::VERB_NETWORK_CONFIG: return "NETWORK_CONFIG"; - case Packet::VERB_MULTICAST_GATHER: return "MULTICAST_GATHER"; - case Packet::VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; - case Packet::VERB_PUSH_DIRECT_PATHS: return "PUSH_DIRECT_PATHS"; - case Packet::VERB_USER_MESSAGE: return "USER_MESSAGE"; - case Packet::VERB_REMOTE_TRACE: return "REMOTE_TRACE"; - } - return "(unknown)"; -} - -static const char *packetErrorString(Packet::ErrorCode e) -{ - switch(e) { - case Packet::ERROR_NONE: return "NONE"; - case Packet::ERROR_INVALID_REQUEST: return "INVALID_REQUEST"; - case Packet::ERROR_BAD_PROTOCOL_VERSION: return "BAD_PROTOCOL_VERSION"; - case Packet::ERROR_OBJ_NOT_FOUND: return "OBJECT_NOT_FOUND"; - case Packet::ERROR_IDENTITY_COLLISION: return "IDENTITY_COLLISION"; - case Packet::ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION"; - case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: return "NEED_MEMBERSHIP_CERTIFICATE"; - case Packet::ERROR_NETWORK_ACCESS_DENIED_: return "NETWORK_ACCESS_DENIED"; - case Packet::ERROR_UNWANTED_MULTICAST: return "UNWANTED_MULTICAST"; - } - return "(unknown)"; -} - -#define TRprintf(f,...) { fprintf(stderr,(f),__VA_ARGS__); fflush(stderr); } - -#else - -#define TRprintf(f,...) - -#endif // ZT_TRACE - -#define ZT_REMOTE_TRACE_FIELD__EVENT "E" -#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "pid" -#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "pv" -#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "ptpid" -#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_APPROVED "ptpok" -#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "phops" -#define ZT_REMOTE_TRACE_FIELD__OLD_REMOTE_PHYADDR "oldrphy" -#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "rzt" -#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "rphy" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "lzt" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "lphy" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "ls" -#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "ipsc" -#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "nwid" -#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "seth" -#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "deth" -#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "et" -#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlan" -#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "fl" -#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "fd" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "credtype" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "credid" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "credts" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "credinfo" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "crediss" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET "credRt" -#define ZT_REMOTE_TRACE_FIELD__REASON "reason" - -#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000" -#define ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT_S "1001" -#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1002" -#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1003" -#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1004" -#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1005" -#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1006" -#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006" - -#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S "2000" -#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S "2001" -#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S "2002" -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003" -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004" - void Trace::resettingPathsInScope(void *const tPtr,const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope) { char tmp[128]; @@ -328,6 +233,7 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfMembership &c d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason) @@ -341,6 +247,7 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c, d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const CertificateOfRepresentation &c,const char *reason) @@ -352,6 +259,7 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfRepresentatio d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const Capability &c,const char *reason) @@ -365,6 +273,7 @@ void Trace::credentialRejected(void *const tPtr,const Capability &c,const char * d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason) @@ -379,6 +288,7 @@ void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *reason) @@ -391,6 +301,7 @@ void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char * d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const CertificateOfMembership &c) @@ -402,6 +313,7 @@ void Trace::credentialAccepted(void *const tPtr,const CertificateOfMembership &c d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const CertificateOfOwnership &c) @@ -413,6 +325,7 @@ void Trace::credentialAccepted(void *const tPtr,const CertificateOfOwnership &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const CertificateOfRepresentation &c) @@ -422,6 +335,7 @@ void Trace::credentialAccepted(void *const tPtr,const CertificateOfRepresentatio d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const Capability &c) @@ -433,6 +347,7 @@ void Trace::credentialAccepted(void *const tPtr,const Capability &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const Tag &c) @@ -445,6 +360,7 @@ void Trace::credentialAccepted(void *const tPtr,const Tag &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const Revocation &c) @@ -455,10 +371,33 @@ void Trace::credentialAccepted(void *const tPtr,const Revocation &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target()); + _send(tPtr,d,0); } void Trace::_send(void *const tPtr,const Dictionary &d) { +#ifdef ZT_TRACE + unsigned int i = 0; + while (i < (unsigned int)(sizeof(_traceMsgBuf) - 1)) { + const char c = d.data()[i]; + if (c == 0) { + break; + } else if (c == '\n') { + _traceMsgBuf[i++] = ' '; + } else if ((c >= 32)&&(c <= 126)) { + _traceMsgBuf[i++] = c; + } else { + if ((i + 3) < (unsigned int)(sizeof(_traceMsgBuf) - 1)) { + _traceMsgBuf[i++] = '\\'; + Utils::hex((uint8_t)c,_traceMsgBuf + i); + } + } + } + _traceMsgBuf[i] = (char)0; + //printf("%s\n",_traceMsgBuf); + RR->node->postEvent(tPtr,ZT_EVENT_TRACE,_traceMsgBuf); +#endif + const Address rtt(RR->node->remoteTraceTarget()); if (rtt) { Packet outp(rtt,RR->identity.address(),Packet::VERB_REMOTE_TRACE); diff --git a/node/Trace.hpp b/node/Trace.hpp index eefd5359..dae67e28 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -155,6 +155,10 @@ private: void _send(void *const tPtr,const Dictionary &d); void _send(void *const tPtr,const Dictionary &d,const uint64_t networkId); void _send(void *const tPtr,const Dictionary &d,const SharedPtr &network); + +#ifdef ZT_TRACE + char _traceMsgBuf[4096]; +#endif }; } // namespace ZeroTier diff --git a/node/Utils.hpp b/node/Utils.hpp index 1139c9f1..8f61d396 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -150,8 +150,8 @@ public: { char *save = s; for(unsigned int i=0;i(d)[i]; - *(s++) = HEXCHARS[(b >> 4) & 0xf]; + const unsigned int b = reinterpret_cast(d)[i]; + *(s++) = HEXCHARS[b >> 4]; *(s++) = HEXCHARS[b & 0xf]; } *s = (char)0; @@ -162,18 +162,18 @@ public: { unsigned int l = 0; while (l < buflen) { - uint8_t hc = (uint8_t)*(h++); + uint8_t hc = *(reinterpret_cast(h++)); if (!hc) break; uint8_t c = 0; - if ((hc >= 48)&&(hc <= 57)) + if ((hc >= 48)&&(hc <= 57)) // 0..9 c = hc - 48; - else if ((hc >= 97)&&(hc <= 102)) + else if ((hc >= 97)&&(hc <= 102)) // a..f c = hc - 87; - else if ((hc >= 65)&&(hc <= 70)) + else if ((hc >= 65)&&(hc <= 70)) // A..F c = hc - 55; - hc = (uint8_t)*(h++); + hc = *(reinterpret_cast(h++)); if (!hc) break; c <<= 4; @@ -195,7 +195,7 @@ public: const char *hend = h + hlen; while (l < buflen) { if (h == hend) break; - uint8_t hc = (uint8_t)*(h++); + uint8_t hc = *(reinterpret_cast(h++)); if (!hc) break; uint8_t c = 0; @@ -207,7 +207,7 @@ public: c = hc - 55; if (h == hend) break; - hc = (uint8_t)*(h++); + hc = *(reinterpret_cast(h++)); if (!hc) break; c <<= 4; diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 126dba28..17a0fbf6 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -58,6 +58,7 @@ #include #include #include +#include #include "../node/NonCopyable.hpp" #include "../node/InetAddress.hpp" @@ -70,6 +71,9 @@ // Period between refreshes of bindings #define ZT_BINDER_REFRESH_PERIOD 30000 +// Max number of bindings +#define ZT_BINDER_MAX_BINDINGS 128 + namespace ZeroTier { /** @@ -95,7 +99,7 @@ private: }; public: - Binder() {} + Binder() : _bindingCount(0) {} /** * Close all bound ports, should be called on shutdown @@ -106,10 +110,11 @@ public: void closeAll(Phy &phy) { Mutex::Lock _l(_lock); - for(std::vector<_Binding>::iterator b(_bindings.begin());b!=_bindings.end();++b) { - phy.close(b->udpSock,false); - phy.close(b->tcpListenSock,false); + for(unsigned int b=0,c=_bindingCount;b newBindings; + const unsigned int oldBindingCount = _bindingCount; + _bindingCount = 0; // Save bindings that are still valid, close those that are not - for(std::vector<_Binding>::iterator b(_bindings.begin());b!=_bindings.end();++b) { - if (localIfAddrs.find(b->address) != localIfAddrs.end()) { - newBindings.push_back(*b); + for(unsigned int b=0;budpSock,false); - phy.close(b->tcpListenSock,false); + PhySocket *const udps = _bindings[b].udpSock; + PhySocket *const tcps = _bindings[b].tcpListenSock; + _bindings[b].udpSock = (PhySocket *)0; + _bindings[b].tcpListenSock = (PhySocket *)0; + phy.close(udps,false); + phy.close(tcps,false); } } // Create new bindings for those not already bound for(std::map::const_iterator ii(localIfAddrs.begin());ii!=localIfAddrs.end();++ii) { - typename std::vector<_Binding>::const_iterator bi(newBindings.begin()); - while (bi != newBindings.end()) { - if (bi->address == ii->first) + unsigned int bi = 0; + while (bi != _bindingCount) { + if (_bindings[bi].address == ii->first) break; ++bi; } - if (bi == newBindings.end()) { + if (bi == _bindingCount) { udps = phy.udpBind(reinterpret_cast(&(ii->first)),(void *)0,ZT_UDP_DESIRED_BUF_SIZE); tcps = phy.tcpListen(reinterpret_cast(&(ii->first)),(void *)0); if ((udps)&&(tcps)) { @@ -358,15 +370,18 @@ public: setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp)); } #endif // __LINUX__ - newBindings.push_back(_Binding()); - newBindings.back().udpSock = udps; - newBindings.back().tcpListenSock = tcps; - newBindings.back().address = ii->first; + if (_bindingCount < ZT_BINDER_MAX_BINDINGS) { + _bindings[_bindingCount].udpSock = udps; + _bindings[_bindingCount].tcpListenSock = tcps; + _bindings[_bindingCount].address = ii->first; + ++_bindingCount; + } + } else { + phy.close(udps,false); + phy.close(tcps,false); } } } - - _bindings.swap(newBindings); } /** @@ -376,8 +391,8 @@ public: { std::vector aa; Mutex::Lock _l(_lock); - for(std::vector<_Binding>::const_iterator b(_bindings.begin());b!=_bindings.end();++b) - aa.push_back(b->address); + for(unsigned int b=0,c=_bindingCount;b::const_iterator b(_bindings.begin());b!=_bindings.end();++b) { - if (ttl) phy.setIp4UdpTtl(b->udpSock,ttl); - if (phy.udpSend(b->udpSock,(const struct sockaddr *)addr,data,len)) r = true; - if (ttl) phy.setIp4UdpTtl(b->udpSock,255); + for(unsigned int b=0,c=_bindingCount;b::const_iterator b(_bindings.begin());b!=_bindings.end();++b) { - if (b->address == addr) + for(unsigned int b=0;b<_bindingCount;++b) { + if (_bindings[b].address == addr) return true; } return false; } + /** + * Quickly check that a UDP socket is valid + * + * @param udpSock UDP socket to check + * @return True if socket is currently bound/allocated + */ + inline bool isUdpSocketValid(PhySocket *const udpSock) + { + for(unsigned int b=0,c=_bindingCount;b _bindings; + _Binding _bindings[ZT_BINDER_MAX_BINDINGS]; + std::atomic _bindingCount; Mutex _lock; }; diff --git a/selftest.cpp b/selftest.cpp index 882422bc..f4de36a9 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -633,33 +633,25 @@ static int testPacket() return 0; } -static void _testExcept(int &depth) -{ - if (depth >= 16) { - throw std::runtime_error("LOL!"); - } else { - ++depth; - _testExcept(depth); - } -} - static int testOther() { char buf[1024]; - - std::cout << "[other] Testing C++ exceptions... "; std::cout.flush(); - int depth = 0; - try { - _testExcept(depth); - } catch (std::runtime_error &e) { - if (depth == 16) { - std::cout << "OK" << std::endl; - } else { - std::cout << "ERROR (depth not 16)" << std::endl; - return -1; - } - } catch ( ... ) { - std::cout << "ERROR (exception not std::runtime_error)" << std::endl; + char buf2[4096]; + char buf3[1024]; + + std::cout << "[other] Testing hex/unhex... "; std::cout.flush(); + Utils::getSecureRandom(buf,(unsigned int)sizeof(buf)); + Utils::hex(buf,(unsigned int)sizeof(buf),buf2); + Utils::unhex(buf2,buf3,(unsigned int)sizeof(buf3)); + if (memcmp(buf,buf3,sizeof(buf)) == 0) { + std::cout << "PASS" << std::endl; + } else { + std::cout << "FAIL!" << std::endl; + buf2[78] = 0; + std::cout << buf2 << std::endl; + Utils::hex(buf3,(unsigned int)sizeof(buf3),buf2); + buf2[78] = 0; + std::cout << buf2 << std::endl; return -1; } diff --git a/service/OneService.cpp b/service/OneService.cpp index 352985c8..1b07eb79 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -658,16 +658,18 @@ public: return _termReason; } - // Bind local control socket + // Bind TCP control socket to 127.0.0.1 and ::1 as well for loopback TCP control socket queries { struct sockaddr_in lo4; memset(&lo4,0,sizeof(lo4)); lo4.sin_family = AF_INET; + lo4.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); lo4.sin_port = Utils::hton((uint16_t)_ports[0]); _localControlSocket4 = _phy.tcpListen((const struct sockaddr *)&lo4); struct sockaddr_in6 lo6; memset(&lo6,0,sizeof(lo6)); lo6.sin6_family = AF_INET6; + lo6.sin6_addr.s6_addr[15] = 1; lo6.sin6_port = lo4.sin_port; _localControlSocket6 = _phy.tcpListen((const struct sockaddr *)&lo6); } @@ -1661,12 +1663,11 @@ public: { if ((len >= 16)&&(reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) _lastDirectReceiveFromGlobal = OSUtils::now(); - const ZT_ResultCode rc = _node->processWirePacket( (void *)0, OSUtils::now(), - (int64_t)((uintptr_t)sock), - (const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big + reinterpret_cast(sock), + reinterpret_cast(from), // Phy<> uses sockaddr_storage, so it'll always be that big data, len, &_nextBackgroundTaskDeadline); @@ -2200,7 +2201,7 @@ public: // proxy fallback, which is slow. #endif // ZT_TCP_FALLBACK_RELAY - if ((localSocket != 0)&&(localSocket != -1)) { + if ((localSocket != -1)&&(localSocket != 0)&&(_binder.isUdpSocketValid((PhySocket *)((uintptr_t)localSocket)))) { if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),ttl); const bool r = _phy.udpSend((PhySocket *)((uintptr_t)localSocket),(const struct sockaddr *)addr,data,len); if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),255); -- cgit v1.2.3 From 23e5c7b38df504868089607491f8114b473f175f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 29 Nov 2017 04:47:10 -0800 Subject: Fix self-test compile. --- selftest.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'selftest.cpp') diff --git a/selftest.cpp b/selftest.cpp index f4de36a9..c3b8ce2f 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -60,8 +60,6 @@ #include "osdep/PortMapper.hpp" #include "osdep/Thread.hpp" -#include "controller/JSONDB.hpp" - #ifdef ZT_USE_X64_ASM_SALSA2012 #include "ext/x64-salsa2012-asm/salsa2012.h" #endif -- cgit v1.2.3 From 060870462606f82d3a9b0fe6aca87f8a5de8705e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 15 Dec 2017 11:03:20 -0800 Subject: Some micro-optimizations, including a memcpy that is faster than Linux for most distro/compiler versions. --- controller/EmbeddedNetworkController.cpp | 8 +++--- make-linux.mk | 6 ++--- node/Buffer.hpp | 8 +++--- node/Capability.hpp | 10 ++++---- node/CertificateOfMembership.hpp | 6 ++--- node/CertificateOfOwnership.hpp | 8 +++--- node/Dictionary.hpp | 2 +- node/Identity.hpp | 4 +-- node/InetAddress.cpp | 16 ++++++------ node/InetAddress.hpp | 34 ++++++++++++------------ node/Network.cpp | 6 ++--- node/NetworkConfig.hpp | 4 +-- node/Node.cpp | 4 +-- node/OutboundMulticast.cpp | 2 +- node/Packet.cpp | 28 ++++++++++---------- node/Path.hpp | 4 +-- node/Revocation.hpp | 2 +- node/Tag.hpp | 2 +- node/Utils.hpp | 38 +++++++++++++++++++++++++++ node/World.hpp | 4 +-- selftest.cpp | 44 ++++++++++++++++++++++++++++++++ service/OneService.cpp | 4 +-- 22 files changed, 163 insertions(+), 81 deletions(-) (limited to 'selftest.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index d8ac1878..2032f097 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -333,14 +333,14 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) } else if (t == "MATCH_IPV6_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); - memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IPV6_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); - memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; @@ -1520,8 +1520,8 @@ void EmbeddedNetworkController::_request( InetAddress ipRangeEnd(OSUtils::jsonString(pool["ipRangeEnd"],"").c_str()); if ( (ipRangeStart.ss_family == AF_INET6) && (ipRangeEnd.ss_family == AF_INET6) ) { uint64_t s[2],e[2],x[2],xx[2]; - memcpy(s,ipRangeStart.rawIpData(),16); - memcpy(e,ipRangeEnd.rawIpData(),16); + ZT_FAST_MEMCPY(s,ipRangeStart.rawIpData(),16); + ZT_FAST_MEMCPY(e,ipRangeEnd.rawIpData(),16); s[0] = Utils::ntoh(s[0]); s[1] = Utils::ntoh(s[1]); e[0] = Utils::ntoh(e[0]); diff --git a/make-linux.mk b/make-linux.mk index 5b623247..99268990 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -66,9 +66,9 @@ ifeq ($(ZT_DEBUG),1) node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -g -pthread $(INCLUDES) $(DEFS) else override DEFS+=-D_FORTIFY_SOURCE=2 - CFLAGS?=-Os -fstack-protector + CFLAGS?=-O3 -fstack-protector override CFLAGS+=-Wall -Wno-deprecated -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) - CXXFLAGS?=-Os -fstack-protector + CXXFLAGS?=-O3 -fstack-protector override CXXFLAGS+=-Wall -Wno-deprecated -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS) override LDFLAGS+=-pie -Wl,-z,relro,-z,now STRIP?=strip @@ -241,7 +241,7 @@ zerotier-idtool: one zerotier-cli: one libzerotiercore.a: FORCE - make CFLAGS="-Os -fstack-protector -fPIC" CXXFLAGS="-Os -std=c++11 -fstack-protector -fPIC" $(CORE_OBJS) + make CFLAGS="-O3 -fstack-protector -fPIC" CXXFLAGS="-O3 -std=c++11 -fstack-protector -fPIC" $(CORE_OBJS) ar rcs libzerotiercore.a $(CORE_OBJS) ranlib libzerotiercore.a diff --git a/node/Buffer.hpp b/node/Buffer.hpp index 7b91e72f..f84b3774 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -116,9 +116,9 @@ public: if (unlikely(b._l > C)) throw ZT_EXCEPTION_OUT_OF_BOUNDS; if (C2 == C) { - memcpy(this,&b,sizeof(Buffer)); + ZT_FAST_MEMCPY(this,&b,sizeof(Buffer)); } else { - memcpy(_b,b._b,_l = b._l); + ZT_FAST_MEMCPY(_b,b._b,_l = b._l); } return *this; } @@ -127,7 +127,7 @@ public: { if (unlikely(l > C)) throw ZT_EXCEPTION_OUT_OF_BOUNDS; - memcpy(_b,b,l); + ZT_FAST_MEMCPY(_b,b,l); _l = l; } @@ -281,7 +281,7 @@ public: { if (unlikely((_l + l) > C)) throw ZT_EXCEPTION_OUT_OF_BOUNDS; - memcpy(_b + _l,b,l); + ZT_FAST_MEMCPY(_b + _l,b,l); _l += l; } diff --git a/node/Capability.hpp b/node/Capability.hpp index 407884ad..bec1f47f 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -94,7 +94,7 @@ public: _maxCustodyChainLength = (mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1; _ruleCount = (ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES; if (_ruleCount) - memcpy(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount); + ZT_FAST_MEMCPY(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount); } /** @@ -320,16 +320,16 @@ public: break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: - memcpy(rules[ruleCount].v.mac,b.field(p,6),6); + ZT_FAST_MEMCPY(rules[ruleCount].v.mac,b.field(p,6),6); break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - memcpy(&(rules[ruleCount].v.ipv4.ip),b.field(p,4),4); + ZT_FAST_MEMCPY(&(rules[ruleCount].v.ipv4.ip),b.field(p,4),4); rules[ruleCount].v.ipv4.mask = (uint8_t)b[p + 4]; break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - memcpy(rules[ruleCount].v.ipv6.ip,b.field(p,16),16); + ZT_FAST_MEMCPY(rules[ruleCount].v.ipv6.ip,b.field(p,16),16); rules[ruleCount].v.ipv6.mask = (uint8_t)b[p + 16]; break; case ZT_NETWORK_RULE_MATCH_IP_TOS: @@ -452,7 +452,7 @@ public: if (b.template at(p) != ZT_C25519_SIGNATURE_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; p += 2; - memcpy(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else { p += 2 + b.template at(p); } diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 0105fade..2eff1083 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -119,7 +119,7 @@ public: CertificateOfMembership(const CertificateOfMembership &c) { - memcpy(this,&c,sizeof(CertificateOfMembership)); + ZT_FAST_MEMCPY(this,&c,sizeof(CertificateOfMembership)); } /** @@ -147,7 +147,7 @@ public: inline CertificateOfMembership &operator=(const CertificateOfMembership &c) { - memcpy(this,&c,sizeof(CertificateOfMembership)); + ZT_FAST_MEMCPY(this,&c,sizeof(CertificateOfMembership)); return *this; } @@ -329,7 +329,7 @@ public: p += ZT_ADDRESS_LENGTH; if (_signedBy) { - memcpy(_signature.data,b.field(p,(unsigned int)_signature.size()),_signature.size()); + ZT_FAST_MEMCPY(_signature.data,b.field(p,(unsigned int)_signature.size()),_signature.size()); p += (unsigned int)_signature.size(); } diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index 431bcc03..e397fd63 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -115,11 +115,11 @@ public: if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; if (ip.ss_family == AF_INET) { _thingTypes[_thingCount] = THING_IPV4_ADDRESS; - memcpy(_thingValues[_thingCount],&(reinterpret_cast(&ip)->sin_addr.s_addr),4); + ZT_FAST_MEMCPY(_thingValues[_thingCount],&(reinterpret_cast(&ip)->sin_addr.s_addr),4); ++_thingCount; } else if (ip.ss_family == AF_INET6) { _thingTypes[_thingCount] = THING_IPV6_ADDRESS; - memcpy(_thingValues[_thingCount],reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(_thingValues[_thingCount],reinterpret_cast(&ip)->sin6_addr.s6_addr,16); ++_thingCount; } } @@ -198,7 +198,7 @@ public: for(unsigned int i=0,j=_thingCount;i(p) != ZT_C25519_SIGNATURE_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; p += 2; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else { p += 2 + b.template at(p); } diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 061dcac1..a1b0f9cb 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -81,7 +81,7 @@ public: if (s) { if (len > (C-1)) len = C-1; - memcpy(_d,s,len); + ZT_FAST_MEMCPY(_d,s,len); _d[len] = (char)0; } else { _d[0] = (char)0; diff --git a/node/Identity.hpp b/node/Identity.hpp index 3d4d9385..ab2886ad 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -249,7 +249,7 @@ public: if (b[p++] != 0) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; - memcpy(_publicKey.data,b.field(p,(unsigned int)_publicKey.size()),(unsigned int)_publicKey.size()); + ZT_FAST_MEMCPY(_publicKey.data,b.field(p,(unsigned int)_publicKey.size()),(unsigned int)_publicKey.size()); p += (unsigned int)_publicKey.size(); unsigned int privateKeyLength = (unsigned int)b[p++]; @@ -257,7 +257,7 @@ public: if (privateKeyLength != ZT_C25519_PRIVATE_KEY_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; _privateKey = new C25519::Private(); - memcpy(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN); + ZT_FAST_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/InetAddress.cpp b/node/InetAddress.cpp index d3efc089..ee32ce72 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -115,13 +115,13 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) memset(this,0,sizeof(InetAddress)); if (ipLen == 4) { uint32_t ipb[1]; - memcpy(ipb,ipBytes,4); + ZT_FAST_MEMCPY(ipb,ipBytes,4); ss_family = AF_INET; reinterpret_cast(this)->sin_addr.s_addr = ipb[0]; reinterpret_cast(this)->sin_port = Utils::hton((uint16_t)port); } else if (ipLen == 16) { ss_family = AF_INET6; - memcpy(reinterpret_cast(this)->sin6_addr.s6_addr,ipBytes,16); + ZT_FAST_MEMCPY(reinterpret_cast(this)->sin6_addr.s6_addr,ipBytes,16); reinterpret_cast(this)->sin6_port = Utils::hton((uint16_t)port); } } @@ -154,7 +154,7 @@ char *InetAddress::toIpString(char buf[64]) const case AF_INET6: { uint16_t a[8]; - memcpy(a,reinterpret_cast(this)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(a,reinterpret_cast(this)->sin6_addr.s6_addr,16); char *p = buf; for(int i=0;i<8;++i) { Utils::hex(Utils::ntoh(a[i]),p); @@ -199,7 +199,7 @@ bool InetAddress::fromString(const char *ipSlashPort) struct sockaddr_in6 *const in6 = reinterpret_cast(this); in6->sin6_family = AF_INET6; - memcpy(in6->sin6_addr.s6_addr,a,16); + ZT_FAST_MEMCPY(in6->sin6_addr.s6_addr,a,16); in6->sin6_port = Utils::hton((uint16_t)port); return true; @@ -212,7 +212,7 @@ bool InetAddress::fromString(const char *ipSlashPort) struct sockaddr_in *const in = reinterpret_cast(this); in->sin_family = AF_INET; - memcpy(&(in->sin_addr.s_addr),a,4); + ZT_FAST_MEMCPY(&(in->sin_addr.s_addr),a,4); in->sin_port = Utils::hton((uint16_t)port); return true; @@ -238,7 +238,7 @@ InetAddress InetAddress::netmask() const nm[0] = 0; nm[1] = 0; } - memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); + ZT_FAST_MEMCPY(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); } break; } return r; @@ -264,10 +264,10 @@ InetAddress InetAddress::network() const case AF_INET6: { uint64_t nm[2]; const unsigned int bits = netmaskBits(); - memcpy(nm,reinterpret_cast(&r)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(nm,reinterpret_cast(&r)->sin6_addr.s6_addr,16); nm[0] &= Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); nm[1] &= Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); - memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); + ZT_FAST_MEMCPY(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); } break; } return r; diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 76810b93..fd430099 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -91,8 +91,8 @@ struct InetAddress : public sockaddr_storage }; InetAddress() { memset(this,0,sizeof(InetAddress)); } - InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); } - InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); } + InetAddress(const InetAddress &a) { ZT_FAST_MEMCPY(this,&a,sizeof(InetAddress)); } + InetAddress(const InetAddress *a) { ZT_FAST_MEMCPY(this,a,sizeof(InetAddress)); } InetAddress(const struct sockaddr_storage &ss) { *this = ss; } InetAddress(const struct sockaddr_storage *ss) { *this = ss; } InetAddress(const struct sockaddr &sa) { *this = sa; } @@ -108,28 +108,28 @@ struct InetAddress : public sockaddr_storage inline InetAddress &operator=(const InetAddress &a) { if (&a != this) - memcpy(this,&a,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,&a,sizeof(InetAddress)); return *this; } inline InetAddress &operator=(const InetAddress *a) { if (a != this) - memcpy(this,a,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,a,sizeof(InetAddress)); return *this; } inline InetAddress &operator=(const struct sockaddr_storage &ss) { if (reinterpret_cast(&ss) != this) - memcpy(this,&ss,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,&ss,sizeof(InetAddress)); return *this; } inline InetAddress &operator=(const struct sockaddr_storage *ss) { if (reinterpret_cast(ss) != this) - memcpy(this,ss,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,ss,sizeof(InetAddress)); return *this; } @@ -137,7 +137,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,&sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in)); } return *this; } @@ -146,7 +146,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in)); } return *this; } @@ -155,7 +155,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,&sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in6)); } return *this; } @@ -164,7 +164,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in6)); } return *this; } @@ -175,10 +175,10 @@ struct InetAddress : public sockaddr_storage memset(this,0,sizeof(InetAddress)); switch(sa.sa_family) { case AF_INET: - memcpy(this,&sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in)); break; case AF_INET6: - memcpy(this,&sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in6)); break; } } @@ -191,10 +191,10 @@ struct InetAddress : public sockaddr_storage memset(this,0,sizeof(InetAddress)); switch(sa->sa_family) { case AF_INET: - memcpy(this,sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in)); break; case AF_INET6: - memcpy(this,sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in6)); break; } } @@ -388,7 +388,7 @@ struct InetAddress : public sockaddr_storage break; case AF_INET6: r.ss_family = AF_INET6; - memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,reinterpret_cast(this)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(reinterpret_cast(&r)->sin6_addr.s6_addr,reinterpret_cast(this)->sin6_addr.s6_addr,16); break; } return r; @@ -537,12 +537,12 @@ struct InetAddress : public sockaddr_storage return (unsigned int)(b.template at(p) + 3); // other addresses begin with 16-bit non-inclusive length case 0x04: ss_family = AF_INET; - memcpy(&(reinterpret_cast(this)->sin_addr.s_addr),b.field(p,4),4); p += 4; + ZT_FAST_MEMCPY(&(reinterpret_cast(this)->sin_addr.s_addr),b.field(p,4),4); p += 4; reinterpret_cast(this)->sin_port = Utils::hton(b.template at(p)); p += 2; break; case 0x06: ss_family = AF_INET6; - memcpy(reinterpret_cast(this)->sin6_addr.s6_addr,b.field(p,16),16); p += 16; + ZT_FAST_MEMCPY(reinterpret_cast(this)->sin6_addr.s6_addr,b.field(p,16),16); p += 16; reinterpret_cast(this)->sin_port = Utils::hton(b.template at(p)); p += 2; break; default: diff --git a/node/Network.cpp b/node/Network.cpp index a9e8539e..e8e91174 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -983,7 +983,7 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add return false; c->haveChunkIds[c->haveChunks++] = chunkId; - memcpy(c->data.unsafeData() + chunkIndex,chunkData,chunkLen); + ZT_FAST_MEMCPY(c->data.unsafeData() + chunkIndex,chunkData,chunkLen); c->haveBytes += chunkLen; if (c->haveBytes == totalLength) { @@ -1385,7 +1385,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const ec->assignedAddressCount = 0; for(unsigned int i=0;iassignedAddresses[i]),&(_config.staticIps[i]),sizeof(struct sockaddr_storage)); + ZT_FAST_MEMCPY(&(ec->assignedAddresses[i]),&(_config.staticIps[i]),sizeof(struct sockaddr_storage)); ++ec->assignedAddressCount; } else { memset(&(ec->assignedAddresses[i]),0,sizeof(struct sockaddr_storage)); @@ -1395,7 +1395,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const ec->routeCount = 0; for(unsigned int i=0;iroutes[i]),&(_config.routes[i]),sizeof(ZT_VirtualNetworkRoute)); + ZT_FAST_MEMCPY(&(ec->routes[i]),&(_config.routes[i]),sizeof(ZT_VirtualNetworkRoute)); ++ec->routeCount; } else { memset(&(ec->routes[i]),0,sizeof(ZT_VirtualNetworkRoute)); diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index bb48e6aa..19823e24 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -234,12 +234,12 @@ public: NetworkConfig(const NetworkConfig &nc) { - memcpy(this,&nc,sizeof(NetworkConfig)); + ZT_FAST_MEMCPY(this,&nc,sizeof(NetworkConfig)); } inline NetworkConfig &operator=(const NetworkConfig &nc) { - memcpy(this,&nc,sizeof(NetworkConfig)); + ZT_FAST_MEMCPY(this,&nc,sizeof(NetworkConfig)); return *this; } diff --git a/node/Node.cpp b/node/Node.cpp index ef8925d5..8d8f5ca0 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -66,7 +66,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64 { if (callbacks->version != 0) throw ZT_EXCEPTION_INVALID_ARGUMENT; - memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks)); + ZT_FAST_MEMCPY(&_cb,callbacks,sizeof(ZT_Node_Callbacks)); // Initialize non-cryptographic PRNG from a good random source Utils::getSecureRandom((void *)_prngState,sizeof(_prngState)); @@ -441,7 +441,7 @@ ZT_PeerList *Node::peers() const SharedPtr bestp(pi->second->getBestPath(_now,false)); p->pathCount = 0; for(std::vector< SharedPtr >::iterator path(paths.begin());path!=paths.end();++path) { - memcpy(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage)); + ZT_FAST_MEMCPY(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage)); p->paths[p->pathCount].lastSend = (*path)->lastOut(); p->paths[p->pathCount].lastReceive = (*path)->lastIn(); p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address()); diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 04ba2c2a..9aa44736 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -78,7 +78,7 @@ void OutboundMulticast::init( if (!disableCompression) _packet.compress(); - memcpy(_frameData,payload,_frameLen); + ZT_FAST_MEMCPY(_frameData,payload,_frameLen); } void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr) diff --git a/node/Packet.cpp b/node/Packet.cpp index d3f7dfd6..af42cda5 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -387,27 +387,27 @@ static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = val static inline U16 LZ4_read16(const void* memPtr) { - U16 val; memcpy(&val, memPtr, sizeof(val)); return val; + U16 val; ZT_FAST_MEMCPY(&val, memPtr, sizeof(val)); return val; } static inline U32 LZ4_read32(const void* memPtr) { - U32 val; memcpy(&val, memPtr, sizeof(val)); return val; + U32 val; ZT_FAST_MEMCPY(&val, memPtr, sizeof(val)); return val; } static inline reg_t LZ4_read_ARCH(const void* memPtr) { - reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; + reg_t val; ZT_FAST_MEMCPY(&val, memPtr, sizeof(val)); return val; } static inline void LZ4_write16(void* memPtr, U16 value) { - memcpy(memPtr, &value, sizeof(value)); + ZT_FAST_MEMCPY(memPtr, &value, sizeof(value)); } static inline void LZ4_write32(void* memPtr, U32 value) { - memcpy(memPtr, &value, sizeof(value)); + ZT_FAST_MEMCPY(memPtr, &value, sizeof(value)); } #endif /* LZ4_FORCE_MEMORY_ACCESS */ @@ -435,7 +435,7 @@ static inline void LZ4_writeLE16(void* memPtr, U16 value) static inline void LZ4_copy8(void* dst, const void* src) { - memcpy(dst,src,8); + ZT_FAST_MEMCPY(dst,src,8); } /* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ @@ -830,7 +830,7 @@ _last_literals: } else { *op++ = (BYTE)(lastRun< oend))) goto _output_error; /* Error : input must be consumed */ } - memcpy(op, ip, length); + ZT_FAST_MEMCPY(op, ip, length); ip += length; op += length; break; /* Necessarily EOF, due to parsing restrictions */ @@ -995,14 +995,14 @@ FORCE_INLINE int LZ4_decompress_generic( /* match encompass external dictionary and current block */ size_t const copySize = (size_t)(lowPrefix-match); size_t const restSize = length - copySize; - memcpy(op, dictEnd - copySize, copySize); + ZT_FAST_MEMCPY(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) *op++ = *copyFrom++; } else { - memcpy(op, lowPrefix, restSize); + ZT_FAST_MEMCPY(op, lowPrefix, restSize); op += restSize; } } continue; @@ -1017,7 +1017,7 @@ FORCE_INLINE int LZ4_decompress_generic( op[2] = match[2]; op[3] = match[3]; match += dec32table[offset]; - memcpy(op+4, match, 4); + ZT_FAST_MEMCPY(op+4, match, 4); match -= dec64; } else { LZ4_copy8(op, match); match+=8; } op += 8; @@ -1095,7 +1095,7 @@ void Packet::armor(const void *key,bool encryptPayload,unsigned int counter) s20.crypt12(payload,payload,payloadLen); uint64_t mac[2]; Poly1305::compute(mac,payload,payloadLen,macKey); - memcpy(data + ZT_PACKET_IDX_MAC,mac,8); + ZT_FAST_MEMCPY(data + ZT_PACKET_IDX_MAC,mac,8); } } @@ -1167,7 +1167,7 @@ bool Packet::compress() if ((cl > 0)&&(cl < pl)) { data[ZT_PACKET_IDX_VERB] |= (char)ZT_PROTO_VERB_FLAG_COMPRESSED; setSize((unsigned int)cl + ZT_PACKET_IDX_PAYLOAD); - memcpy(data + ZT_PACKET_IDX_PAYLOAD,buf,cl); + ZT_FAST_MEMCPY(data + ZT_PACKET_IDX_PAYLOAD,buf,cl); return true; } } @@ -1187,7 +1187,7 @@ bool Packet::uncompress() int ucl = LZ4_decompress_safe((const char *)data + ZT_PACKET_IDX_PAYLOAD,buf,compLen,sizeof(buf)); if ((ucl > 0)&&(ucl <= (int)(capacity() - ZT_PACKET_IDX_PAYLOAD))) { setSize((unsigned int)ucl + ZT_PACKET_IDX_PAYLOAD); - memcpy(data + ZT_PACKET_IDX_PAYLOAD,buf,ucl); + ZT_FAST_MEMCPY(data + ZT_PACKET_IDX_PAYLOAD,buf,ucl); } else { return false; } diff --git a/node/Path.hpp b/node/Path.hpp index ab52ced6..008b05c5 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -73,10 +73,10 @@ public: _k[1] = (uint64_t)reinterpret_cast(&r)->sin_port; _k[2] = (uint64_t)l; } else if (r.ss_family == AF_INET6) { - memcpy(_k,reinterpret_cast(&r)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(_k,reinterpret_cast(&r)->sin6_addr.s6_addr,16); _k[2] = ((uint64_t)reinterpret_cast(&r)->sin6_port << 32) ^ (uint64_t)l; } else { - memcpy(_k,&r,std::min(sizeof(_k),sizeof(InetAddress))); + ZT_FAST_MEMCPY(_k,&r,std::min(sizeof(_k),sizeof(InetAddress))); _k[2] += (uint64_t)l; } } diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 7f7498bb..4a18914f 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -166,7 +166,7 @@ public: if (b[p++] == 1) { if (b.template at(p) == ZT_C25519_SIGNATURE_LEN) { p += 2; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; } else { diff --git a/node/Tag.hpp b/node/Tag.hpp index fc1377de..394c7be6 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -163,7 +163,7 @@ public: if (b.template at(p) != ZT_C25519_SIGNATURE_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; p += 2; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else { p += 2 + b.template at(p); } diff --git a/node/Utils.hpp b/node/Utils.hpp index 87584fcf..20108e27 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -40,6 +40,44 @@ #include "Constants.hpp" +// So it's 2017 and this still helps on most Linux versions. It shouldn't but it does. Go figure. +#if defined(__LINUX__) && ((defined(_MSC_VER) || defined(__GNUC__)) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))) +#include +static inline void ZT_FAST_MEMCPY(void *a,const void *b,unsigned long k) +{ + char *aa = reinterpret_cast(a); + const char *bb = reinterpret_cast(b); + while (likely(k >= 128)) { + __m128i t1 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t2 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t3 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t4 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t1); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t2); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t3); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t4); aa += 16; + __m128i t5 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t6 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t7 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t8 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t5); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t6); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t7); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t8); aa += 16; + k -= 128; + } + while (likely(k >= 16)) { + __m128i t1 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t1); aa += 16; + k -= 16; + } + for(unsigned long i=0;i(p); p += 8; _ts = b.template at(p); p += 8; - memcpy(_updatesMustBeSignedBy.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); p += ZT_C25519_PUBLIC_KEY_LEN; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_updatesMustBeSignedBy.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); p += ZT_C25519_PUBLIC_KEY_LEN; + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; const unsigned int numRoots = (unsigned int)b[p++]; if (numRoots > ZT_WORLD_MAX_ROOTS) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; diff --git a/selftest.cpp b/selftest.cpp index c3b8ce2f..86894564 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -660,6 +660,50 @@ static int testOther() std::cout << " " << InetAddress("").toString(buf); std::cout << std::endl; + std::cout << "[other] Benchmarking memcpy... "; std::cout.flush(); + { + unsigned char *bb = (unsigned char *)::malloc(1234567); + unsigned char *cc = (unsigned char *)::malloc(1234567); + for(unsigned int i=0;i<1234567;++i) + bb[i] = (unsigned char)i; + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for(unsigned int i=0;i<20000;++i) { + ++bb[i]; + ++bb[i+1]; + memcpy(cc,bb,1234567); + bytes += 1234567.0; + } + if (cc[0] != bb[0]) + abort(); + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + ::free((void *)bb); + ::free((void *)cc); + } + + std::cout << "[other] Benchmarking ZT_FAST_MEMCPY... "; std::cout.flush(); + { + unsigned char *bb = (unsigned char *)::malloc(1234567); + unsigned char *cc = (unsigned char *)::malloc(1234567); + for(unsigned int i=0;i<1234567;++i) + bb[i] = (unsigned char)i; + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for(unsigned int i=0;i<20000;++i) { + ++bb[0]; + ++bb[1234566]; + ZT_FAST_MEMCPY(cc,bb,1234567); + bytes += 1234567.0; + } + if (cc[0] != bb[0]) + abort(); + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + ::free((void *)bb); + ::free((void *)cc); + } + #if 0 std::cout << "[other] Testing Hashtable... "; std::cout.flush(); { diff --git a/service/OneService.cpp b/service/OneService.cpp index b30dc390..3ca75362 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1971,7 +1971,7 @@ public: // After setting up tap, fall through to CONFIG_UPDATE since we also want to do this... case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE: - memcpy(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); + ZT_FAST_MEMCPY(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); if (n.tap) { // sanity check #ifdef __WINDOWS__ // wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized @@ -2298,7 +2298,7 @@ public: else return 0; const std::vector *l = lh->get(ztaddr); if ((l)&&(l->size() > 0)) { - memcpy(result,&((*l)[(unsigned long)_node->prng() % l->size()]),sizeof(struct sockaddr_storage)); + ZT_FAST_MEMCPY(result,&((*l)[(unsigned long)_node->prng() % l->size()]),sizeof(struct sockaddr_storage)); return 1; } else return 0; } -- cgit v1.2.3 From 65c07afe055e6d33a07ea6adf87aedcf564806a2 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 8 Jan 2018 14:33:28 -0800 Subject: Copyright updates for 2018. --- COPYING | 2 +- include/ZeroTierOne.h | 2 +- node/Address.hpp | 2 +- node/Array.hpp | 2 +- node/AtomicCounter.hpp | 2 +- node/Buffer.hpp | 2 +- node/C25519.hpp | 2 +- node/Capability.cpp | 2 +- node/Capability.hpp | 2 +- node/CertificateOfMembership.cpp | 2 +- node/CertificateOfMembership.hpp | 2 +- node/CertificateOfOwnership.cpp | 2 +- node/CertificateOfOwnership.hpp | 2 +- node/Constants.hpp | 2 +- node/Credential.hpp | 2 +- node/Dictionary.hpp | 2 +- node/Hashtable.hpp | 2 +- node/Identity.cpp | 2 +- node/Identity.hpp | 2 +- node/IncomingPacket.cpp | 2 +- node/IncomingPacket.hpp | 2 +- node/InetAddress.cpp | 2 +- node/InetAddress.hpp | 2 +- node/MAC.hpp | 2 +- node/Membership.cpp | 2 +- node/Membership.hpp | 2 +- node/MulticastGroup.hpp | 2 +- node/Multicaster.cpp | 2 +- node/Multicaster.hpp | 2 +- node/Mutex.hpp | 2 +- node/Network.cpp | 2 +- node/Network.hpp | 2 +- node/NetworkConfig.cpp | 2 +- node/NetworkConfig.hpp | 2 +- node/NetworkController.hpp | 2 +- node/Node.cpp | 2 +- node/Node.hpp | 2 +- node/NonCopyable.hpp | 2 +- node/OutboundMulticast.cpp | 2 +- node/OutboundMulticast.hpp | 2 +- node/Packet.cpp | 2 +- node/Packet.hpp | 2 +- node/Path.cpp | 2 +- node/Path.hpp | 2 +- node/Peer.cpp | 2 +- node/Peer.hpp | 2 +- node/Poly1305.hpp | 2 +- node/Revocation.cpp | 2 +- node/Revocation.hpp | 2 +- node/RuntimeEnvironment.hpp | 2 +- node/SHA512.hpp | 2 +- node/SelfAwareness.cpp | 2 +- node/SelfAwareness.hpp | 2 +- node/SharedPtr.hpp | 2 +- node/Switch.cpp | 2 +- node/Switch.hpp | 2 +- node/Tag.cpp | 2 +- node/Tag.hpp | 2 +- node/Topology.cpp | 2 +- node/Topology.hpp | 2 +- node/Trace.cpp | 2 +- node/Trace.hpp | 2 +- node/Utils.cpp | 2 +- node/Utils.hpp | 2 +- node/World.hpp | 2 +- one.cpp | 4 ++-- osdep/Arp.cpp | 2 +- osdep/Arp.hpp | 2 +- osdep/BSDEthernetTap.cpp | 2 +- osdep/BSDEthernetTap.hpp | 2 +- osdep/Binder.hpp | 2 +- osdep/BlockingQueue.hpp | 2 +- osdep/Http.cpp | 2 +- osdep/Http.hpp | 2 +- osdep/LinuxEthernetTap.cpp | 2 +- osdep/LinuxEthernetTap.hpp | 2 +- osdep/ManagedRoute.cpp | 2 +- osdep/ManagedRoute.hpp | 2 +- osdep/NeighborDiscovery.cpp | 2 +- osdep/NeighborDiscovery.hpp | 2 +- osdep/OSUtils.cpp | 2 +- osdep/OSUtils.hpp | 2 +- osdep/OSXEthernetTap.cpp | 2 +- osdep/OSXEthernetTap.hpp | 2 +- osdep/Phy.hpp | 2 +- osdep/PortMapper.cpp | 2 +- osdep/PortMapper.hpp | 2 +- osdep/TestEthernetTap.hpp | 2 +- osdep/Thread.hpp | 2 +- osdep/WindowsEthernetTap.cpp | 2 +- osdep/WindowsEthernetTap.hpp | 2 +- selftest.cpp | 2 +- service/OneService.cpp | 2 +- service/OneService.hpp | 2 +- service/SoftwareUpdater.cpp | 2 +- service/SoftwareUpdater.hpp | 2 +- version.h | 2 +- 97 files changed, 98 insertions(+), 98 deletions(-) (limited to 'selftest.cpp') diff --git a/COPYING b/COPYING index 23d42dfa..8008d3e0 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ ZeroTier One, an endpoint server for the ZeroTier virtual network layer. -Copyright © 2011–2016 ZeroTier, Inc. +Copyright © 2011–2018 ZeroTier, Inc. ZeroTier One is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 93a91933..f07650b5 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Address.hpp b/node/Address.hpp index 12c52a3f..41977af2 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Array.hpp b/node/Array.hpp index ef2611e4..de827c08 100644 --- a/node/Array.hpp +++ b/node/Array.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp index 34b58e91..d58c4b56 100644 --- a/node/AtomicCounter.hpp +++ b/node/AtomicCounter.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Buffer.hpp b/node/Buffer.hpp index f84b3774..bbf4ee37 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/C25519.hpp b/node/C25519.hpp index 950c7fed..3f22b445 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Capability.cpp b/node/Capability.cpp index 47dca1fc..fb52be8a 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Capability.hpp b/node/Capability.hpp index bec1f47f..91a46566 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index dedcccff..a849a44c 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 2eff1083..19fe5367 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index eeb0d99c..8ee67865 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index e397fd63..278ae863 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Constants.hpp b/node/Constants.hpp index 6360a693..23bebafd 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Credential.hpp b/node/Credential.hpp index e8767e22..34e94162 100644 --- a/node/Credential.hpp +++ b/node/Credential.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index a1b0f9cb..59afb7c6 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index 5aa045b9..58dc8fca 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Identity.cpp b/node/Identity.cpp index 72bea75d..9cc507f7 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Identity.hpp b/node/Identity.hpp index ab2886ad..cd24757e 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 38fd3aa0..341f3281 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index c8f52721..88f4f066 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index ee32ce72..ecfc81ab 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index fd430099..e6dfabf9 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/MAC.hpp b/node/MAC.hpp index 18fe2032..c08323a4 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Membership.cpp b/node/Membership.cpp index de5fb99d..affe7a71 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Membership.hpp b/node/Membership.hpp index 95ec2180..ad0bb73e 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 6039d3c4..0f4a621e 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index fa6f7bd1..d5bdfdf6 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 08c96485..59959328 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Mutex.hpp b/node/Mutex.hpp index 53ae05c4..cbd80524 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Network.cpp b/node/Network.cpp index e8e91174..e8a52e33 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Network.hpp b/node/Network.hpp index 1b4da7d2..db285108 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 2e07ac82..f9b16cc5 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 19823e24..4121a241 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp index 63d44a46..393bcc91 100644 --- a/node/NetworkController.hpp +++ b/node/NetworkController.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Node.cpp b/node/Node.cpp index d4b69689..af03669c 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Node.hpp b/node/Node.hpp index f8236db8..82f35c56 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/NonCopyable.hpp b/node/NonCopyable.hpp index 5e8c753d..31107a50 100644 --- a/node/NonCopyable.hpp +++ b/node/NonCopyable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 9aa44736..d7a7b4d8 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 2f6d8338..836b840b 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Packet.cpp b/node/Packet.cpp index cb9e1e0f..de059054 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Packet.hpp b/node/Packet.hpp index 8cfb5492..b96ab375 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Path.cpp b/node/Path.cpp index ca366e39..b1b3dd06 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Path.hpp b/node/Path.hpp index 6b4b9915..62d750b7 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Peer.cpp b/node/Peer.cpp index 6e46089f..71afd852 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Peer.hpp b/node/Peer.hpp index 99728736..99216bab 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Poly1305.hpp b/node/Poly1305.hpp index 0bdfa74f..adcc2410 100644 --- a/node/Poly1305.hpp +++ b/node/Poly1305.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Revocation.cpp b/node/Revocation.cpp index 89a2db95..78098f8c 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 4a18914f..eaf01915 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 0bb78599..9ecdc400 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/SHA512.hpp b/node/SHA512.hpp index 584f8e11..eedc284a 100644 --- a/node/SHA512.hpp +++ b/node/SHA512.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 83cd89c9..c4f107fb 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 7ddba465..ce6e8c76 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index af66545f..aa03cf0b 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Switch.cpp b/node/Switch.cpp index b2cab1d0..c3626f9f 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Switch.hpp b/node/Switch.hpp index b42389fc..4fc5453d 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Tag.cpp b/node/Tag.cpp index bde41a70..62d9cb2e 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Tag.hpp b/node/Tag.hpp index 394c7be6..d2e932c2 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Topology.cpp b/node/Topology.cpp index d1b389df..fa9868e9 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Topology.hpp b/node/Topology.hpp index b09f95cf..0bcdfb0a 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Trace.cpp b/node/Trace.cpp index 4303946b..a60a0194 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Trace.hpp b/node/Trace.hpp index 08241d37..05d5b66a 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Utils.cpp b/node/Utils.cpp index 4ac18366..a69a575e 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/Utils.hpp b/node/Utils.hpp index 54af3aec..5565fad6 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/node/World.hpp b/node/World.hpp index 26d94fcd..459470ca 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/one.cpp b/one.cpp index a1238bb8..8d4b8fc5 100644 --- a/one.cpp +++ b/one.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -93,7 +93,7 @@ using namespace ZeroTier; static OneService *volatile zt1Service = (OneService *)0; #define PROGRAM_NAME "ZeroTier One" -#define COPYRIGHT_NOTICE "Copyright (c) 2011-2017 ZeroTier, Inc." +#define COPYRIGHT_NOTICE "Copyright (c) 2011-2018 ZeroTier, Inc." #define LICENSE_GRANT \ "This is free software: you may copy, modify, and/or distribute this" ZT_EOL_S \ "work under the terms of the GNU General Public License, version 3 or" ZT_EOL_S \ diff --git a/osdep/Arp.cpp b/osdep/Arp.cpp index c06f459b..cc4e920a 100644 --- a/osdep/Arp.cpp +++ b/osdep/Arp.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/Arp.hpp b/osdep/Arp.hpp index e26fcdb3..27e92fdb 100644 --- a/osdep/Arp.hpp +++ b/osdep/Arp.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index c0fdad9c..053df21d 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index fd2685f3..3d91dbbb 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index e3c2dc02..399ce04a 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/BlockingQueue.hpp b/osdep/BlockingQueue.hpp index 5e1a24ef..351a095a 100644 --- a/osdep/BlockingQueue.hpp +++ b/osdep/BlockingQueue.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/Http.cpp b/osdep/Http.cpp index d6d0238c..16785c96 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/Http.hpp b/osdep/Http.hpp index 3f98d760..b717c5c9 100644 --- a/osdep/Http.hpp +++ b/osdep/Http.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 848f3638..6ef42744 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index e05dee8c..5142eec1 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 2289b23a..8ffbed2a 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index 849bddf5..873d0cfb 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/NeighborDiscovery.cpp b/osdep/NeighborDiscovery.cpp index ac95748b..d9862f3d 100644 --- a/osdep/NeighborDiscovery.cpp +++ b/osdep/NeighborDiscovery.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/NeighborDiscovery.hpp b/osdep/NeighborDiscovery.hpp index 2e7a68ba..59186289 100644 --- a/osdep/NeighborDiscovery.hpp +++ b/osdep/NeighborDiscovery.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 3325c621..aa531243 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 274b48df..324b7923 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index b43d34c0..dbff6200 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/OSXEthernetTap.hpp b/osdep/OSXEthernetTap.hpp index d0a8a99d..fe402901 100644 --- a/osdep/OSXEthernetTap.hpp +++ b/osdep/OSXEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index f71bd56c..8e683f10 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index 9aeeb8d6..a7dd3046 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/PortMapper.hpp b/osdep/PortMapper.hpp index 61015a09..fa3cdc31 100644 --- a/osdep/PortMapper.hpp +++ b/osdep/PortMapper.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/TestEthernetTap.hpp b/osdep/TestEthernetTap.hpp index 047a19b1..2f73258a 100644 --- a/osdep/TestEthernetTap.hpp +++ b/osdep/TestEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/Thread.hpp b/osdep/Thread.hpp index b3011f32..35ea5035 100644 --- a/osdep/Thread.hpp +++ b/osdep/Thread.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 93da8ad6..22b81454 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 70789e75..856c3be7 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/selftest.cpp b/selftest.cpp index 86894564..9edb4928 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/service/OneService.cpp b/service/OneService.cpp index 71bb6983..e65ad0e2 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/service/OneService.hpp b/service/OneService.hpp index 23e572d0..3b670e4a 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 39833c90..6a25dbec 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index f16c99a0..ed329b1f 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/version.h b/version.h index b3b2fc81..d80bec80 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From 01b4cb64ee3736a66014aaa53394c3c3690531e0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 Jan 2018 08:35:02 -0800 Subject: cleanup --- node/Utils.hpp | 18 +++++------------- selftest.cpp | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'selftest.cpp') diff --git a/node/Utils.hpp b/node/Utils.hpp index 5565fad6..8dd0292a 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -47,7 +47,7 @@ static inline void ZT_FAST_MEMCPY(void *a,const void *b,unsigned long k) { char *aa = reinterpret_cast(a); const char *bb = reinterpret_cast(b); - while (likely(k >= 128)) { + while (k >= 64) { __m128 t1 = _mm_loadu_ps(reinterpret_cast(bb)); __m128 t2 = _mm_loadu_ps(reinterpret_cast(bb + 16)); __m128 t3 = _mm_loadu_ps(reinterpret_cast(bb + 32)); @@ -56,19 +56,11 @@ static inline void ZT_FAST_MEMCPY(void *a,const void *b,unsigned long k) _mm_storeu_ps(reinterpret_cast(aa + 16),t2); _mm_storeu_ps(reinterpret_cast(aa + 32),t3); _mm_storeu_ps(reinterpret_cast(aa + 48),t4); - t1 = _mm_loadu_ps(reinterpret_cast(bb + 64)); - t2 = _mm_loadu_ps(reinterpret_cast(bb + 80)); - t3 = _mm_loadu_ps(reinterpret_cast(bb + 96)); - t4 = _mm_loadu_ps(reinterpret_cast(bb + 112)); - _mm_storeu_ps(reinterpret_cast(aa + 64),t1); - _mm_storeu_ps(reinterpret_cast(aa + 80),t2); - _mm_storeu_ps(reinterpret_cast(aa + 96),t3); - _mm_storeu_ps(reinterpret_cast(aa + 112),t4); - bb += 128; - aa += 128; - k -= 128; + bb += 64; + aa += 64; + k -= 64; } - while (likely(k >= 16)) { + while (k >= 16) { __m128 t1 = _mm_loadu_si128(reinterpret_cast(bb)); _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t1); bb += 16; diff --git a/selftest.cpp b/selftest.cpp index 9edb4928..c3fd397c 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -621,7 +621,7 @@ static int testPacket() return -1; } - a.armor(salsaKey,true,0); + a.armor(salsaKey,true); if (!a.dearmor(salsaKey)) { std::cout << "FAIL (encrypt-decrypt/verify)" << std::endl; return -1; -- cgit v1.2.3 From f3dfd636343904a01681c80e91b44aa00ce33f2e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jan 2018 20:00:37 -0500 Subject: Clean up some old stuff. --- node/Array.hpp | 117 --------------------------------------- node/C25519.hpp | 31 ++--------- node/CertificateOfMembership.cpp | 6 +- node/CertificateOfMembership.hpp | 10 ++-- node/Identity.cpp | 8 +-- node/Identity.hpp | 14 ++--- node/Multicaster.hpp | 66 +++++++++++----------- node/World.hpp | 4 +- one.cpp | 12 ++-- osdep/Phy.hpp | 23 ++++---- selftest.cpp | 10 ++-- service/OneService.cpp | 4 +- service/SoftwareUpdater.cpp | 26 +++++---- service/SoftwareUpdater.hpp | 6 +- 14 files changed, 101 insertions(+), 236 deletions(-) delete mode 100644 node/Array.hpp (limited to 'selftest.cpp') diff --git a/node/Array.hpp b/node/Array.hpp deleted file mode 100644 index de827c08..00000000 --- a/node/Array.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_ARRAY_HPP -#define ZT_ARRAY_HPP - -#include - -namespace ZeroTier { - -/** - * Static array -- a simple thing that's belonged in STL since the time of the dinosaurs - */ -template -class Array -{ -public: - Array() {} - - Array(const Array &a) - { - for(unsigned long i=0;i reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - inline iterator begin() { return data; } - inline iterator end() { return &(data[S]); } - inline const_iterator begin() const { return data; } - inline const_iterator end() const { return &(data[S]); } - - inline reverse_iterator rbegin() { return reverse_iterator(begin()); } - inline reverse_iterator rend() { return reverse_iterator(end()); } - inline const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } - inline const_reverse_iterator rend() const { return const_reverse_iterator(end()); } - */ - - inline unsigned long size() const { return S; } - inline unsigned long max_size() const { return S; } - - inline reference operator[](const std::size_t n) { return data[n]; } - inline const_reference operator[](const std::size_t n) const { return data[n]; } - - inline reference front() { return data[0]; } - inline const_reference front() const { return data[0]; } - inline reference back() { return data[S-1]; } - inline const_reference back() const { return data[S-1]; } - - inline bool operator==(const Array &k) const - { - for(unsigned long i=0;i(const Array &k) const { return (k < *this); } - inline bool operator<=(const Array &k) const { return !(k < *this); } - inline bool operator>=(const Array &k) const { return !(*this < k); } - - T data[S]; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/C25519.hpp b/node/C25519.hpp index 3f22b445..2e9184a0 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -27,7 +27,6 @@ #ifndef ZT_C25519_HPP #define ZT_C25519_HPP -#include "Array.hpp" #include "Utils.hpp" namespace ZeroTier { @@ -42,28 +41,10 @@ namespace ZeroTier { class C25519 { public: - /** - * Public key (both crypto and signing) - */ - typedef Array Public; // crypto key, signing key (both 32 bytes) - - /** - * Private key (both crypto and signing) - */ - typedef Array Private; // crypto key, signing key (both 32 bytes) - - /** - * Message signature - */ - typedef Array Signature; - - /** - * Public/private key pair - */ - typedef struct { - Public pub; - Private priv; - } Pair; + struct Public { uint8_t data[ZT_C25519_PUBLIC_KEY_LEN]; }; + struct Private { uint8_t data[ZT_C25519_PRIVATE_KEY_LEN]; }; + struct Signature { uint8_t data[ZT_C25519_SIGNATURE_LEN]; }; + struct Pair { Public pub; Private priv; }; /** * Generate a C25519 elliptic curve key pair @@ -71,7 +52,7 @@ public: static inline Pair generate() { Pair kp; - Utils::getSecureRandom(kp.priv.data,(unsigned int)kp.priv.size()); + Utils::getSecureRandom(kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN); _calcPubDH(kp); _calcPubED(kp); return kp; @@ -95,7 +76,7 @@ public: { Pair kp; void *const priv = (void *)kp.priv.data; - Utils::getSecureRandom(priv,(unsigned int)kp.priv.size()); + Utils::getSecureRandom(priv,ZT_C25519_PRIVATE_KEY_LEN); _calcPubED(kp); // do Ed25519 key -- bytes 32-63 of pub and priv do { ++(((uint64_t *)priv)[1]); diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index a849a44c..8184ce99 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -84,7 +84,7 @@ std::string CertificateOfMembership::toString() const if (_signedBy) { s.push_back(':'); - s.append(Utils::hex(_signature.data,(unsigned int)_signature.size(),tmp)); + s.append(Utils::hex(_signature.data,ZT_C25519_SIGNATURE_LEN,tmp)); } return s; @@ -94,7 +94,7 @@ void CertificateOfMembership::fromString(const char *s) { _qualifierCount = 0; _signedBy.zero(); - memset(_signature.data,0,_signature.size()); + memset(_signature.data,0,ZT_C25519_SIGNATURE_LEN); if (!*s) return; @@ -145,7 +145,7 @@ void CertificateOfMembership::fromString(const char *s) colonAt = 0; while ((s[colonAt])&&(s[colonAt] != ':')) ++colonAt; if (colonAt) { - if (Utils::unhex(s,colonAt,_signature.data,(unsigned int)_signature.size()) != _signature.size()) + if (Utils::unhex(s,colonAt,_signature.data,ZT_C25519_SIGNATURE_LEN) != ZT_C25519_SIGNATURE_LEN) _signedBy.zero(); } else { _signedBy.zero(); diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 19fe5367..b5a90007 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -142,7 +142,7 @@ public: _qualifiers[2].value = issuedTo.toInt(); _qualifiers[2].maxDelta = 0xffffffffffffffffULL; _qualifierCount = 3; - memset(_signature.data,0,_signature.size()); + memset(_signature.data,0,ZT_C25519_SIGNATURE_LEN); } inline CertificateOfMembership &operator=(const CertificateOfMembership &c) @@ -293,7 +293,7 @@ public: } _signedBy.appendTo(b); if (_signedBy) - b.append(_signature.data,(unsigned int)_signature.size()); + b.append(_signature.data,ZT_C25519_SIGNATURE_LEN); } template @@ -329,8 +329,8 @@ public: p += ZT_ADDRESS_LENGTH; if (_signedBy) { - ZT_FAST_MEMCPY(_signature.data,b.field(p,(unsigned int)_signature.size()),_signature.size()); - p += (unsigned int)_signature.size(); + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); + p += ZT_C25519_SIGNATURE_LEN; } return (p - startAt); @@ -348,7 +348,7 @@ public: if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta)) return false; } - return (_signature == c._signature); + return (memcmp(_signature.data,c._signature.data,ZT_C25519_SIGNATURE_LEN) == 0); } inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); } diff --git a/node/Identity.cpp b/node/Identity.cpp index 9cc507f7..03f27083 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -87,7 +87,7 @@ struct _Identity_generate_cond _Identity_generate_cond(unsigned char *sb,char *gm) : digest(sb),genmem(gm) {} inline bool operator()(const C25519::Pair &kp) const { - _computeMemoryHardHash(kp.pub.data,(unsigned int)kp.pub.size(),digest,genmem); + _computeMemoryHardHash(kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem); return (digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN); } unsigned char *digest; @@ -120,7 +120,7 @@ bool Identity::locallyValidate() const unsigned char digest[64]; char *genmem = new char[ZT_IDENTITY_GEN_MEMORY]; - _computeMemoryHardHash(_publicKey.data,(unsigned int)_publicKey.size(),digest,genmem); + _computeMemoryHardHash(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem); delete [] genmem; unsigned char addrb[5]; @@ -187,14 +187,14 @@ bool Identity::fromString(const char *str) } break; case 2: - if (Utils::unhex(f,_publicKey.data,(unsigned int)_publicKey.size()) != _publicKey.size()) { + if (Utils::unhex(f,_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) { _address.zero(); return false; } break; case 3: _privateKey = new C25519::Private(); - if (Utils::unhex(f,_privateKey->data,(unsigned int)_privateKey->size()) != _privateKey->size()) { + if (Utils::unhex(f,_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) { _address.zero(); return false; } diff --git a/node/Identity.hpp b/node/Identity.hpp index 74514436..74716aa0 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -215,10 +215,10 @@ public: { _address.appendTo(b); b.append((uint8_t)0); // C25519/Ed25519 identity type - b.append(_publicKey.data,(unsigned int)_publicKey.size()); + b.append(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN); if ((_privateKey)&&(includePrivate)) { - b.append((unsigned char)_privateKey->size()); - b.append(_privateKey->data,(unsigned int)_privateKey->size()); + b.append((unsigned char)ZT_C25519_PRIVATE_KEY_LEN); + b.append(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN); } else b.append((unsigned char)0); } @@ -248,8 +248,8 @@ public: if (b[p++] != 0) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; - ZT_FAST_MEMCPY(_publicKey.data,b.field(p,(unsigned int)_publicKey.size()),(unsigned int)_publicKey.size()); - p += (unsigned int)_publicKey.size(); + ZT_FAST_MEMCPY(_publicKey.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); + p += ZT_C25519_PUBLIC_KEY_LEN; unsigned int privateKeyLength = (unsigned int)b[p++]; if (privateKeyLength) { @@ -306,8 +306,8 @@ public: */ inline operator bool() const { return (_address); } - inline bool operator==(const Identity &id) const { return ((_address == id._address)&&(_publicKey == id._publicKey)); } - inline bool operator<(const Identity &id) const { return ((_address < id._address)||((_address == id._address)&&(_publicKey < id._publicKey))); } + inline bool operator==(const Identity &id) const { return ((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)); } + inline bool operator<(const Identity &id) const { return ((_address < id._address)||((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) < 0))); } inline bool operator!=(const Identity &id) const { return !(*this == id); } inline bool operator>(const Identity &id) const { return (id < *this); } inline bool operator<=(const Identity &id) const { return !(id < *this); } diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 59959328..999efb61 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -42,7 +42,6 @@ #include "OutboundMulticast.hpp" #include "Utils.hpp" #include "Mutex.hpp" -#include "NonCopyable.hpp" namespace ZeroTier { @@ -53,39 +52,8 @@ class Packet; /** * Database of known multicast peers within a network */ -class Multicaster : NonCopyable +class Multicaster { -private: - struct Key - { - Key() : nwid(0),mg() {} - Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {} - - uint64_t nwid; - MulticastGroup mg; - - inline bool operator==(const Key &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); } - inline unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); } - }; - - struct MulticastGroupMember - { - MulticastGroupMember() {} - MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {} - - Address address; - uint64_t timestamp; // time of last notification - }; - - struct MulticastGroupStatus - { - MulticastGroupStatus() : lastExplicitGather(0) {} - - uint64_t lastExplicitGather; - std::list txQueue; // pending outbound multicasts - std::vector members; // members of this group - }; - public: Multicaster(const RuntimeEnvironment *renv); ~Multicaster(); @@ -220,9 +188,39 @@ public: } private: + struct Key + { + Key() : nwid(0),mg() {} + Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {} + + uint64_t nwid; + MulticastGroup mg; + + inline bool operator==(const Key &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); } + inline unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); } + }; + + struct MulticastGroupMember + { + MulticastGroupMember() {} + MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {} + + Address address; + uint64_t timestamp; // time of last notification + }; + + struct MulticastGroupStatus + { + MulticastGroupStatus() : lastExplicitGather(0) {} + + uint64_t lastExplicitGather; + std::list txQueue; // pending outbound multicasts + std::vector members; // members of this group + }; + void _add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member); - const RuntimeEnvironment *RR; + const RuntimeEnvironment *const RR; Hashtable _groups; Mutex _groups_m; diff --git a/node/World.hpp b/node/World.hpp index 459470ca..9edf2a6a 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -240,11 +240,9 @@ public: return (p - startAt); } - inline bool operator==(const World &w) const { return ((_id == w._id)&&(_ts == w._ts)&&(_updatesMustBeSignedBy == w._updatesMustBeSignedBy)&&(_signature == w._signature)&&(_roots == w._roots)&&(_type == w._type)); } + inline bool operator==(const World &w) const { return ((_id == w._id)&&(_ts == w._ts)&&(memcmp(_updatesMustBeSignedBy.data,w._updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)&&(memcmp(_signature.data,w._signature.data,ZT_C25519_SIGNATURE_LEN) == 0)&&(_roots == w._roots)&&(_type == w._type)); } inline bool operator!=(const World &w) const { return (!(*this == w)); } - inline bool operator<(const World &w) const { return (((int)_type < (int)w._type) ? true : ((_type == w._type) ? (_id < w._id) : false)); } - /** * Create a World object signed with a key pair * diff --git a/one.cpp b/one.cpp index a8f51b45..4bf35e82 100644 --- a/one.cpp +++ b/one.cpp @@ -795,7 +795,7 @@ static int idtool(int argc,char **argv) } C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length()); char hexbuf[1024]; - printf("%s",Utils::hex(signature.data,(unsigned int)signature.size(),hexbuf)); + printf("%s",Utils::hex(signature.data,ZT_C25519_SIGNATURE_LEN,hexbuf)); } else if (!strcmp(argv[1],"verify")) { if (argc < 4) { idtoolPrintHelp(stdout,argv[0]); @@ -838,8 +838,8 @@ static int idtool(int argc,char **argv) nlohmann::json mj; mj["objtype"] = "world"; mj["worldType"] = "moon"; - mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,(unsigned int)kp.pub.size(),idtmp); - mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,(unsigned int)kp.priv.size(),idtmp); + mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN,idtmp); + mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN,idtmp); mj["id"] = id.address().toString(idtmp); nlohmann::json seedj; seedj["identity"] = id.toString(false,idtmp); @@ -878,9 +878,9 @@ static int idtool(int argc,char **argv) C25519::Pair signingKey; C25519::Public updatesMustBeSignedBy; - Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,(unsigned int)signingKey.pub.size()); - Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,(unsigned int)signingKey.priv.size()); - Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,(unsigned int)updatesMustBeSignedBy.size()); + Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,ZT_C25519_PUBLIC_KEY_LEN); + Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,ZT_C25519_PRIVATE_KEY_LEN); + Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN); std::vector roots; nlohmann::json &rootsj = mj["roots"]; diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 8e683f10..243db0a8 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -688,25 +688,26 @@ public: * until one works. * * @param sock Socket - * @param bufferSize Desired buffer sizes + * @param receiveBufferSize Desired size of receive buffer + * @param sendBufferSize Desired size of send buffer */ - inline void setBufferSizes(const PhySocket *sock,int bufferSize) + inline void setBufferSizes(const PhySocket *sock,int receiveBufferSize,int sendBufferSize) { PhySocketImpl &sws = *(reinterpret_cast(sock)); - if (bufferSize > 0) { - int bs = bufferSize; - while (bs >= 65536) { - int tmpbs = bs; + if (receiveBufferSize > 0) { + while (receiveBufferSize > 0) { + int tmpbs = receiveBufferSize; if (::setsockopt(sws.sock,SOL_SOCKET,SO_RCVBUF,(const char *)&tmpbs,sizeof(tmpbs)) == 0) break; - bs -= 16384; + receiveBufferSize -= 16384; } - bs = bufferSize; - while (bs >= 65536) { - int tmpbs = bs; + } + if (sendBufferSize > 0) { + while (sendBufferSize > 0) { + int tmpbs = sendBufferSize; if (::setsockopt(sws.sock,SOL_SOCKET,SO_SNDBUF,(const char *)&tmpbs,sizeof(tmpbs)) == 0) break; - bs -= 16384; + sendBufferSize -= 16384; } } } diff --git a/selftest.cpp b/selftest.cpp index c3fd397c..cf3bbdeb 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -321,10 +321,10 @@ static int testCrypto() std::cout << "[crypto] Testing C25519 and Ed25519 against test vectors... "; std::cout.flush(); for(int k=0;k::const_iterator r(world.roots().begin());r!=world.roots().end();++r) { nlohmann::json rj; diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 6a25dbec..d12861d4 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -126,11 +126,13 @@ void SoftwareUpdater::setUpdateDistribution(bool distribute) const std::string binPath(udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)); const std::string metaHash(OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH])); if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile(binPath.c_str(),d.bin))) { - uint8_t sha512[ZT_SHA512_DIGEST_LEN]; - SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length()); - if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct + std::array sha512; + SHA512::hash(sha512.data(),d.bin.data(),(unsigned int)d.bin.length()); + if (!memcmp(sha512.data(),metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE] = d.bin.length(); // override with correct value -- setting this in meta json is optional - _dist[Array(sha512)] = d; + std::array shakey; + memcpy(shakey.data(),sha512.data(),16); + _dist[shakey] = d; if (_distLog) { fprintf(_distLog,".......... INIT: DISTRIBUTING %s (%u bytes)" ZT_EOL_S,binPath.c_str(),(unsigned int)d.bin.length()); fflush(_distLog); @@ -179,7 +181,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void unsigned int bestVMin = rvMin; unsigned int bestVRev = rvRev; unsigned int bestVBld = rvBld; - for(std::map< Array,_D >::const_iterator d(_dist.begin());d!=_dist.end();++d) { + for(std::map< std::array,_D >::const_iterator d(_dist.begin());d!=_dist.end();++d) { // The arch field in update description .json files can be an array for e.g. multi-arch update files const nlohmann::json &dvArch2 = d->second.meta[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE]; std::vector dvArch; @@ -233,14 +235,14 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void _latestValid = false; OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str()); _download = std::string(); - memcpy(_downloadHashPrefix.data,hash.data(),16); + memcpy(_downloadHashPrefix.data(),hash.data(),16); _downloadLength = len; } if ((_downloadLength > 0)&&(_download.length() < _downloadLength)) { Buffer<128> gd; gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data,16); + gd.append(_downloadHashPrefix.data(),16); gd.append((uint32_t)_download.length()); _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); } @@ -257,7 +259,9 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void idx |= (unsigned long)*(reinterpret_cast(data) + 18) << 16; idx |= (unsigned long)*(reinterpret_cast(data) + 19) << 8; idx |= (unsigned long)*(reinterpret_cast(data) + 20); - std::map< Array,_D >::iterator d(_dist.find(Array(reinterpret_cast(data) + 1))); + std::array shakey; + memcpy(shakey.data(),reinterpret_cast(data) + 1,16); + std::map< std::array,_D >::iterator d(_dist.find(shakey)); if ((d != _dist.end())&&(idx < (unsigned long)d->second.bin.length())) { Buffer buf; buf.append((uint8_t)VERB_DATA); @@ -270,7 +274,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void break; case VERB_DATA: - if ((len >= 21)&&(_downloadLength > 0)&&(!memcmp(_downloadHashPrefix.data,reinterpret_cast(data) + 1,16))) { + if ((len >= 21)&&(_downloadLength > 0)&&(!memcmp(_downloadHashPrefix.data(),reinterpret_cast(data) + 1,16))) { unsigned long idx = (unsigned long)*(reinterpret_cast(data) + 17) << 24; idx |= (unsigned long)*(reinterpret_cast(data) + 18) << 16; idx |= (unsigned long)*(reinterpret_cast(data) + 19) << 8; @@ -280,7 +284,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void if (_download.length() < _downloadLength) { Buffer<128> gd; gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data,16); + gd.append(_downloadHashPrefix.data(),16); gd.append((uint32_t)_download.length()); _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); } @@ -371,7 +375,7 @@ bool SoftwareUpdater::check(const int64_t now) } else { Buffer<128> gd; gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data,16); + gd.append(_downloadHashPrefix.data(),16); gd.append((uint32_t)_download.length()); _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); } diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index ed329b1f..7f73eba2 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -33,11 +33,11 @@ #include #include #include +#include #include "../include/ZeroTierOne.h" #include "../node/Identity.hpp" -#include "../node/Array.hpp" #include "../node/Packet.hpp" #include "../ext/json/json.hpp" @@ -202,13 +202,13 @@ private: nlohmann::json meta; std::string bin; }; - std::map< Array,_D > _dist; // key is first 16 bytes of hash + std::map< std::array,_D > _dist; // key is first 16 bytes of hash nlohmann::json _latestMeta; bool _latestValid; std::string _download; - Array _downloadHashPrefix; + std::array _downloadHashPrefix; unsigned long _downloadLength; }; -- cgit v1.2.3 From 26aaf253acf115e67ab969f95e002ce1074df13e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Feb 2018 15:52:41 -0800 Subject: Allow us to build a semi-dynamic official binary that works back to CentOS 6, at least on x64, and is very fast since we can build it with newer clang or icc. --- ext/misc/linux-old-glibc-compat.c | 18 ++++++++++++++++++ make-linux.mk | 11 ++++++++--- selftest.cpp | 2 ++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 ext/misc/linux-old-glibc-compat.c (limited to 'selftest.cpp') diff --git a/ext/misc/linux-old-glibc-compat.c b/ext/misc/linux-old-glibc-compat.c new file mode 100644 index 00000000..6d793a2d --- /dev/null +++ b/ext/misc/linux-old-glibc-compat.c @@ -0,0 +1,18 @@ +#include +#include +#include + +__asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); + +#ifdef __cplusplus +extern "C" { +#endif + +extern void *__wrap_memcpy(void *dest,const void *src,size_t n) +{ + return memcpy(dest,src,n); +} + +#ifdef __cplusplus +} +#endif diff --git a/make-linux.mk b/make-linux.mk index 253a4cb7..a68935da 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -71,7 +71,6 @@ ifeq ($(ZT_DEBUG),1) # C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box! node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -g -pthread $(INCLUDES) $(DEFS) else - override DEFS+=-D_FORTIFY_SOURCE=2 CFLAGS?=-O3 -fstack-protector override CFLAGS+=-Wall -Wno-deprecated -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) CXXFLAGS?=-O3 -fstack-protector @@ -210,6 +209,12 @@ ifeq ($(ZT_STATIC),1) override LDFLAGS+=-static endif +# For building an official semi-static binary on CentOS 7 +ifeq ($(ZT_OFFICIAL),1) + CORE_OBJS+=ext/misc/linux-old-glibc-compat.o + override LDFLAGS+=-Wl,--wrap=memcpy -static-libstdc++ +endif + # ARM32 hell -- use conservative CFLAGS ifeq ($(ZT_ARCHITECTURE),3) ifeq ($(shell if [ -e /usr/bin/dpkg ]; then dpkg --print-architecture; fi),armel) @@ -254,7 +259,7 @@ libzerotiercore.a: FORCE core: libzerotiercore.a selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(CORE_OBJS) $(ONE_OBJS $(LDLIBS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(CORE_OBJS) $(ONE_OBJS) $(LDLIBS) $(STRIP) zerotier-selftest zerotier-selftest: selftest @@ -265,7 +270,7 @@ manpages: FORCE doc: manpages clean: FORCE - rm -rf *.a *.so *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm .depend debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one doc/node_modules + rm -rf *.a *.so *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm .depend debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one doc/node_modules ext/misc/*.o distclean: clean diff --git a/selftest.cpp b/selftest.cpp index cf3bbdeb..03f587b0 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -660,6 +660,7 @@ static int testOther() std::cout << " " << InetAddress("").toString(buf); std::cout << std::endl; +#if 0 std::cout << "[other] Benchmarking memcpy... "; std::cout.flush(); { unsigned char *bb = (unsigned char *)::malloc(1234567); @@ -681,6 +682,7 @@ static int testOther() ::free((void *)bb); ::free((void *)cc); } +#endif std::cout << "[other] Benchmarking ZT_FAST_MEMCPY... "; std::cout.flush(); { -- cgit v1.2.3 From 610e594a501d3419e0b8a1bac061ca1af689d531 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 12 Mar 2018 16:16:20 -0700 Subject: Speed tweaks for signatures, etc. --- node/C25519.cpp | 2117 ++++++++++++++++++++++++++++--------------------------- node/SHA512.cpp | 543 +++++++------- selftest.cpp | 13 +- 3 files changed, 1350 insertions(+), 1323 deletions(-) (limited to 'selftest.cpp') diff --git a/node/C25519.cpp b/node/C25519.cpp index 2a5575aa..3ff6310f 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -20,7 +20,7 @@ Derived from public domain code by D. J. Bernstein. #pragma warning(disable: 4146) #endif -namespace ZeroTier { +namespace { ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -31,265 +31,265 @@ namespace ZeroTier { #define crypto_uint64 uint64_t #define crypto_hash_sha512_BYTES 64 -static inline void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) +void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { - unsigned int j; - unsigned int u; - u = 0; - for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } - u += a[31] + b[31]; out[31] = u; + unsigned int j; + unsigned int u; + u = 0; + for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } + u += a[31] + b[31]; out[31] = u; } -static inline void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) +void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { - unsigned int j; - unsigned int u; - u = 218; - for (j = 0;j < 31;++j) { - u += a[j] + 65280 - b[j]; - out[j] = u & 255; - u >>= 8; - } - u += a[31] - b[31]; - out[31] = u; + unsigned int j; + unsigned int u; + u = 218; + for (j = 0;j < 31;++j) { + u += a[j] + 65280 - b[j]; + out[j] = u & 255; + u >>= 8; + } + u += a[31] - b[31]; + out[31] = u; } -static inline void squeeze(unsigned int a[32]) +void squeeze(unsigned int a[32]) { - unsigned int j; - unsigned int u; - u = 0; - for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } - u += a[31]; a[31] = u & 127; - u = 19 * (u >> 7); - for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } - u += a[31]; a[31] = u; + unsigned int j; + unsigned int u; + u = 0; + for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } + u += a[31]; a[31] = u & 127; + u = 19 * (u >> 7); + for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } + u += a[31]; a[31] = u; } static const unsigned int minusp[32] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 } ; -static inline void freeze(unsigned int a[32]) +void freeze(unsigned int a[32]) { - unsigned int aorig[32]; - unsigned int j; - unsigned int negative; + unsigned int aorig[32]; + unsigned int j; + unsigned int negative; - for (j = 0;j < 32;++j) aorig[j] = a[j]; - add(a,a,minusp); - negative = -((a[31] >> 7) & 1); - for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); + for (j = 0;j < 32;++j) aorig[j] = a[j]; + add(a,a,minusp); + negative = -((a[31] >> 7) & 1); + for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); } -static inline void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) +void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { - unsigned int i; - unsigned int j; - unsigned int u; + unsigned int i; + unsigned int j; + unsigned int u; - for (i = 0;i < 32;++i) { - u = 0; - for (j = 0;j <= i;++j) u += a[j] * b[i - j]; - for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; - out[i] = u; - } - squeeze(out); + for (i = 0;i < 32;++i) { + u = 0; + for (j = 0;j <= i;++j) u += a[j] * b[i - j]; + for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; + out[i] = u; + } + squeeze(out); } -static inline void mult121665(unsigned int out[32],const unsigned int a[32]) +void mult121665(unsigned int out[32],const unsigned int a[32]) { - unsigned int j; - unsigned int u; + unsigned int j; + unsigned int u; - u = 0; - for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } - u += 121665 * a[31]; out[31] = u & 127; - u = 19 * (u >> 7); - for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } - u += out[j]; out[j] = u; + u = 0; + for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } + u += 121665 * a[31]; out[31] = u & 127; + u = 19 * (u >> 7); + for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } + u += out[j]; out[j] = u; } -static inline void square(unsigned int out[32],const unsigned int a[32]) +void square(unsigned int out[32],const unsigned int a[32]) { - unsigned int i; - unsigned int j; - unsigned int u; + unsigned int i; + unsigned int j; + unsigned int u; - for (i = 0;i < 32;++i) { - u = 0; - for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; - for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; - u *= 2; - if ((i & 1) == 0) { - u += a[i / 2] * a[i / 2]; - u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; - } - out[i] = u; - } - squeeze(out); + for (i = 0;i < 32;++i) { + u = 0; + for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; + for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; + u *= 2; + if ((i & 1) == 0) { + u += a[i / 2] * a[i / 2]; + u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; + } + out[i] = u; + } + squeeze(out); } -static inline void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) +void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) { - unsigned int j; - unsigned int t; - unsigned int bminus1; + unsigned int j; + unsigned int t; + unsigned int bminus1; - bminus1 = b - 1; - for (j = 0;j < 64;++j) { - t = bminus1 & (r[j] ^ s[j]); - p[j] = s[j] ^ t; - q[j] = r[j] ^ t; - } + bminus1 = b - 1; + for (j = 0;j < 64;++j) { + t = bminus1 & (r[j] ^ s[j]); + p[j] = s[j] ^ t; + q[j] = r[j] ^ t; + } } static void mainloop(unsigned int work[64],const unsigned char e[32]) { - unsigned int xzm1[64]; - unsigned int xzm[64]; - unsigned int xzmb[64]; - unsigned int xzm1b[64]; - unsigned int xznb[64]; - unsigned int xzn1b[64]; - unsigned int a0[64]; - unsigned int a1[64]; - unsigned int b0[64]; - unsigned int b1[64]; - unsigned int c1[64]; - unsigned int r[32]; - unsigned int s[32]; - unsigned int t[32]; - unsigned int u[32]; - //unsigned int i; - unsigned int j; - unsigned int b; - int pos; - - for (j = 0;j < 32;++j) xzm1[j] = work[j]; - xzm1[32] = 1; - for (j = 33;j < 64;++j) xzm1[j] = 0; - - xzm[0] = 1; - for (j = 1;j < 64;++j) xzm[j] = 0; - - for (pos = 254;pos >= 0;--pos) { - b = e[pos / 8] >> (pos & 7); - b &= 1; - select(xzmb,xzm1b,xzm,xzm1,b); - add(a0,xzmb,xzmb + 32); - sub(a0 + 32,xzmb,xzmb + 32); - add(a1,xzm1b,xzm1b + 32); - sub(a1 + 32,xzm1b,xzm1b + 32); - square(b0,a0); - square(b0 + 32,a0 + 32); - mult(b1,a1,a0 + 32); - mult(b1 + 32,a1 + 32,a0); - add(c1,b1,b1 + 32); - sub(c1 + 32,b1,b1 + 32); - square(r,c1 + 32); - sub(s,b0,b0 + 32); - mult121665(t,s); - add(u,t,b0); - mult(xznb,b0,b0 + 32); - mult(xznb + 32,s,u); - square(xzn1b,c1); - mult(xzn1b + 32,r,work); - select(xzm,xzm1,xznb,xzn1b,b); - } - - for (j = 0;j < 64;++j) work[j] = xzm[j]; + unsigned int xzm1[64]; + unsigned int xzm[64]; + unsigned int xzmb[64]; + unsigned int xzm1b[64]; + unsigned int xznb[64]; + unsigned int xzn1b[64]; + unsigned int a0[64]; + unsigned int a1[64]; + unsigned int b0[64]; + unsigned int b1[64]; + unsigned int c1[64]; + unsigned int r[32]; + unsigned int s[32]; + unsigned int t[32]; + unsigned int u[32]; + //unsigned int i; + unsigned int j; + unsigned int b; + int pos; + + for (j = 0;j < 32;++j) xzm1[j] = work[j]; + xzm1[32] = 1; + for (j = 33;j < 64;++j) xzm1[j] = 0; + + xzm[0] = 1; + for (j = 1;j < 64;++j) xzm[j] = 0; + + for (pos = 254;pos >= 0;--pos) { + b = e[pos / 8] >> (pos & 7); + b &= 1; + select(xzmb,xzm1b,xzm,xzm1,b); + add(a0,xzmb,xzmb + 32); + sub(a0 + 32,xzmb,xzmb + 32); + add(a1,xzm1b,xzm1b + 32); + sub(a1 + 32,xzm1b,xzm1b + 32); + square(b0,a0); + square(b0 + 32,a0 + 32); + mult(b1,a1,a0 + 32); + mult(b1 + 32,a1 + 32,a0); + add(c1,b1,b1 + 32); + sub(c1 + 32,b1,b1 + 32); + square(r,c1 + 32); + sub(s,b0,b0 + 32); + mult121665(t,s); + add(u,t,b0); + mult(xznb,b0,b0 + 32); + mult(xznb + 32,s,u); + square(xzn1b,c1); + mult(xzn1b + 32,r,work); + select(xzm,xzm1,xznb,xzn1b,b); + } + + for (j = 0;j < 64;++j) work[j] = xzm[j]; } static void recip(unsigned int out[32],const unsigned int z[32]) { - unsigned int z2[32]; - unsigned int z9[32]; - unsigned int z11[32]; - unsigned int z2_5_0[32]; - unsigned int z2_10_0[32]; - unsigned int z2_20_0[32]; - unsigned int z2_50_0[32]; - unsigned int z2_100_0[32]; - unsigned int t0[32]; - unsigned int t1[32]; - int i; - - /* 2 */ square(z2,z); - /* 4 */ square(t1,z2); - /* 8 */ square(t0,t1); - /* 9 */ mult(z9,t0,z); - /* 11 */ mult(z11,z9,z2); - /* 22 */ square(t0,z11); - /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); - - /* 2^6 - 2^1 */ square(t0,z2_5_0); - /* 2^7 - 2^2 */ square(t1,t0); - /* 2^8 - 2^3 */ square(t0,t1); - /* 2^9 - 2^4 */ square(t1,t0); - /* 2^10 - 2^5 */ square(t0,t1); - /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); - - /* 2^11 - 2^1 */ square(t0,z2_10_0); - /* 2^12 - 2^2 */ square(t1,t0); - /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); - - /* 2^21 - 2^1 */ square(t0,z2_20_0); - /* 2^22 - 2^2 */ square(t1,t0); - /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); - - /* 2^41 - 2^1 */ square(t1,t0); - /* 2^42 - 2^2 */ square(t0,t1); - /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } - /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); - - /* 2^51 - 2^1 */ square(t0,z2_50_0); - /* 2^52 - 2^2 */ square(t1,t0); - /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); - - /* 2^101 - 2^1 */ square(t1,z2_100_0); - /* 2^102 - 2^2 */ square(t0,t1); - /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } - /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); - - /* 2^201 - 2^1 */ square(t0,t1); - /* 2^202 - 2^2 */ square(t1,t0); - /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); - - /* 2^251 - 2^1 */ square(t1,t0); - /* 2^252 - 2^2 */ square(t0,t1); - /* 2^253 - 2^3 */ square(t1,t0); - /* 2^254 - 2^4 */ square(t0,t1); - /* 2^255 - 2^5 */ square(t1,t0); - /* 2^255 - 21 */ mult(out,t1,z11); -} - -static inline int crypto_scalarmult(unsigned char *q,const unsigned char *n,const unsigned char *p) -{ - unsigned int work[96]; - unsigned char e[32]; - unsigned int i; - for (i = 0;i < 32;++i) e[i] = n[i]; - e[0] &= 248; - e[31] &= 127; - e[31] |= 64; - for (i = 0;i < 32;++i) work[i] = p[i]; - mainloop(work,e); - recip(work + 32,work + 32); - mult(work + 64,work,work + 32); - freeze(work + 64); - for (i = 0;i < 32;++i) q[i] = work[64 + i]; - return 0; + unsigned int z2[32]; + unsigned int z9[32]; + unsigned int z11[32]; + unsigned int z2_5_0[32]; + unsigned int z2_10_0[32]; + unsigned int z2_20_0[32]; + unsigned int z2_50_0[32]; + unsigned int z2_100_0[32]; + unsigned int t0[32]; + unsigned int t1[32]; + int i; + + /* 2 */ square(z2,z); + /* 4 */ square(t1,z2); + /* 8 */ square(t0,t1); + /* 9 */ mult(z9,t0,z); + /* 11 */ mult(z11,z9,z2); + /* 22 */ square(t0,z11); + /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); + + /* 2^6 - 2^1 */ square(t0,z2_5_0); + /* 2^7 - 2^2 */ square(t1,t0); + /* 2^8 - 2^3 */ square(t0,t1); + /* 2^9 - 2^4 */ square(t1,t0); + /* 2^10 - 2^5 */ square(t0,t1); + /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); + + /* 2^11 - 2^1 */ square(t0,z2_10_0); + /* 2^12 - 2^2 */ square(t1,t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); + + /* 2^21 - 2^1 */ square(t0,z2_20_0); + /* 2^22 - 2^2 */ square(t1,t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); + + /* 2^41 - 2^1 */ square(t1,t0); + /* 2^42 - 2^2 */ square(t0,t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } + /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); + + /* 2^51 - 2^1 */ square(t0,z2_50_0); + /* 2^52 - 2^2 */ square(t1,t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); + + /* 2^101 - 2^1 */ square(t1,z2_100_0); + /* 2^102 - 2^2 */ square(t0,t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } + /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); + + /* 2^201 - 2^1 */ square(t0,t1); + /* 2^202 - 2^2 */ square(t1,t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); + + /* 2^251 - 2^1 */ square(t1,t0); + /* 2^252 - 2^2 */ square(t0,t1); + /* 2^253 - 2^3 */ square(t1,t0); + /* 2^254 - 2^4 */ square(t0,t1); + /* 2^255 - 2^5 */ square(t1,t0); + /* 2^255 - 21 */ mult(out,t1,z11); +} + +int crypto_scalarmult(unsigned char *q,const unsigned char *n,const unsigned char *p) +{ + unsigned int work[96]; + unsigned char e[32]; + unsigned int i; + for (i = 0;i < 32;++i) e[i] = n[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + for (i = 0;i < 32;++i) work[i] = p[i]; + mainloop(work,e); + recip(work + 32,work + 32); + mult(work + 64,work,work + 32); + freeze(work + 64); + for (i = 0;i < 32;++i) q[i] = work[64 + i]; + return 0; } static const unsigned char base[32] = {9}; -static inline int crypto_scalarmult_base(unsigned char *q,const unsigned char *n) +int crypto_scalarmult_base(unsigned char *q,const unsigned char *n) { - return crypto_scalarmult(q,n,base); + return crypto_scalarmult(q,n,base); } ////////////////////////////////////////////////////////////////////////////// @@ -300,588 +300,588 @@ static inline int crypto_scalarmult_base(unsigned char *q,const unsigned char *n // Also public domain, newer version than the Ed25519 found in NaCl -typedef struct +typedef struct { - crypto_uint32 v[32]; + crypto_uint32 v[32]; } fe25519; static void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); -static inline crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { - crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */ - x -= 1; /* 4294967295: yes; 0..65534: no */ - x >>= 31; /* 1: yes; 0: no */ - return x; + crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */ + x -= 1; /* 4294967295: yes; 0..65534: no */ + x >>= 31; /* 1: yes; 0: no */ + return x; } -static inline crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { - unsigned int x = a; - x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */ - x >>= 31; /* 0: yes; 1: no */ - x ^= 1; /* 1: yes; 0: no */ - return x; + unsigned int x = a; + x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */ + x >>= 31; /* 0: yes; 1: no */ + x ^= 1; /* 1: yes; 0: no */ + return x; } -static inline crypto_uint32 times19(crypto_uint32 a) +crypto_uint32 times19(crypto_uint32 a) { - return (a << 4) + (a << 1) + a; + return (a << 4) + (a << 1) + a; } -static inline crypto_uint32 times38(crypto_uint32 a) +crypto_uint32 times38(crypto_uint32 a) { - return (a << 5) + (a << 2) + (a << 1); + return (a << 5) + (a << 2) + (a << 1); } -static inline void reduce_add_sub(fe25519 *r) +void reduce_add_sub(fe25519 *r) { - crypto_uint32 t; - int i,rep; + crypto_uint32 t; + int i,rep; - for(rep=0;rep<4;rep++) - { - t = r->v[31] >> 7; - r->v[31] &= 127; - t = times19(t); - r->v[0] += t; - for(i=0;i<31;i++) - { - t = r->v[i] >> 8; - r->v[i+1] += t; - r->v[i] &= 255; - } - } + for(rep=0;rep<4;rep++) + { + t = r->v[31] >> 7; + r->v[31] &= 127; + t = times19(t); + r->v[0] += t; + for(i=0;i<31;i++) + { + t = r->v[i] >> 8; + r->v[i+1] += t; + r->v[i] &= 255; + } + } } -static inline void reduce_mul(fe25519 *r) +void reduce_mul(fe25519 *r) { - crypto_uint32 t; - int i,rep; + crypto_uint32 t; + int i,rep; - for(rep=0;rep<2;rep++) - { - t = r->v[31] >> 7; - r->v[31] &= 127; - t = times19(t); - r->v[0] += t; - for(i=0;i<31;i++) - { - t = r->v[i] >> 8; - r->v[i+1] += t; - r->v[i] &= 255; - } - } + for(rep=0;rep<2;rep++) + { + t = r->v[31] >> 7; + r->v[31] &= 127; + t = times19(t); + r->v[0] += t; + for(i=0;i<31;i++) + { + t = r->v[i] >> 8; + r->v[i+1] += t; + r->v[i] &= 255; + } + } } /* reduction modulo 2^255-19 */ -static inline void fe25519_freeze(fe25519 *r) +void fe25519_freeze(fe25519 *r) { - int i; - crypto_uint32 m = equal(r->v[31],127); - for(i=30;i>0;i--) - m &= equal(r->v[i],255); - m &= ge(r->v[0],237); + int i; + crypto_uint32 m = equal(r->v[31],127); + for(i=30;i>0;i--) + m &= equal(r->v[i],255); + m &= ge(r->v[0],237); - m = -m; + m = -m; - r->v[31] -= m&127; - for(i=30;i>0;i--) - r->v[i] -= m&255; - r->v[0] -= m&237; + r->v[31] -= m&127; + for(i=30;i>0;i--) + r->v[i] -= m&255; + r->v[0] -= m&237; } -static inline void fe25519_unpack(fe25519 *r, const unsigned char x[32]) +void fe25519_unpack(fe25519 *r, const unsigned char x[32]) { - int i; - for(i=0;i<32;i++) r->v[i] = x[i]; - r->v[31] &= 127; + int i; + for(i=0;i<32;i++) r->v[i] = x[i]; + r->v[31] &= 127; } /* Assumes input x being reduced below 2^255 */ -static inline void fe25519_pack(unsigned char r[32], const fe25519 *x) +void fe25519_pack(unsigned char r[32], const fe25519 *x) { - int i; - fe25519 y = *x; - fe25519_freeze(&y); - for(i=0;i<32;i++) - r[i] = y.v[i]; + int i; + fe25519 y = *x; + fe25519_freeze(&y); + for(i=0;i<32;i++) + r[i] = y.v[i]; } -static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) +int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) { - int i; - fe25519 t1 = *x; - fe25519 t2 = *y; - fe25519_freeze(&t1); - fe25519_freeze(&t2); - for(i=0;i<32;i++) - if(t1.v[i] != t2.v[i]) return 0; - return 1; + int i; + fe25519 t1 = *x; + fe25519 t2 = *y; + fe25519_freeze(&t1); + fe25519_freeze(&t2); + for(i=0;i<32;i++) + if(t1.v[i] != t2.v[i]) return 0; + return 1; } -static inline void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) +void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) { - int i; - crypto_uint32 mask = b; - mask = -mask; - for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); + int i; + crypto_uint32 mask = b; + mask = -mask; + for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); } -static inline unsigned char fe25519_getparity(const fe25519 *x) +unsigned char fe25519_getparity(const fe25519 *x) { - fe25519 t = *x; - fe25519_freeze(&t); - return t.v[0] & 1; + fe25519 t = *x; + fe25519_freeze(&t); + return t.v[0] & 1; } -static inline void fe25519_setone(fe25519 *r) +void fe25519_setone(fe25519 *r) { - int i; - r->v[0] = 1; - for(i=1;i<32;i++) r->v[i]=0; + int i; + r->v[0] = 1; + for(i=1;i<32;i++) r->v[i]=0; } -static inline void fe25519_setzero(fe25519 *r) +void fe25519_setzero(fe25519 *r) { - int i; - for(i=0;i<32;i++) r->v[i]=0; + int i; + for(i=0;i<32;i++) r->v[i]=0; } -static inline void fe25519_neg(fe25519 *r, const fe25519 *x) +void fe25519_neg(fe25519 *r, const fe25519 *x) { - fe25519 t; - int i; - for(i=0;i<32;i++) t.v[i]=x->v[i]; - fe25519_setzero(r); - fe25519_sub(r, r, &t); + fe25519 t; + int i; + for(i=0;i<32;i++) t.v[i]=x->v[i]; + fe25519_setzero(r); + fe25519_sub(r, r, &t); } -static inline void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) +void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) { - int i; - for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; - reduce_add_sub(r); + int i; + for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; + reduce_add_sub(r); } -static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) +void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) { - int i; - crypto_uint32 t[32]; - t[0] = x->v[0] + 0x1da; - t[31] = x->v[31] + 0xfe; - for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe; - for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i]; - reduce_add_sub(r); + int i; + crypto_uint32 t[32]; + t[0] = x->v[0] + 0x1da; + t[31] = x->v[31] + 0xfe; + for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe; + for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i]; + reduce_add_sub(r); } -static inline void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) +void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) { - int i,j; - crypto_uint32 t[63]; - for(i=0;i<63;i++)t[i] = 0; + int i,j; + crypto_uint32 t[63]; + for(i=0;i<63;i++)t[i] = 0; - for(i=0;i<32;i++) - for(j=0;j<32;j++) - t[i+j] += x->v[i] * y->v[j]; + for(i=0;i<32;i++) + for(j=0;j<32;j++) + t[i+j] += x->v[i] * y->v[j]; - for(i=32;i<63;i++) - r->v[i-32] = t[i-32] + times38(t[i]); - r->v[31] = t[31]; /* result now in r[0]...r[31] */ + for(i=32;i<63;i++) + r->v[i-32] = t[i-32] + times38(t[i]); + r->v[31] = t[31]; /* result now in r[0]...r[31] */ - reduce_mul(r); + reduce_mul(r); } -static inline void fe25519_square(fe25519 *r, const fe25519 *x) +void fe25519_square(fe25519 *r, const fe25519 *x) { - fe25519_mul(r, x, x); + fe25519_mul(r, x, x); } -static void fe25519_invert(fe25519 *r, const fe25519 *x) +void fe25519_invert(fe25519 *r, const fe25519 *x) { - fe25519 z2; - fe25519 z9; - fe25519 z11; - fe25519 z2_5_0; - fe25519 z2_10_0; - fe25519 z2_20_0; - fe25519 z2_50_0; - fe25519 z2_100_0; - fe25519 t0; - fe25519 t1; - int i; - - /* 2 */ fe25519_square(&z2,x); - /* 4 */ fe25519_square(&t1,&z2); - /* 8 */ fe25519_square(&t0,&t1); - /* 9 */ fe25519_mul(&z9,&t0,x); - /* 11 */ fe25519_mul(&z11,&z9,&z2); - /* 22 */ fe25519_square(&t0,&z11); - /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9); + fe25519 z2; + fe25519 z9; + fe25519 z11; + fe25519 z2_5_0; + fe25519 z2_10_0; + fe25519 z2_20_0; + fe25519 z2_50_0; + fe25519 z2_100_0; + fe25519 t0; + fe25519 t1; + int i; - /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0); - /* 2^7 - 2^2 */ fe25519_square(&t1,&t0); - /* 2^8 - 2^3 */ fe25519_square(&t0,&t1); - /* 2^9 - 2^4 */ fe25519_square(&t1,&t0); - /* 2^10 - 2^5 */ fe25519_square(&t0,&t1); - /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0); + /* 2 */ fe25519_square(&z2,x); + /* 4 */ fe25519_square(&t1,&z2); + /* 8 */ fe25519_square(&t0,&t1); + /* 9 */ fe25519_mul(&z9,&t0,x); + /* 11 */ fe25519_mul(&z11,&z9,&z2); + /* 22 */ fe25519_square(&t0,&z11); + /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9); - /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0); - /* 2^12 - 2^2 */ fe25519_square(&t1,&t0); - /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } - /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0); + /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0); + /* 2^7 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^8 - 2^3 */ fe25519_square(&t0,&t1); + /* 2^9 - 2^4 */ fe25519_square(&t1,&t0); + /* 2^10 - 2^5 */ fe25519_square(&t0,&t1); + /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0); - /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0); - /* 2^22 - 2^2 */ fe25519_square(&t1,&t0); - /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } - /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0); + /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0); + /* 2^12 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0); - /* 2^41 - 2^1 */ fe25519_square(&t1,&t0); - /* 2^42 - 2^2 */ fe25519_square(&t0,&t1); - /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } - /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0); + /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0); + /* 2^22 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0); - /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0); - /* 2^52 - 2^2 */ fe25519_square(&t1,&t0); - /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } - /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0); + /* 2^41 - 2^1 */ fe25519_square(&t1,&t0); + /* 2^42 - 2^2 */ fe25519_square(&t0,&t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } + /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0); - /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0); - /* 2^102 - 2^2 */ fe25519_square(&t0,&t1); - /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } - /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0); - - /* 2^201 - 2^1 */ fe25519_square(&t0,&t1); - /* 2^202 - 2^2 */ fe25519_square(&t1,&t0); - /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } - /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0); + /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0); + /* 2^52 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0); - /* 2^251 - 2^1 */ fe25519_square(&t1,&t0); - /* 2^252 - 2^2 */ fe25519_square(&t0,&t1); - /* 2^253 - 2^3 */ fe25519_square(&t1,&t0); - /* 2^254 - 2^4 */ fe25519_square(&t0,&t1); - /* 2^255 - 2^5 */ fe25519_square(&t1,&t0); - /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11); -} - -static void fe25519_pow2523(fe25519 *r, const fe25519 *x) -{ - fe25519 z2; - fe25519 z9; - fe25519 z11; - fe25519 z2_5_0; - fe25519 z2_10_0; - fe25519 z2_20_0; - fe25519 z2_50_0; - fe25519 z2_100_0; - fe25519 t; - int i; - - /* 2 */ fe25519_square(&z2,x); - /* 4 */ fe25519_square(&t,&z2); - /* 8 */ fe25519_square(&t,&t); - /* 9 */ fe25519_mul(&z9,&t,x); - /* 11 */ fe25519_mul(&z11,&z9,&z2); - /* 22 */ fe25519_square(&t,&z11); - /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9); - - /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0); - /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); } - /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0); - - /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0); - /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } - /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0); - - /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0); - /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); } - /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0); - - /* 2^41 - 2^1 */ fe25519_square(&t,&t); - /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } - /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0); - - /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0); - /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } - /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0); - - /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0); - /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); } - /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0); - - /* 2^201 - 2^1 */ fe25519_square(&t,&t); - /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } - /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0); - - /* 2^251 - 2^1 */ fe25519_square(&t,&t); - /* 2^252 - 2^2 */ fe25519_square(&t,&t); - /* 2^252 - 3 */ fe25519_mul(r,&t,x); -} - -typedef struct -{ - crypto_uint32 v[32]; + /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0); + /* 2^102 - 2^2 */ fe25519_square(&t0,&t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } + /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0); + + /* 2^201 - 2^1 */ fe25519_square(&t0,&t1); + /* 2^202 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0); + + /* 2^251 - 2^1 */ fe25519_square(&t1,&t0); + /* 2^252 - 2^2 */ fe25519_square(&t0,&t1); + /* 2^253 - 2^3 */ fe25519_square(&t1,&t0); + /* 2^254 - 2^4 */ fe25519_square(&t0,&t1); + /* 2^255 - 2^5 */ fe25519_square(&t1,&t0); + /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11); +} + +void fe25519_pow2523(fe25519 *r, const fe25519 *x) +{ + fe25519 z2; + fe25519 z9; + fe25519 z11; + fe25519 z2_5_0; + fe25519 z2_10_0; + fe25519 z2_20_0; + fe25519 z2_50_0; + fe25519 z2_100_0; + fe25519 t; + int i; + + /* 2 */ fe25519_square(&z2,x); + /* 4 */ fe25519_square(&t,&z2); + /* 8 */ fe25519_square(&t,&t); + /* 9 */ fe25519_mul(&z9,&t,x); + /* 11 */ fe25519_mul(&z11,&z9,&z2); + /* 22 */ fe25519_square(&t,&z11); + /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9); + + /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0); + /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); } + /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0); + + /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0); + /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } + /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0); + + /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0); + /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); } + /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0); + + /* 2^41 - 2^1 */ fe25519_square(&t,&t); + /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } + /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0); + + /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0); + /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } + /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0); + + /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0); + /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); } + /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0); + + /* 2^201 - 2^1 */ fe25519_square(&t,&t); + /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } + /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0); + + /* 2^251 - 2^1 */ fe25519_square(&t,&t); + /* 2^252 - 2^2 */ fe25519_square(&t,&t); + /* 2^252 - 3 */ fe25519_mul(r,&t,x); +} + +typedef struct +{ + crypto_uint32 v[32]; } sc25519; -typedef struct +typedef struct { - crypto_uint32 v[16]; + crypto_uint32 v[16]; } shortsc25519; -static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; +static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; -static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, - 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; +static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, + 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; -static inline crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { - unsigned int x = a; - x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ - x >>= 31; /* 0: no; 1: yes */ - return x; + unsigned int x = a; + x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ + x >>= 31; /* 0: no; 1: yes */ + return x; } /* Reduce coefficients of r before calling reduce_add_sub */ -static inline void reduce_add_sub(sc25519 *r) -{ - crypto_uint32 pb = 0; - crypto_uint32 b; - crypto_uint32 mask; - int i; - unsigned char t[32]; - - for(i=0;i<32;i++) - { - pb += m[i]; - b = lt(r->v[i],pb); - t[i] = r->v[i]-pb+(b<<8); - pb = b; - } - mask = b - 1; - for(i=0;i<32;i++) - r->v[i] ^= mask & (r->v[i] ^ t[i]); +void reduce_add_sub(sc25519 *r) +{ + crypto_uint32 pb = 0; + crypto_uint32 b; + crypto_uint32 mask; + int i; + unsigned char t[32]; + + for(i=0;i<32;i++) + { + pb += m[i]; + b = lt(r->v[i],pb); + t[i] = r->v[i]-pb+(b<<8); + pb = b; + } + mask = b - 1; + for(i=0;i<32;i++) + r->v[i] ^= mask & (r->v[i] ^ t[i]); } /* Reduce coefficients of x before calling barrett_reduce */ -static inline void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) +void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) +{ + /* See HAC, Alg. 14.42 */ + int i,j; + crypto_uint32 q2[66]; + crypto_uint32 *q3 = q2 + 33; + crypto_uint32 r1[33]; + crypto_uint32 r2[33]; + crypto_uint32 carry; + crypto_uint32 pb = 0; + crypto_uint32 b; + + for (i = 0;i < 66;++i) q2[i] = 0; + for (i = 0;i < 33;++i) r2[i] = 0; + + for(i=0;i<33;i++) + for(j=0;j<33;j++) + if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; + carry = q2[31] >> 8; + q2[32] += carry; + carry = q2[32] >> 8; + q2[33] += carry; + + for(i=0;i<33;i++)r1[i] = x[i]; + for(i=0;i<32;i++) + for(j=0;j<33;j++) + if(i+j < 33) r2[i+j] += m[i]*q3[j]; + + for(i=0;i<32;i++) + { + carry = r2[i] >> 8; + r2[i+1] += carry; + r2[i] &= 0xff; + } + + for(i=0;i<32;i++) + { + pb += r2[i]; + b = lt(r1[i],pb); + r->v[i] = r1[i]-pb+(b<<8); + pb = b; + } + + /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 + * If so: Handle it here! + */ + + reduce_add_sub(r); + reduce_add_sub(r); +} + +void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) +{ + int i; + crypto_uint32 t[64]; + for(i=0;i<32;i++) t[i] = x[i]; + for(i=32;i<64;++i) t[i] = 0; + barrett_reduce(r, t); +} + +void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) { - /* See HAC, Alg. 14.42 */ - int i,j; - crypto_uint32 q2[66]; - crypto_uint32 *q3 = q2 + 33; - crypto_uint32 r1[33]; - crypto_uint32 r2[33]; - crypto_uint32 carry; - crypto_uint32 pb = 0; - crypto_uint32 b; + int i; + crypto_uint32 t[64]; + for(i=0;i<64;i++) t[i] = x[i]; + barrett_reduce(r, t); +} - for (i = 0;i < 66;++i) q2[i] = 0; - for (i = 0;i < 33;++i) r2[i] = 0; +void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) +{ + int i; + for(i=0;i<32;i++) r[i] = x->v[i]; +} - for(i=0;i<33;i++) - for(j=0;j<33;j++) - if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; - carry = q2[31] >> 8; - q2[32] += carry; - carry = q2[32] >> 8; - q2[33] += carry; - - for(i=0;i<33;i++)r1[i] = x[i]; - for(i=0;i<32;i++) - for(j=0;j<33;j++) - if(i+j < 33) r2[i+j] += m[i]*q3[j]; - - for(i=0;i<32;i++) - { - carry = r2[i] >> 8; - r2[i+1] += carry; - r2[i] &= 0xff; - } - - for(i=0;i<32;i++) - { - pb += r2[i]; - b = lt(r1[i],pb); - r->v[i] = r1[i]-pb+(b<<8); - pb = b; - } - - /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 - * If so: Handle it here! - */ - - reduce_add_sub(r); - reduce_add_sub(r); -} - -static inline void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) -{ - int i; - crypto_uint32 t[64]; - for(i=0;i<32;i++) t[i] = x[i]; - for(i=32;i<64;++i) t[i] = 0; - barrett_reduce(r, t); -} - -static inline void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) -{ - int i; - crypto_uint32 t[64]; - for(i=0;i<64;i++) t[i] = x[i]; - barrett_reduce(r, t); -} - -static inline void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) -{ - int i; - for(i=0;i<32;i++) r[i] = x->v[i]; -} - -static inline void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) -{ - int i, carry; - for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; - for(i=0;i<31;i++) - { - carry = r->v[i] >> 8; - r->v[i+1] += carry; - r->v[i] &= 0xff; - } - reduce_add_sub(r); -} - -static inline void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) -{ - int i,j,carry; - crypto_uint32 t[64]; - for(i=0;i<64;i++)t[i] = 0; - - for(i=0;i<32;i++) - for(j=0;j<32;j++) - t[i+j] += x->v[i] * y->v[j]; - - /* Reduce coefficients */ - for(i=0;i<63;i++) - { - carry = t[i] >> 8; - t[i+1] += carry; - t[i] &= 0xff; - } - - barrett_reduce(r, t); -} - -static inline void sc25519_window3(signed char r[85], const sc25519 *s) -{ - char carry; - int i; - for(i=0;i<10;i++) - { - r[8*i+0] = s->v[3*i+0] & 7; - r[8*i+1] = (s->v[3*i+0] >> 3) & 7; - r[8*i+2] = (s->v[3*i+0] >> 6) & 7; - r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; - r[8*i+3] = (s->v[3*i+1] >> 1) & 7; - r[8*i+4] = (s->v[3*i+1] >> 4) & 7; - r[8*i+5] = (s->v[3*i+1] >> 7) & 7; - r[8*i+5] ^= (s->v[3*i+2] << 1) & 7; - r[8*i+6] = (s->v[3*i+2] >> 2) & 7; - r[8*i+7] = (s->v[3*i+2] >> 5) & 7; - } - r[8*i+0] = s->v[3*i+0] & 7; - r[8*i+1] = (s->v[3*i+0] >> 3) & 7; - r[8*i+2] = (s->v[3*i+0] >> 6) & 7; - r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; - r[8*i+3] = (s->v[3*i+1] >> 1) & 7; - r[8*i+4] = (s->v[3*i+1] >> 4) & 7; - - /* Making it signed */ - carry = 0; - for(i=0;i<84;i++) - { - r[i] += carry; - r[i+1] += r[i] >> 3; - r[i] &= 7; - carry = r[i] >> 2; - r[i] -= carry<<3; - } - r[84] += carry; -} - -static inline void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) +void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) { - int i; - for(i=0;i<31;i++) - { - r[4*i] = ( s1->v[i] & 3) ^ (( s2->v[i] & 3) << 2); - r[4*i+1] = ((s1->v[i] >> 2) & 3) ^ (((s2->v[i] >> 2) & 3) << 2); - r[4*i+2] = ((s1->v[i] >> 4) & 3) ^ (((s2->v[i] >> 4) & 3) << 2); - r[4*i+3] = ((s1->v[i] >> 6) & 3) ^ (((s2->v[i] >> 6) & 3) << 2); - } - r[124] = ( s1->v[31] & 3) ^ (( s2->v[31] & 3) << 2); - r[125] = ((s1->v[31] >> 2) & 3) ^ (((s2->v[31] >> 2) & 3) << 2); - r[126] = ((s1->v[31] >> 4) & 3) ^ (((s2->v[31] >> 4) & 3) << 2); + int i, carry; + for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; + for(i=0;i<31;i++) + { + carry = r->v[i] >> 8; + r->v[i+1] += carry; + r->v[i] &= 0xff; + } + reduce_add_sub(r); +} + +void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) +{ + int i,j,carry; + crypto_uint32 t[64]; + for(i=0;i<64;i++)t[i] = 0; + + for(i=0;i<32;i++) + for(j=0;j<32;j++) + t[i+j] += x->v[i] * y->v[j]; + + /* Reduce coefficients */ + for(i=0;i<63;i++) + { + carry = t[i] >> 8; + t[i+1] += carry; + t[i] &= 0xff; + } + + barrett_reduce(r, t); +} + +void sc25519_window3(signed char r[85], const sc25519 *s) +{ + char carry; + int i; + for(i=0;i<10;i++) + { + r[8*i+0] = s->v[3*i+0] & 7; + r[8*i+1] = (s->v[3*i+0] >> 3) & 7; + r[8*i+2] = (s->v[3*i+0] >> 6) & 7; + r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; + r[8*i+3] = (s->v[3*i+1] >> 1) & 7; + r[8*i+4] = (s->v[3*i+1] >> 4) & 7; + r[8*i+5] = (s->v[3*i+1] >> 7) & 7; + r[8*i+5] ^= (s->v[3*i+2] << 1) & 7; + r[8*i+6] = (s->v[3*i+2] >> 2) & 7; + r[8*i+7] = (s->v[3*i+2] >> 5) & 7; + } + r[8*i+0] = s->v[3*i+0] & 7; + r[8*i+1] = (s->v[3*i+0] >> 3) & 7; + r[8*i+2] = (s->v[3*i+0] >> 6) & 7; + r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; + r[8*i+3] = (s->v[3*i+1] >> 1) & 7; + r[8*i+4] = (s->v[3*i+1] >> 4) & 7; + + /* Making it signed */ + carry = 0; + for(i=0;i<84;i++) + { + r[i] += carry; + r[i+1] += r[i] >> 3; + r[i] &= 7; + carry = r[i] >> 2; + r[i] -= carry<<3; + } + r[84] += carry; +} + +void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) +{ + int i; + for(i=0;i<31;i++) + { + r[4*i] = ( s1->v[i] & 3) ^ (( s2->v[i] & 3) << 2); + r[4*i+1] = ((s1->v[i] >> 2) & 3) ^ (((s2->v[i] >> 2) & 3) << 2); + r[4*i+2] = ((s1->v[i] >> 4) & 3) ^ (((s2->v[i] >> 4) & 3) << 2); + r[4*i+3] = ((s1->v[i] >> 6) & 3) ^ (((s2->v[i] >> 6) & 3) << 2); + } + r[124] = ( s1->v[31] & 3) ^ (( s2->v[31] & 3) << 2); + r[125] = ((s1->v[31] >> 2) & 3) ^ (((s2->v[31] >> 2) & 3) << 2); + r[126] = ((s1->v[31] >> 4) & 3) ^ (((s2->v[31] >> 4) & 3) << 2); } typedef struct { - fe25519 x; - fe25519 y; - fe25519 z; - fe25519 t; + fe25519 x; + fe25519 y; + fe25519 z; + fe25519 t; } ge25519; /* d */ -static const fe25519 ge25519_ecd = {{0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, - 0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52}}; +static const fe25519 ge25519_ecd = {{0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, + 0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52}}; /* 2*d */ -static const fe25519 ge25519_ec2d = {{0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00, - 0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24}}; +static const fe25519 ge25519_ec2d = {{0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00, + 0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24}}; /* sqrt(-1) */ -static const fe25519 ge25519_sqrtm1 = {{0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F, - 0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B}}; +static const fe25519 ge25519_sqrtm1 = {{0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F, + 0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B}}; #define ge25519_p3 ge25519 typedef struct { - fe25519 x; - fe25519 z; - fe25519 y; - fe25519 t; + fe25519 x; + fe25519 z; + fe25519 y; + fe25519 t; } ge25519_p1p1; typedef struct { - fe25519 x; - fe25519 y; - fe25519 z; + fe25519 x; + fe25519 y; + fe25519 z; } ge25519_p2; typedef struct { - fe25519 x; - fe25519 y; + fe25519 x; + fe25519 y; } ge25519_aff; /* Packed coordinates of the base point */ -static const ge25519 ge25519_base = {{{0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, - 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}}, - {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}, - {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20, - 0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67}}}; +static const ge25519 ge25519_base = {{{0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, + 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}}, + {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20, + 0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67}}}; /* Multiples of the base point in affine representation */ static const ge25519_aff ge25519_base_multiples_affine[425] = { -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}} , {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}}, @@ -891,7 +891,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xd4, 0xb4, 0xf5, 0x78, 0x48, 0x68, 0xc3, 0x02, 0x04, 0x03, 0x24, 0x67, 0x17, 0xec, 0x16, 0x9f, 0xf7, 0x9e, 0x26, 0x60, 0x8e, 0xa1, 0x26, 0xa1, 0xab, 0x69, 0xee, 0x77, 0xd1, 0xb1, 0x67, 0x12}}}, {{{0x70, 0xf8, 0xc9, 0xc4, 0x57, 0xa6, 0x3a, 0x49, 0x47, 0x15, 0xce, 0x93, 0xc1, 0x9e, 0x73, 0x1a, 0xf9, 0x20, 0x35, 0x7a, 0xb8, 0xd4, 0x25, 0x83, 0x46, 0xf1, 0xcf, 0x56, 0xdb, 0xa8, 0x3d, 0x20}} , {{0x2f, 0x11, 0x32, 0xca, 0x61, 0xab, 0x38, 0xdf, 0xf0, 0x0f, 0x2f, 0xea, 0x32, 0x28, 0xf2, 0x4c, 0x6c, 0x71, 0xd5, 0x80, 0x85, 0xb8, 0x0e, 0x47, 0xe1, 0x95, 0x15, 0xcb, 0x27, 0xe8, 0xd0, 0x47}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc8, 0x84, 0xa5, 0x08, 0xbc, 0xfd, 0x87, 0x3b, 0x99, 0x8b, 0x69, 0x80, 0x7b, 0xc6, 0x3a, 0xeb, 0x93, 0xcf, 0x4e, 0xf8, 0x5c, 0x2d, 0x86, 0x42, 0xb6, 0x71, 0xd7, 0x97, 0x5f, 0xe1, 0x42, 0x67}} , {{0xb4, 0xb9, 0x37, 0xfc, 0xa9, 0x5b, 0x2f, 0x1e, 0x93, 0xe4, 0x1e, 0x62, 0xfc, 0x3c, 0x78, 0x81, 0x8f, 0xf3, 0x8a, 0x66, 0x09, 0x6f, 0xad, 0x6e, 0x79, 0x73, 0xe5, 0xc9, 0x00, 0x06, 0xd3, 0x21}}}, @@ -901,7 +901,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xf1, 0x79, 0x7b, 0xed, 0x4f, 0x44, 0xb2, 0xe7, 0x08, 0x0d, 0xc2, 0x08, 0x12, 0xd2, 0x9f, 0xdf, 0xcd, 0x93, 0x20, 0x8a, 0xcf, 0x33, 0xca, 0x6d, 0x89, 0xb9, 0x77, 0xc8, 0x93, 0x1b, 0x4e, 0x60}}}, {{{0x26, 0x4f, 0x7e, 0x97, 0xf6, 0x40, 0xdd, 0x4f, 0xfc, 0x52, 0x78, 0xf9, 0x90, 0x31, 0x03, 0xe6, 0x7d, 0x56, 0x39, 0x0b, 0x1d, 0x56, 0x82, 0x85, 0xf9, 0x1a, 0x42, 0x17, 0x69, 0x6c, 0xcf, 0x39}} , {{0x69, 0xd2, 0x06, 0x3a, 0x4f, 0x39, 0x2d, 0xf9, 0x38, 0x40, 0x8c, 0x4c, 0xe7, 0x05, 0x12, 0xb4, 0x78, 0x8b, 0xf8, 0xc0, 0xec, 0x93, 0xde, 0x7a, 0x6b, 0xce, 0x2c, 0xe1, 0x0e, 0xa9, 0x34, 0x44}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0b, 0xa4, 0x3c, 0xb0, 0x0f, 0x7a, 0x51, 0xf1, 0x78, 0xd6, 0xd9, 0x6a, 0xfd, 0x46, 0xe8, 0xb8, 0xa8, 0x79, 0x1d, 0x87, 0xf9, 0x90, 0xf2, 0x9c, 0x13, 0x29, 0xf8, 0x0b, 0x20, 0x64, 0xfa, 0x05}} , {{0x26, 0x09, 0xda, 0x17, 0xaf, 0x95, 0xd6, 0xfb, 0x6a, 0x19, 0x0d, 0x6e, 0x5e, 0x12, 0xf1, 0x99, 0x4c, 0xaa, 0xa8, 0x6f, 0x79, 0x86, 0xf4, 0x72, 0x28, 0x00, 0x26, 0xf9, 0xea, 0x9e, 0x19, 0x3d}}}, @@ -911,7 +911,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x1c, 0x59, 0x1c, 0x65, 0x5d, 0x34, 0xa4, 0x09, 0xcd, 0x13, 0x9c, 0x70, 0x7d, 0xb1, 0x2a, 0xc5, 0x88, 0xaf, 0x0b, 0x60, 0xc7, 0x9f, 0x34, 0x8d, 0xd6, 0xb7, 0x7f, 0xea, 0x78, 0x65, 0x8d, 0x77}}}, {{{0x56, 0xa5, 0xc2, 0x0c, 0xdd, 0xbc, 0xb8, 0x20, 0x6d, 0x57, 0x61, 0xb5, 0xfb, 0x78, 0xb5, 0xd4, 0x49, 0x54, 0x90, 0x26, 0xc1, 0xcb, 0xe9, 0xe6, 0xbf, 0xec, 0x1d, 0x4e, 0xed, 0x07, 0x7e, 0x5e}} , {{0xc7, 0xf6, 0x6c, 0x56, 0x31, 0x20, 0x14, 0x0e, 0xa8, 0xd9, 0x27, 0xc1, 0x9a, 0x3d, 0x1b, 0x7d, 0x0e, 0x26, 0xd3, 0x81, 0xaa, 0xeb, 0xf5, 0x6b, 0x79, 0x02, 0xf1, 0x51, 0x5c, 0x75, 0x55, 0x0f}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0a, 0x34, 0xcd, 0x82, 0x3c, 0x33, 0x09, 0x54, 0xd2, 0x61, 0x39, 0x30, 0x9b, 0xfd, 0xef, 0x21, 0x26, 0xd4, 0x70, 0xfa, 0xee, 0xf9, 0x31, 0x33, 0x73, 0x84, 0xd0, 0xb3, 0x81, 0xbf, 0xec, 0x2e}} , {{0xe8, 0x93, 0x8b, 0x00, 0x64, 0xf7, 0x9c, 0xb8, 0x74, 0xe0, 0xe6, 0x49, 0x48, 0x4d, 0x4d, 0x48, 0xb6, 0x19, 0xa1, 0x40, 0xb7, 0xd9, 0x32, 0x41, 0x7c, 0x82, 0x37, 0xa1, 0x2d, 0xdc, 0xd2, 0x54}}}, @@ -921,7 +921,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xbc, 0x58, 0xe6, 0xc0, 0x95, 0x2a, 0x2a, 0x81, 0x9a, 0x7a, 0xf3, 0xd2, 0x06, 0xbe, 0x48, 0xbc, 0x0c, 0xc5, 0x46, 0xe0, 0x6a, 0xd4, 0xac, 0x0f, 0xd9, 0xcc, 0x82, 0x34, 0x2c, 0xaf, 0xdb, 0x1f}}}, {{{0xf7, 0x17, 0x13, 0xbd, 0xfb, 0xbc, 0xd2, 0xec, 0x45, 0xb3, 0x15, 0x31, 0xe9, 0xaf, 0x82, 0x84, 0x3d, 0x28, 0xc6, 0xfc, 0x11, 0xf5, 0x41, 0xb5, 0x8b, 0xd3, 0x12, 0x76, 0x52, 0xe7, 0x1a, 0x3c}} , {{0x4e, 0x36, 0x11, 0x07, 0xa2, 0x15, 0x20, 0x51, 0xc4, 0x2a, 0xc3, 0x62, 0x8b, 0x5e, 0x7f, 0xa6, 0x0f, 0xf9, 0x45, 0x85, 0x6c, 0x11, 0x86, 0xb7, 0x7e, 0xe5, 0xd7, 0xf9, 0xc3, 0x91, 0x1c, 0x05}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xea, 0xd6, 0xde, 0x29, 0x3a, 0x00, 0xb9, 0x02, 0x59, 0xcb, 0x26, 0xc4, 0xba, 0x99, 0xb1, 0x97, 0x2f, 0x8e, 0x00, 0x92, 0x26, 0x4f, 0x52, 0xeb, 0x47, 0x1b, 0x89, 0x8b, 0x24, 0xc0, 0x13, 0x7d}} , {{0xd5, 0x20, 0x5b, 0x80, 0xa6, 0x80, 0x20, 0x95, 0xc3, 0xe9, 0x9f, 0x8e, 0x87, 0x9e, 0x1e, 0x9e, 0x7a, 0xc7, 0xcc, 0x75, 0x6c, 0xa5, 0xf1, 0x91, 0x1a, 0xa8, 0x01, 0x2c, 0xab, 0x76, 0xa9, 0x59}}}, @@ -931,7 +931,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x22, 0xf5, 0x5f, 0x4d, 0x15, 0xef, 0xfc, 0x4e, 0x57, 0x03, 0x36, 0x89, 0xf0, 0xeb, 0x5b, 0x91, 0xd6, 0xe2, 0xca, 0x01, 0xa5, 0xee, 0x52, 0xec, 0xa0, 0x3c, 0x8f, 0x33, 0x90, 0x5a, 0x94, 0x72}}}, {{{0x8a, 0x4b, 0xe7, 0x38, 0xbc, 0xda, 0xc2, 0xb0, 0x85, 0xe1, 0x4a, 0xfe, 0x2d, 0x44, 0x84, 0xcb, 0x20, 0x6b, 0x2d, 0xbf, 0x11, 0x9c, 0xd7, 0xbe, 0xd3, 0x3e, 0x5f, 0xbf, 0x68, 0xbc, 0xa8, 0x07}} , {{0x01, 0x89, 0x28, 0x22, 0x6a, 0x78, 0xaa, 0x29, 0x03, 0xc8, 0x74, 0x95, 0x03, 0x3e, 0xdc, 0xbd, 0x07, 0x13, 0xa8, 0xa2, 0x20, 0x2d, 0xb3, 0x18, 0x70, 0x42, 0xfd, 0x7a, 0xc4, 0xd7, 0x49, 0x72}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x02, 0xff, 0x32, 0x2b, 0x5c, 0x93, 0x54, 0x32, 0xe8, 0x57, 0x54, 0x1a, 0x8b, 0x33, 0x60, 0x65, 0xd3, 0x67, 0xa4, 0xc1, 0x26, 0xc4, 0xa4, 0x34, 0x1f, 0x9b, 0xa7, 0xa9, 0xf4, 0xd9, 0x4f, 0x5b}} , {{0x46, 0x8d, 0xb0, 0x33, 0x54, 0x26, 0x5b, 0x68, 0xdf, 0xbb, 0xc5, 0xec, 0xc2, 0xf9, 0x3c, 0x5a, 0x37, 0xc1, 0x8e, 0x27, 0x47, 0xaa, 0x49, 0x5a, 0xf8, 0xfb, 0x68, 0x04, 0x23, 0xd1, 0xeb, 0x40}}}, @@ -941,7 +941,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x60, 0xd6, 0xdd, 0x78, 0xe6, 0xd4, 0x22, 0x42, 0x1f, 0x00, 0xf9, 0xb1, 0x6a, 0x63, 0xe2, 0x92, 0x59, 0xd1, 0x1a, 0xb7, 0x00, 0x54, 0x29, 0xc9, 0xc1, 0xf6, 0x6f, 0x7a, 0xc5, 0x3c, 0x5f, 0x65}}}, {{{0x27, 0x4f, 0xd0, 0x72, 0xb1, 0x11, 0x14, 0x27, 0x15, 0x94, 0x48, 0x81, 0x7e, 0x74, 0xd8, 0x32, 0xd5, 0xd1, 0x11, 0x28, 0x60, 0x63, 0x36, 0x32, 0x37, 0xb5, 0x13, 0x1c, 0xa0, 0x37, 0xe3, 0x74}} , {{0xf1, 0x25, 0x4e, 0x11, 0x96, 0x67, 0xe6, 0x1c, 0xc2, 0xb2, 0x53, 0xe2, 0xda, 0x85, 0xee, 0xb2, 0x9f, 0x59, 0xf3, 0xba, 0xbd, 0xfa, 0xcf, 0x6e, 0xf9, 0xda, 0xa4, 0xb3, 0x02, 0x8f, 0x64, 0x08}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x34, 0x94, 0xf2, 0x64, 0x54, 0x47, 0x37, 0x07, 0x40, 0x8a, 0x20, 0xba, 0x4a, 0x55, 0xd7, 0x3f, 0x47, 0xba, 0x25, 0x23, 0x14, 0xb0, 0x2c, 0xe8, 0x55, 0xa8, 0xa6, 0xef, 0x51, 0xbd, 0x6f, 0x6a}} , {{0x71, 0xd6, 0x16, 0x76, 0xb2, 0x06, 0xea, 0x79, 0xf5, 0xc4, 0xc3, 0x52, 0x7e, 0x61, 0xd1, 0xe1, 0xad, 0x70, 0x78, 0x1d, 0x16, 0x11, 0xf8, 0x7c, 0x2b, 0xfc, 0x55, 0x9f, 0x52, 0xf8, 0xf5, 0x16}}}, @@ -951,7 +951,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x02, 0xcc, 0x22, 0x74, 0x4d, 0x19, 0x07, 0xc0, 0xda, 0xb5, 0x76, 0x51, 0x2a, 0xaa, 0xa6, 0x0a, 0x5f, 0x26, 0xd4, 0xbc, 0xaf, 0x48, 0x88, 0x7f, 0x02, 0xbc, 0xf2, 0xe1, 0xcf, 0xe9, 0xdd, 0x15}}}, {{{0xed, 0xb5, 0x9a, 0x8c, 0x9a, 0xdd, 0x27, 0xf4, 0x7f, 0x47, 0xd9, 0x52, 0xa7, 0xcd, 0x65, 0xa5, 0x31, 0x22, 0xed, 0xa6, 0x63, 0x5b, 0x80, 0x4a, 0xad, 0x4d, 0xed, 0xbf, 0xee, 0x49, 0xb3, 0x06}} , {{0xf8, 0x64, 0x8b, 0x60, 0x90, 0xe9, 0xde, 0x44, 0x77, 0xb9, 0x07, 0x36, 0x32, 0xc2, 0x50, 0xf5, 0x65, 0xdf, 0x48, 0x4c, 0x37, 0xaa, 0x68, 0xab, 0x9a, 0x1f, 0x3e, 0xff, 0x89, 0x92, 0xa0, 0x07}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x7d, 0x4f, 0x9c, 0x19, 0xc0, 0x4a, 0x31, 0xec, 0xf9, 0xaa, 0xeb, 0xb2, 0x16, 0x9c, 0xa3, 0x66, 0x5f, 0xd1, 0xd4, 0xed, 0xb8, 0x92, 0x1c, 0xab, 0xda, 0xea, 0xd9, 0x57, 0xdf, 0x4c, 0x2a, 0x48}} , {{0x4b, 0xb0, 0x4e, 0x6e, 0x11, 0x3b, 0x51, 0xbd, 0x6a, 0xfd, 0xe4, 0x25, 0xa5, 0x5f, 0x11, 0x3f, 0x98, 0x92, 0x51, 0x14, 0xc6, 0x5f, 0x3c, 0x0b, 0xa8, 0xf7, 0xc2, 0x81, 0x43, 0xde, 0x91, 0x73}}}, @@ -961,7 +961,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x2e, 0x69, 0x98, 0xfd, 0xc6, 0xbd, 0xcc, 0xca, 0xdf, 0x9a, 0x44, 0x7e, 0x9d, 0xca, 0x89, 0x6d, 0xbf, 0x27, 0xc2, 0xf8, 0xcd, 0x46, 0x00, 0x2b, 0xb5, 0x58, 0x4e, 0xb7, 0x89, 0x09, 0xe9, 0x2d}}}, {{{0x54, 0xbe, 0x75, 0xcb, 0x05, 0xb0, 0x54, 0xb7, 0xe7, 0x26, 0x86, 0x4a, 0xfc, 0x19, 0xcf, 0x27, 0x46, 0xd4, 0x22, 0x96, 0x5a, 0x11, 0xe8, 0xd5, 0x1b, 0xed, 0x71, 0xc5, 0x5d, 0xc8, 0xaf, 0x45}} , {{0x40, 0x7b, 0x77, 0x57, 0x49, 0x9e, 0x80, 0x39, 0x23, 0xee, 0x81, 0x0b, 0x22, 0xcf, 0xdb, 0x7a, 0x2f, 0x14, 0xb8, 0x57, 0x8f, 0xa1, 0x39, 0x1e, 0x77, 0xfc, 0x0b, 0xa6, 0xbf, 0x8a, 0x0c, 0x6c}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x77, 0x3a, 0xd4, 0xd8, 0x27, 0xcf, 0xe8, 0xa1, 0x72, 0x9d, 0xca, 0xdd, 0x0d, 0x96, 0xda, 0x79, 0xed, 0x56, 0x42, 0x15, 0x60, 0xc7, 0x1c, 0x6b, 0x26, 0x30, 0xf6, 0x6a, 0x95, 0x67, 0xf3, 0x0a}} , {{0xc5, 0x08, 0xa4, 0x2b, 0x2f, 0xbd, 0x31, 0x81, 0x2a, 0xa6, 0xb6, 0xe4, 0x00, 0x91, 0xda, 0x3d, 0xb2, 0xb0, 0x96, 0xce, 0x8a, 0xd2, 0x8d, 0x70, 0xb3, 0xd3, 0x34, 0x01, 0x90, 0x8d, 0x10, 0x21}}}, @@ -971,7 +971,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x61, 0x36, 0xd6, 0x08, 0x90, 0xbf, 0xa7, 0x7a, 0x97, 0x6c, 0x0f, 0x84, 0xd5, 0x33, 0x2d, 0x37, 0xc9, 0x6a, 0x80, 0x90, 0x3d, 0x0a, 0xa2, 0xaa, 0xe1, 0xb8, 0x84, 0xba, 0x61, 0x36, 0xdd, 0x69}}}, {{{0x6b, 0xdb, 0x5b, 0x9c, 0xc6, 0x92, 0xbc, 0x23, 0xaf, 0xc5, 0xb8, 0x75, 0xf8, 0x42, 0xfa, 0xd6, 0xb6, 0x84, 0x94, 0x63, 0x98, 0x93, 0x48, 0x78, 0x38, 0xcd, 0xbb, 0x18, 0x34, 0xc3, 0xdb, 0x67}} , {{0x96, 0xf3, 0x3a, 0x09, 0x56, 0xb0, 0x6f, 0x7c, 0x51, 0x1e, 0x1b, 0x39, 0x48, 0xea, 0xc9, 0x0c, 0x25, 0xa2, 0x7a, 0xca, 0xe7, 0x92, 0xfc, 0x59, 0x30, 0xa3, 0x89, 0x85, 0xdf, 0x6f, 0x43, 0x38}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x79, 0x84, 0x44, 0x19, 0xbd, 0xe9, 0x54, 0xc4, 0xc0, 0x6e, 0x2a, 0xa8, 0xa8, 0x9b, 0x43, 0xd5, 0x71, 0x22, 0x5f, 0xdc, 0x01, 0xfa, 0xdf, 0xb3, 0xb8, 0x47, 0x4b, 0x0a, 0xa5, 0x44, 0xea, 0x29}} , {{0x05, 0x90, 0x50, 0xaf, 0x63, 0x5f, 0x9d, 0x9e, 0xe1, 0x9d, 0x38, 0x97, 0x1f, 0x6c, 0xac, 0x30, 0x46, 0xb2, 0x6a, 0x19, 0xd1, 0x4b, 0xdb, 0xbb, 0x8c, 0xda, 0x2e, 0xab, 0xc8, 0x5a, 0x77, 0x6c}}}, @@ -981,7 +981,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x5d, 0x04, 0xb3, 0x40, 0x28, 0x95, 0x2d, 0x30, 0x83, 0xec, 0x5e, 0xe4, 0xff, 0x75, 0xfe, 0x79, 0x26, 0x9d, 0x1d, 0x36, 0xcd, 0x0a, 0x15, 0xd2, 0x24, 0x14, 0x77, 0x71, 0xd7, 0x8a, 0x1b, 0x04}}}, {{{0x5d, 0x93, 0xc9, 0xbe, 0xaa, 0x90, 0xcd, 0x9b, 0xfb, 0x73, 0x7e, 0xb0, 0x64, 0x98, 0x57, 0x44, 0x42, 0x41, 0xb1, 0xaf, 0xea, 0xc1, 0xc3, 0x22, 0xff, 0x60, 0x46, 0xcb, 0x61, 0x81, 0x70, 0x61}} , {{0x0d, 0x82, 0xb9, 0xfe, 0x21, 0xcd, 0xc4, 0xf5, 0x98, 0x0c, 0x4e, 0x72, 0xee, 0x87, 0x49, 0xf8, 0xa1, 0x95, 0xdf, 0x8f, 0x2d, 0xbd, 0x21, 0x06, 0x7c, 0x15, 0xe8, 0x12, 0x6d, 0x93, 0xd6, 0x38}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x91, 0xf7, 0x51, 0xd9, 0xef, 0x7d, 0x42, 0x01, 0x13, 0xe9, 0xb8, 0x7f, 0xa6, 0x49, 0x17, 0x64, 0x21, 0x80, 0x83, 0x2c, 0x63, 0x4c, 0x60, 0x09, 0x59, 0x91, 0x92, 0x77, 0x39, 0x51, 0xf4, 0x48}} , {{0x60, 0xd5, 0x22, 0x83, 0x08, 0x2f, 0xff, 0x99, 0x3e, 0x69, 0x6d, 0x88, 0xda, 0xe7, 0x5b, 0x52, 0x26, 0x31, 0x2a, 0xe5, 0x89, 0xde, 0x68, 0x90, 0xb6, 0x22, 0x5a, 0xbd, 0xd3, 0x85, 0x53, 0x31}}}, @@ -991,7 +991,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xba, 0x38, 0x02, 0xf7, 0x81, 0x43, 0x83, 0xa3, 0x20, 0x4f, 0x01, 0x3b, 0x8a, 0x04, 0x38, 0x31, 0xc6, 0x0f, 0xc8, 0xdf, 0xd7, 0xfa, 0x2f, 0x88, 0x3f, 0xfc, 0x0c, 0x76, 0xc4, 0xa6, 0x45, 0x72}}}, {{{0xbb, 0x0c, 0xbc, 0x6a, 0xa4, 0x97, 0x17, 0x93, 0x2d, 0x6f, 0xde, 0x72, 0x10, 0x1c, 0x08, 0x2c, 0x0f, 0x80, 0x32, 0x68, 0x27, 0xd4, 0xab, 0xdd, 0xc5, 0x58, 0x61, 0x13, 0x6d, 0x11, 0x1e, 0x4d}} , {{0x1a, 0xb9, 0xc9, 0x10, 0xfb, 0x1e, 0x4e, 0xf4, 0x84, 0x4b, 0x8a, 0x5e, 0x7b, 0x4b, 0xe8, 0x43, 0x8c, 0x8f, 0x00, 0xb5, 0x54, 0x13, 0xc5, 0x5c, 0xb6, 0x35, 0x4e, 0x9d, 0xe4, 0x5b, 0x41, 0x6d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x15, 0x7d, 0x12, 0x48, 0x82, 0x14, 0x42, 0xcd, 0x32, 0xd4, 0x4b, 0xc1, 0x72, 0x61, 0x2a, 0x8c, 0xec, 0xe2, 0xf8, 0x24, 0x45, 0x94, 0xe3, 0xbe, 0xdd, 0x67, 0xa8, 0x77, 0x5a, 0xae, 0x5b, 0x4b}} , {{0xcb, 0x77, 0x9a, 0x20, 0xde, 0xb8, 0x23, 0xd9, 0xa0, 0x0f, 0x8c, 0x7b, 0xa5, 0xcb, 0xae, 0xb6, 0xec, 0x42, 0x67, 0x0e, 0x58, 0xa4, 0x75, 0x98, 0x21, 0x71, 0x84, 0xb3, 0xe0, 0x76, 0x94, 0x73}}}, @@ -1001,7 +1001,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x32, 0xfb, 0x86, 0xec, 0x33, 0x6b, 0x2e, 0x51, 0x2b, 0xc8, 0xfa, 0x6c, 0x70, 0x47, 0x7e, 0xce, 0x05, 0x0c, 0x71, 0xf3, 0xb4, 0x56, 0xa6, 0xdc, 0xcc, 0x78, 0x07, 0x75, 0xd0, 0xdd, 0xb2, 0x6a}}}, {{{0xc6, 0xef, 0xb9, 0xc0, 0x2b, 0x22, 0x08, 0x1e, 0x71, 0x70, 0xb3, 0x35, 0x9c, 0x7a, 0x01, 0x92, 0x44, 0x9a, 0xf6, 0xb0, 0x58, 0x95, 0xc1, 0x9b, 0x02, 0xed, 0x2d, 0x7c, 0x34, 0x29, 0x49, 0x44}} , {{0x45, 0x62, 0x1d, 0x2e, 0xff, 0x2a, 0x1c, 0x21, 0xa4, 0x25, 0x7b, 0x0d, 0x8c, 0x15, 0x39, 0xfc, 0x8f, 0x7c, 0xa5, 0x7d, 0x1e, 0x25, 0xa3, 0x45, 0xd6, 0xab, 0xbd, 0xcb, 0xc5, 0x5e, 0x78, 0x77}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0xd3, 0x42, 0xed, 0x1d, 0x00, 0x3c, 0x15, 0x2c, 0x9c, 0x77, 0x81, 0xd2, 0x73, 0xd1, 0x06, 0xd5, 0xc4, 0x7f, 0x94, 0xbb, 0x92, 0x2d, 0x2c, 0x4b, 0x45, 0x4b, 0xe9, 0x2a, 0x89, 0x6b, 0x2b}} , {{0xd2, 0x0c, 0x88, 0xc5, 0x48, 0x4d, 0xea, 0x0d, 0x4a, 0xc9, 0x52, 0x6a, 0x61, 0x79, 0xe9, 0x76, 0xf3, 0x85, 0x52, 0x5c, 0x1b, 0x2c, 0xe1, 0xd6, 0xc4, 0x0f, 0x18, 0x0e, 0x4e, 0xf6, 0x1c, 0x7f}}}, @@ -1011,7 +1011,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x4c, 0xe6, 0xb0, 0xc1, 0xa5, 0x2a, 0x82, 0x09, 0x08, 0xad, 0x79, 0x9c, 0x56, 0xf6, 0xf9, 0xc1, 0xd7, 0x7c, 0x39, 0x7f, 0x93, 0xca, 0x11, 0x55, 0xbf, 0x07, 0x1b, 0x82, 0x29, 0x69, 0x95, 0x5c}}}, {{{0x87, 0xee, 0xa6, 0x56, 0x9e, 0xc2, 0x9a, 0x56, 0x24, 0x42, 0x85, 0x4d, 0x98, 0x31, 0x1e, 0x60, 0x4d, 0x87, 0x85, 0x04, 0xae, 0x46, 0x12, 0xf9, 0x8e, 0x7f, 0xe4, 0x7f, 0xf6, 0x1c, 0x37, 0x01}} , {{0x73, 0x4c, 0xb6, 0xc5, 0xc4, 0xe9, 0x6c, 0x85, 0x48, 0x4a, 0x5a, 0xac, 0xd9, 0x1f, 0x43, 0xf8, 0x62, 0x5b, 0xee, 0x98, 0x2a, 0x33, 0x8e, 0x79, 0xce, 0x61, 0x06, 0x35, 0xd8, 0xd7, 0xca, 0x71}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x72, 0xd3, 0xae, 0xa6, 0xca, 0x8f, 0xcd, 0xcc, 0x78, 0x8e, 0x19, 0x4d, 0xa7, 0xd2, 0x27, 0xe9, 0xa4, 0x3c, 0x16, 0x5b, 0x84, 0x80, 0xf9, 0xd0, 0xcc, 0x6a, 0x1e, 0xca, 0x1e, 0x67, 0xbd, 0x63}} , {{0x7b, 0x6e, 0x2a, 0xd2, 0x87, 0x48, 0xff, 0xa1, 0xca, 0xe9, 0x15, 0x85, 0xdc, 0xdb, 0x2c, 0x39, 0x12, 0x91, 0xa9, 0x20, 0xaa, 0x4f, 0x29, 0xf4, 0x15, 0x7a, 0xd2, 0xf5, 0x32, 0xcc, 0x60, 0x04}}}, @@ -1021,7 +1021,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xbb, 0x40, 0x5e, 0xbc, 0x16, 0x92, 0x05, 0xc4, 0xc0, 0x4e, 0x72, 0x90, 0x0e, 0xab, 0xcf, 0x8a, 0xed, 0xef, 0xb9, 0x2d, 0x3b, 0xf8, 0x43, 0x5b, 0xba, 0x2d, 0xeb, 0x2f, 0x52, 0xd2, 0xd1, 0x5a}}}, {{{0x40, 0xb4, 0xab, 0xe6, 0xad, 0x9f, 0x46, 0x69, 0x4a, 0xb3, 0x8e, 0xaa, 0xea, 0x9c, 0x8a, 0x20, 0x16, 0x5d, 0x8c, 0x13, 0xbd, 0xf6, 0x1d, 0xc5, 0x24, 0xbd, 0x90, 0x2a, 0x1c, 0xc7, 0x13, 0x3b}} , {{0x54, 0xdc, 0x16, 0x0d, 0x18, 0xbe, 0x35, 0x64, 0x61, 0x52, 0x02, 0x80, 0xaf, 0x05, 0xf7, 0xa6, 0x42, 0xd3, 0x8f, 0x2e, 0x79, 0x26, 0xa8, 0xbb, 0xb2, 0x17, 0x48, 0xb2, 0x7a, 0x0a, 0x89, 0x14}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x20, 0xa8, 0x88, 0xe3, 0x91, 0xc0, 0x6e, 0xbb, 0x8a, 0x27, 0x82, 0x51, 0x83, 0xb2, 0x28, 0xa9, 0x83, 0xeb, 0xa6, 0xa9, 0x4d, 0x17, 0x59, 0x22, 0x54, 0x00, 0x50, 0x45, 0xcb, 0x48, 0x4b, 0x18}} , {{0x33, 0x7c, 0xe7, 0x26, 0xba, 0x4d, 0x32, 0xfe, 0x53, 0xf4, 0xfa, 0x83, 0xe3, 0xa5, 0x79, 0x66, 0x73, 0xef, 0x80, 0x23, 0x68, 0xc2, 0x60, 0xdd, 0xa9, 0x33, 0xdc, 0x03, 0x7a, 0xe0, 0xe0, 0x3e}}}, @@ -1031,7 +1031,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x6e, 0x44, 0xa3, 0xf9, 0x64, 0xaf, 0xe7, 0x6d, 0x7d, 0xdf, 0x1e, 0xac, 0x04, 0xea, 0x3b, 0x5f, 0x9b, 0xe8, 0x24, 0x9d, 0x0e, 0xe5, 0x2e, 0x3e, 0xdf, 0xa9, 0xf7, 0xd4, 0x50, 0x71, 0xf0, 0x78}}}, {{{0x3e, 0xa8, 0x38, 0xc2, 0x57, 0x56, 0x42, 0x9a, 0xb1, 0xe2, 0xf8, 0x45, 0xaa, 0x11, 0x48, 0x5f, 0x17, 0xc4, 0x54, 0x27, 0xdc, 0x5d, 0xaa, 0xdd, 0x41, 0xbc, 0xdf, 0x81, 0xb9, 0x53, 0xee, 0x52}} , {{0xc3, 0xf1, 0xa7, 0x6d, 0xb3, 0x5f, 0x92, 0x6f, 0xcc, 0x91, 0xb8, 0x95, 0x05, 0xdf, 0x3c, 0x64, 0x57, 0x39, 0x61, 0x51, 0xad, 0x8c, 0x38, 0x7b, 0xc8, 0xde, 0x00, 0x34, 0xbe, 0xa1, 0xb0, 0x7e}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0x24, 0x1d, 0x8a, 0x67, 0x20, 0xee, 0x42, 0xeb, 0x38, 0xed, 0x0b, 0x8b, 0xcd, 0x46, 0x9d, 0x5e, 0x6b, 0x1e, 0x24, 0x9d, 0x12, 0x05, 0x1a, 0xcc, 0x05, 0x4e, 0x92, 0x38, 0xe1, 0x1f, 0x50}} , {{0x4e, 0xee, 0x1c, 0x91, 0xe6, 0x11, 0xbd, 0x8e, 0x55, 0x1a, 0x18, 0x75, 0x66, 0xaf, 0x4d, 0x7b, 0x0f, 0xae, 0x6d, 0x85, 0xca, 0x82, 0x58, 0x21, 0x9c, 0x18, 0xe0, 0xed, 0xec, 0x22, 0x80, 0x2f}}}, @@ -1041,7 +1041,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xa1, 0x0c, 0xf3, 0x08, 0x43, 0xd9, 0x24, 0x1e, 0x83, 0xa7, 0xdf, 0x91, 0xca, 0xbd, 0x69, 0x47, 0x8d, 0x1b, 0xe2, 0xb9, 0x4e, 0xb5, 0xe1, 0x76, 0xb3, 0x1c, 0x93, 0x03, 0xce, 0x5f, 0xb3, 0x5a}}}, {{{0x1d, 0xda, 0xe4, 0x61, 0x03, 0x50, 0xa9, 0x8b, 0x68, 0x18, 0xef, 0xb2, 0x1c, 0x84, 0x3b, 0xa2, 0x44, 0x95, 0xa3, 0x04, 0x3b, 0xd6, 0x99, 0x00, 0xaf, 0x76, 0x42, 0x67, 0x02, 0x7d, 0x85, 0x56}} , {{0xce, 0x72, 0x0e, 0x29, 0x84, 0xb2, 0x7d, 0xd2, 0x45, 0xbe, 0x57, 0x06, 0xed, 0x7f, 0xcf, 0xed, 0xcd, 0xef, 0x19, 0xd6, 0xbc, 0x15, 0x79, 0x64, 0xd2, 0x18, 0xe3, 0x20, 0x67, 0x3a, 0x54, 0x0b}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x52, 0xfd, 0x04, 0xc5, 0xfb, 0x99, 0xe7, 0xe8, 0xfb, 0x8c, 0xe1, 0x42, 0x03, 0xef, 0x9d, 0xd9, 0x9e, 0x4d, 0xf7, 0x80, 0xcf, 0x2e, 0xcc, 0x9b, 0x45, 0xc9, 0x7b, 0x7a, 0xbc, 0x37, 0xa8, 0x52}} , {{0x96, 0x11, 0x41, 0x8a, 0x47, 0x91, 0xfe, 0xb6, 0xda, 0x7a, 0x54, 0x63, 0xd1, 0x14, 0x35, 0x05, 0x86, 0x8c, 0xa9, 0x36, 0x3f, 0xf2, 0x85, 0x54, 0x4e, 0x92, 0xd8, 0x85, 0x01, 0x46, 0xd6, 0x50}}}, @@ -1051,7 +1051,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x93, 0x1c, 0x06, 0x2d, 0x66, 0x65, 0x02, 0xa4, 0x97, 0x18, 0xfd, 0x00, 0xe7, 0xab, 0x03, 0xec, 0xce, 0xc1, 0xbf, 0x37, 0xf8, 0x13, 0x53, 0xa5, 0xe5, 0x0c, 0x3a, 0xa8, 0x55, 0xb9, 0xff, 0x68}}}, {{{0xe4, 0xe6, 0x6d, 0x30, 0x7d, 0x30, 0x35, 0xc2, 0x78, 0x87, 0xf9, 0xfc, 0x6b, 0x5a, 0xc3, 0xb7, 0x65, 0xd8, 0x2e, 0xc7, 0xa5, 0x0c, 0xc6, 0xdc, 0x12, 0xaa, 0xd6, 0x4f, 0xc5, 0x38, 0xbc, 0x0e}} , {{0xe2, 0x3c, 0x76, 0x86, 0x38, 0xf2, 0x7b, 0x2c, 0x16, 0x78, 0x8d, 0xf5, 0xa4, 0x15, 0xda, 0xdb, 0x26, 0x85, 0xa0, 0x56, 0xdd, 0x1d, 0xe3, 0xb3, 0xfd, 0x40, 0xef, 0xf2, 0xd9, 0xa1, 0xb3, 0x04}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xdb, 0x49, 0x0e, 0xe6, 0x58, 0x10, 0x7a, 0x52, 0xda, 0xb5, 0x7d, 0x37, 0x6a, 0x3e, 0xa1, 0x78, 0xce, 0xc7, 0x1c, 0x24, 0x23, 0xdb, 0x7d, 0xfb, 0x8c, 0x8d, 0xdc, 0x30, 0x67, 0x69, 0x75, 0x3b}} , {{0xa9, 0xea, 0x6d, 0x16, 0x16, 0x60, 0xf4, 0x60, 0x87, 0x19, 0x44, 0x8c, 0x4a, 0x8b, 0x3e, 0xfb, 0x16, 0x00, 0x00, 0x54, 0xa6, 0x9e, 0x9f, 0xef, 0xcf, 0xd9, 0xd2, 0x4c, 0x74, 0x31, 0xd0, 0x34}}}, @@ -1061,7 +1061,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xb0, 0x8b, 0xaa, 0x1e, 0xec, 0xc7, 0xa5, 0x8f, 0x1f, 0x92, 0x04, 0xc6, 0x05, 0xf6, 0xdf, 0xa1, 0xcc, 0x1f, 0x81, 0xf5, 0x0e, 0x9c, 0x57, 0xdc, 0xe3, 0xbb, 0x06, 0x87, 0x1e, 0xfe, 0x23, 0x6c}}}, {{{0xd8, 0x2b, 0x5b, 0x16, 0xea, 0x20, 0xf1, 0xd3, 0x68, 0x8f, 0xae, 0x5b, 0xd0, 0xa9, 0x1a, 0x19, 0xa8, 0x36, 0xfb, 0x2b, 0x57, 0x88, 0x7d, 0x90, 0xd5, 0xa6, 0xf3, 0xdc, 0x38, 0x89, 0x4e, 0x1f}} , {{0xcc, 0x19, 0xda, 0x9b, 0x3b, 0x43, 0x48, 0x21, 0x2e, 0x23, 0x4d, 0x3d, 0xae, 0xf8, 0x8c, 0xfc, 0xdd, 0xa6, 0x74, 0x37, 0x65, 0xca, 0xee, 0x1a, 0x19, 0x8e, 0x9f, 0x64, 0x6f, 0x0c, 0x8b, 0x5a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0xb9, 0xc2, 0xf0, 0x72, 0xb8, 0x15, 0x16, 0xcc, 0x8d, 0x3c, 0x6f, 0x25, 0xed, 0xf4, 0x46, 0x2e, 0x0c, 0x60, 0x0f, 0xe2, 0x84, 0x34, 0x55, 0x89, 0x59, 0x34, 0x1b, 0xf5, 0x8d, 0xfe, 0x08}} , {{0xf8, 0xab, 0x93, 0xbc, 0x44, 0xba, 0x1b, 0x75, 0x4b, 0x49, 0x6f, 0xd0, 0x54, 0x2e, 0x63, 0xba, 0xb5, 0xea, 0xed, 0x32, 0x14, 0xc9, 0x94, 0xd8, 0xc5, 0xce, 0xf4, 0x10, 0x68, 0xe0, 0x38, 0x27}}}, @@ -1071,7 +1071,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x6c, 0xba, 0x14, 0xc5, 0xea, 0x12, 0x9e, 0x2e, 0x82, 0x63, 0xce, 0x9b, 0x4a, 0xe7, 0x1d, 0xec, 0xf1, 0x2e, 0x51, 0x1c, 0xf4, 0xd0, 0x69, 0x15, 0x42, 0x9d, 0xa3, 0x3f, 0x0e, 0xbf, 0xe9, 0x5c}}}, {{{0xe4, 0x0d, 0xf4, 0xbd, 0xee, 0x31, 0x10, 0xed, 0xcb, 0x12, 0x86, 0xad, 0xd4, 0x2f, 0x90, 0x37, 0x32, 0xc3, 0x0b, 0x73, 0xec, 0x97, 0x85, 0xa4, 0x01, 0x1c, 0x76, 0x35, 0xfe, 0x75, 0xdd, 0x71}} , {{0x11, 0xa4, 0x88, 0x9f, 0x3e, 0x53, 0x69, 0x3b, 0x1b, 0xe0, 0xf7, 0xba, 0x9b, 0xad, 0x4e, 0x81, 0x5f, 0xb5, 0x5c, 0xae, 0xbe, 0x67, 0x86, 0x37, 0x34, 0x8e, 0x07, 0x32, 0x45, 0x4a, 0x67, 0x39}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x90, 0x70, 0x58, 0x20, 0x03, 0x1e, 0x67, 0xb2, 0xc8, 0x9b, 0x58, 0xc5, 0xb1, 0xeb, 0x2d, 0x4a, 0xde, 0x82, 0x8c, 0xf2, 0xd2, 0x14, 0xb8, 0x70, 0x61, 0x4e, 0x73, 0xd6, 0x0b, 0x6b, 0x0d, 0x30}} , {{0x81, 0xfc, 0x55, 0x5c, 0xbf, 0xa7, 0xc4, 0xbd, 0xe2, 0xf0, 0x4b, 0x8f, 0xe9, 0x7d, 0x99, 0xfa, 0xd3, 0xab, 0xbc, 0xc7, 0x83, 0x2b, 0x04, 0x7f, 0x0c, 0x19, 0x43, 0x03, 0x3d, 0x07, 0xca, 0x40}}}, @@ -1081,7 +1081,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x17, 0x62, 0x6b, 0x14, 0xa1, 0x7c, 0xd0, 0x79, 0x6e, 0xd8, 0x8a, 0xa5, 0x6d, 0x8c, 0x93, 0xd2, 0x3f, 0xec, 0x44, 0x8d, 0x6e, 0x91, 0x01, 0x8c, 0x8f, 0xee, 0x01, 0x8f, 0xc0, 0xb4, 0x85, 0x0e}}}, {{{0x02, 0x3a, 0x70, 0x41, 0xe4, 0x11, 0x57, 0x23, 0xac, 0xe6, 0xfc, 0x54, 0x7e, 0xcd, 0xd7, 0x22, 0xcb, 0x76, 0x9f, 0x20, 0xce, 0xa0, 0x73, 0x76, 0x51, 0x3b, 0xa4, 0xf8, 0xe3, 0x62, 0x12, 0x6c}} , {{0x7f, 0x00, 0x9c, 0x26, 0x0d, 0x6f, 0x48, 0x7f, 0x3a, 0x01, 0xed, 0xc5, 0x96, 0xb0, 0x1f, 0x4f, 0xa8, 0x02, 0x62, 0x27, 0x8a, 0x50, 0x8d, 0x9a, 0x8b, 0x52, 0x0f, 0x1e, 0xcf, 0x41, 0x38, 0x19}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf5, 0x6c, 0xd4, 0x2f, 0x0f, 0x69, 0x0f, 0x87, 0x3f, 0x61, 0x65, 0x1e, 0x35, 0x34, 0x85, 0xba, 0x02, 0x30, 0xac, 0x25, 0x3d, 0xe2, 0x62, 0xf1, 0xcc, 0xe9, 0x1b, 0xc2, 0xef, 0x6a, 0x42, 0x57}} , {{0x34, 0x1f, 0x2e, 0xac, 0xd1, 0xc7, 0x04, 0x52, 0x32, 0x66, 0xb2, 0x33, 0x73, 0x21, 0x34, 0x54, 0xf7, 0x71, 0xed, 0x06, 0xb0, 0xff, 0xa6, 0x59, 0x6f, 0x8a, 0x4e, 0xfb, 0x02, 0xb0, 0x45, 0x6b}}}, @@ -1091,7 +1091,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xdd, 0xb5, 0x7d, 0xab, 0x5a, 0x21, 0x41, 0x53, 0xbb, 0x17, 0x79, 0x0d, 0xd1, 0xa8, 0x0c, 0x0c, 0x20, 0x88, 0x09, 0xe9, 0x84, 0xe8, 0x25, 0x11, 0x67, 0x7a, 0x8b, 0x1a, 0xe4, 0x5d, 0xe1, 0x5d}}}, {{{0x37, 0xea, 0xfe, 0x65, 0x3b, 0x25, 0xe8, 0xe1, 0xc2, 0xc5, 0x02, 0xa4, 0xbe, 0x98, 0x0a, 0x2b, 0x61, 0xc1, 0x9b, 0xe2, 0xd5, 0x92, 0xe6, 0x9e, 0x7d, 0x1f, 0xca, 0x43, 0x88, 0x8b, 0x2c, 0x59}} , {{0xe0, 0xb5, 0x00, 0x1d, 0x2a, 0x6f, 0xaf, 0x79, 0x86, 0x2f, 0xa6, 0x5a, 0x93, 0xd1, 0xfe, 0xae, 0x3a, 0xee, 0xdb, 0x7c, 0x61, 0xbe, 0x7c, 0x01, 0xf9, 0xfe, 0x52, 0xdc, 0xd8, 0x52, 0xa3, 0x42}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x22, 0xaf, 0x13, 0x37, 0xbd, 0x37, 0x71, 0xac, 0x04, 0x46, 0x63, 0xac, 0xa4, 0x77, 0xed, 0x25, 0x38, 0xe0, 0x15, 0xa8, 0x64, 0x00, 0x0d, 0xce, 0x51, 0x01, 0xa9, 0xbc, 0x0f, 0x03, 0x1c, 0x04}} , {{0x89, 0xf9, 0x80, 0x07, 0xcf, 0x3f, 0xb3, 0xe9, 0xe7, 0x45, 0x44, 0x3d, 0x2a, 0x7c, 0xe9, 0xe4, 0x16, 0x5c, 0x5e, 0x65, 0x1c, 0xc7, 0x7d, 0xc6, 0x7a, 0xfb, 0x43, 0xee, 0x25, 0x76, 0x46, 0x72}}}, @@ -1101,7 +1101,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x0d, 0xac, 0x66, 0x6d, 0xc3, 0x8b, 0xba, 0x16, 0xb5, 0xe2, 0xa0, 0x0d, 0x0c, 0xbd, 0xa4, 0x8e, 0x18, 0x6c, 0xf2, 0xdc, 0xf9, 0xdc, 0x4a, 0x86, 0x25, 0x95, 0x14, 0xcb, 0xd8, 0x1a, 0x04, 0x0f}}}, {{{0x97, 0xa5, 0xdb, 0x8b, 0x2d, 0xaa, 0x42, 0x11, 0x09, 0xf2, 0x93, 0xbb, 0xd9, 0x06, 0x84, 0x4e, 0x11, 0xa8, 0xa0, 0x25, 0x2b, 0xa6, 0x5f, 0xae, 0xc4, 0xb4, 0x4c, 0xc8, 0xab, 0xc7, 0x3b, 0x02}} , {{0xee, 0xc9, 0x29, 0x0f, 0xdf, 0x11, 0x85, 0xed, 0xce, 0x0d, 0x62, 0x2c, 0x8f, 0x4b, 0xf9, 0x04, 0xe9, 0x06, 0x72, 0x1d, 0x37, 0x20, 0x50, 0xc9, 0x14, 0xeb, 0xec, 0x39, 0xa7, 0x97, 0x2b, 0x4d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x69, 0xd1, 0x39, 0xbd, 0xfb, 0x33, 0xbe, 0xc4, 0xf0, 0x5c, 0xef, 0xf0, 0x56, 0x68, 0xfc, 0x97, 0x47, 0xc8, 0x72, 0xb6, 0x53, 0xa4, 0x0a, 0x98, 0xa5, 0xb4, 0x37, 0x71, 0xcf, 0x66, 0x50, 0x6d}} , {{0x17, 0xa4, 0x19, 0x52, 0x11, 0x47, 0xb3, 0x5c, 0x5b, 0xa9, 0x2e, 0x22, 0xb4, 0x00, 0x52, 0xf9, 0x57, 0x18, 0xb8, 0xbe, 0x5a, 0xe3, 0xab, 0x83, 0xc8, 0x87, 0x0a, 0x2a, 0xd8, 0x8c, 0xbb, 0x54}}}, @@ -1111,7 +1111,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x20, 0xd6, 0xd8, 0x91, 0x54, 0xa7, 0xf3, 0x20, 0x4b, 0x34, 0x06, 0xfa, 0x30, 0xc8, 0x6f, 0x14, 0x10, 0x65, 0x74, 0x13, 0x4e, 0xf0, 0x69, 0x26, 0xce, 0xcf, 0x90, 0xf4, 0xd0, 0xc5, 0xc8, 0x64}}}, {{{0x26, 0xa2, 0x50, 0x02, 0x24, 0x72, 0xf1, 0xf0, 0x4e, 0x2d, 0x93, 0xd5, 0x08, 0xe7, 0xae, 0x38, 0xf7, 0x18, 0xa5, 0x32, 0x34, 0xc2, 0xf0, 0xa6, 0xec, 0xb9, 0x61, 0x7b, 0x64, 0x99, 0xac, 0x71}} , {{0x25, 0xcf, 0x74, 0x55, 0x1b, 0xaa, 0xa9, 0x38, 0x41, 0x40, 0xd5, 0x95, 0x95, 0xab, 0x1c, 0x5e, 0xbc, 0x41, 0x7e, 0x14, 0x30, 0xbe, 0x13, 0x89, 0xf4, 0xe5, 0xeb, 0x28, 0xc0, 0xc2, 0x96, 0x3a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2b, 0x77, 0x45, 0xec, 0x67, 0x76, 0x32, 0x4c, 0xb9, 0xdf, 0x25, 0x32, 0x6b, 0xcb, 0xe7, 0x14, 0x61, 0x43, 0xee, 0xba, 0x9b, 0x71, 0xef, 0xd2, 0x48, 0x65, 0xbb, 0x1b, 0x8a, 0x13, 0x1b, 0x22}} , {{0x84, 0xad, 0x0c, 0x18, 0x38, 0x5a, 0xba, 0xd0, 0x98, 0x59, 0xbf, 0x37, 0xb0, 0x4f, 0x97, 0x60, 0x20, 0xb3, 0x9b, 0x97, 0xf6, 0x08, 0x6c, 0xa4, 0xff, 0xfb, 0xb7, 0xfa, 0x95, 0xb2, 0x51, 0x79}}}, @@ -1121,7 +1121,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xa9, 0x85, 0xf4, 0xe7, 0xb0, 0x15, 0x33, 0x84, 0x1b, 0x14, 0x1a, 0x02, 0xd9, 0x3b, 0xad, 0x0f, 0x43, 0x6c, 0xea, 0x3e, 0x0f, 0x7e, 0xda, 0xdd, 0x6b, 0x4c, 0x7f, 0x6e, 0xd4, 0x6b, 0xbf, 0x0f}}}, {{{0x47, 0x9f, 0x7c, 0x56, 0x7c, 0x43, 0x91, 0x1c, 0xbb, 0x4e, 0x72, 0x3e, 0x64, 0xab, 0xa0, 0xa0, 0xdf, 0xb4, 0xd8, 0x87, 0x3a, 0xbd, 0xa8, 0x48, 0xc9, 0xb8, 0xef, 0x2e, 0xad, 0x6f, 0x84, 0x4f}} , {{0x2d, 0x2d, 0xf0, 0x1b, 0x7e, 0x2a, 0x6c, 0xf8, 0xa9, 0x6a, 0xe1, 0xf0, 0x99, 0xa1, 0x67, 0x9a, 0xd4, 0x13, 0xca, 0xca, 0xba, 0x27, 0x92, 0xaa, 0xa1, 0x5d, 0x50, 0xde, 0xcc, 0x40, 0x26, 0x0a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9f, 0x3e, 0xf2, 0xb2, 0x90, 0xce, 0xdb, 0x64, 0x3e, 0x03, 0xdd, 0x37, 0x36, 0x54, 0x70, 0x76, 0x24, 0xb5, 0x69, 0x03, 0xfc, 0xa0, 0x2b, 0x74, 0xb2, 0x05, 0x0e, 0xcc, 0xd8, 0x1f, 0x6a, 0x1f}} , {{0x19, 0x5e, 0x60, 0x69, 0x58, 0x86, 0xa0, 0x31, 0xbd, 0x32, 0xe9, 0x2c, 0x5c, 0xd2, 0x85, 0xba, 0x40, 0x64, 0xa8, 0x74, 0xf8, 0x0e, 0x1c, 0xb3, 0xa9, 0x69, 0xe8, 0x1e, 0x40, 0x64, 0x99, 0x77}}}, @@ -1131,7 +1131,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xca, 0x59, 0x74, 0x1a, 0x11, 0xef, 0x6d, 0xf7, 0x39, 0x5c, 0x3b, 0x1f, 0xfa, 0xe3, 0x40, 0x41, 0x23, 0x9e, 0xf6, 0xd1, 0x21, 0xa2, 0xbf, 0xad, 0x65, 0x42, 0x6b, 0x59, 0x8a, 0xe8, 0xc5, 0x7f}}}, {{{0x64, 0x05, 0x7a, 0x84, 0x4a, 0x13, 0xc3, 0xf6, 0xb0, 0x6e, 0x9a, 0x6b, 0x53, 0x6b, 0x32, 0xda, 0xd9, 0x74, 0x75, 0xc4, 0xba, 0x64, 0x3d, 0x3b, 0x08, 0xdd, 0x10, 0x46, 0xef, 0xc7, 0x90, 0x1f}} , {{0x7b, 0x2f, 0x3a, 0xce, 0xc8, 0xa1, 0x79, 0x3c, 0x30, 0x12, 0x44, 0x28, 0xf6, 0xbc, 0xff, 0xfd, 0xf4, 0xc0, 0x97, 0xb0, 0xcc, 0xc3, 0x13, 0x7a, 0xb9, 0x9a, 0x16, 0xe4, 0xcb, 0x4c, 0x34, 0x63}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x07, 0x4e, 0xd3, 0x2d, 0x09, 0x33, 0x0e, 0xd2, 0x0d, 0xbe, 0x3e, 0xe7, 0xe4, 0xaa, 0xb7, 0x00, 0x8b, 0xe8, 0xad, 0xaa, 0x7a, 0x8d, 0x34, 0x28, 0xa9, 0x81, 0x94, 0xc5, 0xe7, 0x42, 0xac, 0x47}} , {{0x24, 0x89, 0x7a, 0x8f, 0xb5, 0x9b, 0xf0, 0xc2, 0x03, 0x64, 0xd0, 0x1e, 0xf5, 0xa4, 0xb2, 0xf3, 0x74, 0xe9, 0x1a, 0x16, 0xfd, 0xcb, 0x15, 0xea, 0xeb, 0x10, 0x6c, 0x35, 0xd1, 0xc1, 0xa6, 0x28}}}, @@ -1141,7 +1141,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x19, 0xa6, 0x5a, 0x65, 0x93, 0xc3, 0xb5, 0x31, 0x22, 0x4f, 0xf3, 0xf6, 0x0f, 0xeb, 0x28, 0xc3, 0x7c, 0xeb, 0xce, 0x86, 0xec, 0x67, 0x76, 0x6e, 0x35, 0x45, 0x7b, 0xd8, 0x6b, 0x92, 0x01, 0x65}}}, {{{0x3d, 0xd5, 0x9a, 0x64, 0x73, 0x36, 0xb1, 0xd6, 0x86, 0x98, 0x42, 0x3f, 0x8a, 0xf1, 0xc7, 0xf5, 0x42, 0xa8, 0x9c, 0x52, 0xa8, 0xdc, 0xf9, 0x24, 0x3f, 0x4a, 0xa1, 0xa4, 0x5b, 0xe8, 0x62, 0x1a}} , {{0xc5, 0xbd, 0xc8, 0x14, 0xd5, 0x0d, 0xeb, 0xe1, 0xa5, 0xe6, 0x83, 0x11, 0x09, 0x00, 0x1d, 0x55, 0x83, 0x51, 0x7e, 0x75, 0x00, 0x81, 0xb9, 0xcb, 0xd8, 0xc5, 0xe5, 0xa1, 0xd9, 0x17, 0x6d, 0x1f}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xea, 0xf9, 0xe4, 0xe9, 0xe1, 0x52, 0x3f, 0x51, 0x19, 0x0d, 0xdd, 0xd9, 0x9d, 0x93, 0x31, 0x87, 0x23, 0x09, 0xd5, 0x83, 0xeb, 0x92, 0x09, 0x76, 0x6e, 0xe3, 0xf8, 0xc0, 0xa2, 0x66, 0xb5, 0x36}} , {{0x3a, 0xbb, 0x39, 0xed, 0x32, 0x02, 0xe7, 0x43, 0x7a, 0x38, 0x14, 0x84, 0xe3, 0x44, 0xd2, 0x5e, 0x94, 0xdd, 0x78, 0x89, 0x55, 0x4c, 0x73, 0x9e, 0xe1, 0xe4, 0x3e, 0x43, 0xd0, 0x4a, 0xde, 0x1b}}}, @@ -1151,7 +1151,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x46, 0xda, 0x9e, 0x51, 0x3a, 0xe6, 0xd1, 0xa6, 0xbb, 0x4d, 0x7b, 0x08, 0xbe, 0x8c, 0xd5, 0xf3, 0x3f, 0xfd, 0xf7, 0x44, 0x80, 0x2d, 0x53, 0x4b, 0xd0, 0x87, 0x68, 0xc1, 0xb5, 0xd8, 0xf7, 0x07}}}, {{{0xf4, 0x10, 0x46, 0xbe, 0xb7, 0xd2, 0xd1, 0xce, 0x5e, 0x76, 0xa2, 0xd7, 0x03, 0xdc, 0xe4, 0x81, 0x5a, 0xf6, 0x3c, 0xde, 0xae, 0x7a, 0x9d, 0x21, 0x34, 0xa5, 0xf6, 0xa9, 0x73, 0xe2, 0x8d, 0x60}} , {{0xfa, 0x44, 0x71, 0xf6, 0x41, 0xd8, 0xc6, 0x58, 0x13, 0x37, 0xeb, 0x84, 0x0f, 0x96, 0xc7, 0xdc, 0xc8, 0xa9, 0x7a, 0x83, 0xb2, 0x2f, 0x31, 0xb1, 0x1a, 0xd8, 0x98, 0x3f, 0x11, 0xd0, 0x31, 0x3b}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x81, 0xd5, 0x34, 0x16, 0x01, 0xa3, 0x93, 0xea, 0x52, 0x94, 0xec, 0x93, 0xb7, 0x81, 0x11, 0x2d, 0x58, 0xf9, 0xb5, 0x0a, 0xaa, 0x4f, 0xf6, 0x2e, 0x3f, 0x36, 0xbf, 0x33, 0x5a, 0xe7, 0xd1, 0x08}} , {{0x1a, 0xcf, 0x42, 0xae, 0xcc, 0xb5, 0x77, 0x39, 0xc4, 0x5b, 0x5b, 0xd0, 0x26, 0x59, 0x27, 0xd0, 0x55, 0x71, 0x12, 0x9d, 0x88, 0x3d, 0x9c, 0xea, 0x41, 0x6a, 0xf0, 0x50, 0x93, 0x93, 0xdd, 0x47}}}, @@ -1161,7 +1161,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x13, 0xa8, 0x82, 0x3e, 0xe9, 0x13, 0xad, 0xeb, 0x01, 0xca, 0xcf, 0xda, 0xcd, 0xf7, 0x6c, 0xc7, 0x7a, 0xdc, 0x1e, 0x6e, 0xc8, 0x4e, 0x55, 0x62, 0x80, 0xea, 0x78, 0x0c, 0x86, 0xb9, 0x40, 0x51}}}, {{{0x27, 0xae, 0xd3, 0x0d, 0x4c, 0x8f, 0x34, 0xea, 0x7d, 0x3c, 0xe5, 0x8a, 0xcf, 0x5b, 0x92, 0xd8, 0x30, 0x16, 0xb4, 0xa3, 0x75, 0xff, 0xeb, 0x27, 0xc8, 0x5c, 0x6c, 0xc2, 0xee, 0x6c, 0x21, 0x0b}} , {{0xc3, 0xba, 0x12, 0x53, 0x2a, 0xaa, 0x77, 0xad, 0x19, 0x78, 0x55, 0x8a, 0x2e, 0x60, 0x87, 0xc2, 0x6e, 0x91, 0x38, 0x91, 0x3f, 0x7a, 0xc5, 0x24, 0x8f, 0x51, 0xc5, 0xde, 0xb0, 0x53, 0x30, 0x56}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x02, 0xfe, 0x54, 0x12, 0x18, 0xca, 0x7d, 0xa5, 0x68, 0x43, 0xa3, 0x6d, 0x14, 0x2a, 0x6a, 0xa5, 0x8e, 0x32, 0xe7, 0x63, 0x4f, 0xe3, 0xc6, 0x44, 0x3e, 0xab, 0x63, 0xca, 0x17, 0x86, 0x74, 0x3f}} , {{0x1e, 0x64, 0xc1, 0x7d, 0x52, 0xdc, 0x13, 0x5a, 0xa1, 0x9c, 0x4e, 0xee, 0x99, 0x28, 0xbb, 0x4c, 0xee, 0xac, 0xa9, 0x1b, 0x89, 0xa2, 0x38, 0x39, 0x7b, 0xc4, 0x0f, 0x42, 0xe6, 0x89, 0xed, 0x0f}}}, @@ -1171,7 +1171,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xe7, 0x29, 0xf9, 0x37, 0xd9, 0x46, 0x5a, 0xcd, 0x70, 0xfe, 0x4d, 0x5b, 0xbf, 0xa5, 0xcf, 0x91, 0xf4, 0xef, 0xee, 0x8a, 0x29, 0xd0, 0xe7, 0xc4, 0x25, 0x92, 0x8a, 0xff, 0x36, 0xfc, 0xe4, 0x49}}}, {{{0xbd, 0x00, 0xb9, 0x04, 0x7d, 0x35, 0xfc, 0xeb, 0xd0, 0x0b, 0x05, 0x32, 0x52, 0x7a, 0x89, 0x24, 0x75, 0x50, 0xe1, 0x63, 0x02, 0x82, 0x8e, 0xe7, 0x85, 0x0c, 0xf2, 0x56, 0x44, 0x37, 0x83, 0x25}} , {{0x8f, 0xa1, 0xce, 0xcb, 0x60, 0xda, 0x12, 0x02, 0x1e, 0x29, 0x39, 0x2a, 0x03, 0xb7, 0xeb, 0x77, 0x40, 0xea, 0xc9, 0x2b, 0x2c, 0xd5, 0x7d, 0x7e, 0x2c, 0xc7, 0x5a, 0xfd, 0xff, 0xc4, 0xd1, 0x62}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x1d, 0x88, 0x98, 0x5b, 0x4e, 0xfc, 0x41, 0x24, 0x05, 0xe6, 0x50, 0x2b, 0xae, 0x96, 0x51, 0xd9, 0x6b, 0x72, 0xb2, 0x33, 0x42, 0x98, 0x68, 0xbb, 0x10, 0x5a, 0x7a, 0x8c, 0x9d, 0x07, 0xb4, 0x05}} , {{0x2f, 0x61, 0x9f, 0xd7, 0xa8, 0x3f, 0x83, 0x8c, 0x10, 0x69, 0x90, 0xe6, 0xcf, 0xd2, 0x63, 0xa3, 0xe4, 0x54, 0x7e, 0xe5, 0x69, 0x13, 0x1c, 0x90, 0x57, 0xaa, 0xe9, 0x53, 0x22, 0x43, 0x29, 0x23}}}, @@ -1181,7 +1181,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xf5, 0xff, 0xcc, 0xf0, 0xb4, 0x12, 0x03, 0x5f, 0xc9, 0x84, 0xcb, 0x1d, 0x17, 0xe0, 0xbc, 0xcc, 0x03, 0x62, 0xa9, 0x8b, 0x94, 0xa6, 0xaa, 0x18, 0xcb, 0x27, 0x8d, 0x49, 0xa6, 0x17, 0x15, 0x07}}}, {{{0xd9, 0xb6, 0xd4, 0x9d, 0xd4, 0x6a, 0xaf, 0x70, 0x07, 0x2c, 0x10, 0x9e, 0xbd, 0x11, 0xad, 0xe4, 0x26, 0x33, 0x70, 0x92, 0x78, 0x1c, 0x74, 0x9f, 0x75, 0x60, 0x56, 0xf4, 0x39, 0xa8, 0xa8, 0x62}} , {{0x3b, 0xbf, 0x55, 0x35, 0x61, 0x8b, 0x44, 0x97, 0xe8, 0x3a, 0x55, 0xc1, 0xc8, 0x3b, 0xfd, 0x95, 0x29, 0x11, 0x60, 0x96, 0x1e, 0xcb, 0x11, 0x9d, 0xc2, 0x03, 0x8a, 0x1b, 0xc6, 0xd6, 0x45, 0x3d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x7e, 0x0e, 0x50, 0xb2, 0xcc, 0x0d, 0x6b, 0xa6, 0x71, 0x5b, 0x42, 0xed, 0xbd, 0xaf, 0xac, 0xf0, 0xfc, 0x12, 0xa2, 0x3f, 0x4e, 0xda, 0xe8, 0x11, 0xf3, 0x23, 0xe1, 0x04, 0x62, 0x03, 0x1c, 0x4e}} , {{0xc8, 0xb1, 0x1b, 0x6f, 0x73, 0x61, 0x3d, 0x27, 0x0d, 0x7d, 0x7a, 0x25, 0x5f, 0x73, 0x0e, 0x2f, 0x93, 0xf6, 0x24, 0xd8, 0x4f, 0x90, 0xac, 0xa2, 0x62, 0x0a, 0xf0, 0x61, 0xd9, 0x08, 0x59, 0x6a}}}, @@ -1191,7 +1191,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x8d, 0xa6, 0xd5, 0xac, 0x9d, 0xcc, 0x68, 0x75, 0x7f, 0xc3, 0x4d, 0x4b, 0xdd, 0x6c, 0xbb, 0x11, 0x5a, 0x60, 0xe5, 0xbd, 0x7d, 0x27, 0x8b, 0xda, 0xb4, 0x95, 0xf6, 0x03, 0x27, 0xa4, 0x92, 0x3f}}}, {{{0x22, 0xd6, 0xb5, 0x17, 0x84, 0xbf, 0x12, 0xcc, 0x23, 0x14, 0x4a, 0xdf, 0x14, 0x31, 0xbc, 0xa1, 0xac, 0x6e, 0xab, 0xfa, 0x57, 0x11, 0x53, 0xb3, 0x27, 0xe6, 0xf9, 0x47, 0x33, 0x44, 0x34, 0x1e}} , {{0x79, 0xfc, 0xa6, 0xb4, 0x0b, 0x35, 0x20, 0xc9, 0x4d, 0x22, 0x84, 0xc4, 0xa9, 0x20, 0xec, 0x89, 0x94, 0xba, 0x66, 0x56, 0x48, 0xb9, 0x87, 0x7f, 0xca, 0x1e, 0x06, 0xed, 0xa5, 0x55, 0x59, 0x29}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x56, 0xe1, 0xf5, 0xf1, 0xd5, 0xab, 0xa8, 0x2b, 0xae, 0x89, 0xf3, 0xcf, 0x56, 0x9f, 0xf2, 0x4b, 0x31, 0xbc, 0x18, 0xa9, 0x06, 0x5b, 0xbe, 0xb4, 0x61, 0xf8, 0xb2, 0x06, 0x9c, 0x81, 0xab, 0x4c}} , {{0x1f, 0x68, 0x76, 0x01, 0x16, 0x38, 0x2b, 0x0f, 0x77, 0x97, 0x92, 0x67, 0x4e, 0x86, 0x6a, 0x8b, 0xe5, 0xe8, 0x0c, 0xf7, 0x36, 0x39, 0xb5, 0x33, 0xe6, 0xcf, 0x5e, 0xbd, 0x18, 0xfb, 0x10, 0x1f}}}, @@ -1201,7 +1201,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xf5, 0x1a, 0x61, 0xf7, 0x37, 0x9d, 0x00, 0xf4, 0xf2, 0x69, 0x6f, 0x4b, 0x01, 0x85, 0x19, 0x45, 0x4d, 0x7f, 0x02, 0x7c, 0x6a, 0x05, 0x47, 0x6c, 0x1f, 0x81, 0x20, 0xd4, 0xe8, 0x50, 0x27, 0x72}}}, {{{0x2c, 0x3a, 0xe5, 0xad, 0xf4, 0xdd, 0x2d, 0xf7, 0x5c, 0x44, 0xb5, 0x5b, 0x21, 0xa3, 0x89, 0x5f, 0x96, 0x45, 0xca, 0x4d, 0xa4, 0x21, 0x99, 0x70, 0xda, 0xc4, 0xc4, 0xa0, 0xe5, 0xf4, 0xec, 0x0a}} , {{0x07, 0x68, 0x21, 0x65, 0xe9, 0x08, 0xa0, 0x0b, 0x6a, 0x4a, 0xba, 0xb5, 0x80, 0xaf, 0xd0, 0x1b, 0xc5, 0xf5, 0x4b, 0x73, 0x50, 0x60, 0x2d, 0x71, 0x69, 0x61, 0x0e, 0xc0, 0x20, 0x40, 0x30, 0x19}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0x75, 0x57, 0x3b, 0xeb, 0x5c, 0x14, 0x56, 0x50, 0xc9, 0x4f, 0xb8, 0xb8, 0x1e, 0xa3, 0xf4, 0xab, 0xf5, 0xa9, 0x20, 0x15, 0x94, 0x82, 0xda, 0x96, 0x1c, 0x9b, 0x59, 0x8c, 0xff, 0xf4, 0x51}} , {{0xc1, 0x3a, 0x86, 0xd7, 0xb0, 0x06, 0x84, 0x7f, 0x1b, 0xbd, 0xd4, 0x07, 0x78, 0x80, 0x2e, 0xb1, 0xb4, 0xee, 0x52, 0x38, 0xee, 0x9a, 0xf9, 0xf6, 0xf3, 0x41, 0x6e, 0xd4, 0x88, 0x95, 0xac, 0x35}}}, @@ -1211,7 +1211,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x34, 0xe9, 0x59, 0x93, 0x9d, 0x26, 0x80, 0x54, 0xf2, 0xcc, 0x3c, 0xc2, 0x25, 0x85, 0xe3, 0x6a, 0xc1, 0x62, 0x04, 0xa7, 0x08, 0x32, 0x6d, 0xa1, 0x39, 0x84, 0x8a, 0x3b, 0x87, 0x5f, 0x11, 0x13}}}, {{{0xda, 0x03, 0x34, 0x66, 0xc4, 0x0c, 0x73, 0x6e, 0xbc, 0x24, 0xb5, 0xf9, 0x70, 0x81, 0x52, 0xe9, 0xf4, 0x7c, 0x23, 0xdd, 0x9f, 0xb8, 0x46, 0xef, 0x1d, 0x22, 0x55, 0x7d, 0x71, 0xc4, 0x42, 0x33}} , {{0xc5, 0x37, 0x69, 0x5b, 0xa8, 0xc6, 0x9d, 0xa4, 0xfc, 0x61, 0x6e, 0x68, 0x46, 0xea, 0xd7, 0x1c, 0x67, 0xd2, 0x7d, 0xfa, 0xf1, 0xcc, 0x54, 0x8d, 0x36, 0x35, 0xc9, 0x00, 0xdf, 0x6c, 0x67, 0x50}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9a, 0x4d, 0x42, 0x29, 0x5d, 0xa4, 0x6b, 0x6f, 0xa8, 0x8a, 0x4d, 0x91, 0x7b, 0xd2, 0xdf, 0x36, 0xef, 0x01, 0x22, 0xc5, 0xcc, 0x8d, 0xeb, 0x58, 0x3d, 0xb3, 0x50, 0xfc, 0x8b, 0x97, 0x96, 0x33}} , {{0x93, 0x33, 0x07, 0xc8, 0x4a, 0xca, 0xd0, 0xb1, 0xab, 0xbd, 0xdd, 0xa7, 0x7c, 0xac, 0x3e, 0x45, 0xcb, 0xcc, 0x07, 0x91, 0xbf, 0x35, 0x9d, 0xcb, 0x7d, 0x12, 0x3c, 0x11, 0x59, 0x13, 0xcf, 0x5c}}}, @@ -1221,7 +1221,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x8b, 0xa4, 0xd6, 0x50, 0xb4, 0xaa, 0x5d, 0x64, 0x64, 0x76, 0x2e, 0xa1, 0xa6, 0xb3, 0xb8, 0x7c, 0x7a, 0x56, 0xf5, 0x5c, 0x4e, 0x84, 0x5c, 0xfb, 0xdd, 0xca, 0x48, 0x8b, 0x48, 0xb9, 0xba, 0x34}}}, {{{0xc5, 0xe3, 0xe8, 0xae, 0x17, 0x27, 0xe3, 0x64, 0x60, 0x71, 0x47, 0x29, 0x02, 0x0f, 0x92, 0x5d, 0x10, 0x93, 0xc8, 0x0e, 0xa1, 0xed, 0xba, 0xa9, 0x96, 0x1c, 0xc5, 0x76, 0x30, 0xcd, 0xf9, 0x30}} , {{0x95, 0xb0, 0xbd, 0x8c, 0xbc, 0xa7, 0x4f, 0x7e, 0xfd, 0x4e, 0x3a, 0xbf, 0x5f, 0x04, 0x79, 0x80, 0x2b, 0x5a, 0x9f, 0x4f, 0x68, 0x21, 0x19, 0x71, 0xc6, 0x20, 0x01, 0x42, 0xaa, 0xdf, 0xae, 0x2c}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x90, 0x6e, 0x7e, 0x4b, 0x71, 0x93, 0xc0, 0x72, 0xed, 0xeb, 0x71, 0x24, 0x97, 0x26, 0x9c, 0xfe, 0xcb, 0x3e, 0x59, 0x19, 0xa8, 0x0f, 0x75, 0x7d, 0xbe, 0x18, 0xe6, 0x96, 0x1e, 0x95, 0x70, 0x60}} , {{0x89, 0x66, 0x3e, 0x1d, 0x4c, 0x5f, 0xfe, 0xc0, 0x04, 0x43, 0xd6, 0x44, 0x19, 0xb5, 0xad, 0xc7, 0x22, 0xdc, 0x71, 0x28, 0x64, 0xde, 0x41, 0x38, 0x27, 0x8f, 0x2c, 0x6b, 0x08, 0xb8, 0xb8, 0x7b}}}, @@ -1231,7 +1231,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x42, 0xa3, 0xf1, 0xc5, 0xb4, 0x0f, 0xd8, 0xc8, 0x8d, 0x15, 0x31, 0xbd, 0xf8, 0x07, 0x8b, 0xcd, 0x08, 0x8a, 0xfb, 0x18, 0x07, 0xfe, 0x8e, 0x52, 0x86, 0xef, 0xbe, 0xec, 0x49, 0x52, 0x99, 0x08}}}, {{{0x0f, 0xa9, 0xd5, 0x01, 0xaa, 0x48, 0x4f, 0x28, 0x66, 0x32, 0x1a, 0xba, 0x7c, 0xea, 0x11, 0x80, 0x17, 0x18, 0x9b, 0x56, 0x88, 0x25, 0x06, 0x69, 0x12, 0x2c, 0xea, 0x56, 0x69, 0x41, 0x24, 0x19}} , {{0xde, 0x21, 0xf0, 0xda, 0x8a, 0xfb, 0xb1, 0xb8, 0xcd, 0xc8, 0x6a, 0x82, 0x19, 0x73, 0xdb, 0xc7, 0xcf, 0x88, 0xeb, 0x96, 0xee, 0x6f, 0xfb, 0x06, 0xd2, 0xcd, 0x7d, 0x7b, 0x12, 0x28, 0x8e, 0x0c}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x93, 0x44, 0x97, 0xce, 0x28, 0xff, 0x3a, 0x40, 0xc4, 0xf5, 0xf6, 0x9b, 0xf4, 0x6b, 0x07, 0x84, 0xfb, 0x98, 0xd8, 0xec, 0x8c, 0x03, 0x57, 0xec, 0x49, 0xed, 0x63, 0xb6, 0xaa, 0xff, 0x98, 0x28}} , {{0x3d, 0x16, 0x35, 0xf3, 0x46, 0xbc, 0xb3, 0xf4, 0xc6, 0xb6, 0x4f, 0xfa, 0xf4, 0xa0, 0x13, 0xe6, 0x57, 0x45, 0x93, 0xb9, 0xbc, 0xd6, 0x59, 0xe7, 0x77, 0x94, 0x6c, 0xab, 0x96, 0x3b, 0x4f, 0x09}}}, @@ -1241,7 +1241,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xcf, 0xe8, 0x0e, 0x6b, 0x96, 0x7d, 0xed, 0x27, 0xd1, 0x3c, 0xa9, 0xd9, 0x50, 0xa9, 0x98, 0x84, 0x5e, 0x86, 0xef, 0xd6, 0xf0, 0xf8, 0x0e, 0x89, 0x05, 0x2f, 0xd9, 0x5f, 0x15, 0x5f, 0x73, 0x79}}}, {{{0xc8, 0x5c, 0x16, 0xfe, 0xed, 0x9f, 0x26, 0x56, 0xf6, 0x4b, 0x9f, 0xa7, 0x0a, 0x85, 0xfe, 0xa5, 0x8c, 0x87, 0xdd, 0x98, 0xce, 0x4e, 0xc3, 0x58, 0x55, 0xb2, 0x7b, 0x3d, 0xd8, 0x6b, 0xb5, 0x4c}} , {{0x65, 0x38, 0xa0, 0x15, 0xfa, 0xa7, 0xb4, 0x8f, 0xeb, 0xc4, 0x86, 0x9b, 0x30, 0xa5, 0x5e, 0x4d, 0xea, 0x8a, 0x9a, 0x9f, 0x1a, 0xd8, 0x5b, 0x53, 0x14, 0x19, 0x25, 0x63, 0xb4, 0x6f, 0x1f, 0x5d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xac, 0x8f, 0xbc, 0x1e, 0x7d, 0x8b, 0x5a, 0x0b, 0x8d, 0xaf, 0x76, 0x2e, 0x71, 0xe3, 0x3b, 0x6f, 0x53, 0x2f, 0x3e, 0x90, 0x95, 0xd4, 0x35, 0x14, 0x4f, 0x8c, 0x3c, 0xce, 0x57, 0x1c, 0x76, 0x49}} , {{0xa8, 0x50, 0xe1, 0x61, 0x6b, 0x57, 0x35, 0xeb, 0x44, 0x0b, 0x0c, 0x6e, 0xf9, 0x25, 0x80, 0x74, 0xf2, 0x8f, 0x6f, 0x7a, 0x3e, 0x7f, 0x2d, 0xf3, 0x4e, 0x09, 0x65, 0x10, 0x5e, 0x03, 0x25, 0x32}}}, @@ -1251,7 +1251,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x97, 0x67, 0x9e, 0xeb, 0x6a, 0xf9, 0x6e, 0xd6, 0x73, 0xe8, 0x6b, 0x29, 0xec, 0x63, 0x82, 0x00, 0xa8, 0x99, 0x1c, 0x1d, 0x30, 0xc8, 0x90, 0x52, 0x90, 0xb6, 0x6a, 0x80, 0x4e, 0xff, 0x4b, 0x51}}}, {{{0x0f, 0x7d, 0x63, 0x8c, 0x6e, 0x5c, 0xde, 0x30, 0xdf, 0x65, 0xfa, 0x2e, 0xb0, 0xa3, 0x25, 0x05, 0x54, 0xbd, 0x25, 0xba, 0x06, 0xae, 0xdf, 0x8b, 0xd9, 0x1b, 0xea, 0x38, 0xb3, 0x05, 0x16, 0x09}} , {{0xc7, 0x8c, 0xbf, 0x64, 0x28, 0xad, 0xf8, 0xa5, 0x5a, 0x6f, 0xc9, 0xba, 0xd5, 0x7f, 0xd5, 0xd6, 0xbd, 0x66, 0x2f, 0x3d, 0xaa, 0x54, 0xf6, 0xba, 0x32, 0x22, 0x9a, 0x1e, 0x52, 0x05, 0xf4, 0x1d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xaa, 0x1f, 0xbb, 0xeb, 0xfe, 0xe4, 0x87, 0xfc, 0xb1, 0x2c, 0xb7, 0x88, 0xf4, 0xc6, 0xb9, 0xf5, 0x24, 0x46, 0xf2, 0xa5, 0x9f, 0x8f, 0x8a, 0x93, 0x70, 0x69, 0xd4, 0x56, 0xec, 0xfd, 0x06, 0x46}} , {{0x4e, 0x66, 0xcf, 0x4e, 0x34, 0xce, 0x0c, 0xd9, 0xa6, 0x50, 0xd6, 0x5e, 0x95, 0xaf, 0xe9, 0x58, 0xfa, 0xee, 0x9b, 0xb8, 0xa5, 0x0f, 0x35, 0xe0, 0x43, 0x82, 0x6d, 0x65, 0xe6, 0xd9, 0x00, 0x0f}}}, @@ -1261,7 +1261,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x99, 0xeb, 0x7c, 0x31, 0x73, 0x64, 0x67, 0x7f, 0x0c, 0x66, 0xaa, 0x8c, 0x69, 0x91, 0xe2, 0x26, 0xd3, 0x23, 0xe2, 0x76, 0x5d, 0x32, 0x52, 0xdf, 0x5d, 0xc5, 0x8f, 0xb7, 0x7c, 0x84, 0xb3, 0x70}}}, {{{0xeb, 0x01, 0xc7, 0x36, 0x97, 0x4e, 0xb6, 0xab, 0x5f, 0x0d, 0x2c, 0xba, 0x67, 0x64, 0x55, 0xde, 0xbc, 0xff, 0xa6, 0xec, 0x04, 0xd3, 0x8d, 0x39, 0x56, 0x5e, 0xee, 0xf8, 0xe4, 0x2e, 0x33, 0x62}} , {{0x65, 0xef, 0xb8, 0x9f, 0xc8, 0x4b, 0xa7, 0xfd, 0x21, 0x49, 0x9b, 0x92, 0x35, 0x82, 0xd6, 0x0a, 0x9b, 0xf2, 0x79, 0xf1, 0x47, 0x2f, 0x6a, 0x7e, 0x9f, 0xcf, 0x18, 0x02, 0x3c, 0xfb, 0x1b, 0x3e}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2f, 0x8b, 0xc8, 0x40, 0x51, 0xd1, 0xac, 0x1a, 0x0b, 0xe4, 0xa9, 0xa2, 0x42, 0x21, 0x19, 0x2f, 0x7b, 0x97, 0xbf, 0xf7, 0x57, 0x6d, 0x3f, 0x3d, 0x4f, 0x0f, 0xe2, 0xb2, 0x81, 0x00, 0x9e, 0x7b}} , {{0x8c, 0x85, 0x2b, 0xc4, 0xfc, 0xf1, 0xab, 0xe8, 0x79, 0x22, 0xc4, 0x84, 0x17, 0x3a, 0xfa, 0x86, 0xa6, 0x7d, 0xf9, 0xf3, 0x6f, 0x03, 0x57, 0x20, 0x4d, 0x79, 0xf9, 0x6e, 0x71, 0x54, 0x38, 0x09}}}, @@ -1271,7 +1271,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x57, 0x82, 0x1c, 0xab, 0xbf, 0x62, 0x70, 0xe8, 0xc4, 0xcf, 0xf0, 0x28, 0x6e, 0x16, 0x3c, 0x08, 0x78, 0x89, 0x85, 0x46, 0x0f, 0xf6, 0x7f, 0xcf, 0xcb, 0x7e, 0xb8, 0x25, 0xe9, 0x5a, 0xfa, 0x03}}}, {{{0xfb, 0x95, 0x92, 0x63, 0x50, 0xfc, 0x62, 0xf0, 0xa4, 0x5e, 0x8c, 0x18, 0xc2, 0x17, 0x24, 0xb7, 0x78, 0xc2, 0xa9, 0xe7, 0x6a, 0x32, 0xd6, 0x29, 0x85, 0xaf, 0xcb, 0x8d, 0x91, 0x13, 0xda, 0x6b}} , {{0x36, 0x0a, 0xc2, 0xb6, 0x4b, 0xa5, 0x5d, 0x07, 0x17, 0x41, 0x31, 0x5f, 0x62, 0x46, 0xf8, 0x92, 0xf9, 0x66, 0x48, 0x73, 0xa6, 0x97, 0x0d, 0x7d, 0x88, 0xee, 0x62, 0xb1, 0x03, 0xa8, 0x3f, 0x2c}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x4a, 0xb1, 0x70, 0x8a, 0xa9, 0xe8, 0x63, 0x79, 0x00, 0xe2, 0x25, 0x16, 0xca, 0x4b, 0x0f, 0xa4, 0x66, 0xad, 0x19, 0x9f, 0x88, 0x67, 0x0c, 0x8b, 0xc2, 0x4a, 0x5b, 0x2b, 0x6d, 0x95, 0xaf, 0x19}} , {{0x8b, 0x9d, 0xb6, 0xcc, 0x60, 0xb4, 0x72, 0x4f, 0x17, 0x69, 0x5a, 0x4a, 0x68, 0x34, 0xab, 0xa1, 0x45, 0x32, 0x3c, 0x83, 0x87, 0x72, 0x30, 0x54, 0x77, 0x68, 0xae, 0xfb, 0xb5, 0x8b, 0x22, 0x5e}}}, @@ -1281,7 +1281,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x32, 0x65, 0x03, 0xe5, 0x89, 0xa6, 0x6e, 0xb3, 0x5b, 0x8e, 0xca, 0xeb, 0xfe, 0x22, 0x56, 0x8b, 0x5d, 0x14, 0x4b, 0x4d, 0xf9, 0xbe, 0xb5, 0xf5, 0xe6, 0x5c, 0x7b, 0x8b, 0xf4, 0x13, 0x11, 0x34}}}, {{{0x07, 0xc6, 0x22, 0x15, 0xe2, 0x9c, 0x60, 0xa2, 0x19, 0xd9, 0x27, 0xae, 0x37, 0x4e, 0xa6, 0xc9, 0x80, 0xa6, 0x91, 0x8f, 0x12, 0x49, 0xe5, 0x00, 0x18, 0x47, 0xd1, 0xd7, 0x28, 0x22, 0x63, 0x39}} , {{0xe8, 0xe2, 0x00, 0x7e, 0xf2, 0x9e, 0x1e, 0x99, 0x39, 0x95, 0x04, 0xbd, 0x1e, 0x67, 0x7b, 0xb2, 0x26, 0xac, 0xe6, 0xaa, 0xe2, 0x46, 0xd5, 0xe4, 0xe8, 0x86, 0xbd, 0xab, 0x7c, 0x55, 0x59, 0x6f}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x24, 0x64, 0x6e, 0x9b, 0x35, 0x71, 0x78, 0xce, 0x33, 0x03, 0x21, 0x33, 0x36, 0xf1, 0x73, 0x9b, 0xb9, 0x15, 0x8b, 0x2c, 0x69, 0xcf, 0x4d, 0xed, 0x4f, 0x4d, 0x57, 0x14, 0x13, 0x82, 0xa4, 0x4d}} , {{0x65, 0x6e, 0x0a, 0xa4, 0x59, 0x07, 0x17, 0xf2, 0x6b, 0x4a, 0x1f, 0x6e, 0xf6, 0xb5, 0xbc, 0x62, 0xe4, 0xb6, 0xda, 0xa2, 0x93, 0xbc, 0x29, 0x05, 0xd2, 0xd2, 0x73, 0x46, 0x03, 0x16, 0x40, 0x31}}}, @@ -1291,7 +1291,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x86, 0x17, 0x90, 0xe7, 0xc9, 0x1f, 0x10, 0xa5, 0x6a, 0x2d, 0x39, 0xd0, 0x3b, 0xc4, 0xa6, 0xe9, 0x59, 0x13, 0xda, 0x1a, 0xe6, 0xa0, 0xb9, 0x3c, 0x50, 0xb8, 0x40, 0x7c, 0x15, 0x36, 0x5a, 0x42}}}, {{{0xb4, 0x0b, 0x32, 0xab, 0xdc, 0x04, 0x51, 0x55, 0x21, 0x1e, 0x0b, 0x75, 0x99, 0x89, 0x73, 0x35, 0x3a, 0x91, 0x2b, 0xfe, 0xe7, 0x49, 0xea, 0x76, 0xc1, 0xf9, 0x46, 0xb9, 0x53, 0x02, 0x23, 0x04}} , {{0xfc, 0x5a, 0x1e, 0x1d, 0x74, 0x58, 0x95, 0xa6, 0x8f, 0x7b, 0x97, 0x3e, 0x17, 0x3b, 0x79, 0x2d, 0xa6, 0x57, 0xef, 0x45, 0x02, 0x0b, 0x4d, 0x6e, 0x9e, 0x93, 0x8d, 0x2f, 0xd9, 0x9d, 0xdb, 0x04}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc0, 0xd7, 0x56, 0x97, 0x58, 0x91, 0xde, 0x09, 0x4f, 0x9f, 0xbe, 0x63, 0xb0, 0x83, 0x86, 0x43, 0x5d, 0xbc, 0xe0, 0xf3, 0xc0, 0x75, 0xbf, 0x8b, 0x8e, 0xaa, 0xf7, 0x8b, 0x64, 0x6e, 0xb0, 0x63}} , {{0x16, 0xae, 0x8b, 0xe0, 0x9b, 0x24, 0x68, 0x5c, 0x44, 0xc2, 0xd0, 0x08, 0xb7, 0x7b, 0x62, 0xfd, 0x7f, 0xd8, 0xd4, 0xb7, 0x50, 0xfd, 0x2c, 0x1b, 0xbf, 0x41, 0x95, 0xd9, 0x8e, 0xd8, 0x17, 0x1b}}}, @@ -1301,7 +1301,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x02, 0xfb, 0x54, 0xb8, 0x05, 0xf3, 0x81, 0x52, 0x69, 0x34, 0x46, 0x9d, 0x86, 0x76, 0x8f, 0xd7, 0xf8, 0x6a, 0x66, 0xff, 0xe6, 0xa7, 0x90, 0xf7, 0x5e, 0xcd, 0x6a, 0x9b, 0x55, 0xfc, 0x9d, 0x48}}}, {{{0xbd, 0xaa, 0x13, 0xe6, 0xcd, 0x45, 0x4a, 0xa4, 0x59, 0x0a, 0x64, 0xb1, 0x98, 0xd6, 0x34, 0x13, 0x04, 0xe6, 0x97, 0x94, 0x06, 0xcb, 0xd4, 0x4e, 0xbb, 0x96, 0xcd, 0xd1, 0x57, 0xd1, 0xe3, 0x06}} , {{0x7a, 0x6c, 0x45, 0x27, 0xc4, 0x93, 0x7f, 0x7d, 0x7c, 0x62, 0x50, 0x38, 0x3a, 0x6b, 0xb5, 0x88, 0xc6, 0xd9, 0xf1, 0x78, 0x19, 0xb9, 0x39, 0x93, 0x3d, 0xc9, 0xe0, 0x9c, 0x3c, 0xce, 0xf5, 0x72}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x24, 0xea, 0x23, 0x7d, 0x56, 0x2c, 0xe2, 0x59, 0x0e, 0x85, 0x60, 0x04, 0x88, 0x5a, 0x74, 0x1e, 0x4b, 0xef, 0x13, 0xda, 0x4c, 0xff, 0x83, 0x45, 0x85, 0x3f, 0x08, 0x95, 0x2c, 0x20, 0x13, 0x1f}} , {{0x48, 0x5f, 0x27, 0x90, 0x5c, 0x02, 0x42, 0xad, 0x78, 0x47, 0x5c, 0xb5, 0x7e, 0x08, 0x85, 0x00, 0xfa, 0x7f, 0xfd, 0xfd, 0xe7, 0x09, 0x11, 0xf2, 0x7e, 0x1b, 0x38, 0x6c, 0x35, 0x6d, 0x33, 0x66}}}, @@ -1311,7 +1311,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x4e, 0x3b, 0x69, 0xc8, 0x43, 0x75, 0x51, 0x6c, 0x79, 0x56, 0xe4, 0xcb, 0xf7, 0xa6, 0x51, 0xc2, 0x2c, 0x42, 0x0b, 0xd4, 0x82, 0x20, 0x1c, 0x01, 0x08, 0x66, 0xd7, 0xbf, 0x04, 0x56, 0xfc, 0x02}}}, {{{0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2, 0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95, 0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c}} , {{0x6b, 0xa6, 0xf5, 0x4b, 0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90, 0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52, 0xe6, 0x99, 0x2c, 0x5f}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x85, 0xe0, 0x24, 0x32, 0xb4, 0xd1, 0xef, 0xfc, 0x69, 0xa2, 0xbf, 0x8f, 0x72, 0x2c, 0x95, 0xf6, 0xe4, 0x6e, 0x7d, 0x90, 0xf7, 0x57, 0x81, 0xa0, 0xf7, 0xda, 0xef, 0x33, 0x07, 0xe3, 0x6b, 0x78}} , {{0x36, 0x27, 0x3e, 0xc6, 0x12, 0x07, 0xab, 0x4e, 0xbe, 0x69, 0x9d, 0xb3, 0xbe, 0x08, 0x7c, 0x2a, 0x47, 0x08, 0xfd, 0xd4, 0xcd, 0x0e, 0x27, 0x34, 0x5b, 0x98, 0x34, 0x2f, 0x77, 0x5f, 0x3a, 0x65}}}, @@ -1321,7 +1321,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x77, 0x5b, 0xe2, 0x37, 0xc7, 0xe1, 0x7c, 0x13, 0x8c, 0x9f, 0x7b, 0x7b, 0x2a, 0xce, 0x42, 0xa3, 0xb9, 0x2a, 0x99, 0xa8, 0xc0, 0xd8, 0x3c, 0x86, 0xb0, 0xfb, 0xe9, 0x76, 0x77, 0xf7, 0xf5, 0x56}}}, {{{0xdf, 0xb3, 0x46, 0x11, 0x6e, 0x13, 0xb7, 0x28, 0x4e, 0x56, 0xdd, 0xf1, 0xac, 0xad, 0x58, 0xc3, 0xf8, 0x88, 0x94, 0x5e, 0x06, 0x98, 0xa1, 0xe4, 0x6a, 0xfb, 0x0a, 0x49, 0x5d, 0x8a, 0xfe, 0x77}} , {{0x46, 0x02, 0xf5, 0xa5, 0xaf, 0xc5, 0x75, 0x6d, 0xba, 0x45, 0x35, 0x0a, 0xfe, 0xc9, 0xac, 0x22, 0x91, 0x8d, 0x21, 0x95, 0x33, 0x03, 0xc0, 0x8a, 0x16, 0xf3, 0x39, 0xe0, 0x01, 0x0f, 0x53, 0x3c}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x34, 0x75, 0x37, 0x1f, 0x34, 0x4e, 0xa9, 0x1d, 0x68, 0x67, 0xf8, 0x49, 0x98, 0x96, 0xfc, 0x4c, 0x65, 0x97, 0xf7, 0x02, 0x4a, 0x52, 0x6c, 0x01, 0xbd, 0x48, 0xbb, 0x1b, 0xed, 0xa4, 0xe2, 0x53}} , {{0x59, 0xd5, 0x9b, 0x5a, 0xa2, 0x90, 0xd3, 0xb8, 0x37, 0x4c, 0x55, 0x82, 0x28, 0x08, 0x0f, 0x7f, 0xaa, 0x81, 0x65, 0xe0, 0x0c, 0x52, 0xc9, 0xa3, 0x32, 0x27, 0x64, 0xda, 0xfd, 0x34, 0x23, 0x5a}}}, @@ -1331,7 +1331,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x1d, 0x29, 0x7a, 0xa1, 0xec, 0x8e, 0xb5, 0xad, 0xea, 0x02, 0x68, 0x60, 0x74, 0x29, 0x1c, 0xa5, 0xcf, 0xc8, 0x3b, 0x7d, 0x8b, 0x2b, 0x7c, 0xad, 0xa4, 0x40, 0x17, 0x51, 0x59, 0x7c, 0x2e, 0x5d}}}, {{{0x0a, 0x6c, 0x4f, 0xbc, 0x3e, 0x32, 0xe7, 0x4a, 0x1a, 0x13, 0xc1, 0x49, 0x38, 0xbf, 0xf7, 0xc2, 0xd3, 0x8f, 0x6b, 0xad, 0x52, 0xf7, 0xcf, 0xbc, 0x27, 0xcb, 0x40, 0x67, 0x76, 0xcd, 0x6d, 0x56}} , {{0xe5, 0xb0, 0x27, 0xad, 0xbe, 0x9b, 0xf2, 0xb5, 0x63, 0xde, 0x3a, 0x23, 0x95, 0xb7, 0x0a, 0x7e, 0xf3, 0x9e, 0x45, 0x6f, 0x19, 0x39, 0x75, 0x8f, 0x39, 0x3d, 0x0f, 0xc0, 0x9f, 0xf1, 0xe9, 0x51}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x88, 0xaa, 0x14, 0x24, 0x86, 0x94, 0x11, 0x12, 0x3e, 0x1a, 0xb5, 0xcc, 0xbb, 0xe0, 0x9c, 0xd5, 0x9c, 0x6d, 0xba, 0x58, 0x72, 0x8d, 0xfb, 0x22, 0x7b, 0x9f, 0x7c, 0x94, 0x30, 0xb3, 0x51, 0x21}} , {{0xf6, 0x74, 0x3d, 0xf2, 0xaf, 0xd0, 0x1e, 0x03, 0x7c, 0x23, 0x6b, 0xc9, 0xfc, 0x25, 0x70, 0x90, 0xdc, 0x9a, 0xa4, 0xfb, 0x49, 0xfc, 0x3d, 0x0a, 0x35, 0x38, 0x6f, 0xe4, 0x7e, 0x50, 0x01, 0x2a}}}, @@ -1341,7 +1341,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x84, 0x7c, 0xc2, 0xa6, 0x91, 0x23, 0xce, 0xbd, 0xdc, 0xf9, 0xce, 0xd5, 0x75, 0x30, 0x22, 0xe6, 0xf9, 0x43, 0x62, 0x0d, 0xf7, 0x75, 0x9d, 0x7f, 0x8c, 0xff, 0x7d, 0xe4, 0x72, 0xac, 0x9f, 0x1c}}}, {{{0x88, 0xc1, 0x99, 0xd0, 0x3c, 0x1c, 0x5d, 0xb4, 0xef, 0x13, 0x0f, 0x90, 0xb9, 0x36, 0x2f, 0x95, 0x95, 0xc6, 0xdc, 0xde, 0x0a, 0x51, 0xe2, 0x8d, 0xf3, 0xbc, 0x51, 0xec, 0xdf, 0xb1, 0xa2, 0x5f}} , {{0x2e, 0x68, 0xa1, 0x23, 0x7d, 0x9b, 0x40, 0x69, 0x85, 0x7b, 0x42, 0xbf, 0x90, 0x4b, 0xd6, 0x40, 0x2f, 0xd7, 0x52, 0x52, 0xb2, 0x21, 0xde, 0x64, 0xbd, 0x88, 0xc3, 0x6d, 0xa5, 0xfa, 0x81, 0x3f}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xfb, 0xfd, 0x47, 0x7b, 0x8a, 0x66, 0x9e, 0x79, 0x2e, 0x64, 0x82, 0xef, 0xf7, 0x21, 0xec, 0xf6, 0xd8, 0x86, 0x09, 0x31, 0x7c, 0xdd, 0x03, 0x6a, 0x58, 0xa0, 0x77, 0xb7, 0x9b, 0x8c, 0x87, 0x1f}} , {{0x55, 0x47, 0xe4, 0xa8, 0x3d, 0x55, 0x21, 0x34, 0xab, 0x1d, 0xae, 0xe0, 0xf4, 0xea, 0xdb, 0xc5, 0xb9, 0x58, 0xbf, 0xc4, 0x2a, 0x89, 0x31, 0x1a, 0xf4, 0x2d, 0xe1, 0xca, 0x37, 0x99, 0x47, 0x59}}}, @@ -1351,7 +1351,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x29, 0xac, 0xff, 0x27, 0xe0, 0x59, 0xbe, 0x39, 0x9c, 0x0d, 0x83, 0xd7, 0x10, 0x0b, 0x15, 0xb7, 0xe1, 0xc2, 0x2c, 0x30, 0x73, 0x80, 0x3a, 0x7d, 0x5d, 0xab, 0x58, 0x6b, 0xc1, 0xf0, 0xf4, 0x22}}}, {{{0xfe, 0x7f, 0xfb, 0x35, 0x7d, 0xc6, 0x01, 0x23, 0x28, 0xc4, 0x02, 0xac, 0x1f, 0x42, 0xb4, 0x9d, 0xfc, 0x00, 0x94, 0xa5, 0xee, 0xca, 0xda, 0x97, 0x09, 0x41, 0x77, 0x87, 0x5d, 0x7b, 0x87, 0x78}} , {{0xf5, 0xfb, 0x90, 0x2d, 0x81, 0x19, 0x9e, 0x2f, 0x6d, 0x85, 0x88, 0x8c, 0x40, 0x5c, 0x77, 0x41, 0x4d, 0x01, 0x19, 0x76, 0x60, 0xe8, 0x4c, 0x48, 0xe4, 0x33, 0x83, 0x32, 0x6c, 0xb4, 0x41, 0x03}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xff, 0x10, 0xc2, 0x09, 0x4f, 0x6e, 0xf4, 0xd2, 0xdf, 0x7e, 0xca, 0x7b, 0x1c, 0x1d, 0xba, 0xa3, 0xb6, 0xda, 0x67, 0x33, 0xd4, 0x87, 0x36, 0x4b, 0x11, 0x20, 0x05, 0xa6, 0x29, 0xc1, 0x87, 0x17}} , {{0xf6, 0x96, 0xca, 0x2f, 0xda, 0x38, 0xa7, 0x1b, 0xfc, 0xca, 0x7d, 0xfe, 0x08, 0x89, 0xe2, 0x47, 0x2b, 0x6a, 0x5d, 0x4b, 0xfa, 0xa1, 0xb4, 0xde, 0xb6, 0xc2, 0x31, 0x51, 0xf5, 0xe0, 0xa4, 0x0b}}}, @@ -1361,7 +1361,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x0c, 0x0e, 0xf3, 0xba, 0xf0, 0xe5, 0xba, 0xb2, 0x57, 0x77, 0xc6, 0x20, 0x9b, 0x89, 0x24, 0xbe, 0xf2, 0x9c, 0x8a, 0xba, 0x69, 0xc1, 0xf1, 0xb0, 0x4f, 0x2a, 0x05, 0x9a, 0xee, 0x10, 0x7e, 0x36}}}, {{{0x3f, 0x26, 0xe9, 0x40, 0xe9, 0x03, 0xad, 0x06, 0x69, 0x91, 0xe0, 0xd1, 0x89, 0x60, 0x84, 0x79, 0xde, 0x27, 0x6d, 0xe6, 0x76, 0xbd, 0xea, 0xe6, 0xae, 0x48, 0xc3, 0x67, 0xc0, 0x57, 0xcd, 0x2f}} , {{0x7f, 0xc1, 0xdc, 0xb9, 0xc7, 0xbc, 0x86, 0x3d, 0x55, 0x4b, 0x28, 0x7a, 0xfb, 0x4d, 0xc7, 0xf8, 0xbc, 0x67, 0x2a, 0x60, 0x4d, 0x8f, 0x07, 0x0b, 0x1a, 0x17, 0xbf, 0xfa, 0xac, 0xa7, 0x3d, 0x1a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x91, 0x3f, 0xed, 0x5e, 0x18, 0x78, 0x3f, 0x23, 0x2c, 0x0d, 0x8c, 0x44, 0x00, 0xe8, 0xfb, 0xe9, 0x8e, 0xd6, 0xd1, 0x36, 0x58, 0x57, 0x9e, 0xae, 0x4b, 0x5c, 0x0b, 0x07, 0xbc, 0x6b, 0x55, 0x2b}} , {{0x6f, 0x4d, 0x17, 0xd7, 0xe1, 0x84, 0xd9, 0x78, 0xb1, 0x90, 0xfd, 0x2e, 0xb3, 0xb5, 0x19, 0x3f, 0x1b, 0xfa, 0xc0, 0x68, 0xb3, 0xdd, 0x00, 0x2e, 0x89, 0xbd, 0x7e, 0x80, 0x32, 0x13, 0xa0, 0x7b}}}, @@ -1371,7 +1371,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x01, 0xb8, 0xd6, 0x16, 0x67, 0xa0, 0x15, 0xb9, 0xe1, 0x58, 0xa4, 0xa7, 0x31, 0x37, 0x77, 0x2f, 0x8b, 0x12, 0x9f, 0xf4, 0x3f, 0xc7, 0x36, 0x66, 0xd2, 0xa8, 0x56, 0xf7, 0x7f, 0x74, 0xc6, 0x41}}}, {{{0x5d, 0xf8, 0xb4, 0xa8, 0x30, 0xdd, 0xcc, 0x38, 0xa5, 0xd3, 0xca, 0xd8, 0xd1, 0xf8, 0xb2, 0x31, 0x91, 0xd4, 0x72, 0x05, 0x57, 0x4a, 0x3b, 0x82, 0x4a, 0xc6, 0x68, 0x20, 0xe2, 0x18, 0x41, 0x61}} , {{0x19, 0xd4, 0x8d, 0x47, 0x29, 0x12, 0x65, 0xb0, 0x11, 0x78, 0x47, 0xb5, 0xcb, 0xa3, 0xa5, 0xfa, 0x05, 0x85, 0x54, 0xa9, 0x33, 0x97, 0x8d, 0x2b, 0xc2, 0xfe, 0x99, 0x35, 0x28, 0xe5, 0xeb, 0x63}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xb1, 0x3f, 0x3f, 0xef, 0xd8, 0xf4, 0xfc, 0xb3, 0xa0, 0x60, 0x50, 0x06, 0x2b, 0x29, 0x52, 0x70, 0x15, 0x0b, 0x24, 0x24, 0xf8, 0x5f, 0x79, 0x18, 0xcc, 0xff, 0x89, 0x99, 0x84, 0xa1, 0xae, 0x13}} , {{0x44, 0x1f, 0xb8, 0xc2, 0x01, 0xc1, 0x30, 0x19, 0x55, 0x05, 0x60, 0x10, 0xa4, 0x6c, 0x2d, 0x67, 0x70, 0xe5, 0x25, 0x1b, 0xf2, 0xbf, 0xdd, 0xfb, 0x70, 0x2b, 0xa1, 0x8c, 0x9c, 0x94, 0x84, 0x08}}}, @@ -1381,7 +1381,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xdc, 0xff, 0x15, 0x61, 0x2f, 0x4a, 0x2f, 0x62, 0xf2, 0x04, 0x2f, 0xb5, 0x0c, 0xb7, 0x1e, 0x3f, 0x74, 0x1a, 0x0f, 0xd7, 0xea, 0xcd, 0xd9, 0x7d, 0xf6, 0x12, 0x0e, 0x2f, 0xdb, 0x5a, 0x3b, 0x16}}}, {{{0x1b, 0x37, 0x47, 0xe3, 0xf5, 0x9e, 0xea, 0x2c, 0x2a, 0xe7, 0x82, 0x36, 0xf4, 0x1f, 0x81, 0x47, 0x92, 0x4b, 0x69, 0x0e, 0x11, 0x8c, 0x5d, 0x53, 0x5b, 0x81, 0x27, 0x08, 0xbc, 0xa0, 0xae, 0x25}} , {{0x69, 0x32, 0xa1, 0x05, 0x11, 0x42, 0x00, 0xd2, 0x59, 0xac, 0x4d, 0x62, 0x8b, 0x13, 0xe2, 0x50, 0x5d, 0xa0, 0x9d, 0x9b, 0xfd, 0xbb, 0x12, 0x41, 0x75, 0x41, 0x9e, 0xcc, 0xdc, 0xc7, 0xdc, 0x5d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd9, 0xe3, 0x38, 0x06, 0x46, 0x70, 0x82, 0x5e, 0x28, 0x49, 0x79, 0xff, 0x25, 0xd2, 0x4e, 0x29, 0x8d, 0x06, 0xb0, 0x23, 0xae, 0x9b, 0x66, 0xe4, 0x7d, 0xc0, 0x70, 0x91, 0xa3, 0xfc, 0xec, 0x4e}} , {{0x62, 0x12, 0x37, 0x6a, 0x30, 0xf6, 0x1e, 0xfb, 0x14, 0x5c, 0x0d, 0x0e, 0xb7, 0x81, 0x6a, 0xe7, 0x08, 0x05, 0xac, 0xaa, 0x38, 0x46, 0xe2, 0x73, 0xea, 0x4b, 0x07, 0x81, 0x43, 0x7c, 0x9e, 0x5e}}}, @@ -1391,7 +1391,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xe5, 0x44, 0xec, 0x06, 0x9d, 0x90, 0x79, 0x9f, 0xd3, 0xe0, 0x79, 0xaf, 0x8f, 0x10, 0xfd, 0xdd, 0x04, 0xae, 0x27, 0x97, 0x46, 0x33, 0x79, 0xea, 0xb8, 0x4e, 0xca, 0x5a, 0x59, 0x57, 0xe1, 0x0e}}}, {{{0x1a, 0xda, 0xf3, 0xa5, 0x41, 0x43, 0x28, 0xfc, 0x7e, 0xe7, 0x71, 0xea, 0xc6, 0x3b, 0x59, 0xcc, 0x2e, 0xd3, 0x40, 0xec, 0xb3, 0x13, 0x6f, 0x44, 0xcd, 0x13, 0xb2, 0x37, 0xf2, 0x6e, 0xd9, 0x1c}} , {{0xe3, 0xdb, 0x60, 0xcd, 0x5c, 0x4a, 0x18, 0x0f, 0xef, 0x73, 0x36, 0x71, 0x8c, 0xf6, 0x11, 0xb4, 0xd8, 0xce, 0x17, 0x5e, 0x4f, 0x26, 0x77, 0x97, 0x5f, 0xcb, 0xef, 0x91, 0xeb, 0x6a, 0x62, 0x7a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x18, 0x4a, 0xa2, 0x97, 0x08, 0x81, 0x2d, 0x83, 0xc4, 0xcc, 0xf0, 0x83, 0x7e, 0xec, 0x0d, 0x95, 0x4c, 0x5b, 0xfb, 0xfa, 0x98, 0x80, 0x4a, 0x66, 0x56, 0x0c, 0x51, 0xb3, 0xf2, 0x04, 0x5d, 0x27}} , {{0x3b, 0xb9, 0xb8, 0x06, 0x5a, 0x2e, 0xfe, 0xc3, 0x82, 0x37, 0x9c, 0xa3, 0x11, 0x1f, 0x9c, 0xa6, 0xda, 0x63, 0x48, 0x9b, 0xad, 0xde, 0x2d, 0xa6, 0xbc, 0x6e, 0x32, 0xda, 0x27, 0x65, 0xdd, 0x57}}}, @@ -1401,7 +1401,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xa4, 0x4b, 0x62, 0x4c, 0xe6, 0xfd, 0x72, 0x07, 0xf2, 0x81, 0xfc, 0xf2, 0xbd, 0x12, 0x7c, 0x68, 0x76, 0x2a, 0xba, 0xf5, 0x65, 0xb1, 0x1f, 0x17, 0x0a, 0x38, 0xb0, 0xbf, 0xc0, 0xf8, 0xf4, 0x2a}}}, {{{0x55, 0x60, 0x55, 0x5b, 0xe4, 0x1d, 0x71, 0x4c, 0x9d, 0x5b, 0x9f, 0x70, 0xa6, 0x85, 0x9a, 0x2c, 0xa0, 0xe2, 0x32, 0x48, 0xce, 0x9e, 0x2a, 0xa5, 0x07, 0x3b, 0xc7, 0x6c, 0x86, 0x77, 0xde, 0x3c}} , {{0xf7, 0x18, 0x7a, 0x96, 0x7e, 0x43, 0x57, 0xa9, 0x55, 0xfc, 0x4e, 0xb6, 0x72, 0x00, 0xf2, 0xe4, 0xd7, 0x52, 0xd3, 0xd3, 0xb6, 0x85, 0xf6, 0x71, 0xc7, 0x44, 0x3f, 0x7f, 0xd7, 0xb3, 0xf2, 0x79}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x46, 0xca, 0xa7, 0x55, 0x7b, 0x79, 0xf3, 0xca, 0x5a, 0x65, 0xf6, 0xed, 0x50, 0x14, 0x7b, 0xe4, 0xc4, 0x2a, 0x65, 0x9e, 0xe2, 0xf9, 0xca, 0xa7, 0x22, 0x26, 0x53, 0xcb, 0x21, 0x5b, 0xa7, 0x31}} , {{0x90, 0xd7, 0xc5, 0x26, 0x08, 0xbd, 0xb0, 0x53, 0x63, 0x58, 0xc3, 0x31, 0x5e, 0x75, 0x46, 0x15, 0x91, 0xa6, 0xf8, 0x2f, 0x1a, 0x08, 0x65, 0x88, 0x2f, 0x98, 0x04, 0xf1, 0x7c, 0x6e, 0x00, 0x77}}}, @@ -1411,7 +1411,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x68, 0x0e, 0x6f, 0x97, 0xba, 0x70, 0xbb, 0xa3, 0x0e, 0xe5, 0x0b, 0x12, 0xf4, 0xa2, 0xdc, 0x47, 0xf8, 0xe6, 0xd0, 0x23, 0x6c, 0x33, 0xa8, 0x99, 0x46, 0x6e, 0x0f, 0x44, 0xba, 0x76, 0x48, 0x0f}}}, {{{0xa3, 0x2a, 0x61, 0x37, 0xe2, 0x59, 0x12, 0x0e, 0x27, 0xba, 0x64, 0x43, 0xae, 0xc0, 0x42, 0x69, 0x79, 0xa4, 0x1e, 0x29, 0x8b, 0x15, 0xeb, 0xf8, 0xaf, 0xd4, 0xa2, 0x68, 0x33, 0xb5, 0x7a, 0x24}} , {{0x2c, 0x19, 0x33, 0xdd, 0x1b, 0xab, 0xec, 0x01, 0xb0, 0x23, 0xf8, 0x42, 0x2b, 0x06, 0x88, 0xea, 0x3d, 0x2d, 0x00, 0x2a, 0x78, 0x45, 0x4d, 0x38, 0xed, 0x2e, 0x2e, 0x44, 0x49, 0xed, 0xcb, 0x33}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xa0, 0x68, 0xe8, 0x41, 0x8f, 0x91, 0xf8, 0x11, 0x13, 0x90, 0x2e, 0xa7, 0xab, 0x30, 0xef, 0xad, 0xa0, 0x61, 0x00, 0x88, 0xef, 0xdb, 0xce, 0x5b, 0x5c, 0xbb, 0x62, 0xc8, 0x56, 0xf9, 0x00, 0x73}} , {{0x3f, 0x60, 0xc1, 0x82, 0x2d, 0xa3, 0x28, 0x58, 0x24, 0x9e, 0x9f, 0xe3, 0x70, 0xcc, 0x09, 0x4e, 0x1a, 0x3f, 0x11, 0x11, 0x15, 0x07, 0x3c, 0xa4, 0x41, 0xe0, 0x65, 0xa3, 0x0a, 0x41, 0x6d, 0x11}}}, @@ -1421,7 +1421,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x32, 0xb4, 0x18, 0x47, 0x79, 0xcb, 0xd4, 0x5a, 0x07, 0x14, 0x0f, 0xa0, 0xd5, 0xac, 0xd0, 0x41, 0x40, 0xab, 0x61, 0x23, 0xe5, 0x2a, 0x2a, 0x6f, 0xf7, 0xa8, 0xd4, 0x76, 0xef, 0xe7, 0x45, 0x6c}}}, {{{0xa1, 0x5e, 0x60, 0x4f, 0xfb, 0xe1, 0x70, 0x6a, 0x1f, 0x55, 0x4f, 0x09, 0xb4, 0x95, 0x33, 0x36, 0xc6, 0x81, 0x01, 0x18, 0x06, 0x25, 0x27, 0xa4, 0xb4, 0x24, 0xa4, 0x86, 0x03, 0x4c, 0xac, 0x02}} , {{0x77, 0x38, 0xde, 0xd7, 0x60, 0x48, 0x07, 0xf0, 0x74, 0xa8, 0xff, 0x54, 0xe5, 0x30, 0x43, 0xff, 0x77, 0xfb, 0x21, 0x07, 0xff, 0xb2, 0x07, 0x6b, 0xe4, 0xe5, 0x30, 0xfc, 0x19, 0x6c, 0xa3, 0x01}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x13, 0xc5, 0x2c, 0xac, 0xd3, 0x83, 0x82, 0x7c, 0x29, 0xf7, 0x05, 0xa5, 0x00, 0xb6, 0x1f, 0x86, 0x55, 0xf4, 0xd6, 0x2f, 0x0c, 0x99, 0xd0, 0x65, 0x9b, 0x6b, 0x46, 0x0d, 0x43, 0xf8, 0x16, 0x28}} , {{0x1e, 0x7f, 0xb4, 0x74, 0x7e, 0xb1, 0x89, 0x4f, 0x18, 0x5a, 0xab, 0x64, 0x06, 0xdf, 0x45, 0x87, 0xe0, 0x6a, 0xc6, 0xf0, 0x0e, 0xc9, 0x24, 0x35, 0x38, 0xea, 0x30, 0x54, 0xb4, 0xc4, 0x52, 0x54}}}, @@ -1431,7 +1431,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x32, 0xad, 0xae, 0x85, 0x58, 0x43, 0xb8, 0xb1, 0xe6, 0x3e, 0x00, 0x9c, 0x78, 0x88, 0x56, 0xdb, 0x9c, 0xfc, 0x79, 0xf6, 0xf9, 0x41, 0x5f, 0xb7, 0xbc, 0x11, 0xf9, 0x20, 0x36, 0x1c, 0x53, 0x2b}}}, {{{0x5a, 0x20, 0x5b, 0xa1, 0xa5, 0x44, 0x91, 0x24, 0x02, 0x63, 0x12, 0x64, 0xb8, 0x55, 0xf6, 0xde, 0x2c, 0xdb, 0x47, 0xb8, 0xc6, 0x0a, 0xc3, 0x00, 0x78, 0x93, 0xd8, 0xf5, 0xf5, 0x18, 0x28, 0x0a}} , {{0xd6, 0x1b, 0x9a, 0x6c, 0xe5, 0x46, 0xea, 0x70, 0x96, 0x8d, 0x4e, 0x2a, 0x52, 0x21, 0x26, 0x4b, 0xb1, 0xbb, 0x0f, 0x7c, 0xa9, 0x9b, 0x04, 0xbb, 0x51, 0x08, 0xf1, 0x9a, 0xa4, 0x76, 0x7c, 0x18}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xfa, 0x94, 0xf7, 0x40, 0xd0, 0xd7, 0xeb, 0xa9, 0x82, 0x36, 0xd5, 0x15, 0xb9, 0x33, 0x7a, 0xbf, 0x8a, 0xf2, 0x63, 0xaa, 0x37, 0xf5, 0x59, 0xac, 0xbd, 0xbb, 0x32, 0x36, 0xbe, 0x73, 0x99, 0x38}} , {{0x2c, 0xb3, 0xda, 0x7a, 0xd8, 0x3d, 0x99, 0xca, 0xd2, 0xf4, 0xda, 0x99, 0x8e, 0x4f, 0x98, 0xb7, 0xf4, 0xae, 0x3e, 0x9f, 0x8e, 0x35, 0x60, 0xa4, 0x33, 0x75, 0xa4, 0x04, 0x93, 0xb1, 0x6b, 0x4d}}}, @@ -1441,7 +1441,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x53, 0xcf, 0xc2, 0xa1, 0xad, 0x6a, 0xf3, 0xcd, 0x8f, 0xc9, 0xde, 0x1c, 0xf8, 0x6c, 0x8f, 0xf8, 0x76, 0x42, 0xe7, 0xfe, 0xb2, 0x72, 0x21, 0x0a, 0x66, 0x74, 0x8f, 0xb7, 0xeb, 0xe4, 0x6f, 0x01}}}, {{{0x22, 0x8c, 0x6b, 0xbe, 0xfc, 0x4d, 0x70, 0x62, 0x6e, 0x52, 0x77, 0x99, 0x88, 0x7e, 0x7b, 0x57, 0x7a, 0x0d, 0xfe, 0xdc, 0x72, 0x92, 0xf1, 0x68, 0x1d, 0x97, 0xd7, 0x7c, 0x8d, 0x53, 0x10, 0x37}} , {{0x53, 0x88, 0x77, 0x02, 0xca, 0x27, 0xa8, 0xe5, 0x45, 0xe2, 0xa8, 0x48, 0x2a, 0xab, 0x18, 0xca, 0xea, 0x2d, 0x2a, 0x54, 0x17, 0x37, 0x32, 0x09, 0xdc, 0xe0, 0x4a, 0xb7, 0x7d, 0x82, 0x10, 0x7d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x8a, 0x64, 0x1e, 0x14, 0x0a, 0x57, 0xd4, 0xda, 0x5c, 0x96, 0x9b, 0x01, 0x4c, 0x67, 0xbf, 0x8b, 0x30, 0xfe, 0x08, 0xdb, 0x0d, 0xd5, 0xa8, 0xd7, 0x09, 0x11, 0x85, 0xa2, 0xd3, 0x45, 0xfb, 0x7e}} , {{0xda, 0x8c, 0xc2, 0xd0, 0xac, 0x18, 0xe8, 0x52, 0x36, 0xd4, 0x21, 0xa3, 0xdd, 0x57, 0x22, 0x79, 0xb7, 0xf8, 0x71, 0x9d, 0xc6, 0x91, 0x70, 0x86, 0x56, 0xbf, 0xa1, 0x11, 0x8b, 0x19, 0xe1, 0x0f}}}, @@ -1451,7 +1451,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x62, 0x4f, 0xd0, 0x75, 0x77, 0xba, 0x76, 0x77, 0xd7, 0xb8, 0xd8, 0x92, 0x6f, 0x98, 0x34, 0x3d, 0xd6, 0x4e, 0x1c, 0x0f, 0xf0, 0x8f, 0x2e, 0xf1, 0xb3, 0xbd, 0xb1, 0xb9, 0xec, 0x99, 0xb4, 0x07}}}, {{{0x60, 0x57, 0x2e, 0x9a, 0x72, 0x1d, 0x6b, 0x6e, 0x58, 0x33, 0x24, 0x8c, 0x48, 0x39, 0x46, 0x8e, 0x89, 0x6a, 0x88, 0x51, 0x23, 0x62, 0xb5, 0x32, 0x09, 0x36, 0xe3, 0x57, 0xf5, 0x98, 0xde, 0x6f}} , {{0x8b, 0x2c, 0x00, 0x48, 0x4a, 0xf9, 0x5b, 0x87, 0x69, 0x52, 0xe5, 0x5b, 0xd1, 0xb1, 0xe5, 0x25, 0x25, 0xe0, 0x9c, 0xc2, 0x13, 0x44, 0xe8, 0xb9, 0x0a, 0x70, 0xad, 0xbd, 0x0f, 0x51, 0x94, 0x69}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xa2, 0xdc, 0xab, 0xa9, 0x25, 0x2d, 0xac, 0x5f, 0x03, 0x33, 0x08, 0xe7, 0x7e, 0xfe, 0x95, 0x36, 0x3c, 0x5b, 0x3a, 0xd3, 0x05, 0x82, 0x1c, 0x95, 0x2d, 0xd8, 0x77, 0x7e, 0x02, 0xd9, 0x5b, 0x70}} , {{0xc2, 0xfe, 0x1b, 0x0c, 0x67, 0xcd, 0xd6, 0xe0, 0x51, 0x8e, 0x2c, 0xe0, 0x79, 0x88, 0xf0, 0xcf, 0x41, 0x4a, 0xad, 0x23, 0xd4, 0x46, 0xca, 0x94, 0xa1, 0xc3, 0xeb, 0x28, 0x06, 0xfa, 0x17, 0x14}}}, @@ -1461,7 +1461,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x64, 0xe9, 0x28, 0xc7, 0xa4, 0xcf, 0x2a, 0xf9, 0x90, 0x64, 0x72, 0x2c, 0x8b, 0xeb, 0xec, 0xa0, 0xf2, 0x7d, 0x35, 0xb5, 0x90, 0x4d, 0x7f, 0x5b, 0x4a, 0x49, 0xe4, 0xb8, 0x3b, 0xc8, 0xa1, 0x2f}}}, {{{0x8b, 0xc5, 0xcc, 0x3d, 0x69, 0xa6, 0xa1, 0x18, 0x44, 0xbc, 0x4d, 0x77, 0x37, 0xc7, 0x86, 0xec, 0x0c, 0xc9, 0xd6, 0x44, 0xa9, 0x23, 0x27, 0xb9, 0x03, 0x34, 0xa7, 0x0a, 0xd5, 0xc7, 0x34, 0x37}} , {{0xf9, 0x7e, 0x3e, 0x66, 0xee, 0xf9, 0x99, 0x28, 0xff, 0xad, 0x11, 0xd8, 0xe2, 0x66, 0xc5, 0xcd, 0x0f, 0x0d, 0x0b, 0x6a, 0xfc, 0x7c, 0x24, 0xa8, 0x4f, 0xa8, 0x5e, 0x80, 0x45, 0x8b, 0x6c, 0x41}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xef, 0x1e, 0xec, 0xf7, 0x8d, 0x77, 0xf2, 0xea, 0xdb, 0x60, 0x03, 0x21, 0xc0, 0xff, 0x5e, 0x67, 0xc3, 0x71, 0x0b, 0x21, 0xb4, 0x41, 0xa0, 0x68, 0x38, 0xc6, 0x01, 0xa3, 0xd3, 0x51, 0x3c, 0x3c}} , {{0x92, 0xf8, 0xd6, 0x4b, 0xef, 0x42, 0x13, 0xb2, 0x4a, 0xc4, 0x2e, 0x72, 0x3f, 0xc9, 0x11, 0xbd, 0x74, 0x02, 0x0e, 0xf5, 0x13, 0x9d, 0x83, 0x1a, 0x1b, 0xd5, 0x54, 0xde, 0xc4, 0x1e, 0x16, 0x6c}}}, @@ -1471,7 +1471,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x7a, 0x8d, 0xa1, 0x5d, 0x70, 0x5d, 0x51, 0x27, 0xee, 0x30, 0x65, 0x56, 0x95, 0x46, 0xde, 0xbd, 0x03, 0x75, 0xb4, 0x57, 0x59, 0x89, 0xeb, 0x02, 0x9e, 0xcc, 0x89, 0x19, 0xa7, 0xcb, 0x17, 0x67}}}, {{{0x6a, 0xeb, 0xfc, 0x9a, 0x9a, 0x10, 0xce, 0xdb, 0x3a, 0x1c, 0x3c, 0x6a, 0x9d, 0xea, 0x46, 0xbc, 0x45, 0x49, 0xac, 0xe3, 0x41, 0x12, 0x7c, 0xf0, 0xf7, 0x4f, 0xf9, 0xf7, 0xff, 0x2c, 0x89, 0x04}} , {{0x30, 0x31, 0x54, 0x1a, 0x46, 0xca, 0xe6, 0xc6, 0xcb, 0xe2, 0xc3, 0xc1, 0x8b, 0x75, 0x81, 0xbe, 0xee, 0xf8, 0xa3, 0x11, 0x1c, 0x25, 0xa3, 0xa7, 0x35, 0x51, 0x55, 0xe2, 0x25, 0xaa, 0xe2, 0x3a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xb4, 0x48, 0x10, 0x9f, 0x8a, 0x09, 0x76, 0xfa, 0xf0, 0x7a, 0xb0, 0x70, 0xf7, 0x83, 0x80, 0x52, 0x84, 0x2b, 0x26, 0xa2, 0xc4, 0x5d, 0x4f, 0xba, 0xb1, 0xc8, 0x40, 0x0d, 0x78, 0x97, 0xc4, 0x60}} , {{0xd4, 0xb1, 0x6c, 0x08, 0xc7, 0x40, 0x38, 0x73, 0x5f, 0x0b, 0xf3, 0x76, 0x5d, 0xb2, 0xa5, 0x2f, 0x57, 0x57, 0x07, 0xed, 0x08, 0xa2, 0x6c, 0x4f, 0x08, 0x02, 0xb5, 0x0e, 0xee, 0x44, 0xfa, 0x22}}}, @@ -1481,7 +1481,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xff, 0x76, 0x03, 0xc5, 0x4b, 0x89, 0x99, 0x70, 0x00, 0x59, 0x70, 0x9c, 0xd5, 0xd9, 0x11, 0x89, 0x5a, 0x46, 0xfe, 0xef, 0xdc, 0xd9, 0x55, 0x2b, 0x45, 0xa7, 0xb0, 0x2d, 0xfb, 0x24, 0xc2, 0x29}}}, {{{0x38, 0x06, 0xf8, 0x0b, 0xac, 0x82, 0xc4, 0x97, 0x2b, 0x90, 0xe0, 0xf7, 0xa8, 0xab, 0x6c, 0x08, 0x80, 0x66, 0x90, 0x46, 0xf7, 0x26, 0x2d, 0xf8, 0xf1, 0xc4, 0x6b, 0x4a, 0x82, 0x98, 0x8e, 0x37}} , {{0x8e, 0xb4, 0xee, 0xb8, 0xd4, 0x3f, 0xb2, 0x1b, 0xe0, 0x0a, 0x3d, 0x75, 0x34, 0x28, 0xa2, 0x8e, 0xc4, 0x92, 0x7b, 0xfe, 0x60, 0x6e, 0x6d, 0xb8, 0x31, 0x1d, 0x62, 0x0d, 0x78, 0x14, 0x42, 0x11}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x5e, 0xa8, 0xd8, 0x04, 0x9b, 0x73, 0xc9, 0xc9, 0xdc, 0x0d, 0x73, 0xbf, 0x0a, 0x0a, 0x73, 0xff, 0x18, 0x1f, 0x9c, 0x51, 0xaa, 0xc6, 0xf1, 0x83, 0x25, 0xfd, 0xab, 0xa3, 0x11, 0xd3, 0x01, 0x24}} , {{0x4d, 0xe3, 0x7e, 0x38, 0x62, 0x5e, 0x64, 0xbb, 0x2b, 0x53, 0xb5, 0x03, 0x68, 0xc4, 0xf2, 0x2b, 0x5a, 0x03, 0x32, 0x99, 0x4a, 0x41, 0x9a, 0xe1, 0x1a, 0xae, 0x8c, 0x48, 0xf3, 0x24, 0x32, 0x65}}}, @@ -1491,7 +1491,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x7c, 0x31, 0x33, 0xcc, 0xe4, 0xcf, 0x6c, 0xff, 0x80, 0x47, 0x77, 0xd1, 0xd8, 0xe9, 0x69, 0x97, 0x98, 0x7f, 0x20, 0x57, 0x1d, 0x1d, 0x4f, 0x08, 0x27, 0xc8, 0x35, 0x57, 0x40, 0xc6, 0x21, 0x0c}}}, {{{0xd2, 0x8e, 0x9b, 0xfa, 0x42, 0x8e, 0xdf, 0x8f, 0xc7, 0x86, 0xf9, 0xa4, 0xca, 0x70, 0x00, 0x9d, 0x21, 0xbf, 0xec, 0x57, 0x62, 0x30, 0x58, 0x8c, 0x0d, 0x35, 0xdb, 0x5d, 0x8b, 0x6a, 0xa0, 0x5a}} , {{0xc1, 0x58, 0x7c, 0x0d, 0x20, 0xdd, 0x11, 0x26, 0x5f, 0x89, 0x3b, 0x97, 0x58, 0xf8, 0x8b, 0xe3, 0xdf, 0x32, 0xe2, 0xfc, 0xd8, 0x67, 0xf2, 0xa5, 0x37, 0x1e, 0x6d, 0xec, 0x7c, 0x27, 0x20, 0x79}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0xe9, 0xc0, 0xfa, 0x95, 0x45, 0x23, 0x96, 0xf1, 0x2c, 0x79, 0x25, 0x14, 0xce, 0x40, 0x14, 0x44, 0x2c, 0x36, 0x50, 0xd9, 0x63, 0x56, 0xb7, 0x56, 0x3b, 0x9e, 0xa7, 0xef, 0x89, 0xbb, 0x0e}} , {{0xce, 0x7f, 0xdc, 0x0a, 0xcc, 0x82, 0x1c, 0x0a, 0x78, 0x71, 0xe8, 0x74, 0x8d, 0x01, 0x30, 0x0f, 0xa7, 0x11, 0x4c, 0xdf, 0x38, 0xd7, 0xa7, 0x0d, 0xf8, 0x48, 0x52, 0x00, 0x80, 0x7b, 0x5f, 0x0e}}}, @@ -1501,7 +1501,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x50, 0x5b, 0xff, 0xa9, 0xb2, 0xf1, 0xf1, 0x78, 0xcf, 0x14, 0xa4, 0xa9, 0xfc, 0x09, 0x46, 0x94, 0x54, 0x65, 0x0d, 0x9c, 0x5f, 0x72, 0x21, 0xe2, 0x97, 0xa5, 0x2d, 0x81, 0xce, 0x4a, 0x5f, 0x79}}}, {{{0x3d, 0x5f, 0x5c, 0xd2, 0xbc, 0x7d, 0x77, 0x0e, 0x2a, 0x6d, 0x22, 0x45, 0x84, 0x06, 0xc4, 0xdd, 0xc6, 0xa6, 0xc6, 0xd7, 0x49, 0xad, 0x6d, 0x87, 0x91, 0x0e, 0x3a, 0x67, 0x1d, 0x2c, 0x1d, 0x56}} , {{0xfe, 0x7a, 0x74, 0xcf, 0xd4, 0xd2, 0xe5, 0x19, 0xde, 0xd0, 0xdb, 0x70, 0x23, 0x69, 0xe6, 0x6d, 0xec, 0xec, 0xcc, 0x09, 0x33, 0x6a, 0x77, 0xdc, 0x6b, 0x22, 0x76, 0x5d, 0x92, 0x09, 0xac, 0x2d}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x23, 0x15, 0x17, 0xeb, 0xd3, 0xdb, 0x12, 0x5e, 0x01, 0xf0, 0x91, 0xab, 0x2c, 0x41, 0xce, 0xac, 0xed, 0x1b, 0x4b, 0x2d, 0xbc, 0xdb, 0x17, 0x66, 0x89, 0x46, 0xad, 0x4b, 0x1e, 0x6f, 0x0b, 0x14}} , {{0x11, 0xce, 0xbf, 0xb6, 0x77, 0x2d, 0x48, 0x22, 0x18, 0x4f, 0xa3, 0x5d, 0x4a, 0xb0, 0x70, 0x12, 0x3e, 0x54, 0xd7, 0xd8, 0x0e, 0x2b, 0x27, 0xdc, 0x53, 0xff, 0xca, 0x8c, 0x59, 0xb3, 0x4e, 0x44}}}, @@ -1511,7 +1511,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x0d, 0x16, 0xac, 0x3c, 0x4a, 0x58, 0x86, 0x3a, 0x46, 0x7f, 0x6c, 0xa3, 0x52, 0x6e, 0x37, 0xe4, 0x96, 0x9c, 0xe9, 0x5c, 0x66, 0x41, 0x67, 0xe4, 0xfb, 0x79, 0x0c, 0x05, 0xf6, 0x64, 0xd5, 0x7c}}}, {{{0x28, 0xc1, 0xe1, 0x54, 0x73, 0xf2, 0xbf, 0x76, 0x74, 0x19, 0x19, 0x1b, 0xe4, 0xb9, 0xa8, 0x46, 0x65, 0x73, 0xf3, 0x77, 0x9b, 0x29, 0x74, 0x5b, 0xc6, 0x89, 0x6c, 0x2c, 0x7c, 0xf8, 0xb3, 0x0f}} , {{0xf7, 0xd5, 0xe9, 0x74, 0x5d, 0xb8, 0x25, 0x16, 0xb5, 0x30, 0xbc, 0x84, 0xc5, 0xf0, 0xad, 0xca, 0x12, 0x28, 0xbc, 0x9d, 0xd4, 0xfa, 0x82, 0xe6, 0xe3, 0xbf, 0xa2, 0x15, 0x2c, 0xd4, 0x34, 0x10}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x61, 0xb1, 0x46, 0xba, 0x0e, 0x31, 0xa5, 0x67, 0x6c, 0x7f, 0xd6, 0xd9, 0x27, 0x85, 0x0f, 0x79, 0x14, 0xc8, 0x6c, 0x2f, 0x5f, 0x5b, 0x9c, 0x35, 0x3d, 0x38, 0x86, 0x77, 0x65, 0x55, 0x6a, 0x7b}} , {{0xd3, 0xb0, 0x3a, 0x66, 0x60, 0x1b, 0x43, 0xf1, 0x26, 0x58, 0x99, 0x09, 0x8f, 0x2d, 0xa3, 0x14, 0x71, 0x85, 0xdb, 0xed, 0xf6, 0x26, 0xd5, 0x61, 0x9a, 0x73, 0xac, 0x0e, 0xea, 0xac, 0xb7, 0x0c}}}, @@ -1521,7 +1521,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xe8, 0xc1, 0xa9, 0xc2, 0x7b, 0x59, 0x21, 0x33, 0xe2, 0x43, 0x73, 0x2b, 0xac, 0x2d, 0xc1, 0x89, 0x3b, 0x15, 0xe2, 0xd5, 0xc0, 0x97, 0x8a, 0xfd, 0x6f, 0x36, 0x33, 0xb7, 0xb9, 0xc3, 0x88, 0x09}}}, {{{0xd0, 0xb6, 0x56, 0x30, 0x5c, 0xae, 0xb3, 0x75, 0x44, 0xa4, 0x83, 0x51, 0x6e, 0x01, 0x65, 0xef, 0x45, 0x76, 0xe6, 0xf5, 0xa2, 0x0d, 0xd4, 0x16, 0x3b, 0x58, 0x2f, 0xf2, 0x2f, 0x36, 0x18, 0x3f}} , {{0xfd, 0x2f, 0xe0, 0x9b, 0x1e, 0x8c, 0xc5, 0x18, 0xa9, 0xca, 0xd4, 0x2b, 0x35, 0xb6, 0x95, 0x0a, 0x9f, 0x7e, 0xfb, 0xc4, 0xef, 0x88, 0x7b, 0x23, 0x43, 0xec, 0x2f, 0x0d, 0x0f, 0x7a, 0xfc, 0x5c}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb, 0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c, 0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b}} , {{0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63, 0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a, 0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61}}}, @@ -1531,7 +1531,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xa1, 0x4c, 0x70, 0x4b, 0x0e, 0xa0, 0x83, 0x70, 0x13, 0xa4, 0xaf, 0xb8, 0x38, 0x19, 0x22, 0x65, 0x09, 0xb4, 0x02, 0x4f, 0x06, 0xf8, 0x17, 0xce, 0x46, 0x45, 0xda, 0x50, 0x7c, 0x8a, 0xd1, 0x4e}}}, {{{0xf7, 0xd4, 0x16, 0x6c, 0x4e, 0x95, 0x9d, 0x5d, 0x0f, 0x91, 0x2b, 0x52, 0xfe, 0x5c, 0x34, 0xe5, 0x30, 0xe6, 0xa4, 0x3b, 0xf3, 0xf3, 0x34, 0x08, 0xa9, 0x4a, 0xa0, 0xb5, 0x6e, 0xb3, 0x09, 0x0a}} , {{0x26, 0xd9, 0x5e, 0xa3, 0x0f, 0xeb, 0xa2, 0xf3, 0x20, 0x3b, 0x37, 0xd4, 0xe4, 0x9e, 0xce, 0x06, 0x3d, 0x53, 0xed, 0xae, 0x2b, 0xeb, 0xb6, 0x24, 0x0a, 0x11, 0xa3, 0x0f, 0xd6, 0x7f, 0xa4, 0x3a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xdb, 0x9f, 0x2c, 0xfc, 0xd6, 0xb2, 0x1e, 0x2e, 0x52, 0x7a, 0x06, 0x87, 0x2d, 0x86, 0x72, 0x2b, 0x6d, 0x90, 0x77, 0x46, 0x43, 0xb5, 0x7a, 0xf8, 0x60, 0x7d, 0x91, 0x60, 0x5b, 0x9d, 0x9e, 0x07}} , {{0x97, 0x87, 0xc7, 0x04, 0x1c, 0x38, 0x01, 0x39, 0x58, 0xc7, 0x85, 0xa3, 0xfc, 0x64, 0x00, 0x64, 0x25, 0xa2, 0xbf, 0x50, 0x94, 0xca, 0x26, 0x31, 0x45, 0x0a, 0x24, 0xd2, 0x51, 0x29, 0x51, 0x16}}}, @@ -1541,7 +1541,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x95, 0x21, 0x01, 0xce, 0x95, 0x5b, 0x0e, 0x57, 0xc7, 0xb9, 0x62, 0xb5, 0x28, 0xca, 0x11, 0xec, 0xb4, 0x46, 0x06, 0x73, 0x26, 0xff, 0xfb, 0x66, 0x7d, 0xee, 0x5f, 0xb2, 0x56, 0xfd, 0x2a, 0x08}}}, {{{0x92, 0x67, 0x77, 0x56, 0xa1, 0xff, 0xc4, 0xc5, 0x95, 0xf0, 0xe3, 0x3a, 0x0a, 0xca, 0x94, 0x4d, 0x9e, 0x7e, 0x3d, 0xb9, 0x6e, 0xb6, 0xb0, 0xce, 0xa4, 0x30, 0x89, 0x99, 0xe9, 0xad, 0x11, 0x59}} , {{0xf6, 0x48, 0x95, 0xa1, 0x6f, 0x5f, 0xb7, 0xa5, 0xbb, 0x30, 0x00, 0x1c, 0xd2, 0x8a, 0xd6, 0x25, 0x26, 0x1b, 0xb2, 0x0d, 0x37, 0x6a, 0x05, 0xf4, 0x9d, 0x3e, 0x17, 0x2a, 0x43, 0xd2, 0x3a, 0x06}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x32, 0x99, 0x93, 0xd1, 0x9a, 0x72, 0xf3, 0xa9, 0x16, 0xbd, 0xb4, 0x4c, 0xdd, 0xf9, 0xd4, 0xb2, 0x64, 0x9a, 0xd3, 0x05, 0xe4, 0xa3, 0x73, 0x1c, 0xcb, 0x7e, 0x57, 0x67, 0xff, 0x04, 0xb3, 0x10}} , {{0xb9, 0x4b, 0xa4, 0xad, 0xd0, 0x6d, 0x61, 0x23, 0xb4, 0xaf, 0x34, 0xa9, 0xaa, 0x65, 0xec, 0xd9, 0x69, 0xe3, 0x85, 0xcd, 0xcc, 0xe7, 0xb0, 0x9b, 0x41, 0xc1, 0x1c, 0xf9, 0xa0, 0xfa, 0xb7, 0x13}}}, @@ -1551,7 +1551,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xfd, 0x4e, 0x2a, 0xc1, 0x3a, 0xca, 0x8f, 0x00, 0xd8, 0xec, 0x74, 0x67, 0xef, 0x61, 0xe0, 0x28, 0xd0, 0x96, 0xf4, 0x48, 0xde, 0x81, 0xe3, 0xef, 0xdc, 0xaa, 0x7d, 0xf3, 0xb6, 0x55, 0xa6, 0x65}}}, {{{0xeb, 0xcb, 0xc5, 0x70, 0x91, 0x31, 0x10, 0x93, 0x0d, 0xc8, 0xd0, 0xef, 0x62, 0xe8, 0x6f, 0x82, 0xe3, 0x69, 0x3d, 0x91, 0x7f, 0x31, 0xe1, 0x26, 0x35, 0x3c, 0x4a, 0x2f, 0xab, 0xc4, 0x9a, 0x5e}} , {{0xab, 0x1b, 0xb5, 0xe5, 0x2b, 0xc3, 0x0e, 0x29, 0xb0, 0xd0, 0x73, 0xe6, 0x4f, 0x64, 0xf2, 0xbc, 0xe4, 0xe4, 0xe1, 0x9a, 0x52, 0x33, 0x2f, 0xbd, 0xcc, 0x03, 0xee, 0x8a, 0xfa, 0x00, 0x5f, 0x50}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf6, 0xdb, 0x0d, 0x22, 0x3d, 0xb5, 0x14, 0x75, 0x31, 0xf0, 0x81, 0xe2, 0xb9, 0x37, 0xa2, 0xa9, 0x84, 0x11, 0x9a, 0x07, 0xb5, 0x53, 0x89, 0x78, 0xa9, 0x30, 0x27, 0xa1, 0xf1, 0x4e, 0x5c, 0x2e}} , {{0x8b, 0x00, 0x54, 0xfb, 0x4d, 0xdc, 0xcb, 0x17, 0x35, 0x40, 0xff, 0xb7, 0x8c, 0xfe, 0x4a, 0xe4, 0x4e, 0x99, 0x4e, 0xa8, 0x74, 0x54, 0x5d, 0x5c, 0x96, 0xa3, 0x12, 0x55, 0x36, 0x31, 0x17, 0x5c}}}, @@ -1561,7 +1561,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x8c, 0x44, 0x09, 0x28, 0xd5, 0x23, 0xc9, 0x8f, 0xf3, 0x84, 0x45, 0xc6, 0x9a, 0x5e, 0xff, 0xd2, 0xc7, 0x57, 0x93, 0xa3, 0xc1, 0x69, 0xdd, 0x62, 0x0f, 0xda, 0x5c, 0x30, 0x59, 0x5d, 0xe9, 0x4c}}}, {{{0x92, 0x7e, 0x50, 0x27, 0x72, 0xd7, 0x0c, 0xd6, 0x69, 0x96, 0x81, 0x35, 0x84, 0x94, 0x35, 0x8b, 0x6c, 0xaa, 0x62, 0x86, 0x6e, 0x1c, 0x15, 0xf3, 0x6c, 0xb3, 0xff, 0x65, 0x1b, 0xa2, 0x9b, 0x59}} , {{0xe2, 0xa9, 0x65, 0x88, 0xc4, 0x50, 0xfa, 0xbb, 0x3b, 0x6e, 0x5f, 0x44, 0x01, 0xca, 0x97, 0xd4, 0xdd, 0xf6, 0xcd, 0x3f, 0x3f, 0xe5, 0x97, 0x67, 0x2b, 0x8c, 0x66, 0x0f, 0x35, 0x9b, 0xf5, 0x07}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf1, 0x59, 0x27, 0xd8, 0xdb, 0x5a, 0x11, 0x5e, 0x82, 0xf3, 0x38, 0xff, 0x1c, 0xed, 0xfe, 0x3f, 0x64, 0x54, 0x3f, 0x7f, 0xd1, 0x81, 0xed, 0xef, 0x65, 0xc5, 0xcb, 0xfd, 0xe1, 0x80, 0xcd, 0x11}} , {{0xe0, 0xdb, 0x22, 0x28, 0xe6, 0xff, 0x61, 0x9d, 0x41, 0x14, 0x2d, 0x3b, 0x26, 0x22, 0xdf, 0xf1, 0x34, 0x81, 0xe9, 0x45, 0xee, 0x0f, 0x98, 0x8b, 0xa6, 0x3f, 0xef, 0xf7, 0x43, 0x19, 0xf1, 0x43}}}, @@ -1571,7 +1571,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x60, 0xbc, 0x45, 0x1f, 0x23, 0xa2, 0x3b, 0x70, 0x76, 0xe6, 0x97, 0x99, 0x4f, 0x77, 0x54, 0x67, 0x30, 0x9a, 0xe7, 0x66, 0xd6, 0xcd, 0x2e, 0x51, 0x24, 0x2c, 0x42, 0x4a, 0x11, 0xfe, 0x6f, 0x7e}}}, {{{0x87, 0xc0, 0xb1, 0xf0, 0xa3, 0x6f, 0x0c, 0x93, 0xa9, 0x0a, 0x72, 0xef, 0x5c, 0xbe, 0x65, 0x35, 0xa7, 0x6a, 0x4e, 0x2c, 0xbf, 0x21, 0x23, 0xe8, 0x2f, 0x97, 0xc7, 0x3e, 0xc8, 0x17, 0xac, 0x1e}} , {{0x7b, 0xef, 0x21, 0xe5, 0x40, 0xcc, 0x1e, 0xdc, 0xd6, 0xbd, 0x97, 0x7a, 0x7c, 0x75, 0x86, 0x7a, 0x25, 0x5a, 0x6e, 0x7c, 0xe5, 0x51, 0x3c, 0x1b, 0x5b, 0x82, 0x9a, 0x07, 0x60, 0xa1, 0x19, 0x04}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x96, 0x88, 0xa6, 0xab, 0x8f, 0xe3, 0x3a, 0x49, 0xf8, 0xfe, 0x34, 0xe7, 0x6a, 0xb2, 0xfe, 0x40, 0x26, 0x74, 0x57, 0x4c, 0xf6, 0xd4, 0x99, 0xce, 0x5d, 0x7b, 0x2f, 0x67, 0xd6, 0x5a, 0xe4, 0x4e}} , {{0x5c, 0x82, 0xb3, 0xbd, 0x55, 0x25, 0xf6, 0x6a, 0x93, 0xa4, 0x02, 0xc6, 0x7d, 0x5c, 0xb1, 0x2b, 0x5b, 0xff, 0xfb, 0x56, 0xf8, 0x01, 0x41, 0x90, 0xc6, 0xb6, 0xac, 0x4f, 0xfe, 0xa7, 0x41, 0x70}}}, @@ -1581,7 +1581,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x17, 0x0f, 0x86, 0x52, 0xd7, 0x9d, 0xc3, 0x44, 0x51, 0x76, 0x32, 0x65, 0xb4, 0x37, 0x81, 0x99, 0x46, 0x37, 0x62, 0xed, 0xcf, 0x64, 0x9d, 0x72, 0x40, 0x7a, 0x4c, 0x0b, 0x76, 0x2a, 0xfb, 0x56}}}, {{{0x33, 0xa7, 0x90, 0x7c, 0xc3, 0x6f, 0x17, 0xa5, 0xa0, 0x67, 0x72, 0x17, 0xea, 0x7e, 0x63, 0x14, 0x83, 0xde, 0xc1, 0x71, 0x2d, 0x41, 0x32, 0x7a, 0xf3, 0xd1, 0x2b, 0xd8, 0x2a, 0xa6, 0x46, 0x36}} , {{0xac, 0xcc, 0x6b, 0x7c, 0xf9, 0xb8, 0x8b, 0x08, 0x5c, 0xd0, 0x7d, 0x8f, 0x73, 0xea, 0x20, 0xda, 0x86, 0xca, 0x00, 0xc7, 0xad, 0x73, 0x4d, 0xe9, 0xe8, 0xa9, 0xda, 0x1f, 0x03, 0x06, 0xdd, 0x24}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9c, 0xb2, 0x61, 0x0a, 0x98, 0x2a, 0xa5, 0xd7, 0xee, 0xa9, 0xac, 0x65, 0xcb, 0x0a, 0x1e, 0xe2, 0xbe, 0xdc, 0x85, 0x59, 0x0f, 0x9c, 0xa6, 0x57, 0x34, 0xa5, 0x87, 0xeb, 0x7b, 0x1e, 0x0c, 0x3c}} , {{0x2f, 0xbd, 0x84, 0x63, 0x0d, 0xb5, 0xa0, 0xf0, 0x4b, 0x9e, 0x93, 0xc6, 0x34, 0x9a, 0x34, 0xff, 0x73, 0x19, 0x2f, 0x6e, 0x54, 0x45, 0x2c, 0x92, 0x31, 0x76, 0x34, 0xf1, 0xb2, 0x26, 0xe8, 0x74}}}, @@ -1591,7 +1591,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x87, 0xc8, 0xa0, 0x6e, 0xe1, 0xb0, 0xad, 0x6a, 0x4a, 0x34, 0x71, 0xed, 0x7c, 0xd6, 0x44, 0x03, 0x65, 0x4a, 0x5c, 0x5c, 0x04, 0xf5, 0x24, 0x3f, 0xb0, 0x16, 0x5e, 0x8c, 0xb2, 0xd2, 0xc5, 0x20}}}, {{{0x98, 0x83, 0xc2, 0x37, 0xa0, 0x41, 0xa8, 0x48, 0x5c, 0x5f, 0xbf, 0xc8, 0xfa, 0x24, 0xe0, 0x59, 0x2c, 0xbd, 0xf6, 0x81, 0x7e, 0x88, 0xe6, 0xca, 0x04, 0xd8, 0x5d, 0x60, 0xbb, 0x74, 0xa7, 0x0b}} , {{0x21, 0x13, 0x91, 0xbf, 0x77, 0x7a, 0x33, 0xbc, 0xe9, 0x07, 0x39, 0x0a, 0xdd, 0x7d, 0x06, 0x10, 0x9a, 0xee, 0x47, 0x73, 0x1b, 0x15, 0x5a, 0xfb, 0xcd, 0x4d, 0xd0, 0xd2, 0x3a, 0x01, 0xba, 0x54}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x48, 0xd5, 0x39, 0x4a, 0x0b, 0x20, 0x6a, 0x43, 0xa0, 0x07, 0x82, 0x5e, 0x49, 0x7c, 0xc9, 0x47, 0xf1, 0x7c, 0x37, 0xb9, 0x23, 0xef, 0x6b, 0x46, 0x45, 0x8c, 0x45, 0x76, 0xdf, 0x14, 0x6b, 0x6e}} , {{0x42, 0xc9, 0xca, 0x29, 0x4c, 0x76, 0x37, 0xda, 0x8a, 0x2d, 0x7c, 0x3a, 0x58, 0xf2, 0x03, 0xb4, 0xb5, 0xb9, 0x1a, 0x13, 0x2d, 0xde, 0x5f, 0x6b, 0x9d, 0xba, 0x52, 0xc9, 0x5d, 0xb3, 0xf3, 0x30}}}, @@ -1601,7 +1601,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xe4, 0xe7, 0x43, 0x4b, 0xa0, 0x3f, 0x2b, 0x06, 0xba, 0x17, 0xae, 0x3d, 0xe6, 0xce, 0xbd, 0xb8, 0xed, 0x74, 0x11, 0x35, 0xec, 0x96, 0xfe, 0x31, 0xe3, 0x0e, 0x7a, 0x4e, 0xc9, 0x1d, 0xcb, 0x20}}}, {{{0xe0, 0x67, 0xe9, 0x7b, 0xdb, 0x96, 0x5c, 0xb0, 0x32, 0xd0, 0x59, 0x31, 0x90, 0xdc, 0x92, 0x97, 0xac, 0x09, 0x38, 0x31, 0x0f, 0x7e, 0xd6, 0x5d, 0xd0, 0x06, 0xb6, 0x1f, 0xea, 0xf0, 0x5b, 0x07}} , {{0x81, 0x9f, 0xc7, 0xde, 0x6b, 0x41, 0x22, 0x35, 0x14, 0x67, 0x77, 0x3e, 0x90, 0x81, 0xb0, 0xd9, 0x85, 0x4c, 0xca, 0x9b, 0x3f, 0x04, 0x59, 0xd6, 0xaa, 0x17, 0xc3, 0x88, 0x34, 0x37, 0xba, 0x43}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x4c, 0xb6, 0x69, 0xc8, 0x81, 0x95, 0x94, 0x33, 0x92, 0x34, 0xe9, 0x3c, 0x84, 0x0d, 0x3d, 0x5a, 0x37, 0x9c, 0x22, 0xa0, 0xaa, 0x65, 0xce, 0xb4, 0xc2, 0x2d, 0x66, 0x67, 0x02, 0xff, 0x74, 0x10}} , {{0x22, 0xb0, 0xd5, 0xe6, 0xc7, 0xef, 0xb1, 0xa7, 0x13, 0xda, 0x60, 0xb4, 0x80, 0xc1, 0x42, 0x7d, 0x10, 0x70, 0x97, 0x04, 0x4d, 0xda, 0x23, 0x89, 0xc2, 0x0e, 0x68, 0xcb, 0xde, 0xe0, 0x9b, 0x29}}}, @@ -1611,7 +1611,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xa0, 0x20, 0x99, 0x69, 0x0a, 0xae, 0xa3, 0x70, 0x4e, 0x64, 0x80, 0xb7, 0x85, 0x9c, 0x87, 0x54, 0x43, 0x43, 0x55, 0x80, 0x6d, 0x8d, 0x7c, 0xa9, 0x64, 0xca, 0x6c, 0x2e, 0x21, 0xd8, 0xc8, 0x6c}}}, {{{0x91, 0x4a, 0x07, 0xad, 0x08, 0x75, 0xc1, 0x4f, 0xa4, 0xb2, 0xc3, 0x6f, 0x46, 0x3e, 0xb1, 0xce, 0x52, 0xab, 0x67, 0x09, 0x54, 0x48, 0x6b, 0x6c, 0xd7, 0x1d, 0x71, 0x76, 0xcb, 0xff, 0xdd, 0x31}} , {{0x36, 0x88, 0xfa, 0xfd, 0xf0, 0x36, 0x6f, 0x07, 0x74, 0x88, 0x50, 0xd0, 0x95, 0x38, 0x4a, 0x48, 0x2e, 0x07, 0x64, 0x97, 0x11, 0x76, 0x01, 0x1a, 0x27, 0x4d, 0x8e, 0x25, 0x9a, 0x9b, 0x1c, 0x22}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xbe, 0x57, 0xbd, 0x0e, 0x0f, 0xac, 0x5e, 0x76, 0xa3, 0x71, 0xad, 0x2b, 0x10, 0x45, 0x02, 0xec, 0x59, 0xd5, 0x5d, 0xa9, 0x44, 0xcc, 0x25, 0x4c, 0xb3, 0x3c, 0x5b, 0x69, 0x07, 0x55, 0x26, 0x6b}} , {{0x30, 0x6b, 0xd4, 0xa7, 0x51, 0x29, 0xe3, 0xf9, 0x7a, 0x75, 0x2a, 0x82, 0x2f, 0xd6, 0x1d, 0x99, 0x2b, 0x80, 0xd5, 0x67, 0x1e, 0x15, 0x9d, 0xca, 0xfd, 0xeb, 0xac, 0x97, 0x35, 0x09, 0x7f, 0x3f}}}, @@ -1621,7 +1621,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xad, 0xa0, 0x41, 0xec, 0xc8, 0x4d, 0xb9, 0xd2, 0x6e, 0x96, 0x4e, 0x5b, 0xc5, 0xc2, 0xa0, 0x1b, 0xcf, 0x0c, 0xbf, 0x17, 0x66, 0x57, 0xc1, 0x17, 0x90, 0x45, 0x71, 0xc2, 0xe1, 0x24, 0xeb, 0x27}}}, {{{0x2c, 0xb9, 0x42, 0xa4, 0xaf, 0x3b, 0x42, 0x0e, 0xc2, 0x0f, 0xf2, 0xea, 0x83, 0xaf, 0x9a, 0x13, 0x17, 0xb0, 0xbd, 0x89, 0x17, 0xe3, 0x72, 0xcb, 0x0e, 0x76, 0x7e, 0x41, 0x63, 0x04, 0x88, 0x71}} , {{0x75, 0x78, 0x38, 0x86, 0x57, 0xdd, 0x9f, 0xee, 0x54, 0x70, 0x65, 0xbf, 0xf1, 0x2c, 0xe0, 0x39, 0x0d, 0xe3, 0x89, 0xfd, 0x8e, 0x93, 0x4f, 0x43, 0xdc, 0xd5, 0x5b, 0xde, 0xf9, 0x98, 0xe5, 0x7b}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xe7, 0x3b, 0x65, 0x11, 0xdf, 0xb2, 0xf2, 0x63, 0x94, 0x12, 0x6f, 0x5c, 0x9e, 0x77, 0xc1, 0xb6, 0xd8, 0xab, 0x58, 0x7a, 0x1d, 0x95, 0x73, 0xdd, 0xe7, 0xe3, 0x6f, 0xf2, 0x03, 0x1d, 0xdb, 0x76}} , {{0xae, 0x06, 0x4e, 0x2c, 0x52, 0x1b, 0xbc, 0x5a, 0x5a, 0xa5, 0xbe, 0x27, 0xbd, 0xeb, 0xe1, 0x14, 0x17, 0x68, 0x26, 0x07, 0x03, 0xd1, 0x18, 0x0b, 0xdf, 0xf1, 0x06, 0x5c, 0xa6, 0x1b, 0xb9, 0x24}}}, @@ -1631,7 +1631,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x8d, 0xbd, 0xa3, 0xc4, 0x06, 0x9b, 0x1f, 0x90, 0x58, 0x60, 0x74, 0xb2, 0x00, 0x3b, 0x3c, 0xd2, 0xda, 0x82, 0xbb, 0x10, 0x90, 0x69, 0x92, 0xa9, 0xb4, 0x30, 0x81, 0xe3, 0x7c, 0xa8, 0x89, 0x45}}}, {{{0x3f, 0xdc, 0x05, 0xcb, 0x41, 0x3c, 0xc8, 0x23, 0x04, 0x2c, 0x38, 0x99, 0xe3, 0x68, 0x55, 0xf9, 0xd3, 0x32, 0xc7, 0xbf, 0xfa, 0xd4, 0x1b, 0x5d, 0xde, 0xdc, 0x10, 0x42, 0xc0, 0x42, 0xd9, 0x75}} , {{0x2d, 0xab, 0x35, 0x4e, 0x87, 0xc4, 0x65, 0x97, 0x67, 0x24, 0xa4, 0x47, 0xad, 0x3f, 0x8e, 0xf3, 0xcb, 0x31, 0x17, 0x77, 0xc5, 0xe2, 0xd7, 0x8f, 0x3c, 0xc1, 0xcd, 0x56, 0x48, 0xc1, 0x6c, 0x69}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x14, 0xae, 0x5f, 0x88, 0x7b, 0xa5, 0x90, 0xdf, 0x10, 0xb2, 0x8b, 0x5e, 0x24, 0x17, 0xc3, 0xa3, 0xd4, 0x0f, 0x92, 0x61, 0x1a, 0x19, 0x5a, 0xad, 0x76, 0xbd, 0xd8, 0x1c, 0xdd, 0xe0, 0x12, 0x6d}} , {{0x8e, 0xbd, 0x70, 0x8f, 0x02, 0xa3, 0x24, 0x4d, 0x5a, 0x67, 0xc4, 0xda, 0xf7, 0x20, 0x0f, 0x81, 0x5b, 0x7a, 0x05, 0x24, 0x67, 0x83, 0x0b, 0x2a, 0x80, 0xe7, 0xfd, 0x74, 0x4b, 0x9e, 0x5c, 0x0d}}}, @@ -1641,7 +1641,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x97, 0x29, 0x6c, 0xc4, 0x42, 0x0b, 0xdd, 0xc0, 0x29, 0x5c, 0x9b, 0x34, 0x97, 0xd0, 0xc7, 0x79, 0x80, 0x63, 0x74, 0xe4, 0x8e, 0x37, 0xb0, 0x2b, 0x7c, 0xe8, 0x68, 0x6c, 0xc3, 0x82, 0x97, 0x57}}}, {{{0x22, 0xbe, 0x83, 0xb6, 0x4b, 0x80, 0x6b, 0x43, 0x24, 0x5e, 0xef, 0x99, 0x9b, 0xa8, 0xfc, 0x25, 0x8d, 0x3b, 0x03, 0x94, 0x2b, 0x3e, 0xe7, 0x95, 0x76, 0x9b, 0xcc, 0x15, 0xdb, 0x32, 0xe6, 0x66}} , {{0x84, 0xf0, 0x4a, 0x13, 0xa6, 0xd6, 0xfa, 0x93, 0x46, 0x07, 0xf6, 0x7e, 0x5c, 0x6d, 0x5e, 0xf6, 0xa6, 0xe7, 0x48, 0xf0, 0x06, 0xea, 0xff, 0x90, 0xc1, 0xcc, 0x4c, 0x19, 0x9c, 0x3c, 0x4e, 0x53}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2a, 0x50, 0xe3, 0x07, 0x15, 0x59, 0xf2, 0x8b, 0x81, 0xf2, 0xf3, 0xd3, 0x6c, 0x99, 0x8c, 0x70, 0x67, 0xec, 0xcc, 0xee, 0x9e, 0x59, 0x45, 0x59, 0x7d, 0x47, 0x75, 0x69, 0xf5, 0x24, 0x93, 0x5d}} , {{0x6a, 0x4f, 0x1b, 0xbe, 0x6b, 0x30, 0xcf, 0x75, 0x46, 0xe3, 0x7b, 0x9d, 0xfc, 0xcd, 0xd8, 0x5c, 0x1f, 0xb4, 0xc8, 0xe2, 0x24, 0xec, 0x1a, 0x28, 0x05, 0x32, 0x57, 0xfd, 0x3c, 0x5a, 0x98, 0x10}}}, @@ -1651,7 +1651,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x9b, 0x35, 0xe2, 0xa9, 0x3d, 0x32, 0x1e, 0xbb, 0x16, 0x28, 0x70, 0xe9, 0x45, 0x2f, 0x8f, 0x70, 0x7f, 0x08, 0x7e, 0x53, 0xc4, 0x7a, 0xbf, 0xf7, 0xe1, 0xa4, 0x6a, 0xd8, 0xac, 0x64, 0x1b, 0x11}}}, {{{0xb2, 0xeb, 0x47, 0x46, 0x18, 0x3e, 0x1f, 0x99, 0x0c, 0xcc, 0xf1, 0x2c, 0xe0, 0xe7, 0x8f, 0xe0, 0x01, 0x7e, 0x65, 0xb8, 0x0c, 0xd0, 0xfb, 0xc8, 0xb9, 0x90, 0x98, 0x33, 0x61, 0x3b, 0xd8, 0x27}} , {{0xa0, 0xbe, 0x72, 0x3a, 0x50, 0x4b, 0x74, 0xab, 0x01, 0xc8, 0x93, 0xc5, 0xe4, 0xc7, 0x08, 0x6c, 0xb4, 0xca, 0xee, 0xeb, 0x8e, 0xd7, 0x4e, 0x26, 0xc6, 0x1d, 0xe2, 0x71, 0xaf, 0x89, 0xa0, 0x2a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x98, 0x0b, 0xe4, 0xde, 0xdb, 0xa8, 0xfa, 0x82, 0x74, 0x06, 0x52, 0x6d, 0x08, 0x52, 0x8a, 0xff, 0x62, 0xc5, 0x6a, 0x44, 0x0f, 0x51, 0x8c, 0x1f, 0x6e, 0xb6, 0xc6, 0x2c, 0x81, 0xd3, 0x76, 0x46}} , {{0xf4, 0x29, 0x74, 0x2e, 0x80, 0xa7, 0x1a, 0x8f, 0xf6, 0xbd, 0xd6, 0x8e, 0xbf, 0xc1, 0x95, 0x2a, 0xeb, 0xa0, 0x7f, 0x45, 0xa0, 0x50, 0x14, 0x05, 0xb1, 0x57, 0x4c, 0x74, 0xb7, 0xe2, 0x89, 0x7d}}}, @@ -1661,7 +1661,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x29, 0xd8, 0xf2, 0xaa, 0xe9, 0x0e, 0xf7, 0x2e, 0x5f, 0x9d, 0x8a, 0x5b, 0x09, 0xed, 0xc9, 0x24, 0x22, 0xf4, 0x0f, 0x25, 0x8f, 0x1c, 0x84, 0x6e, 0x34, 0x14, 0x6c, 0xea, 0xb3, 0x86, 0x5d, 0x04}}}, {{{0x07, 0x98, 0x61, 0xe8, 0x6a, 0xd2, 0x81, 0x49, 0x25, 0xd5, 0x5b, 0x18, 0xc7, 0x35, 0x52, 0x51, 0xa4, 0x46, 0xad, 0x18, 0x0d, 0xc9, 0x5f, 0x18, 0x91, 0x3b, 0xb4, 0xc0, 0x60, 0x59, 0x8d, 0x66}} , {{0x03, 0x1b, 0x79, 0x53, 0x6e, 0x24, 0xae, 0x57, 0xd9, 0x58, 0x09, 0x85, 0x48, 0xa2, 0xd3, 0xb5, 0xe2, 0x4d, 0x11, 0x82, 0xe6, 0x86, 0x3c, 0xe9, 0xb1, 0x00, 0x19, 0xc2, 0x57, 0xf7, 0x66, 0x7a}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0f, 0xe3, 0x89, 0x03, 0xd7, 0x22, 0x95, 0x9f, 0xca, 0xb4, 0x8d, 0x9e, 0x6d, 0x97, 0xff, 0x8d, 0x21, 0x59, 0x07, 0xef, 0x03, 0x2d, 0x5e, 0xf8, 0x44, 0x46, 0xe7, 0x85, 0x80, 0xc5, 0x89, 0x50}} , {{0x8b, 0xd8, 0x53, 0x86, 0x24, 0x86, 0x29, 0x52, 0x01, 0xfa, 0x20, 0xc3, 0x4e, 0x95, 0xcb, 0xad, 0x7b, 0x34, 0x94, 0x30, 0xb7, 0x7a, 0xfa, 0x96, 0x41, 0x60, 0x2b, 0xcb, 0x59, 0xb9, 0xca, 0x50}}}, @@ -1671,7 +1671,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x19, 0xf9, 0x35, 0xaa, 0x59, 0x1a, 0x0c, 0x5c, 0x06, 0xfc, 0x6a, 0x0b, 0x97, 0x53, 0x36, 0xfc, 0x2a, 0xa5, 0x5a, 0x9b, 0x30, 0xef, 0x23, 0xaf, 0x39, 0x5d, 0x9a, 0x6b, 0x75, 0x57, 0x48, 0x0b}}}, {{{0x26, 0xdc, 0x76, 0x3b, 0xfc, 0xf9, 0x9c, 0x3f, 0x89, 0x0b, 0x62, 0x53, 0xaf, 0x83, 0x01, 0x2e, 0xbc, 0x6a, 0xc6, 0x03, 0x0d, 0x75, 0x2a, 0x0d, 0xe6, 0x94, 0x54, 0xcf, 0xb3, 0xe5, 0x96, 0x25}} , {{0xfe, 0x82, 0xb1, 0x74, 0x31, 0x8a, 0xa7, 0x6f, 0x56, 0xbd, 0x8d, 0xf4, 0xe0, 0x94, 0x51, 0x59, 0xde, 0x2c, 0x5a, 0xf4, 0x84, 0x6b, 0x4a, 0x88, 0x93, 0xc0, 0x0c, 0x9a, 0xac, 0xa7, 0xa0, 0x68}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0x0d, 0xd6, 0xc7, 0x23, 0x47, 0x10, 0xad, 0xc7, 0x08, 0x5c, 0x87, 0x87, 0x93, 0x98, 0x18, 0xb8, 0xd3, 0x9c, 0xac, 0x5a, 0x3d, 0xc5, 0x75, 0xf8, 0x49, 0x32, 0x14, 0xcc, 0x51, 0x96, 0x24}} , {{0x65, 0x9c, 0x5d, 0xf0, 0x37, 0x04, 0xf0, 0x34, 0x69, 0x2a, 0xf0, 0xa5, 0x64, 0xca, 0xde, 0x2b, 0x5b, 0x15, 0x10, 0xd2, 0xab, 0x06, 0xdd, 0xc4, 0xb0, 0xb6, 0x5b, 0xc1, 0x17, 0xdf, 0x8f, 0x02}}}, @@ -1681,7 +1681,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x00, 0xa9, 0x4c, 0xb2, 0x12, 0xf8, 0x32, 0xa8, 0x7a, 0x00, 0x4b, 0x49, 0x32, 0xba, 0x1f, 0x5d, 0x44, 0x8e, 0x44, 0x7a, 0xdc, 0x11, 0xfb, 0x39, 0x08, 0x57, 0x87, 0xa5, 0x12, 0x42, 0x93, 0x0e}}}, {{{0x17, 0xb4, 0xae, 0x72, 0x59, 0xd0, 0xaa, 0xa8, 0x16, 0x8b, 0x63, 0x11, 0xb3, 0x43, 0x04, 0xda, 0x0c, 0xa8, 0xb7, 0x68, 0xdd, 0x4e, 0x54, 0xe7, 0xaf, 0x5d, 0x5d, 0x05, 0x76, 0x36, 0xec, 0x0d}} , {{0x6d, 0x7c, 0x82, 0x32, 0x38, 0x55, 0x57, 0x74, 0x5b, 0x7d, 0xc3, 0xc4, 0xfb, 0x06, 0x29, 0xf0, 0x13, 0x55, 0x54, 0xc6, 0xa7, 0xdc, 0x4c, 0x9f, 0x98, 0x49, 0x20, 0xa8, 0xc3, 0x8d, 0xfa, 0x48}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x87, 0x47, 0x9d, 0xe9, 0x25, 0xd5, 0xe3, 0x47, 0x78, 0xdf, 0x85, 0xa7, 0x85, 0x5e, 0x7a, 0x4c, 0x5f, 0x79, 0x1a, 0xf3, 0xa2, 0xb2, 0x28, 0xa0, 0x9c, 0xdd, 0x30, 0x40, 0xd4, 0x38, 0xbd, 0x28}} , {{0xfc, 0xbb, 0xd5, 0x78, 0x6d, 0x1d, 0xd4, 0x99, 0xb4, 0xaa, 0x44, 0x44, 0x7a, 0x1b, 0xd8, 0xfe, 0xb4, 0x99, 0xb9, 0xcc, 0xe7, 0xc4, 0xd3, 0x3a, 0x73, 0x83, 0x41, 0x5c, 0x40, 0xd7, 0x2d, 0x55}}}, @@ -1691,7 +1691,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xc0, 0x61, 0x48, 0x48, 0x17, 0xf4, 0x9e, 0x18, 0x51, 0x2d, 0xea, 0x2f, 0xf2, 0xf2, 0xe0, 0xa3, 0x14, 0xb7, 0x8b, 0x3a, 0x30, 0xf5, 0x81, 0xc1, 0x5d, 0x71, 0x39, 0x62, 0x55, 0x1f, 0x60, 0x5a}}}, {{{0xe5, 0x89, 0x8a, 0x76, 0x6c, 0xdb, 0x4d, 0x0a, 0x5b, 0x72, 0x9d, 0x59, 0x6e, 0x63, 0x63, 0x18, 0x7c, 0xe3, 0xfa, 0xe2, 0xdb, 0xa1, 0x8d, 0xf4, 0xa5, 0xd7, 0x16, 0xb2, 0xd0, 0xb3, 0x3f, 0x39}} , {{0xce, 0x60, 0x09, 0x6c, 0xf5, 0x76, 0x17, 0x24, 0x80, 0x3a, 0x96, 0xc7, 0x94, 0x2e, 0xf7, 0x6b, 0xef, 0xb5, 0x05, 0x96, 0xef, 0xd3, 0x7b, 0x51, 0xda, 0x05, 0x44, 0x67, 0xbc, 0x07, 0x21, 0x4e}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xe9, 0x73, 0x6f, 0x21, 0xb9, 0xde, 0x22, 0x7d, 0xeb, 0x97, 0x31, 0x10, 0xa3, 0xea, 0xe1, 0xc6, 0x37, 0xeb, 0x8f, 0x43, 0x58, 0xde, 0x41, 0x64, 0x0e, 0x3e, 0x07, 0x99, 0x3d, 0xf1, 0xdf, 0x1e}} , {{0xf8, 0xad, 0x43, 0xc2, 0x17, 0x06, 0xe2, 0xe4, 0xa9, 0x86, 0xcd, 0x18, 0xd7, 0x78, 0xc8, 0x74, 0x66, 0xd2, 0x09, 0x18, 0xa5, 0xf1, 0xca, 0xa6, 0x62, 0x92, 0xc1, 0xcb, 0x00, 0xeb, 0x42, 0x2e}}}, @@ -1701,7 +1701,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xa3, 0x64, 0x17, 0x9b, 0x8b, 0xc8, 0x3a, 0x61, 0xe6, 0x9d, 0xc6, 0xed, 0x7b, 0x03, 0x52, 0x26, 0x9d, 0x3a, 0xb3, 0x13, 0xcc, 0x8a, 0xfd, 0x2c, 0x1a, 0x1d, 0xed, 0x13, 0xd0, 0x55, 0x57, 0x0e}}}, {{{0x1a, 0xea, 0xbf, 0xfd, 0x4a, 0x3c, 0x8e, 0xec, 0x29, 0x7e, 0x77, 0x77, 0x12, 0x99, 0xd7, 0x84, 0xf9, 0x55, 0x7f, 0xf1, 0x8b, 0xb4, 0xd2, 0x95, 0xa3, 0x8d, 0xf0, 0x8a, 0xa7, 0xeb, 0x82, 0x4b}} , {{0x2c, 0x28, 0xf4, 0x3a, 0xf6, 0xde, 0x0a, 0xe0, 0x41, 0x44, 0x23, 0xf8, 0x3f, 0x03, 0x64, 0x9f, 0xc3, 0x55, 0x4c, 0xc6, 0xc1, 0x94, 0x1c, 0x24, 0x5d, 0x5f, 0x92, 0x45, 0x96, 0x57, 0x37, 0x14}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc1, 0xcd, 0x90, 0x66, 0xb9, 0x76, 0xa0, 0x5b, 0xa5, 0x85, 0x75, 0x23, 0xf9, 0x89, 0xa5, 0x82, 0xb2, 0x6f, 0xb1, 0xeb, 0xc4, 0x69, 0x6f, 0x18, 0x5a, 0xed, 0x94, 0x3d, 0x9d, 0xd9, 0x2c, 0x1a}} , {{0x35, 0xb0, 0xe6, 0x73, 0x06, 0xb7, 0x37, 0xe0, 0xf8, 0xb0, 0x22, 0xe8, 0xd2, 0xed, 0x0b, 0xef, 0xe6, 0xc6, 0x5a, 0x99, 0x9e, 0x1a, 0x9f, 0x04, 0x97, 0xe4, 0x4d, 0x0b, 0xbe, 0xba, 0x44, 0x40}}}, @@ -1711,7 +1711,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0xa7, 0xbb, 0xf6, 0x8e, 0xad, 0xdd, 0xf7, 0x90, 0xdd, 0x5f, 0x93, 0x89, 0xae, 0x04, 0x37, 0xe6, 0x9a, 0xb7, 0xe8, 0xc0, 0xdf, 0x16, 0x2a, 0xbf, 0xc4, 0x3a, 0x3c, 0x41, 0xd5, 0x89, 0x72, 0x5a}}}, {{{0x1f, 0x96, 0xff, 0x34, 0x2c, 0x13, 0x21, 0xcb, 0x0a, 0x89, 0x85, 0xbe, 0xb3, 0x70, 0x9e, 0x1e, 0xde, 0x97, 0xaf, 0x96, 0x30, 0xf7, 0x48, 0x89, 0x40, 0x8d, 0x07, 0xf1, 0x25, 0xf0, 0x30, 0x58}} , {{0x1e, 0xd4, 0x93, 0x57, 0xe2, 0x17, 0xe7, 0x9d, 0xab, 0x3c, 0x55, 0x03, 0x82, 0x2f, 0x2b, 0xdb, 0x56, 0x1e, 0x30, 0x2e, 0x24, 0x47, 0x6e, 0xe6, 0xff, 0x33, 0x24, 0x2c, 0x75, 0x51, 0xd4, 0x67}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2b, 0x06, 0xd9, 0xa1, 0x5d, 0xe1, 0xf4, 0xd1, 0x1e, 0x3c, 0x9a, 0xc6, 0x29, 0x2b, 0x13, 0x13, 0x78, 0xc0, 0xd8, 0x16, 0x17, 0x2d, 0x9e, 0xa9, 0xc9, 0x79, 0x57, 0xab, 0x24, 0x91, 0x92, 0x19}} , {{0x69, 0xfb, 0xa1, 0x9c, 0xa6, 0x75, 0x49, 0x7d, 0x60, 0x73, 0x40, 0x42, 0xc4, 0x13, 0x0a, 0x95, 0x79, 0x1e, 0x04, 0x83, 0x94, 0x99, 0x9b, 0x1e, 0x0c, 0xe8, 0x1f, 0x54, 0xef, 0xcb, 0xc0, 0x52}}}, @@ -1721,7 +1721,7 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x9d, 0x45, 0xd6, 0x80, 0xe6, 0x45, 0xaa, 0xf4, 0x15, 0xaa, 0x5c, 0x34, 0x87, 0x99, 0xa2, 0x8c, 0x26, 0x84, 0x62, 0x7d, 0xb6, 0x29, 0xc0, 0x52, 0xea, 0xf5, 0x81, 0x18, 0x0f, 0x35, 0xa9, 0x0e}}}, {{{0xe7, 0x20, 0x72, 0x7c, 0x6d, 0x94, 0x5f, 0x52, 0x44, 0x54, 0xe3, 0xf1, 0xb2, 0xb0, 0x36, 0x46, 0x0f, 0xae, 0x92, 0xe8, 0x70, 0x9d, 0x6e, 0x79, 0xb1, 0xad, 0x37, 0xa9, 0x5f, 0xc0, 0xde, 0x03}} , {{0x15, 0x55, 0x37, 0xc6, 0x1c, 0x27, 0x1c, 0x6d, 0x14, 0x4f, 0xca, 0xa4, 0xc4, 0x88, 0x25, 0x46, 0x39, 0xfc, 0x5a, 0xe5, 0xfe, 0x29, 0x11, 0x69, 0xf5, 0x72, 0x84, 0x4d, 0x78, 0x9f, 0x94, 0x15}}}, -{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xec, 0xd3, 0xff, 0x57, 0x0b, 0xb0, 0xb2, 0xdc, 0xf8, 0x4f, 0xe2, 0x12, 0xd5, 0x36, 0xbe, 0x6b, 0x09, 0x43, 0x6d, 0xa3, 0x4d, 0x90, 0x2d, 0xb8, 0x74, 0xe8, 0x71, 0x45, 0x19, 0x8b, 0x0c, 0x6a}} , {{0xb8, 0x42, 0x1c, 0x03, 0xad, 0x2c, 0x03, 0x8e, 0xac, 0xd7, 0x98, 0x29, 0x13, 0xc6, 0x02, 0x29, 0xb5, 0xd4, 0xe7, 0xcf, 0xcc, 0x8b, 0x83, 0xec, 0x35, 0xc7, 0x9c, 0x74, 0xb7, 0xad, 0x85, 0x5f}}}, @@ -1733,270 +1733,274 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x69, 0x3e, 0x47, 0x97, 0x2c, 0xaf, 0x52, 0x7c, 0x78, 0x83, 0xad, 0x1b, 0x39, 0x82, 0x2f, 0x02, 0x6f, 0x47, 0xdb, 0x2a, 0xb0, 0xe1, 0x91, 0x99, 0x55, 0xb8, 0x99, 0x3a, 0xa0, 0x44, 0x11, 0x51}}} }; -static inline void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) +void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) { - fe25519_mul(&r->x, &p->x, &p->t); - fe25519_mul(&r->y, &p->y, &p->z); - fe25519_mul(&r->z, &p->z, &p->t); + fe25519_mul(&r->x, &p->x, &p->t); + fe25519_mul(&r->y, &p->y, &p->z); + fe25519_mul(&r->z, &p->z, &p->t); } -static inline void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p) +void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p) { - fe25519_mul(&r->x, &p->x, &p->t); - fe25519_mul(&r->y, &p->y, &p->z); - fe25519_mul(&r->z, &p->z, &p->t); + fe25519_mul(&r->x, &p->x, &p->t); + fe25519_mul(&r->y, &p->y, &p->z); + fe25519_mul(&r->z, &p->z, &p->t); } -static inline void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) +void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) { - p1p1_to_p2_2(r, p); - fe25519_mul(&r->t, &p->x, &p->y); + p1p1_to_p2_2(r, p); + fe25519_mul(&r->t, &p->x, &p->y); } -static void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) +void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) { - fe25519 a,b,t1,t2,c,d,e,f,g,h,qt; - fe25519_mul(&qt, &q->x, &q->y); - fe25519_sub(&a, &r->y, &r->x); /* A = (Y1-X1)*(Y2-X2) */ - fe25519_add(&b, &r->y, &r->x); /* B = (Y1+X1)*(Y2+X2) */ - fe25519_sub(&t1, &q->y, &q->x); - fe25519_add(&t2, &q->y, &q->x); - fe25519_mul(&a, &a, &t1); - fe25519_mul(&b, &b, &t2); - fe25519_sub(&e, &b, &a); /* E = B-A */ - fe25519_add(&h, &b, &a); /* H = B+A */ - fe25519_mul(&c, &r->t, &qt); /* C = T1*k*T2 */ - fe25519_mul(&c, &c, &ge25519_ec2d); - fe25519_add(&d, &r->z, &r->z); /* D = Z1*2 */ - fe25519_sub(&f, &d, &c); /* F = D-C */ - fe25519_add(&g, &d, &c); /* G = D+C */ - fe25519_mul(&r->x, &e, &f); - fe25519_mul(&r->y, &h, &g); - fe25519_mul(&r->z, &g, &f); - fe25519_mul(&r->t, &e, &h); + fe25519 a,b,t1,t2,c,d,e,f,g,h,qt; + fe25519_mul(&qt, &q->x, &q->y); + fe25519_sub(&a, &r->y, &r->x); /* A = (Y1-X1)*(Y2-X2) */ + fe25519_add(&b, &r->y, &r->x); /* B = (Y1+X1)*(Y2+X2) */ + fe25519_sub(&t1, &q->y, &q->x); + fe25519_add(&t2, &q->y, &q->x); + fe25519_mul(&a, &a, &t1); + fe25519_mul(&b, &b, &t2); + fe25519_sub(&e, &b, &a); /* E = B-A */ + fe25519_add(&h, &b, &a); /* H = B+A */ + fe25519_mul(&c, &r->t, &qt); /* C = T1*k*T2 */ + fe25519_mul(&c, &c, &ge25519_ec2d); + fe25519_add(&d, &r->z, &r->z); /* D = Z1*2 */ + fe25519_sub(&f, &d, &c); /* F = D-C */ + fe25519_add(&g, &d, &c); /* G = D+C */ + fe25519_mul(&r->x, &e, &f); + fe25519_mul(&r->y, &h, &g); + fe25519_mul(&r->z, &g, &f); + fe25519_mul(&r->t, &e, &h); } -static void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) +void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) { - fe25519 a, b, c, d, t; - - fe25519_sub(&a, &p->y, &p->x); /* A = (Y1-X1)*(Y2-X2) */ - fe25519_sub(&t, &q->y, &q->x); - fe25519_mul(&a, &a, &t); - fe25519_add(&b, &p->x, &p->y); /* B = (Y1+X1)*(Y2+X2) */ - fe25519_add(&t, &q->x, &q->y); - fe25519_mul(&b, &b, &t); - fe25519_mul(&c, &p->t, &q->t); /* C = T1*k*T2 */ - fe25519_mul(&c, &c, &ge25519_ec2d); - fe25519_mul(&d, &p->z, &q->z); /* D = Z1*2*Z2 */ - fe25519_add(&d, &d, &d); - fe25519_sub(&r->x, &b, &a); /* E = B-A */ - fe25519_sub(&r->t, &d, &c); /* F = D-C */ - fe25519_add(&r->z, &d, &c); /* G = D+C */ - fe25519_add(&r->y, &b, &a); /* H = B+A */ + fe25519 a, b, c, d, t; + + fe25519_sub(&a, &p->y, &p->x); /* A = (Y1-X1)*(Y2-X2) */ + fe25519_sub(&t, &q->y, &q->x); + fe25519_mul(&a, &a, &t); + fe25519_add(&b, &p->x, &p->y); /* B = (Y1+X1)*(Y2+X2) */ + fe25519_add(&t, &q->x, &q->y); + fe25519_mul(&b, &b, &t); + fe25519_mul(&c, &p->t, &q->t); /* C = T1*k*T2 */ + fe25519_mul(&c, &c, &ge25519_ec2d); + fe25519_mul(&d, &p->z, &q->z); /* D = Z1*2*Z2 */ + fe25519_add(&d, &d, &d); + fe25519_sub(&r->x, &b, &a); /* E = B-A */ + fe25519_sub(&r->t, &d, &c); /* F = D-C */ + fe25519_add(&r->z, &d, &c); /* G = D+C */ + fe25519_add(&r->y, &b, &a); /* H = B+A */ } /* See http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */ -static void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) +void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) { - fe25519 a,b,c,d; - fe25519_square(&a, &p->x); - fe25519_square(&b, &p->y); - fe25519_square(&c, &p->z); - fe25519_add(&c, &c, &c); - fe25519_neg(&d, &a); + fe25519 a,b,c,d; + fe25519_square(&a, &p->x); + fe25519_square(&b, &p->y); + fe25519_square(&c, &p->z); + fe25519_add(&c, &c, &c); + fe25519_neg(&d, &a); - fe25519_add(&r->x, &p->x, &p->y); - fe25519_square(&r->x, &r->x); - fe25519_sub(&r->x, &r->x, &a); - fe25519_sub(&r->x, &r->x, &b); - fe25519_add(&r->z, &d, &b); - fe25519_sub(&r->t, &r->z, &c); - fe25519_sub(&r->y, &d, &b); + fe25519_add(&r->x, &p->x, &p->y); + fe25519_square(&r->x, &r->x); + fe25519_sub(&r->x, &r->x, &a); + fe25519_sub(&r->x, &r->x, &b); + fe25519_add(&r->z, &d, &b); + fe25519_sub(&r->t, &r->z, &c); + fe25519_sub(&r->y, &d, &b); } /* Constant-time version of: if(b) r = p */ -static inline void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) +void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) { - fe25519_cmov(&r->x, &p->x, b); - fe25519_cmov(&r->y, &p->y, b); + fe25519_cmov(&r->x, &p->x, b); + fe25519_cmov(&r->y, &p->y, b); } -static inline unsigned char equal(signed char b,signed char c) +unsigned char equal(signed char b,signed char c) { - unsigned char ub = b; - unsigned char uc = c; - unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ - crypto_uint32 y = x; /* 0: yes; 1..255: no */ - y -= 1; /* 4294967295: yes; 0..254: no */ - y >>= 31; /* 1: yes; 0: no */ - return (unsigned char)y; + unsigned char ub = b; + unsigned char uc = c; + unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ + crypto_uint32 y = x; /* 0: yes; 1..255: no */ + y -= 1; /* 4294967295: yes; 0..254: no */ + y >>= 31; /* 1: yes; 0: no */ + return (unsigned char)y; } -static inline unsigned char negative(signed char b) +unsigned char negative(signed char b) { - unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ - x >>= 63; /* 1: yes; 0: no */ - return (unsigned char)x; + unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ + x >>= 63; /* 1: yes; 0: no */ + return (unsigned char)x; } -static inline void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) +void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) { - /* constant time */ - fe25519 v; - *t = ge25519_base_multiples_affine[5*pos+0]; - cmov_aff(t, &ge25519_base_multiples_affine[5*pos+1],equal(b,1) | equal(b,-1)); - cmov_aff(t, &ge25519_base_multiples_affine[5*pos+2],equal(b,2) | equal(b,-2)); - cmov_aff(t, &ge25519_base_multiples_affine[5*pos+3],equal(b,3) | equal(b,-3)); - cmov_aff(t, &ge25519_base_multiples_affine[5*pos+4],equal(b,-4)); - fe25519_neg(&v, &t->x); - fe25519_cmov(&t->x, &v, negative(b)); + /* constant time */ + fe25519 v; + *t = ge25519_base_multiples_affine[5*pos+0]; + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+1],equal(b,1) | equal(b,-1)); + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+2],equal(b,2) | equal(b,-2)); + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+3],equal(b,3) | equal(b,-3)); + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+4],equal(b,-4)); + fe25519_neg(&v, &t->x); + fe25519_cmov(&t->x, &v, negative(b)); } -static inline void setneutral(ge25519 *r) +void setneutral(ge25519 *r) { - fe25519_setzero(&r->x); - fe25519_setone(&r->y); - fe25519_setone(&r->z); - fe25519_setzero(&r->t); + fe25519_setzero(&r->x); + fe25519_setone(&r->y); + fe25519_setone(&r->z); + fe25519_setzero(&r->t); } /* return 0 on success, -1 otherwise */ -static int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) -{ - unsigned char par; - fe25519 t, chk, num, den, den2, den4, den6; - fe25519_setone(&r->z); - par = p[31] >> 7; - fe25519_unpack(&r->y, p); - fe25519_square(&num, &r->y); /* x = y^2 */ - fe25519_mul(&den, &num, &ge25519_ecd); /* den = dy^2 */ - fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */ - fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */ - - /* Computation of sqrt(num/den) */ - /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ - fe25519_square(&den2, &den); - fe25519_square(&den4, &den2); - fe25519_mul(&den6, &den4, &den2); - fe25519_mul(&t, &den6, &num); - fe25519_mul(&t, &t, &den); - - fe25519_pow2523(&t, &t); - /* 2. computation of r->x = t * num * den^3 */ - fe25519_mul(&t, &t, &num); - fe25519_mul(&t, &t, &den); - fe25519_mul(&t, &t, &den); - fe25519_mul(&r->x, &t, &den); - - /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */ - fe25519_square(&chk, &r->x); - fe25519_mul(&chk, &chk, &den); - if (!fe25519_iseq_vartime(&chk, &num)) - fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1); - - /* 4. Now we have one of the two square roots, except if input was not a square */ - fe25519_square(&chk, &r->x); - fe25519_mul(&chk, &chk, &den); - if (!fe25519_iseq_vartime(&chk, &num)) - return -1; - - /* 5. Choose the desired square root according to parity: */ - if(fe25519_getparity(&r->x) != (1-par)) - fe25519_neg(&r->x, &r->x); - - fe25519_mul(&r->t, &r->x, &r->y); - return 0; -} - -static inline void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) -{ - fe25519 tx, ty, zi; - fe25519_invert(&zi, &p->z); - fe25519_mul(&tx, &p->x, &zi); - fe25519_mul(&ty, &p->y, &zi); - fe25519_pack(r, &ty); - r[31] ^= fe25519_getparity(&tx) << 7; +int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) +{ + unsigned char par; + fe25519 t, chk, num, den, den2, den4, den6; + fe25519_setone(&r->z); + par = p[31] >> 7; + fe25519_unpack(&r->y, p); + fe25519_square(&num, &r->y); /* x = y^2 */ + fe25519_mul(&den, &num, &ge25519_ecd); /* den = dy^2 */ + fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */ + fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */ + + /* Computation of sqrt(num/den) */ + /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ + fe25519_square(&den2, &den); + fe25519_square(&den4, &den2); + fe25519_mul(&den6, &den4, &den2); + fe25519_mul(&t, &den6, &num); + fe25519_mul(&t, &t, &den); + + fe25519_pow2523(&t, &t); + /* 2. computation of r->x = t * num * den^3 */ + fe25519_mul(&t, &t, &num); + fe25519_mul(&t, &t, &den); + fe25519_mul(&t, &t, &den); + fe25519_mul(&r->x, &t, &den); + + /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */ + fe25519_square(&chk, &r->x); + fe25519_mul(&chk, &chk, &den); + if (!fe25519_iseq_vartime(&chk, &num)) + fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1); + + /* 4. Now we have one of the two square roots, except if input was not a square */ + fe25519_square(&chk, &r->x); + fe25519_mul(&chk, &chk, &den); + if (!fe25519_iseq_vartime(&chk, &num)) + return -1; + + /* 5. Choose the desired square root according to parity: */ + if(fe25519_getparity(&r->x) != (1-par)) + fe25519_neg(&r->x, &r->x); + + fe25519_mul(&r->t, &r->x, &r->y); + return 0; +} + +void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) +{ + fe25519 tx, ty, zi; + fe25519_invert(&zi, &p->z); + fe25519_mul(&tx, &p->x, &zi); + fe25519_mul(&ty, &p->y, &zi); + fe25519_pack(r, &ty); + r[31] ^= fe25519_getparity(&tx) << 7; } /* computes [s1]p1 + [s2]p2 */ -static void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) -{ - ge25519_p1p1 tp1p1; - ge25519_p3 pre[16]; - char *pre5 = (char *)(&(pre[5])); // eliminate type punning warning - unsigned char b[127]; - int i; - - /* precomputation s2 s1 */ - setneutral(pre); /* 00 00 */ - pre[1] = *p1; /* 00 01 */ - dbl_p1p1(&tp1p1,(ge25519_p2 *)p1); p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */ - add_p1p1(&tp1p1,&pre[1], &pre[2]); p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */ - pre[4] = *p2; /* 01 00 */ - add_p1p1(&tp1p1,&pre[1], &pre[4]); p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */ - add_p1p1(&tp1p1,&pre[2], &pre[4]); p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */ - add_p1p1(&tp1p1,&pre[3], &pre[4]); p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */ - dbl_p1p1(&tp1p1,(ge25519_p2 *)p2); p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */ - add_p1p1(&tp1p1,&pre[1], &pre[8]); p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */ - dbl_p1p1(&tp1p1,(ge25519_p2 *)pre5); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */ - add_p1p1(&tp1p1,&pre[3], &pre[8]); p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */ - add_p1p1(&tp1p1,&pre[4], &pre[8]); p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */ - add_p1p1(&tp1p1,&pre[1],&pre[12]); p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */ - add_p1p1(&tp1p1,&pre[2],&pre[12]); p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */ - add_p1p1(&tp1p1,&pre[3],&pre[12]); p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */ - - sc25519_2interleave2(b,s1,s2); - - /* scalar multiplication */ - *r = pre[b[126]]; - for(i=125;i>=0;i--) - { - dbl_p1p1(&tp1p1, (ge25519_p2 *)r); - p1p1_to_p2((ge25519_p2 *) r, &tp1p1); - dbl_p1p1(&tp1p1, (ge25519_p2 *)r); - if(b[i]!=0) - { - p1p1_to_p3(r, &tp1p1); - add_p1p1(&tp1p1, r, &pre[b[i]]); - } - if(i != 0) p1p1_to_p2((ge25519_p2 *)r, &tp1p1); - else p1p1_to_p3(r, &tp1p1); - } -} - -static inline void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) -{ - signed char b[85]; - int i; - ge25519_aff t; - sc25519_window3(b,s); - - choose_t((ge25519_aff *)r, 0, b[0]); - fe25519_setone(&r->z); - fe25519_mul(&r->t, &r->x, &r->y); - for(i=1;i<85;i++) - { - choose_t(&t, (unsigned long long) i, b[i]); - ge25519_mixadd2(r, &t); - } -} - -static inline void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) -{ - unsigned long long i; - - for (i = 0;i < 32;++i) playground[i] = sm[i]; - for (i = 32;i < 64;++i) playground[i] = pk[i-32]; - for (i = 64;i < smlen;++i) playground[i] = sm[i]; - - //crypto_hash_sha512(hram,playground,smlen); - SHA512::hash(hram,playground,(unsigned int)smlen); +void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) +{ + ge25519_p1p1 tp1p1; + ge25519_p3 pre[16]; + char *pre5 = (char *)(&(pre[5])); // eliminate type punning warning + unsigned char b[127]; + int i; + + /* precomputation s2 s1 */ + setneutral(pre); /* 00 00 */ + pre[1] = *p1; /* 00 01 */ + dbl_p1p1(&tp1p1,(ge25519_p2 *)p1); p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */ + add_p1p1(&tp1p1,&pre[1], &pre[2]); p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */ + pre[4] = *p2; /* 01 00 */ + add_p1p1(&tp1p1,&pre[1], &pre[4]); p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */ + add_p1p1(&tp1p1,&pre[2], &pre[4]); p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */ + add_p1p1(&tp1p1,&pre[3], &pre[4]); p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */ + dbl_p1p1(&tp1p1,(ge25519_p2 *)p2); p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */ + add_p1p1(&tp1p1,&pre[1], &pre[8]); p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */ + dbl_p1p1(&tp1p1,(ge25519_p2 *)pre5); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */ + add_p1p1(&tp1p1,&pre[3], &pre[8]); p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */ + add_p1p1(&tp1p1,&pre[4], &pre[8]); p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */ + add_p1p1(&tp1p1,&pre[1],&pre[12]); p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */ + add_p1p1(&tp1p1,&pre[2],&pre[12]); p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */ + add_p1p1(&tp1p1,&pre[3],&pre[12]); p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */ + + sc25519_2interleave2(b,s1,s2); + + /* scalar multiplication */ + *r = pre[b[126]]; + for(i=125;i>=0;i--) + { + dbl_p1p1(&tp1p1, (ge25519_p2 *)r); + p1p1_to_p2((ge25519_p2 *) r, &tp1p1); + dbl_p1p1(&tp1p1, (ge25519_p2 *)r); + if(b[i]!=0) + { + p1p1_to_p3(r, &tp1p1); + add_p1p1(&tp1p1, r, &pre[b[i]]); + } + if(i != 0) p1p1_to_p2((ge25519_p2 *)r, &tp1p1); + else p1p1_to_p3(r, &tp1p1); + } +} + +void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) +{ + signed char b[85]; + int i; + ge25519_aff t; + sc25519_window3(b,s); + + choose_t((ge25519_aff *)r, 0, b[0]); + fe25519_setone(&r->z); + fe25519_mul(&r->t, &r->x, &r->y); + for(i=1;i<85;i++) + { + choose_t(&t, (unsigned long long) i, b[i]); + ge25519_mixadd2(r, &t); + } +} + +void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) +{ + unsigned long long i; + + for (i = 0;i < 32;++i) playground[i] = sm[i]; + for (i = 32;i < 64;++i) playground[i] = pk[i-32]; + for (i = 64;i < smlen;++i) playground[i] = sm[i]; + + //crypto_hash_sha512(hram,playground,smlen); + ZeroTier::SHA512::hash(hram,playground,(unsigned int)smlen); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// +} // anonymous namespace + +namespace ZeroTier { + void C25519::agree(const C25519::Private &mine,const C25519::Public &their,void *keybuf,unsigned int keylen) { unsigned char rawkey[32]; @@ -2015,109 +2019,108 @@ 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) { - sc25519 sck, scs, scsk; - ge25519 ger; - unsigned char r[32]; - unsigned char s[32]; - unsigned char extsk[64]; - 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; - extsk[31] &= 127; - extsk[31] |= 64; - - for(unsigned int i=0;i<32;i++) - sig[32 + i] = extsk[32 + i]; - for(unsigned int i=0;i<32;i++) - sig[64 + i] = digest[i]; - - SHA512::hash(hmg,sig + 32,64); - //crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */ - - /* Computation of R */ - sc25519_from64bytes(&sck, hmg); - ge25519_scalarmult_base(&ger, &sck); - ge25519_pack(r, &ger); - - /* Computation of s */ - for(unsigned int i=0;i<32;i++) - sig[i] = r[i]; - - get_hram(hram,sig,myPublic.data + 32,sig,96); - - sc25519_from64bytes(&scs, hram); - sc25519_from32bytes(&scsk, extsk); - sc25519_mul(&scs, &scs, &scsk); - - sc25519_add(&scs, &scs, &sck); - - sc25519_to32bytes(s,&scs); /* cat s */ - for(unsigned int i=0;i<32;i++) - sig[32 + i] = s[i]; + sc25519 sck, scs, scsk; + ge25519 ger; + unsigned char r[32]; + unsigned char s[32]; + unsigned char extsk[64]; + 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; + extsk[31] &= 127; + extsk[31] |= 64; + + for(unsigned int i=0;i<32;i++) + sig[32 + i] = extsk[32 + i]; + for(unsigned int i=0;i<32;i++) + sig[64 + i] = digest[i]; + + SHA512::hash(hmg,sig + 32,64); + + /* Computation of R */ + sc25519_from64bytes(&sck, hmg); + ge25519_scalarmult_base(&ger, &sck); + ge25519_pack(r, &ger); + + /* Computation of s */ + for(unsigned int i=0;i<32;i++) + sig[i] = r[i]; + + get_hram(hram,sig,myPublic.data + 32,sig,96); + + sc25519_from64bytes(&scs, hram); + sc25519_from32bytes(&scsk, extsk); + sc25519_mul(&scs, &scs, &scsk); + + sc25519_add(&scs, &scs, &sck); + + sc25519_to32bytes(s,&scs); /* cat s */ + for(unsigned int i=0;i<32;i++) + sig[32 + i] = s[i]; } bool C25519::verify(const C25519::Public &their,const void *msg,unsigned int len,const void *signature) { - 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; + 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; + // 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; + if (ge25519_unpackneg_vartime(&get1,their.data + 32)) + return false; - get_hram(hram,sig,their.data + 32,m,96); + get_hram(hram,sig,their.data + 32,m,96); - sc25519_from64bytes(&schram, hram); + sc25519_from64bytes(&schram, hram); - sc25519_from32bytes(&scs, sig+32); + sc25519_from32bytes(&scs, sig+32); - ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); - ge25519_pack(t2, &get2); + ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); + ge25519_pack(t2, &get2); - return Utils::secureEq(sig,t2,32); + return Utils::secureEq(sig,t2,32); } void C25519::_calcPubDH(C25519::Pair &kp) { - // First 32 bytes of pub and priv are the keys for ECDH key - // agreement. This generates the public portion from the private. - crypto_scalarmult_base(kp.pub.data,kp.priv.data); + // First 32 bytes of pub and priv are the keys for ECDH key + // agreement. This generates the public portion from the private. + crypto_scalarmult_base(kp.pub.data,kp.priv.data); } void C25519::_calcPubED(C25519::Pair &kp) { - unsigned char extsk[64]; - sc25519 scsk; - ge25519 gepk; - - // Second 32 bytes of pub and priv are the keys for ed25519 - // signing and verification. - SHA512::hash(extsk,kp.priv.data + 32,32); - extsk[0] &= 248; - extsk[31] &= 127; - extsk[31] |= 64; - sc25519_from32bytes(&scsk,extsk); - ge25519_scalarmult_base(&gepk,&scsk); - ge25519_pack(kp.pub.data + 32,&gepk); - // In NaCl, the public key is crammed into the next 32 bytes - // of the private key for signing since both keys are required - // to sign. In this version we just get it from kp.pub, so we - // leave that out of private. + unsigned char extsk[64]; + sc25519 scsk; + ge25519 gepk; + + // Second 32 bytes of pub and priv are the keys for ed25519 + // signing and verification. + SHA512::hash(extsk,kp.priv.data + 32,32); + extsk[0] &= 248; + extsk[31] &= 127; + extsk[31] |= 64; + sc25519_from32bytes(&scsk,extsk); + ge25519_scalarmult_base(&gepk,&scsk); + ge25519_pack(kp.pub.data + 32,&gepk); + // In NaCl, the public key is crammed into the next 32 bytes + // of the private key for signing since both keys are required + // to sign. In this version we just get it from kp.pub, so we + // leave that out of private. } } // namespace ZeroTier diff --git a/node/SHA512.cpp b/node/SHA512.cpp index c8d81dd1..226c23e1 100644 --- a/node/SHA512.cpp +++ b/node/SHA512.cpp @@ -14,6 +14,22 @@ Public domain. #include "SHA512.hpp" #include "Utils.hpp" +#ifdef __APPLE__ +#include +#define ZT_HAVE_NATIVE_SHA512 +namespace ZeroTier { +void SHA512::hash(void *digest,const void *data,unsigned int len) +{ + CC_SHA512_CTX ctx; + CC_SHA512_Init(&ctx); + CC_SHA512_Update(&ctx,data,len); + CC_SHA512_Final(reinterpret_cast(digest),&ctx); +} +} +#endif + +#ifndef ZT_HAVE_NATIVE_SHA512 + namespace ZeroTier { #define uint64 uint64_t @@ -22,28 +38,28 @@ namespace ZeroTier { static uint64 load_bigendian(const unsigned char *x) { - return - (uint64) (x[7]) \ - | (((uint64) (x[6])) << 8) \ - | (((uint64) (x[5])) << 16) \ - | (((uint64) (x[4])) << 24) \ - | (((uint64) (x[3])) << 32) \ - | (((uint64) (x[2])) << 40) \ - | (((uint64) (x[1])) << 48) \ - | (((uint64) (x[0])) << 56) - ; + return + (uint64) (x[7]) \ + | (((uint64) (x[6])) << 8) \ + | (((uint64) (x[5])) << 16) \ + | (((uint64) (x[4])) << 24) \ + | (((uint64) (x[3])) << 32) \ + | (((uint64) (x[2])) << 40) \ + | (((uint64) (x[1])) << 48) \ + | (((uint64) (x[0])) << 56) + ; } static void store_bigendian(unsigned char *x,uint64 u) { - x[7] = u; u >>= 8; - x[6] = u; u >>= 8; - x[5] = u; u >>= 8; - x[4] = u; u >>= 8; - x[3] = u; u >>= 8; - x[2] = u; u >>= 8; - x[1] = u; u >>= 8; - x[0] = u; + x[7] = u; u >>= 8; + x[6] = u; u >>= 8; + x[5] = u; u >>= 8; + x[4] = u; u >>= 8; + x[3] = u; u >>= 8; + x[2] = u; u >>= 8; + x[1] = u; u >>= 8; + x[0] = u; } #else // !ZT_NO_TYPE_PUNNING @@ -66,266 +82,265 @@ static void store_bigendian(unsigned char *x,uint64 u) #define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0; #define EXPAND \ - M(w0 ,w14,w9 ,w1 ) \ - M(w1 ,w15,w10,w2 ) \ - M(w2 ,w0 ,w11,w3 ) \ - M(w3 ,w1 ,w12,w4 ) \ - M(w4 ,w2 ,w13,w5 ) \ - M(w5 ,w3 ,w14,w6 ) \ - M(w6 ,w4 ,w15,w7 ) \ - M(w7 ,w5 ,w0 ,w8 ) \ - M(w8 ,w6 ,w1 ,w9 ) \ - M(w9 ,w7 ,w2 ,w10) \ - M(w10,w8 ,w3 ,w11) \ - M(w11,w9 ,w4 ,w12) \ - M(w12,w10,w5 ,w13) \ - M(w13,w11,w6 ,w14) \ - M(w14,w12,w7 ,w15) \ - M(w15,w13,w8 ,w0 ) + M(w0 ,w14,w9 ,w1 ) \ + M(w1 ,w15,w10,w2 ) \ + M(w2 ,w0 ,w11,w3 ) \ + M(w3 ,w1 ,w12,w4 ) \ + M(w4 ,w2 ,w13,w5 ) \ + M(w5 ,w3 ,w14,w6 ) \ + M(w6 ,w4 ,w15,w7 ) \ + M(w7 ,w5 ,w0 ,w8 ) \ + M(w8 ,w6 ,w1 ,w9 ) \ + M(w9 ,w7 ,w2 ,w10) \ + M(w10,w8 ,w3 ,w11) \ + M(w11,w9 ,w4 ,w12) \ + M(w12,w10,w5 ,w13) \ + M(w13,w11,w6 ,w14) \ + M(w14,w12,w7 ,w15) \ + M(w15,w13,w8 ,w0 ) #define F(w,k) \ - T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \ - T2 = Sigma0(a) + Maj(a,b,c); \ - h = g; \ - g = f; \ - f = e; \ - e = d + T1; \ - d = c; \ - c = b; \ - b = a; \ - a = T1 + T2; + T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \ + T2 = Sigma0(a) + Maj(a,b,c); \ + h = g; \ + g = f; \ + f = e; \ + e = d + T1; \ + d = c; \ + c = b; \ + b = a; \ + a = T1 + T2; static inline int crypto_hashblocks(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) { - uint64 state[8]; - uint64 a; - uint64 b; - uint64 c; - uint64 d; - uint64 e; - uint64 f; - uint64 g; - uint64 h; - uint64 T1; - uint64 T2; - - a = load_bigendian(statebytes + 0); state[0] = a; - b = load_bigendian(statebytes + 8); state[1] = b; - c = load_bigendian(statebytes + 16); state[2] = c; - d = load_bigendian(statebytes + 24); state[3] = d; - e = load_bigendian(statebytes + 32); state[4] = e; - f = load_bigendian(statebytes + 40); state[5] = f; - g = load_bigendian(statebytes + 48); state[6] = g; - h = load_bigendian(statebytes + 56); state[7] = h; - - while (inlen >= 128) { - uint64 w0 = load_bigendian(in + 0); - uint64 w1 = load_bigendian(in + 8); - uint64 w2 = load_bigendian(in + 16); - uint64 w3 = load_bigendian(in + 24); - uint64 w4 = load_bigendian(in + 32); - uint64 w5 = load_bigendian(in + 40); - uint64 w6 = load_bigendian(in + 48); - uint64 w7 = load_bigendian(in + 56); - uint64 w8 = load_bigendian(in + 64); - uint64 w9 = load_bigendian(in + 72); - uint64 w10 = load_bigendian(in + 80); - uint64 w11 = load_bigendian(in + 88); - uint64 w12 = load_bigendian(in + 96); - uint64 w13 = load_bigendian(in + 104); - uint64 w14 = load_bigendian(in + 112); - uint64 w15 = load_bigendian(in + 120); - - F(w0 ,0x428a2f98d728ae22ULL) - F(w1 ,0x7137449123ef65cdULL) - F(w2 ,0xb5c0fbcfec4d3b2fULL) - F(w3 ,0xe9b5dba58189dbbcULL) - F(w4 ,0x3956c25bf348b538ULL) - F(w5 ,0x59f111f1b605d019ULL) - F(w6 ,0x923f82a4af194f9bULL) - F(w7 ,0xab1c5ed5da6d8118ULL) - F(w8 ,0xd807aa98a3030242ULL) - F(w9 ,0x12835b0145706fbeULL) - F(w10,0x243185be4ee4b28cULL) - F(w11,0x550c7dc3d5ffb4e2ULL) - F(w12,0x72be5d74f27b896fULL) - F(w13,0x80deb1fe3b1696b1ULL) - F(w14,0x9bdc06a725c71235ULL) - F(w15,0xc19bf174cf692694ULL) - - EXPAND - - F(w0 ,0xe49b69c19ef14ad2ULL) - F(w1 ,0xefbe4786384f25e3ULL) - F(w2 ,0x0fc19dc68b8cd5b5ULL) - F(w3 ,0x240ca1cc77ac9c65ULL) - F(w4 ,0x2de92c6f592b0275ULL) - F(w5 ,0x4a7484aa6ea6e483ULL) - F(w6 ,0x5cb0a9dcbd41fbd4ULL) - F(w7 ,0x76f988da831153b5ULL) - F(w8 ,0x983e5152ee66dfabULL) - F(w9 ,0xa831c66d2db43210ULL) - F(w10,0xb00327c898fb213fULL) - F(w11,0xbf597fc7beef0ee4ULL) - F(w12,0xc6e00bf33da88fc2ULL) - F(w13,0xd5a79147930aa725ULL) - F(w14,0x06ca6351e003826fULL) - F(w15,0x142929670a0e6e70ULL) - - EXPAND - - F(w0 ,0x27b70a8546d22ffcULL) - F(w1 ,0x2e1b21385c26c926ULL) - F(w2 ,0x4d2c6dfc5ac42aedULL) - F(w3 ,0x53380d139d95b3dfULL) - F(w4 ,0x650a73548baf63deULL) - F(w5 ,0x766a0abb3c77b2a8ULL) - F(w6 ,0x81c2c92e47edaee6ULL) - F(w7 ,0x92722c851482353bULL) - F(w8 ,0xa2bfe8a14cf10364ULL) - F(w9 ,0xa81a664bbc423001ULL) - F(w10,0xc24b8b70d0f89791ULL) - F(w11,0xc76c51a30654be30ULL) - F(w12,0xd192e819d6ef5218ULL) - F(w13,0xd69906245565a910ULL) - F(w14,0xf40e35855771202aULL) - F(w15,0x106aa07032bbd1b8ULL) - - EXPAND - - F(w0 ,0x19a4c116b8d2d0c8ULL) - F(w1 ,0x1e376c085141ab53ULL) - F(w2 ,0x2748774cdf8eeb99ULL) - F(w3 ,0x34b0bcb5e19b48a8ULL) - F(w4 ,0x391c0cb3c5c95a63ULL) - F(w5 ,0x4ed8aa4ae3418acbULL) - F(w6 ,0x5b9cca4f7763e373ULL) - F(w7 ,0x682e6ff3d6b2b8a3ULL) - F(w8 ,0x748f82ee5defb2fcULL) - F(w9 ,0x78a5636f43172f60ULL) - F(w10,0x84c87814a1f0ab72ULL) - F(w11,0x8cc702081a6439ecULL) - F(w12,0x90befffa23631e28ULL) - F(w13,0xa4506cebde82bde9ULL) - F(w14,0xbef9a3f7b2c67915ULL) - F(w15,0xc67178f2e372532bULL) - - EXPAND - - F(w0 ,0xca273eceea26619cULL) - F(w1 ,0xd186b8c721c0c207ULL) - F(w2 ,0xeada7dd6cde0eb1eULL) - F(w3 ,0xf57d4f7fee6ed178ULL) - F(w4 ,0x06f067aa72176fbaULL) - F(w5 ,0x0a637dc5a2c898a6ULL) - F(w6 ,0x113f9804bef90daeULL) - F(w7 ,0x1b710b35131c471bULL) - F(w8 ,0x28db77f523047d84ULL) - F(w9 ,0x32caab7b40c72493ULL) - F(w10,0x3c9ebe0a15c9bebcULL) - F(w11,0x431d67c49c100d4cULL) - F(w12,0x4cc5d4becb3e42b6ULL) - F(w13,0x597f299cfc657e2aULL) - F(w14,0x5fcb6fab3ad6faecULL) - F(w15,0x6c44198c4a475817ULL) - - a += state[0]; - b += state[1]; - c += state[2]; - d += state[3]; - e += state[4]; - f += state[5]; - g += state[6]; - h += state[7]; - - state[0] = a; - state[1] = b; - state[2] = c; - state[3] = d; - state[4] = e; - state[5] = f; - state[6] = g; - state[7] = h; - - in += 128; - inlen -= 128; - } - - store_bigendian(statebytes + 0,state[0]); - store_bigendian(statebytes + 8,state[1]); - store_bigendian(statebytes + 16,state[2]); - store_bigendian(statebytes + 24,state[3]); - store_bigendian(statebytes + 32,state[4]); - store_bigendian(statebytes + 40,state[5]); - store_bigendian(statebytes + 48,state[6]); - store_bigendian(statebytes + 56,state[7]); - - return 0; + uint64 state[8]; + uint64 a; + uint64 b; + uint64 c; + uint64 d; + uint64 e; + uint64 f; + uint64 g; + uint64 h; + uint64 T1; + uint64 T2; + + a = load_bigendian(statebytes + 0); state[0] = a; + b = load_bigendian(statebytes + 8); state[1] = b; + c = load_bigendian(statebytes + 16); state[2] = c; + d = load_bigendian(statebytes + 24); state[3] = d; + e = load_bigendian(statebytes + 32); state[4] = e; + f = load_bigendian(statebytes + 40); state[5] = f; + g = load_bigendian(statebytes + 48); state[6] = g; + h = load_bigendian(statebytes + 56); state[7] = h; + + while (inlen >= 128) { + uint64 w0 = load_bigendian(in + 0); + uint64 w1 = load_bigendian(in + 8); + uint64 w2 = load_bigendian(in + 16); + uint64 w3 = load_bigendian(in + 24); + uint64 w4 = load_bigendian(in + 32); + uint64 w5 = load_bigendian(in + 40); + uint64 w6 = load_bigendian(in + 48); + uint64 w7 = load_bigendian(in + 56); + uint64 w8 = load_bigendian(in + 64); + uint64 w9 = load_bigendian(in + 72); + uint64 w10 = load_bigendian(in + 80); + uint64 w11 = load_bigendian(in + 88); + uint64 w12 = load_bigendian(in + 96); + uint64 w13 = load_bigendian(in + 104); + uint64 w14 = load_bigendian(in + 112); + uint64 w15 = load_bigendian(in + 120); + + F(w0 ,0x428a2f98d728ae22ULL) + F(w1 ,0x7137449123ef65cdULL) + F(w2 ,0xb5c0fbcfec4d3b2fULL) + F(w3 ,0xe9b5dba58189dbbcULL) + F(w4 ,0x3956c25bf348b538ULL) + F(w5 ,0x59f111f1b605d019ULL) + F(w6 ,0x923f82a4af194f9bULL) + F(w7 ,0xab1c5ed5da6d8118ULL) + F(w8 ,0xd807aa98a3030242ULL) + F(w9 ,0x12835b0145706fbeULL) + F(w10,0x243185be4ee4b28cULL) + F(w11,0x550c7dc3d5ffb4e2ULL) + F(w12,0x72be5d74f27b896fULL) + F(w13,0x80deb1fe3b1696b1ULL) + F(w14,0x9bdc06a725c71235ULL) + F(w15,0xc19bf174cf692694ULL) + + EXPAND + + F(w0 ,0xe49b69c19ef14ad2ULL) + F(w1 ,0xefbe4786384f25e3ULL) + F(w2 ,0x0fc19dc68b8cd5b5ULL) + F(w3 ,0x240ca1cc77ac9c65ULL) + F(w4 ,0x2de92c6f592b0275ULL) + F(w5 ,0x4a7484aa6ea6e483ULL) + F(w6 ,0x5cb0a9dcbd41fbd4ULL) + F(w7 ,0x76f988da831153b5ULL) + F(w8 ,0x983e5152ee66dfabULL) + F(w9 ,0xa831c66d2db43210ULL) + F(w10,0xb00327c898fb213fULL) + F(w11,0xbf597fc7beef0ee4ULL) + F(w12,0xc6e00bf33da88fc2ULL) + F(w13,0xd5a79147930aa725ULL) + F(w14,0x06ca6351e003826fULL) + F(w15,0x142929670a0e6e70ULL) + + EXPAND + + F(w0 ,0x27b70a8546d22ffcULL) + F(w1 ,0x2e1b21385c26c926ULL) + F(w2 ,0x4d2c6dfc5ac42aedULL) + F(w3 ,0x53380d139d95b3dfULL) + F(w4 ,0x650a73548baf63deULL) + F(w5 ,0x766a0abb3c77b2a8ULL) + F(w6 ,0x81c2c92e47edaee6ULL) + F(w7 ,0x92722c851482353bULL) + F(w8 ,0xa2bfe8a14cf10364ULL) + F(w9 ,0xa81a664bbc423001ULL) + F(w10,0xc24b8b70d0f89791ULL) + F(w11,0xc76c51a30654be30ULL) + F(w12,0xd192e819d6ef5218ULL) + F(w13,0xd69906245565a910ULL) + F(w14,0xf40e35855771202aULL) + F(w15,0x106aa07032bbd1b8ULL) + + EXPAND + + F(w0 ,0x19a4c116b8d2d0c8ULL) + F(w1 ,0x1e376c085141ab53ULL) + F(w2 ,0x2748774cdf8eeb99ULL) + F(w3 ,0x34b0bcb5e19b48a8ULL) + F(w4 ,0x391c0cb3c5c95a63ULL) + F(w5 ,0x4ed8aa4ae3418acbULL) + F(w6 ,0x5b9cca4f7763e373ULL) + F(w7 ,0x682e6ff3d6b2b8a3ULL) + F(w8 ,0x748f82ee5defb2fcULL) + F(w9 ,0x78a5636f43172f60ULL) + F(w10,0x84c87814a1f0ab72ULL) + F(w11,0x8cc702081a6439ecULL) + F(w12,0x90befffa23631e28ULL) + F(w13,0xa4506cebde82bde9ULL) + F(w14,0xbef9a3f7b2c67915ULL) + F(w15,0xc67178f2e372532bULL) + + EXPAND + + F(w0 ,0xca273eceea26619cULL) + F(w1 ,0xd186b8c721c0c207ULL) + F(w2 ,0xeada7dd6cde0eb1eULL) + F(w3 ,0xf57d4f7fee6ed178ULL) + F(w4 ,0x06f067aa72176fbaULL) + F(w5 ,0x0a637dc5a2c898a6ULL) + F(w6 ,0x113f9804bef90daeULL) + F(w7 ,0x1b710b35131c471bULL) + F(w8 ,0x28db77f523047d84ULL) + F(w9 ,0x32caab7b40c72493ULL) + F(w10,0x3c9ebe0a15c9bebcULL) + F(w11,0x431d67c49c100d4cULL) + F(w12,0x4cc5d4becb3e42b6ULL) + F(w13,0x597f299cfc657e2aULL) + F(w14,0x5fcb6fab3ad6faecULL) + F(w15,0x6c44198c4a475817ULL) + + a += state[0]; + b += state[1]; + c += state[2]; + d += state[3]; + e += state[4]; + f += state[5]; + g += state[6]; + h += state[7]; + + state[0] = a; + state[1] = b; + state[2] = c; + state[3] = d; + state[4] = e; + state[5] = f; + state[6] = g; + state[7] = h; + + in += 128; + inlen -= 128; + } + + store_bigendian(statebytes + 0,state[0]); + store_bigendian(statebytes + 8,state[1]); + store_bigendian(statebytes + 16,state[2]); + store_bigendian(statebytes + 24,state[3]); + store_bigendian(statebytes + 32,state[4]); + store_bigendian(statebytes + 40,state[5]); + store_bigendian(statebytes + 48,state[6]); + store_bigendian(statebytes + 56,state[7]); + + return 0; } #define blocks crypto_hashblocks static const unsigned char iv[64] = { - 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, - 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, - 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, - 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, - 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, - 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, - 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, - 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 }; -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - void SHA512::hash(void *digest,const void *data,unsigned int len) { - unsigned char h[64]; - unsigned char padded[256]; - int i; - uint64_t bytes = len; - - const unsigned char *in = (const unsigned char *)data; - unsigned int inlen = len; - - for (i = 0;i < 64;++i) h[i] = iv[i]; - - blocks(h,in,inlen); - in += inlen; - inlen &= 127; - in -= inlen; - - for (i = 0;i < (int)inlen;++i) padded[i] = in[i]; - padded[inlen] = 0x80; - - if (inlen < 112) { - for (i = inlen + 1;i < 119;++i) padded[i] = 0; - padded[119] = (unsigned char)((bytes >> 61) & 0xff); - padded[120] = (unsigned char)((bytes >> 53) & 0xff); - padded[121] = (unsigned char)((bytes >> 45) & 0xff); - padded[122] = (unsigned char)((bytes >> 37) & 0xff); - padded[123] = (unsigned char)((bytes >> 29) & 0xff); - padded[124] = (unsigned char)((bytes >> 21) & 0xff); - padded[125] = (unsigned char)((bytes >> 13) & 0xff); - padded[126] = (unsigned char)((bytes >> 5) & 0xff); - padded[127] = (unsigned char)((bytes << 3) & 0xff); - blocks(h,padded,128); - } else { - for (i = inlen + 1;i < 247;++i) padded[i] = 0; - padded[247] = (unsigned char)((bytes >> 61) & 0xff); - padded[248] = (unsigned char)((bytes >> 53) & 0xff); - padded[249] = (unsigned char)((bytes >> 45) & 0xff); - padded[250] = (unsigned char)((bytes >> 37) & 0xff); - padded[251] = (unsigned char)((bytes >> 29) & 0xff); - padded[252] = (unsigned char)((bytes >> 21) & 0xff); - padded[253] = (unsigned char)((bytes >> 13) & 0xff); - padded[254] = (unsigned char)((bytes >> 5) & 0xff); - padded[255] = (unsigned char)((bytes << 3) & 0xff); - blocks(h,padded,256); - } - - for (i = 0;i < 64;++i) ((unsigned char *)digest)[i] = h[i]; + unsigned char h[64]; + unsigned char padded[256]; + int i; + uint64_t bytes = len; + + const unsigned char *in = (const unsigned char *)data; + unsigned int inlen = len; + + for (i = 0;i < 64;++i) h[i] = iv[i]; + + blocks(h,in,inlen); + in += inlen; + inlen &= 127; + in -= inlen; + + for (i = 0;i < (int)inlen;++i) padded[i] = in[i]; + padded[inlen] = 0x80; + + if (inlen < 112) { + for (i = inlen + 1;i < 119;++i) padded[i] = 0; + padded[119] = (unsigned char)((bytes >> 61) & 0xff); + padded[120] = (unsigned char)((bytes >> 53) & 0xff); + padded[121] = (unsigned char)((bytes >> 45) & 0xff); + padded[122] = (unsigned char)((bytes >> 37) & 0xff); + padded[123] = (unsigned char)((bytes >> 29) & 0xff); + padded[124] = (unsigned char)((bytes >> 21) & 0xff); + padded[125] = (unsigned char)((bytes >> 13) & 0xff); + padded[126] = (unsigned char)((bytes >> 5) & 0xff); + padded[127] = (unsigned char)((bytes << 3) & 0xff); + blocks(h,padded,128); + } else { + for (i = inlen + 1;i < 247;++i) padded[i] = 0; + padded[247] = (unsigned char)((bytes >> 61) & 0xff); + padded[248] = (unsigned char)((bytes >> 53) & 0xff); + padded[249] = (unsigned char)((bytes >> 45) & 0xff); + padded[250] = (unsigned char)((bytes >> 37) & 0xff); + padded[251] = (unsigned char)((bytes >> 29) & 0xff); + padded[252] = (unsigned char)((bytes >> 21) & 0xff); + padded[253] = (unsigned char)((bytes >> 13) & 0xff); + padded[254] = (unsigned char)((bytes >> 5) & 0xff); + padded[255] = (unsigned char)((bytes << 3) & 0xff); + blocks(h,padded,256); + } + + for (i = 0;i < 64;++i) ((unsigned char *)digest)[i] = h[i]; } } // namespace ZeroTier + +#endif diff --git a/selftest.cpp b/selftest.cpp index 03f587b0..4008cd2a 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -376,11 +376,11 @@ static int testCrypto() C25519::Pair bp[8]; for(int k=0;k<8;++k) bp[k] = C25519::generate(); - const uint64_t st = OSUtils::now(); + uint64_t st = OSUtils::now(); for(unsigned int k=0;k<50;++k) { C25519::agree(bp[~k & 7],bp[k & 7].pub,buf1,64); } - const uint64_t et = OSUtils::now(); + uint64_t et = OSUtils::now(); std::cout << ((double)(et - st) / 50.0) << "ms per agreement." << std::endl; std::cout << "[crypto] Testing Ed25519 ECC signatures... "; std::cout.flush(); @@ -419,6 +419,15 @@ static int testCrypto() } std::cout << "PASS" << std::endl; + std::cout << "[crypto] Benchmarking Ed25519 ECC signatures... "; std::cout.flush(); + st = OSUtils::now(); + for(int k=0;k<1000;++k) { + C25519::Signature sig; + C25519::sign(didntSign.priv,didntSign.pub,buf1,sizeof(buf1),sig.data); + } + et = OSUtils::now(); + std::cout << ((double)(et - st) / 50.0) << "ms per signature." << std::endl; + return 0; } -- cgit v1.2.3