diff --git a/make-linux.mk b/make-linux.mk index 6db07bada..71ead3650 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -65,8 +65,8 @@ ifeq ($(ZT_SANITIZE),1) SANFLAGS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1 endif ifeq ($(ZT_DEBUG),1) - override CFLAGS+=-Wall -Wno-deprecated -g -pthread $(INCLUDES) $(DEFS) - override CXXFLAGS+=-Wall -Wno-deprecated -g -std=c++11 -pthread $(INCLUDES) $(DEFS) + override CFLAGS+=-Wall -Wno-deprecated -g -O -pthread $(INCLUDES) $(DEFS) + override CXXFLAGS+=-Wall -Wno-deprecated -g -O -std=c++11 -pthread $(INCLUDES) $(DEFS) ZT_TRACE=1 STRIP?=echo # The following line enables optimization for the crypto code, since @@ -112,12 +112,6 @@ ifeq ($(ZT_VAULT_SUPPORT),1) override LDLIBS+=-lcurl endif -# Uncomment for gprof profile build -#CFLAGS=-Wall -g -pg -pthread $(INCLUDES) $(DEFS) -#CXXFLAGS=-Wall -g -pg -pthread $(INCLUDES) $(DEFS) -#LDFLAGS= -#STRIP=echo - # Determine system build architecture from compiler target CC_MACH=$(shell $(CC) -dumpmachine | cut -d '-' -f 1) ZT_ARCHITECTURE=999 @@ -125,13 +119,15 @@ ifeq ($(CC_MACH),x86_64) ZT_ARCHITECTURE=2 ZT_USE_X64_ASM_SALSA=1 ZT_USE_X64_ASM_ED25519=1 - override CFLAGS+=-msse -msse2 -mssse3 -msse4 -msse4.1 -maes -mpclmul + override CFLAGS+=-msse -msse2 -mssse3 -msse4 -msse4.1 -msse4.2 -maes -mpclmul + override CXXFLAGS+=-msse -msse2 -mssse3 -msse4 -msse4.1 -msse4.2 -maes -mpclmul endif ifeq ($(CC_MACH),amd64) ZT_ARCHITECTURE=2 ZT_USE_X64_ASM_SALSA=1 ZT_USE_X64_ASM_ED25519=1 - override CFLAGS+=-msse -msse2 -mssse3 -msse4 -msse4.1 -maes -mpclmul + override CFLAGS+=-msse -msse2 -mssse3 -msse4 -msse4.1 -msse4.2 -maes -mpclmul + override CXXFLAGS+=-msse -msse2 -mssse3 -msse4 -msse4.1 -msse4.2 -maes -mpclmul endif ifeq ($(CC_MACH),powerpc64le) ZT_ARCHITECTURE=8 diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 9ff6edd58..56f1a5732 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -67,7 +67,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f const SharedPtr peer(RR->topology->getPeer(tPtr,sourceAddress)); if (peer) { if (!trusted) { - if (!dearmor(peer->key())) { + if (!dearmor(peer->key(), peer->aesKeysIfSupported())) { RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"invalid MAC"); peer->recordIncomingInvalidPacket(_path); return true; @@ -288,7 +288,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool 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 + if (dearmor(key, peer->aesKeysIfSupported())) { // ensure packet is authentic, otherwise drop RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"address collision"); Packet outp(id.address(),RR->identity.address(),Packet::VERB_ERROR); outp.append((uint8_t)Packet::VERB_HELLO); @@ -307,7 +307,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool } else { // Identity is the same as the one we already have -- check packet integrity - if (!dearmor(peer->key())) { + if (!dearmor(peer->key(), peer->aesKeysIfSupported())) { RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC"); return true; } @@ -332,7 +332,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool // 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())) { + if (!dearmor(newPeer->key(), newPeer->aesKeysIfSupported())) { RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC"); return true; } diff --git a/node/Packet.cpp b/node/Packet.cpp index 04d8f92e5..8cc0f47c7 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -901,14 +901,16 @@ void Packet::armor(const void *key,bool encryptPayload,const AES aesKeys[2]) *reinterpret_cast(data + ZT_PACKET_IDX_MAC) = tag[1]; #endif } else { - uint8_t mangledKey[32]; setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE); + + uint8_t mangledKey[32]; _salsa20MangleKey((const unsigned char *)key,mangledKey); + if (ZT_HAS_FAST_CRYPTO()) { - const unsigned int encryptLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0; + const unsigned int payloadLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0; uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8]; - 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); + ZT_FAST_SINGLE_PASS_SALSA2012(keyStream,payloadLen + 64,(data + ZT_PACKET_IDX_IV),mangledKey); + Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast(keyStream + 8),payloadLen); uint64_t mac[2]; Poly1305::compute(mac,data + ZT_PACKET_IDX_VERB,size() - ZT_PACKET_IDX_VERB,keyStream); #ifdef ZT_NO_TYPE_PUNNING @@ -934,15 +936,33 @@ void Packet::armor(const void *key,bool encryptPayload,const AES aesKeys[2]) } } -bool Packet::dearmor(const void *key) +bool Packet::dearmor(const void *key,const AES aesKeys[2]) { - 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; const unsigned int cs = cipher(); - if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) { + if (cs == ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV) { + if (aesKeys) { + AES::GMACSIVDecryptor dec(aesKeys[0],aesKeys[1]); + + uint64_t tag[2]; +#ifdef ZT_NO_UNALIGNED_ACCESS + Utils::copy<8>(tag, data); + Utils::copy<8>(tag + 1, data + ZT_PACKET_IDX_MAC); +#else + tag[0] = *reinterpret_cast(data); + tag[1] = *reinterpret_cast(data + ZT_PACKET_IDX_MAC); +#endif + + dec.init(tag, payload); + dec.aad(data + ZT_PACKET_IDX_DEST,11); + dec.update(payload, payloadLen); + return dec.finish(); + } + } else if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) { + uint8_t mangledKey[32]; _salsa20MangleKey((const unsigned char *)key,mangledKey); if (ZT_HAS_FAST_CRYPTO()) { uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8]; @@ -974,11 +994,10 @@ bool Packet::dearmor(const void *key) if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) s20.crypt12(payload,payload,payloadLen); } - return true; - } else { - return false; // unrecognized cipher suite } + + return false; } void Packet::cryptField(const void *key,unsigned int start,unsigned int len) diff --git a/node/Packet.hpp b/node/Packet.hpp index 9089e5264..b12ca4b6e 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1313,7 +1313,7 @@ public: * * @param key 32-byte key * @param encryptPayload If true, encrypt packet payload, else just MAC - * @param aes Use new AES-GMAC-SIV constrution + * @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV */ void armor(const void *key,bool encryptPayload,const AES aesKeys[2]); @@ -1325,9 +1325,10 @@ public: * address and MAC field match a trusted path. * * @param key 32-byte key + * @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV * @return False if packet is invalid or failed MAC authenticity check */ - bool dearmor(const void *key); + bool dearmor(const void *key,const AES aesKeys[2]); /** * Encrypt/decrypt a separately armored portion of a packet diff --git a/node/Peer.hpp b/node/Peer.hpp index dd362d697..63cbdbedc 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -533,11 +533,11 @@ public: */ inline int8_t bondingPolicy() { return _bondingPolicy; } - const AES *aesKeysIfSupported() const - { return (const AES *)0; } - //const AES *aesKeysIfSupported() const - //{ return (_vProto >= 10) ? _aesKeys : (const AES *)0; } + //{ return (const AES *)0; } + + const AES *aesKeysIfSupported() const + { return (_vProto >= 10) ? _aesKeys : (const AES *)0; } private: struct _PeerPath