summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/Identity.cpp5
-rw-r--r--node/NodeConfig.cpp5
-rw-r--r--node/Packet.hpp9
-rw-r--r--node/Salsa20.cpp7
-rw-r--r--node/Salsa20.hpp11
-rw-r--r--selftest-crypto-vectors.hpp4
-rw-r--r--selftest.cpp14
7 files changed, 41 insertions, 14 deletions
diff --git a/node/Identity.cpp b/node/Identity.cpp
index 0ea3dc18..d50c56fe 100644
--- a/node/Identity.cpp
+++ b/node/Identity.cpp
@@ -48,6 +48,9 @@
// Step distance for mixing genmem[]
#define ZT_IDENTITY_GEN_MEMORY_MIX_STEP 1024
+// Rounds used for Salsa20 step
+#define ZT_IDENTITY_GEN_SALSA20_ROUNDS 20
+
namespace ZeroTier {
// A memory-hard composition of SHA-512 and Salsa20 for hashcash hashing
@@ -58,7 +61,7 @@ static inline void _computeMemoryHardHash(const void *publicKey,unsigned int pub
// Generate genmem[] bytes of Salsa20 key stream
memset(genmem,0,ZT_IDENTITY_GEN_MEMORY);
- Salsa20 s20(digest,256,(char *)digest + 32);
+ Salsa20 s20(digest,256,(char *)digest + 32,ZT_IDENTITY_GEN_SALSA20_ROUNDS);
s20.encrypt(genmem,genmem,ZT_IDENTITY_GEN_MEMORY);
// Do something to genmem[] that iteratively makes every value
diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp
index 0dda8da7..f26cd8ea 100644
--- a/node/NodeConfig.cpp
+++ b/node/NodeConfig.cpp
@@ -49,6 +49,7 @@
#include "Logger.hpp"
#include "Topology.hpp"
#include "Demarc.hpp"
+#include "Packet.hpp"
#include "InetAddress.hpp"
#include "Peer.hpp"
#include "Salsa20.hpp"
@@ -283,7 +284,7 @@ std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > NodeConfig::encodeControlMe
Utils::getSecureRandom(iv,8);
memcpy(packet.field(8,8),iv,8);
- Salsa20 s20(key,256,iv);
+ Salsa20 s20(key,256,iv,ZT_PROTO_SALSA20_ROUNDS);
s20.encrypt(packet.field(16,packet.size() - 16),packet.field(16,packet.size() - 16),packet.size() - 16);
memcpy(keytmp,key,32);
@@ -322,7 +323,7 @@ bool NodeConfig::decodeControlMessagePacket(const void *key,const void *data,uns
if (!Utils::secureEq(packet.field(0,8),poly1305tag,8))
return false;
- Salsa20 s20(key,256,packet.field(8,8));
+ Salsa20 s20(key,256,packet.field(8,8),ZT_PROTO_SALSA20_ROUNDS);
s20.decrypt(packet.field(16,packet.size() - 16),packet.field(16,packet.size() - 16),packet.size() - 16);
conversationId = packet.at<uint32_t>(16);
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 486faebb..aeb5d0bb 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -92,6 +92,11 @@
*/
#define ZT_PROTO_VERB_FLAG_COMPRESSED 0x80
+/**
+ * Rounds used for Salsa20 encryption in ZT
+ */
+#define ZT_PROTO_SALSA20_ROUNDS 12
+
// Indices of fields in normal packet header -- do not change as this
// might require both code rework and will break compatibility.
#define ZT_PACKET_IDX_IV 0
@@ -852,7 +857,7 @@ public:
else (*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_ENCRYPTED);
_mangleKey((const unsigned char *)key,mangledKey);
- Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8));
+ Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8),ZT_PROTO_SALSA20_ROUNDS);
// MAC key is always the first 32 bytes of the Salsa20 key stream
// This is the same construction DJB's NaCl library uses
@@ -880,7 +885,7 @@ public:
unsigned char *const payload = field(ZT_PACKET_IDX_VERB,payloadLen);
_mangleKey((const unsigned char *)key,mangledKey);
- Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8));
+ Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8),ZT_PROTO_SALSA20_ROUNDS);
s20.encrypt(ZERO_KEY,macKey,sizeof(macKey));
Poly1305::compute(mac,payload,payloadLen,macKey);
diff --git a/node/Salsa20.cpp b/node/Salsa20.cpp
index d80ea28d..b634dd69 100644
--- a/node/Salsa20.cpp
+++ b/node/Salsa20.cpp
@@ -29,7 +29,7 @@ namespace ZeroTier {
static const char *sigma = "expand 32-byte k";
static const char *tau = "expand 16-byte k";
-void Salsa20::init(const void *key,unsigned int kbits,const void *iv)
+void Salsa20::init(const void *key,unsigned int kbits,const void *iv,unsigned int rounds)
throw()
{
const char *constants;
@@ -59,6 +59,8 @@ void Salsa20::init(const void *key,unsigned int kbits,const void *iv)
_state[5] = U8TO32_LITTLE(constants + 4);
_state[10] = U8TO32_LITTLE(constants + 8);
_state[15] = U8TO32_LITTLE(constants + 12);
+
+ _roundsDiv2 = rounds / 2;
}
void Salsa20::encrypt(const void *in,void *out,unsigned int bytes)
@@ -114,7 +116,8 @@ void Salsa20::encrypt(const void *in,void *out,unsigned int bytes)
x13 = j13;
x14 = j14;
x15 = j15;
- for (i = 20;i > 0;i -= 2) {
+ //for (i = 20;i > 0;i -= 2) {
+ for(i=0;i<_roundsDiv2;++i) {
x4 = XOR( x4,ROTATE(PLUS( x0,x12), 7));
x8 = XOR( x8,ROTATE(PLUS( x4, x0), 9));
x12 = XOR(x12,ROTATE(PLUS( x8, x4),13));
diff --git a/node/Salsa20.hpp b/node/Salsa20.hpp
index fa95ed39..9f34ba78 100644
--- a/node/Salsa20.hpp
+++ b/node/Salsa20.hpp
@@ -14,7 +14,7 @@
namespace ZeroTier {
/**
- * Salsa20/20 stream cipher
+ * Salsa20 stream cipher
*/
class Salsa20
{
@@ -25,11 +25,12 @@ public:
* @param key Key bits
* @param kbits Number of key bits: 128 or 256 (recommended)
* @param iv 64-bit initialization vector
+ * @param rounds Number of rounds: 8, 12, or 20
*/
- Salsa20(const void *key,unsigned int kbits,const void *iv)
+ Salsa20(const void *key,unsigned int kbits,const void *iv,unsigned int rounds)
throw()
{
- init(key,kbits,iv);
+ init(key,kbits,iv,rounds);
}
/**
@@ -38,8 +39,9 @@ public:
* @param key Key bits
* @param kbits Number of key bits: 128 or 256 (recommended)
* @param iv 64-bit initialization vector
+ * @param rounds Number of rounds: 8, 12, or 20
*/
- void init(const void *key,unsigned int kbits,const void *iv)
+ void init(const void *key,unsigned int kbits,const void *iv,unsigned int rounds)
throw();
/**
@@ -67,6 +69,7 @@ public:
private:
uint32_t _state[16];
+ unsigned int _roundsDiv2;
};
} // namespace ZeroTier
diff --git a/selftest-crypto-vectors.hpp b/selftest-crypto-vectors.hpp
index baf3cddb..8e07e36a 100644
--- a/selftest-crypto-vectors.hpp
+++ b/selftest-crypto-vectors.hpp
@@ -10,6 +10,10 @@ static const unsigned char s20TV0Key[32] = { 0x0f,0x62,0xb5,0x08,0x5b,0xae,0x01,
static const unsigned char s20TV0Iv[8] = { 0x28,0x8f,0xf6,0x5d,0xc4,0x2b,0x92,0xf9 };
static const unsigned char s20TV0Ks[64] = { 0x5e,0x5e,0x71,0xf9,0x01,0x99,0x34,0x03,0x04,0xab,0xb2,0x2a,0x37,0xb6,0x62,0x5b,0xf8,0x83,0xfb,0x89,0xce,0x3b,0x21,0xf5,0x4a,0x10,0xb8,0x10,0x66,0xef,0x87,0xda,0x30,0xb7,0x76,0x99,0xaa,0x73,0x79,0xda,0x59,0x5c,0x77,0xdd,0x59,0x54,0x2d,0xa2,0x08,0xe5,0x95,0x4f,0x89,0xe4,0x0e,0xb7,0xaa,0x80,0xa8,0x4a,0x61,0x76,0x66,0x3f };
+static const unsigned char s2012TV0Key[32] = { 0x0f,0x62,0xb5,0x08,0x5b,0xae,0x01,0x54,0xa7,0xfa,0x4d,0xa0,0xf3,0x46,0x99,0xec,0x3f,0x92,0xe5,0x38,0x8b,0xde,0x31,0x84,0xd7,0x2a,0x7d,0xd0,0x23,0x76,0xc9,0x1c };
+static const unsigned char s2012TV0Iv[8] = { 0x28,0x8f,0xf6,0x5d,0xc4,0x2b,0x92,0xf9 };
+static const unsigned char s2012TV0Ks[64] = { 0x99,0xDB,0x33,0xAD,0x11,0xCE,0x0C,0xCB,0x3B,0xFD,0xBF,0x8D,0x0C,0x18,0x16,0x04,0x52,0xD0,0x14,0xCD,0xE9,0x89,0xB4,0xC4,0x11,0xA5,0x59,0xFF,0x7C,0x20,0xA1,0x69,0xE6,0xDC,0x99,0x09,0xD8,0x16,0xBE,0xCE,0xDC,0x40,0x63,0xCE,0x07,0xCE,0xA8,0x28,0xF4,0x4B,0xF9,0xB6,0xC9,0xA0,0xA0,0xB2,0x00,0xE1,0xB5,0x2A,0xF4,0x18,0x59,0xC5 };
+
static const unsigned char poly1305TV0Input[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
static const unsigned char poly1305TV0Key[32] = { 0x74,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x33,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b,0x65,0x79,0x20,0x66,0x6f,0x72,0x20,0x50,0x6f,0x6c,0x79,0x31,0x33,0x30,0x35 };
static const unsigned char poly1305TV0Tag[16] = { 0x49,0xec,0x78,0x09,0x0e,0x48,0x1e,0xc6,0xc2,0x6b,0x33,0xb9,0x1c,0xcc,0x03,0x07 };
diff --git a/selftest.cpp b/selftest.cpp
index 637b579e..8404f4a1 100644
--- a/selftest.cpp
+++ b/selftest.cpp
@@ -180,16 +180,16 @@ static int testCrypto()
memset(buf2,0,sizeof(buf2));
memset(buf3,0,sizeof(buf3));
Salsa20 s20;
- s20.init("12345678123456781234567812345678",256,"12345678");
+ s20.init("12345678123456781234567812345678",256,"12345678",20);
s20.encrypt(buf1,buf2,sizeof(buf1));
- s20.init("12345678123456781234567812345678",256,"12345678");
+ s20.init("12345678123456781234567812345678",256,"12345678",20);
s20.decrypt(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,256,s20TV0Iv,20);
memset(buf1,0,sizeof(buf1));
memset(buf2,0,sizeof(buf2));
s20.encrypt(buf1,buf2,64);
@@ -197,6 +197,14 @@ static int testCrypto()
std::cout << "FAIL (test vector 0)" << std::endl;
return -1;
}
+ s20.init(s2012TV0Key,256,s2012TV0Iv,12);
+ memset(buf1,0,sizeof(buf1));
+ memset(buf2,0,sizeof(buf2));
+ s20.encrypt(buf1,buf2,64);
+ if (memcmp(buf2,s2012TV0Ks,64)) {
+ std::cout << "FAIL (test vector 1)" << std::endl;
+ return -1;
+ }
std::cout << "PASS" << std::endl;
return 0;