summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp5
-rw-r--r--node/Identity.cpp6
-rw-r--r--node/IncomingPacket.cpp88
-rw-r--r--node/Node.cpp4
-rw-r--r--node/Packet.cpp62
-rw-r--r--node/Packet.hpp31
-rw-r--r--node/Peer.cpp22
-rw-r--r--node/Peer.hpp3
-rw-r--r--node/Salsa20.cpp4
-rw-r--r--node/Salsa20.hpp34
-rw-r--r--node/Switch.cpp2
-rw-r--r--node/Utils.cpp4
12 files changed, 157 insertions, 108 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index be4eb475..3bda3805 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -294,6 +294,11 @@
#define ZT_PEER_PATH_EXPIRATION ((ZT_PEER_PING_PERIOD * 4) + 3000)
/**
+ * Send a full HELLO every this often (ms)
+ */
+#define ZT_PEER_SEND_FULL_HELLO_EVERY (ZT_PEER_PING_PERIOD * 2)
+
+/**
* How often to retry expired paths that we're still remembering
*/
#define ZT_PEER_EXPIRED_PATH_TRIAL_PERIOD (ZT_PEER_PING_PERIOD * 10)
diff --git a/node/Identity.cpp b/node/Identity.cpp
index 05b70873..89fdb836 100644
--- a/node/Identity.cpp
+++ b/node/Identity.cpp
@@ -46,7 +46,7 @@ static inline void _computeMemoryHardHash(const void *publicKey,unsigned int pub
// but is not what we want for sequential memory-harndess.
memset(genmem,0,ZT_IDENTITY_GEN_MEMORY);
Salsa20 s20(digest,256,(char *)digest + 32);
- s20.encrypt20((char *)genmem,(char *)genmem,64);
+ s20.crypt20((char *)genmem,(char *)genmem,64);
for(unsigned long i=64;i<ZT_IDENTITY_GEN_MEMORY;i+=64) {
unsigned long k = i - 64;
*((uint64_t *)((char *)genmem + i)) = *((uint64_t *)((char *)genmem + k));
@@ -57,7 +57,7 @@ static inline void _computeMemoryHardHash(const void *publicKey,unsigned int pub
*((uint64_t *)((char *)genmem + i + 40)) = *((uint64_t *)((char *)genmem + k + 40));
*((uint64_t *)((char *)genmem + i + 48)) = *((uint64_t *)((char *)genmem + k + 48));
*((uint64_t *)((char *)genmem + i + 56)) = *((uint64_t *)((char *)genmem + k + 56));
- s20.encrypt20((char *)genmem + i,(char *)genmem + i,64);
+ s20.crypt20((char *)genmem + i,(char *)genmem + i,64);
}
// Render final digest using genmem as a lookup table
@@ -67,7 +67,7 @@ static inline void _computeMemoryHardHash(const void *publicKey,unsigned int pub
uint64_t tmp = ((uint64_t *)genmem)[idx2];
((uint64_t *)genmem)[idx2] = ((uint64_t *)digest)[idx1];
((uint64_t *)digest)[idx1] = tmp;
- s20.encrypt20(digest,digest,64);
+ s20.crypt20(digest,digest,64);
}
}
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 6b38c4ec..1bf70d68 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -213,41 +213,16 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION);
const uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP);
- Identity id;
- InetAddress externalSurfaceAddress;
- uint64_t planetWorldId = 0;
- uint64_t planetWorldTimestamp = 0;
- std::vector< std::pair<uint64_t,uint64_t> > moonIdsAndTimestamps;
- {
- unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
-
- // Get external surface address if present (was not in old versions)
- if (ptr < size())
- ptr += externalSurfaceAddress.deserialize(*this,ptr);
-
- // Get primary planet world ID and world timestamp if present
- if ((ptr + 16) <= size()) {
- planetWorldId = at<uint64_t>(ptr); ptr += 8;
- planetWorldTimestamp = at<uint64_t>(ptr);
- }
-
- // Get moon IDs and timestamps if present
- if ((ptr + 2) <= size()) {
- unsigned int numMoons = at<uint16_t>(ptr); ptr += 2;
- for(unsigned int i=0;i<numMoons;++i) {
- if ((World::Type)(*this)[ptr++] == World::TYPE_MOON)
- moonIdsAndTimestamps.push_back(std::pair<uint64_t,uint64_t>(at<uint64_t>(ptr),at<uint64_t>(ptr + 8)));
- ptr += 16;
- }
- }
+ if (protoVersion < ZT_PROTO_VERSION_MIN) {
+ TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_path->address().toString().c_str());
+ return true;
}
+ Identity id;
+ unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
+
if (fromAddress != id.address()) {
- TRACE("dropped HELLO from %s(%s): identity not for sending address",fromAddress.toString().c_str(),_path->address().toString().c_str());
- return true;
- }
- if (protoVersion < ZT_PROTO_VERSION_MIN) {
- TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_path->address().toString().c_str());
+ TRACE("dropped HELLO from %s(%s): identity does not match packet source address",fromAddress.toString().c_str(),_path->address().toString().c_str());
return true;
}
@@ -324,6 +299,43 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
// VALID -- if we made it here, packet passed identity and authenticity checks!
+ // Get external surface address if present (was not in old versions)
+ InetAddress externalSurfaceAddress;
+ if (ptr < size())
+ ptr += externalSurfaceAddress.deserialize(*this,ptr);
+
+ // Get primary planet world ID and world timestamp if present
+ uint64_t planetWorldId = 0;
+ uint64_t planetWorldTimestamp = 0;
+ if ((ptr + 16) <= size()) {
+ planetWorldId = at<uint64_t>(ptr); ptr += 8;
+ planetWorldTimestamp = at<uint64_t>(ptr);
+ }
+
+ std::vector< std::pair<uint64_t,uint64_t> > moonIdsAndTimestamps;
+ if (ptr < size()) {
+ // Remainder of packet, if present, is encrypted
+ cryptField(peer->key(),ptr,size() - ptr);
+
+ // Get moon IDs and timestamps if present
+ if ((ptr + 2) <= size()) {
+ unsigned int numMoons = at<uint16_t>(ptr); ptr += 2;
+ for(unsigned int i=0;i<numMoons;++i) {
+ if ((World::Type)(*this)[ptr++] == World::TYPE_MOON)
+ moonIdsAndTimestamps.push_back(std::pair<uint64_t,uint64_t>(at<uint64_t>(ptr),at<uint64_t>(ptr + 8)));
+ ptr += 16;
+ }
+ }
+
+ // Handle COR if present (older versions don't send this)
+ if ((ptr + 2) <= size()) {
+ //const unsigned int corSize = at<uint16_t>(ptr); ptr += 2;
+ ptr += 2;
+ CertificateOfRepresentation cor;
+ ptr += cor.deserialize(*this,ptr);
+ }
+ }
+
// Learn our external surface address from other peers to help us negotiate symmetric NATs
// and detect changes to our global IP that can trigger path renegotiation.
if ((externalSurfaceAddress)&&(hops() == 0))
@@ -337,6 +349,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
+
if (protoVersion >= 5) {
_path->address().serialize(outp);
} else {
@@ -387,6 +400,11 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
}
outp.setAt<uint16_t>(worldUpdateSizeAt,(uint16_t)(outp.size() - (worldUpdateSizeAt + 2)));
+ const unsigned int corSizeAt = outp.size();
+ outp.addSize(2);
+ RR->topology->appendCertificateOfRepresentation(outp);
+ outp.setAt(corSizeAt,(uint16_t)(outp.size() - (corSizeAt + 2)));
+
outp.armor(peer->key(),true);
_path->send(RR,outp.data(),outp.size(),now);
@@ -586,7 +604,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<
const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
if (RR->node->shouldUsePathForZeroTierTraffic(with,_path->localAddress(),atAddr)) {
RR->node->putPacket(_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls
- rendezvousWith->attemptToContactAt(_path->localAddress(),atAddr,RR->node->now());
+ rendezvousWith->attemptToContactAt(_path->localAddress(),atAddr,RR->node->now(),false);
TRACE("RENDEZVOUS from %s says %s might be at %s, sent verification attempt",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
} else {
TRACE("RENDEZVOUS from %s says %s might be at %s, ignoring since path is not suitable",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
@@ -1155,7 +1173,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) {
if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
- peer->attemptToContactAt(InetAddress(),a,now);
+ peer->attemptToContactAt(InetAddress(),a,now,false);
} else {
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
}
@@ -1174,7 +1192,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) {
if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
- peer->attemptToContactAt(InetAddress(),a,now);
+ peer->attemptToContactAt(InetAddress(),a,now,false);
} else {
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
}
diff --git a/node/Node.cpp b/node/Node.cpp
index 3d5b5c3d..b8e74a52 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -70,7 +70,7 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
Utils::getSecureRandom(foo,32);
_prng.init(foo,256,foo);
memset(_prngStream,0,sizeof(_prngStream));
- _prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream));
+ _prng.crypt12(_prngStream,_prngStream,sizeof(_prngStream));
std::string idtmp(dataStoreGet("identity.secret"));
if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) {
@@ -686,7 +686,7 @@ uint64_t Node::prng()
{
unsigned int p = (++_prngStreamPtr % ZT_NODE_PRNG_BUF_SIZE);
if (!p)
- _prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream));
+ _prng.crypt12(_prngStream,_prngStream,sizeof(_prngStream));
return _prngStream[p];
}
diff --git a/node/Packet.cpp b/node/Packet.cpp
index 05fe8dd9..a1bb3132 100644
--- a/node/Packet.cpp
+++ b/node/Packet.cpp
@@ -18,9 +18,21 @@
#include <stdint.h>
#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
#include "Packet.hpp"
+#ifdef _MSC_VER
+#define FORCE_INLINE static __forceinline
+#include <intrin.h>
+#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+#pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
+#else
+#define FORCE_INLINE static inline
+#endif
+
namespace ZeroTier {
/************************************************************************** */
@@ -367,7 +379,7 @@ LZ4_decompress_*_continue() :
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-#include <stdint.h>
+//#include <stdint.h>
typedef struct {
uint32_t hashTable[LZ4_HASH_SIZE_U32];
@@ -536,6 +548,7 @@ union LZ4_streamDecode_u {
/*-************************************
* Compiler Options
**************************************/
+#if 0
#ifdef _MSC_VER /* Visual Studio */
# define FORCE_INLINE static __forceinline
# include <intrin.h>
@@ -550,6 +563,7 @@ union LZ4_streamDecode_u {
# define FORCE_INLINE static
# endif
#endif /* _MSC_VER */
+#endif
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
# define expect(expr,value) (__builtin_expect ((expr),(value)) )
@@ -564,38 +578,39 @@ union LZ4_streamDecode_u {
/*-************************************
* Memory routines
**************************************/
-#include <stdlib.h> /* malloc, calloc, free */
+//#include <stdlib.h> /* malloc, calloc, free */
#define ALLOCATOR(n,s) calloc(n,s)
#define FREEMEM free
-#include <string.h> /* memset, memcpy */
+//#include <string.h> /* memset, memcpy */
#define MEM_INIT memset
/*-************************************
* Basic Types
**************************************/
-#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-# include <stdint.h>
+//#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
+//# include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t U16;
typedef uint32_t U32;
typedef int32_t S32;
typedef uint64_t U64;
typedef uintptr_t uptrval;
-#else
+/*#else
typedef unsigned char BYTE;
typedef unsigned short U16;
typedef unsigned int U32;
typedef signed int S32;
typedef unsigned long long U64;
- typedef size_t uptrval; /* generally true, except OpenVMS-64 */
-#endif
+ typedef size_t uptrval;
+#endif */
-#if defined(__x86_64__)
- typedef U64 reg_t; /* 64-bits in x32 mode */
-#else
- typedef size_t reg_t; /* 32-bits in x32 mode */
-#endif
+typedef uintptr_t reg_t;
+//#if defined(__x86_64__)
+// typedef U64 reg_t; /* 64-bits in x32 mode */
+//#else
+// typedef size_t reg_t; /* 32-bits in x32 mode */
+//#endif
/*-************************************
* Reading and writing into memory
@@ -606,7 +621,6 @@ static unsigned LZ4_isLittleEndian(void)
return one.c[0];
}
-
#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)
/* lie to the compiler about data alignment; use with caution */
@@ -1975,10 +1989,10 @@ void Packet::armor(const void *key,bool encryptPayload)
// MAC key is always the first 32 bytes of the Salsa20 key stream
// This is the same construction DJB's NaCl library uses
- s20.encrypt12(ZERO_KEY,macKey,sizeof(macKey));
+ s20.crypt12(ZERO_KEY,macKey,sizeof(macKey));
if (encryptPayload)
- s20.encrypt12(payload,payload,payloadLen);
+ s20.crypt12(payload,payload,payloadLen);
Poly1305::compute(mac,payload,payloadLen,macKey);
memcpy(field(ZT_PACKET_IDX_MAC,8),mac,8);
@@ -1995,20 +2009,30 @@ 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);
- Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8)/*,ZT_PROTO_SALSA20_ROUNDS*/);
+ Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8));
- s20.encrypt12(ZERO_KEY,macKey,sizeof(macKey));
+ s20.crypt12(ZERO_KEY,macKey,sizeof(macKey));
Poly1305::compute(mac,payload,payloadLen,macKey);
if (!Utils::secureEq(mac,field(ZT_PACKET_IDX_MAC,8),8))
return false;
if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)
- s20.decrypt12(payload,payload,payloadLen);
+ s20.crypt12(payload,payload,payloadLen);
return true;
} else return false; // unrecognized cipher suite
}
+void Packet::cryptField(const void *key,unsigned int start,unsigned int len)
+{
+ unsigned char mangledKey[32];
+ uint64_t iv = Utils::hton((uint64_t)start ^ at<uint64_t>(ZT_PACKET_IDX_IV));
+ _salsa20MangleKey((const unsigned char *)key,mangledKey);
+ Salsa20 s20(mangledKey,256,&iv);
+ unsigned char *const ptr = field(start,len);
+ s20.crypt12(ptr,ptr,len);
+}
+
bool Packet::compress()
{
unsigned char buf[ZT_PROTO_MAX_PACKET_LENGTH * 2];
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 7d404b25..03bd9ed3 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -542,6 +542,7 @@ public:
* [<[...] destination address to which packet was sent>]
* <[8] 64-bit world ID of current planet>
* <[8] 64-bit timestamp of current planet>
+ * [... remainder if packet is encrypted using cryptField() ...]
* <[2] 16-bit number of moons>
* [<[1] 8-bit type ID of moon>]
* [<[8] 64-bit world ID of moon>]
@@ -550,9 +551,10 @@ public:
* <[2] 16-bit length of certificate of representation>
* [... certificate of representation ...]
*
- * HELLO is sent in the clear, and therefore cannot contain anything
- * secret or highly confidential. It should contain nothing that is
- * not either public or easy to obtain via other means.
+ * The initial fields of HELLO are sent in the clear. Fields after the
+ * planet definition (which are common knowledge) are however encrypted
+ * using the cryptField() function. The packet is MAC'd as usual using
+ * the same MAC construct as other packets.
*
* The destination address is the wire address to which this packet is
* being sent, and in OK is *also* the destination address of the OK
@@ -566,7 +568,7 @@ public:
* 0x04 - 6-byte IPv4 UDP address/port -- format: <[4] IP>, <[2] port>
* 0x06 - 18-byte IPv6 UDP address/port -- format: <[16] IP>, <[2] port>
*
- * OK payload:
+ * OK payload (note that OK is encrypted):
* <[8] timestamp (echoed from original HELLO)>
* <[1] protocol version (of responder)>
* <[1] software major version (of responder)>
@@ -576,6 +578,8 @@ public:
* [<[...] destination address>]
* <[2] 16-bit length of world update or 0 if none>
* [[...] updates to planets and/or moons]
+ * <[2] 16-bit length of certificate of representation (of responder)>
+ * [... certificate of representation ...]
*
* ERROR has no payload.
*/
@@ -1349,6 +1353,25 @@ public:
bool dearmor(const void *key);
/**
+ * Encrypt/decrypt a separately armored portion of a packet
+ *
+ * This keys using the same key in the same way as armor/dearmor, but
+ * uses a different IV computed from the packet's IV plus the starting
+ * point index.
+ *
+ * This currently uses Salsa20/12, but any message that uses this should
+ * incorporate a cipher selector to permit this to be changed later.
+ *
+ * This is currently only used to mask portions of HELLO as an extra
+ * security precation since most of that message is sent in the clear.
+ *
+ * @param key 32-byte key
+ * @param start Start of encrypted portion
+ * @param len Length of encrypted portion
+ */
+ void cryptField(const void *key,unsigned int start,unsigned int len);
+
+ /**
* Attempt to compress payload if not already (must be unencrypted)
*
* This requires that the payload at least contain the verb byte already
diff --git a/node/Peer.cpp b/node/Peer.cpp
index bb6b945d..338bea10 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -203,7 +203,7 @@ void Peer::received(
#endif
} else {
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str());
- attemptToContactAt(path->localAddress(),path->address(),now);
+ attemptToContactAt(path->localAddress(),path->address(),now,true);
path->sent(now);
}
}
@@ -357,6 +357,8 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u
outp.append((uint64_t)RR->topology->planetWorldId());
outp.append((uint64_t)RR->topology->planetWorldTimestamp());
+ const unsigned int startCryptedPortionAt = outp.size();
+
std::vector<World> moons(RR->topology->moons());
outp.append((uint16_t)moons.size());
for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) {
@@ -368,21 +370,23 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u
const unsigned int corSizeAt = outp.size();
outp.addSize(2);
RR->topology->appendCertificateOfRepresentation(outp);
- outp.setAt(corSizeAt,(uint16_t)((outp.size() - corSizeAt) - 2));
+ outp.setAt(corSizeAt,(uint16_t)(outp.size() - (corSizeAt + 2)));
+
+ outp.cryptField(_key,startCryptedPortionAt,outp.size() - startCryptedPortionAt);
RR->node->expectReplyTo(outp.packetId());
if (atAddress) {
- outp.armor(_key,false);
+ outp.armor(_key,false); // false == don't encrypt full payload, but add MAC
RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size());
} else {
- RR->sw->send(outp,false);
+ RR->sw->send(outp,false); // false == don't encrypt full payload, but add MAC
}
}
-void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now)
+void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello)
{
- if ( (_vProto >= 5) && ( !((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0)) ) ) {
+ if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) {
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
RR->node->expectReplyTo(outp.packetId());
outp.armor(_key,true);
@@ -398,7 +402,7 @@ void Peer::tryMemorizedPath(uint64_t now)
_lastTriedMemorizedPath = now;
InetAddress mp;
if (RR->node->externalPathLookup(_id.address(),-1,mp))
- attemptToContactAt(InetAddress(),mp,now);
+ attemptToContactAt(InetAddress(),mp,now,true);
}
}
@@ -420,7 +424,7 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
if (bestp >= 0) {
if ( ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) || (_paths[bestp].path->needsHeartbeat(now)) ) {
- attemptToContactAt(_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now);
+ attemptToContactAt(_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now,false);
_paths[bestp].path->sent(now);
}
return true;
@@ -444,7 +448,7 @@ void Peer::resetWithinScope(InetAddress::IpScope scope,int inetAddressFamily,uin
Mutex::Lock _l(_paths_m);
for(unsigned int p=0;p<_numPaths;++p) {
if ( (_paths[p].path->address().ss_family == inetAddressFamily) && (_paths[p].path->address().ipScope() == scope) ) {
- attemptToContactAt(_paths[p].path->localAddress(),_paths[p].path->address(),now);
+ attemptToContactAt(_paths[p].path->localAddress(),_paths[p].path->address(),now,false);
_paths[p].path->sent(now);
_paths[p].lastReceive = 0; // path will not be used unless it speaks again
}
diff --git a/node/Peer.hpp b/node/Peer.hpp
index e79739a3..a3ec0088 100644
--- a/node/Peer.hpp
+++ b/node/Peer.hpp
@@ -161,8 +161,9 @@ public:
* @param localAddr Local address
* @param atAddress Destination address
* @param now Current time
+ * @param sendFullHello If true, always send a full HELLO instead of just an ECHO
*/
- void attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now);
+ void attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello);
/**
* Try a memorized or statically defined path if any are known
diff --git a/node/Salsa20.cpp b/node/Salsa20.cpp
index 3aa19ac6..1a4641f7 100644
--- a/node/Salsa20.cpp
+++ b/node/Salsa20.cpp
@@ -123,7 +123,7 @@ void Salsa20::init(const void *key,unsigned int kbits,const void *iv)
#endif
}
-void Salsa20::encrypt12(const void *in,void *out,unsigned int bytes)
+void Salsa20::crypt12(const void *in,void *out,unsigned int bytes)
throw()
{
uint8_t tmp[64];
@@ -623,7 +623,7 @@ void Salsa20::encrypt12(const void *in,void *out,unsigned int bytes)
}
}
-void Salsa20::encrypt20(const void *in,void *out,unsigned int bytes)
+void Salsa20::crypt20(const void *in,void *out,unsigned int bytes)
throw()
{
uint8_t tmp[64];
diff --git a/node/Salsa20.hpp b/node/Salsa20.hpp
index 7e4c1e53..6405d450 100644
--- a/node/Salsa20.hpp
+++ b/node/Salsa20.hpp
@@ -56,51 +56,25 @@ public:
throw();
/**
- * Encrypt data using Salsa20/12
+ * Encrypt/decrypt data using Salsa20/12
*
* @param in Input data
* @param out Output buffer
* @param bytes Length of data
*/
- void encrypt12(const void *in,void *out,unsigned int bytes)
+ void crypt12(const void *in,void *out,unsigned int bytes)
throw();
/**
- * Encrypt data using Salsa20/20
+ * Encrypt/decrypt data using Salsa20/20
*
* @param in Input data
* @param out Output buffer
* @param bytes Length of data
*/
- void encrypt20(const void *in,void *out,unsigned int bytes)
+ void crypt20(const void *in,void *out,unsigned int bytes)
throw();
- /**
- * Decrypt data
- *
- * @param in Input data
- * @param out Output buffer
- * @param bytes Length of data
- */
- inline void decrypt12(const void *in,void *out,unsigned int bytes)
- throw()
- {
- encrypt12(in,out,bytes);
- }
-
- /**
- * Decrypt data
- *
- * @param in Input data
- * @param out Output buffer
- * @param bytes Length of data
- */
- inline void decrypt20(const void *in,void *out,unsigned int bytes)
- throw()
- {
- encrypt20(in,out,bytes);
- }
-
private:
union {
#ifdef ZT_SALSA20_SSE
diff --git a/node/Switch.cpp b/node/Switch.cpp
index a769faea..346091a4 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -777,7 +777,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
if ((clusterMostRecentMemberId < 0)||(viaPath->lastIn() > clusterMostRecentTs)) {
#endif
if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) {
- peer->attemptToContactAt(viaPath->localAddress(),viaPath->address(),now);
+ peer->attemptToContactAt(viaPath->localAddress(),viaPath->address(),now,false);
viaPath->sent(now);
}
#ifdef ZT_ENABLE_CLUSTER
diff --git a/node/Utils.cpp b/node/Utils.cpp
index 06b726cc..247dd54a 100644
--- a/node/Utils.cpp
+++ b/node/Utils.cpp
@@ -182,7 +182,7 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
#else // not __WINDOWS__
- static char randomBuf[131072];
+ static char randomBuf[65536];
static unsigned int randomPtr = sizeof(randomBuf);
static int devURandomFd = -1;
@@ -215,7 +215,7 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
#endif // __WINDOWS__ or not
- s20.encrypt12(buf,buf,bytes);
+ s20.crypt12(buf,buf,bytes);
}
bool Utils::scopy(char *dest,unsigned int len,const char *src)