2
0
Adam Ierymenko 5 жил өмнө
parent
commit
b7b01da742

+ 4 - 4
node/IncomingPacket.cpp

@@ -67,7 +67,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
 		const SharedPtr<Peer> 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<Peer> 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;
 		}

+ 29 - 10
node/Packet.cpp

@@ -901,14 +901,16 @@ void Packet::armor(const void *key,bool encryptPayload,const AES aesKeys[2])
 		*reinterpret_cast<uint64_t *>(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<const uint8_t *>(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<const uint8_t *>(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<uint8_t *>(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<uint64_t *>(data);
+			tag[1] = *reinterpret_cast<uint64_t *>(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)

+ 3 - 2
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

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