Code cleanup, Linux build fixes.

This commit is contained in:
Adam Ierymenko 2020-06-05 22:18:58 -07:00
parent e2ca065f28
commit d18c33d6df
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
10 changed files with 142 additions and 235 deletions

View file

@ -996,14 +996,14 @@ void AES::_initSW(const uint8_t key[32]) noexcept
rk[7] = readuint32_t(key + 28); rk[7] = readuint32_t(key + 28);
for (int i = 0;;) { for (int i = 0;;) {
uint32_t temp = rk[7]; uint32_t temp = rk[7];
rk[8] = rk[0] ^ (Te2[(temp >> 16U) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8U) & 0xff] & 0x00ff0000) ^ (Te0[(temp) & 0xff] & 0x0000ff00) ^ (Te1[(temp >> 24U)] & 0x000000ff) ^ rcon[i]; rk[8] = rk[0] ^ (Te2[(temp >> 16U) & 0xffU] & 0xff000000U) ^ (Te3[(temp >> 8U) & 0xffU] & 0x00ff0000U) ^ (Te0[(temp) & 0xffU] & 0x0000ff00U) ^ (Te1[(temp >> 24U)] & 0x000000ffU) ^ rcon[i];
rk[9] = rk[1] ^ rk[8]; rk[9] = rk[1] ^ rk[8];
rk[10] = rk[2] ^ rk[9]; rk[10] = rk[2] ^ rk[9];
rk[11] = rk[3] ^ rk[10]; rk[11] = rk[3] ^ rk[10];
if (++i == 7) if (++i == 7)
break; break;
temp = rk[11]; temp = rk[11];
rk[12] = rk[4] ^ (Te2[(temp >> 24U)] & 0xff000000) ^ (Te3[(temp >> 16U) & 0xff] & 0x00ff0000) ^ (Te0[(temp >> 8U) & 0xff] & 0x0000ff00) ^ (Te1[(temp) & 0xff] & 0x000000ff); rk[12] = rk[4] ^ (Te2[(temp >> 24U)] & 0xff000000U) ^ (Te3[(temp >> 16U) & 0xffU] & 0x00ff0000U) ^ (Te0[(temp >> 8U) & 0xffU] & 0x0000ff00U) ^ (Te1[(temp) & 0xffU] & 0x000000ffU);
rk[13] = rk[5] ^ rk[12]; rk[13] = rk[5] ^ rk[12];
rk[14] = rk[6] ^ rk[13]; rk[14] = rk[6] ^ rk[13];
rk[15] = rk[7] ^ rk[14]; rk[15] = rk[7] ^ rk[14];
@ -1037,10 +1037,10 @@ void AES::_initSW(const uint8_t key[32]) noexcept
} }
for (int i = 1; i < 14; ++i) { for (int i = 1; i < 14; ++i) {
rk += 4; rk += 4;
rk[0] = Td0[Te4[(rk[0] >> 24U)] & 0xff] ^ Td1[Te4[(rk[0] >> 16U) & 0xffU] & 0xff] ^ Td2[Te4[(rk[0] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[0]) & 0xffU] & 0xffU]; rk[0] = Td0[Te4[(rk[0] >> 24U)] & 0xffU] ^ Td1[Te4[(rk[0] >> 16U) & 0xffU] & 0xffU] ^ Td2[Te4[(rk[0] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[0]) & 0xffU] & 0xffU];
rk[1] = Td0[Te4[(rk[1] >> 24U)] & 0xff] ^ Td1[Te4[(rk[1] >> 16U) & 0xffU] & 0xff] ^ Td2[Te4[(rk[1] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[1]) & 0xffU] & 0xffU]; rk[1] = Td0[Te4[(rk[1] >> 24U)] & 0xffU] ^ Td1[Te4[(rk[1] >> 16U) & 0xffU] & 0xffU] ^ Td2[Te4[(rk[1] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[1]) & 0xffU] & 0xffU];
rk[2] = Td0[Te4[(rk[2] >> 24U)] & 0xff] ^ Td1[Te4[(rk[2] >> 16U) & 0xffU] & 0xff] ^ Td2[Te4[(rk[2] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[2]) & 0xffU] & 0xffU]; rk[2] = Td0[Te4[(rk[2] >> 24U)] & 0xffU] ^ Td1[Te4[(rk[2] >> 16U) & 0xffU] & 0xffU] ^ Td2[Te4[(rk[2] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[2]) & 0xffU] & 0xffU];
rk[3] = Td0[Te4[(rk[3] >> 24U)] & 0xff] ^ Td1[Te4[(rk[3] >> 16U) & 0xffU] & 0xff] ^ Td2[Te4[(rk[3] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[3]) & 0xffU] & 0xffU]; rk[3] = Td0[Te4[(rk[3] >> 24U)] & 0xffU] ^ Td1[Te4[(rk[3] >> 16U) & 0xffU] & 0xffU] ^ Td2[Te4[(rk[3] >> 8U) & 0xffU] & 0xffU] ^ Td3[Te4[(rk[3]) & 0xffU] & 0xffU];
} }
} }

View file

@ -18,17 +18,9 @@
#include "Utils.hpp" #include "Utils.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
#include <cstdint> #if !defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_X64)
#include <cstring>
#ifndef ZT_AES_NO_ACCEL
#ifdef ZT_ARCH_X64
#include <xmmintrin.h>
#include <emmintrin.h>
#include <immintrin.h>
#define ZT_AES_AESNI 1 #define ZT_AES_AESNI 1
#endif #endif
#endif
namespace ZeroTier { namespace ZeroTier {
@ -56,7 +48,8 @@ public:
/** /**
* Create an un-initialized AES instance (must call init() before use) * Create an un-initialized AES instance (must call init() before use)
*/ */
ZT_INLINE AES() noexcept {} ZT_INLINE AES() noexcept
{}
/** /**
* Create an AES instance with the given key * Create an AES instance with the given key
@ -70,7 +63,7 @@ public:
ZT_INLINE ~AES() ZT_INLINE ~AES()
{ {
Utils::burn(&_k,sizeof(_k)); Utils::burn(&_k, sizeof(_k));
} }
/** /**
@ -95,15 +88,15 @@ public:
* @param in Input block * @param in Input block
* @param out Output block (can be same as input) * @param out Output block (can be same as input)
*/ */
ZT_INLINE void encrypt(const void *const in,void *const out) const noexcept ZT_INLINE void encrypt(const void *const in, void *const out) const noexcept
{ {
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
if (likely(Utils::CPUID.aes)) { if (likely(Utils::CPUID.aes)) {
_encrypt_aesni(in,out); _encrypt_aesni(in, out);
return; return;
} }
#endif #endif
_encryptSW(reinterpret_cast<const uint8_t *>(in),reinterpret_cast<uint8_t *>(out)); _encryptSW(reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out));
} }
/** /**
@ -112,18 +105,19 @@ public:
* @param in Input block * @param in Input block
* @param out Output block (can be same as input) * @param out Output block (can be same as input)
*/ */
ZT_INLINE void decrypt(const void *const in,void *const out) const noexcept ZT_INLINE void decrypt(const void *const in, void *const out) const noexcept
{ {
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
if (likely(Utils::CPUID.aes)) { if (likely(Utils::CPUID.aes)) {
_decrypt_aesni(in,out); _decrypt_aesni(in, out);
return; return;
} }
#endif #endif
_decryptSW(reinterpret_cast<const uint8_t *>(in),reinterpret_cast<uint8_t *>(out)); _decryptSW(reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out));
} }
class GMACSIVEncryptor; class GMACSIVEncryptor;
class GMACSIVDecryptor; class GMACSIVDecryptor;
/** /**
@ -132,6 +126,7 @@ public:
class GMAC class GMAC
{ {
friend class GMACSIVEncryptor; friend class GMACSIVEncryptor;
friend class GMACSIVDecryptor; friend class GMACSIVDecryptor;
public: public:
@ -140,7 +135,8 @@ public:
* *
* @param aes Keyed AES instance to use * @param aes Keyed AES instance to use
*/ */
ZT_INLINE GMAC(const AES &aes) : _aes(aes) {} ZT_INLINE GMAC(const AES &aes) : _aes(aes)
{}
/** /**
* Reset and initialize for a new GMAC calculation * Reset and initialize for a new GMAC calculation
@ -176,7 +172,7 @@ public:
* @param data Bytes to process * @param data Bytes to process
* @param len Length of input * @param len Length of input
*/ */
void update(const void *data,unsigned int len) noexcept; void update(const void *data, unsigned int len) noexcept;
/** /**
* Process any remaining cached bytes and generate tag * Process any remaining cached bytes and generate tag
@ -205,10 +201,12 @@ public:
class CTR class CTR
{ {
friend class GMACSIVEncryptor; friend class GMACSIVEncryptor;
friend class GMACSIVDecryptor; friend class GMACSIVDecryptor;
public: public:
ZT_INLINE CTR(const AES &aes) noexcept : _aes(aes) {} ZT_INLINE CTR(const AES &aes) noexcept: _aes(aes)
{}
/** /**
* Initialize this CTR instance to encrypt a new stream * Initialize this CTR instance to encrypt a new stream
@ -216,9 +214,9 @@ public:
* @param iv Unique initialization vector and initial 32-bit counter (least significant 32 bits, big-endian) * @param iv Unique initialization vector and initial 32-bit counter (least significant 32 bits, big-endian)
* @param output Buffer to which to store output (MUST be large enough for total bytes processed!) * @param output Buffer to which to store output (MUST be large enough for total bytes processed!)
*/ */
ZT_INLINE void init(const uint8_t iv[16],void *const output) noexcept ZT_INLINE void init(const uint8_t iv[16], void *const output) noexcept
{ {
Utils::copy<16>(_ctr,iv); Utils::copy< 16 >(_ctr, iv);
_out = reinterpret_cast<uint8_t *>(output); _out = reinterpret_cast<uint8_t *>(output);
_len = 0; _len = 0;
} }
@ -230,9 +228,9 @@ public:
* @param ic Initial counter (must be in big-endian byte order!) * @param ic Initial counter (must be in big-endian byte order!)
* @param output Buffer to which to store output (MUST be large enough for total bytes processed!) * @param output Buffer to which to store output (MUST be large enough for total bytes processed!)
*/ */
ZT_INLINE void init(const uint8_t iv[12],const uint32_t ic,void *const output) noexcept ZT_INLINE void init(const uint8_t iv[12], const uint32_t ic, void *const output) noexcept
{ {
Utils::copy<12>(_ctr,iv); Utils::copy< 12 >(_ctr, iv);
reinterpret_cast<uint32_t *>(_ctr)[3] = ic; reinterpret_cast<uint32_t *>(_ctr)[3] = ic;
_out = reinterpret_cast<uint8_t *>(output); _out = reinterpret_cast<uint8_t *>(output);
_len = 0; _len = 0;
@ -244,7 +242,7 @@ public:
* @param input Input data * @param input Input data
* @param len Length of input * @param len Length of input
*/ */
void crypt(const void *input,unsigned int len) noexcept; void crypt(const void *input, unsigned int len) noexcept;
/** /**
* Finish any remaining bytes if total bytes processed wasn't a multiple of 16 * Finish any remaining bytes if total bytes processed wasn't a multiple of 16
@ -280,9 +278,10 @@ public:
* @param k0 First of two AES instances keyed with K0 * @param k0 First of two AES instances keyed with K0
* @param k1 Second of two AES instances keyed with K1 * @param k1 Second of two AES instances keyed with K1
*/ */
ZT_INLINE GMACSIVEncryptor(const AES &k0,const AES &k1) noexcept : ZT_INLINE GMACSIVEncryptor(const AES &k0, const AES &k1) noexcept:
_gmac(k0), _gmac(k0),
_ctr(k1) {} _ctr(k1)
{}
/** /**
* Initialize AES-GMAC-SIV * Initialize AES-GMAC-SIV
@ -290,7 +289,7 @@ public:
* @param iv IV in network byte order (byte order in which it will appear on the wire) * @param iv IV in network byte order (byte order in which it will appear on the wire)
* @param output Pointer to buffer to receive ciphertext, must be large enough for all to-be-processed data! * @param output Pointer to buffer to receive ciphertext, must be large enough for all to-be-processed data!
*/ */
ZT_INLINE void init(const uint64_t iv,void *const output) noexcept ZT_INLINE void init(const uint64_t iv, void *const output) noexcept
{ {
// Output buffer to receive the result of AES-CTR encryption. // Output buffer to receive the result of AES-CTR encryption.
_output = output; _output = output;
@ -312,15 +311,15 @@ public:
* @param aad Additional authenticated data * @param aad Additional authenticated data
* @param len Length of AAD in bytes * @param len Length of AAD in bytes
*/ */
ZT_INLINE void aad(const void *const aad,unsigned int len) noexcept ZT_INLINE void aad(const void *const aad, unsigned int len) noexcept
{ {
// Feed ADD into GMAC first // Feed ADD into GMAC first
_gmac.update(aad,len); _gmac.update(aad, len);
// End of AAD is padded to a multiple of 16 bytes to ensure unique encoding. // End of AAD is padded to a multiple of 16 bytes to ensure unique encoding.
len &= 0xfU; len &= 0xfU;
if (len != 0) if (len != 0)
_gmac.update(Utils::ZERO256,16 - len); _gmac.update(Utils::ZERO256, 16 - len);
} }
/** /**
@ -329,9 +328,9 @@ public:
* @param input Plaintext chunk * @param input Plaintext chunk
* @param len Length of plaintext chunk * @param len Length of plaintext chunk
*/ */
ZT_INLINE void update1(const void *const input,const unsigned int len) noexcept ZT_INLINE void update1(const void *const input, const unsigned int len) noexcept
{ {
_gmac.update(input,len); _gmac.update(input, len);
} }
/** /**
@ -350,7 +349,7 @@ public:
// packet and then recombined on receipt for legacy reasons (but with no // packet and then recombined on receipt for legacy reasons (but with no
// cryptographic or performance impact). // cryptographic or performance impact).
_tag[1] = tmp[0] ^ tmp[1]; _tag[1] = tmp[0] ^ tmp[1];
_ctr._aes.encrypt(_tag,_tag); _ctr._aes.encrypt(_tag, _tag);
// Initialize CTR with 96-bit CTR nonce and 32-bit counter. The counter // Initialize CTR with 96-bit CTR nonce and 32-bit counter. The counter
// incorporates 31 more bits of entropy which should raise our security margin // incorporates 31 more bits of entropy which should raise our security margin
@ -362,7 +361,7 @@ public:
// and so 2^31 should be considered the input limit. // and so 2^31 should be considered the input limit.
tmp[0] = _tag[0]; tmp[0] = _tag[0];
tmp[1] = _tag[1] & ZT_CONST_TO_BE_UINT64(0xffffffff7fffffffULL); tmp[1] = _tag[1] & ZT_CONST_TO_BE_UINT64(0xffffffff7fffffffULL);
_ctr.init(reinterpret_cast<const uint8_t *>(tmp),_output); _ctr.init(reinterpret_cast<const uint8_t *>(tmp), _output);
} }
/** /**
@ -374,9 +373,9 @@ public:
* @param input Plaintext chunk * @param input Plaintext chunk
* @param len Length of plaintext chunk * @param len Length of plaintext chunk
*/ */
ZT_INLINE void update2(const void *const input,const unsigned int len) noexcept ZT_INLINE void update2(const void *const input, const unsigned int len) noexcept
{ {
_ctr.crypt(input,len); _ctr.crypt(input, len);
} }
/** /**
@ -408,9 +407,10 @@ public:
class GMACSIVDecryptor class GMACSIVDecryptor
{ {
public: public:
ZT_INLINE GMACSIVDecryptor(const AES &k0,const AES &k1) noexcept : ZT_INLINE GMACSIVDecryptor(const AES &k0, const AES &k1) noexcept:
_ctr(k1), _ctr(k1),
_gmac(k0) {} _gmac(k0)
{}
/** /**
* Initialize decryptor for a new message * Initialize decryptor for a new message
@ -418,14 +418,14 @@ public:
* @param tag 128-bit combined IV/MAC originally created by GMAC-SIV encryption * @param tag 128-bit combined IV/MAC originally created by GMAC-SIV encryption
* @param output Buffer in which to write output plaintext (must be large enough!) * @param output Buffer in which to write output plaintext (must be large enough!)
*/ */
ZT_INLINE void init(const uint64_t tag[2],void *const output) noexcept ZT_INLINE void init(const uint64_t tag[2], void *const output) noexcept
{ {
uint64_t tmp[2]; uint64_t tmp[2];
tmp[0] = tag[0]; tmp[0] = tag[0];
tmp[1] = tag[1] & ZT_CONST_TO_BE_UINT64(0xffffffff7fffffffULL); tmp[1] = tag[1] & ZT_CONST_TO_BE_UINT64(0xffffffff7fffffffULL);
_ctr.init(reinterpret_cast<const uint8_t *>(tmp),output); _ctr.init(reinterpret_cast<const uint8_t *>(tmp), output);
_ctr._aes.decrypt(tag,_ivMac); _ctr._aes.decrypt(tag, _ivMac);
tmp[0] = _ivMac[0]; tmp[0] = _ivMac[0];
tmp[1] = 0; tmp[1] = 0;
@ -441,12 +441,12 @@ public:
* @param aad Additional authenticated data * @param aad Additional authenticated data
* @param len Length of AAD in bytes * @param len Length of AAD in bytes
*/ */
ZT_INLINE void aad(const void *const aad,unsigned int len) noexcept ZT_INLINE void aad(const void *const aad, unsigned int len) noexcept
{ {
_gmac.update(aad,len); _gmac.update(aad, len);
len &= 0xfU; len &= 0xfU;
if (len != 0) if (len != 0)
_gmac.update(Utils::ZERO256,16 - len); _gmac.update(Utils::ZERO256, 16 - len);
} }
/** /**
@ -457,9 +457,9 @@ public:
* @param input Input ciphertext * @param input Input ciphertext
* @param len Length of ciphertext * @param len Length of ciphertext
*/ */
ZT_INLINE void update(const void *const input,const unsigned int len) noexcept ZT_INLINE void update(const void *const input, const unsigned int len) noexcept
{ {
_ctr.crypt(input,len); _ctr.crypt(input, len);
_decryptedLen += len; _decryptedLen += len;
} }
@ -473,7 +473,7 @@ public:
_ctr.finish(); _ctr.finish();
uint64_t gmacTag[2]; uint64_t gmacTag[2];
_gmac.update(_output,_decryptedLen); _gmac.update(_output, _decryptedLen);
_gmac.finish(reinterpret_cast<uint8_t *>(gmacTag)); _gmac.finish(reinterpret_cast<uint8_t *>(gmacTag));
return (gmacTag[0] ^ gmacTag[1]) == _ivMac[1]; return (gmacTag[0] ^ gmacTag[1]) == _ivMac[1];
} }
@ -500,18 +500,23 @@ private:
static const uint32_t rcon[10]; static const uint32_t rcon[10];
void _initSW(const uint8_t key[32]) noexcept; void _initSW(const uint8_t key[32]) noexcept;
void _encryptSW(const uint8_t in[16],uint8_t out[16]) const noexcept;
void _decryptSW(const uint8_t in[16],uint8_t out[16]) const noexcept;
union { void _encryptSW(const uint8_t in[16], uint8_t out[16]) const noexcept;
void _decryptSW(const uint8_t in[16], uint8_t out[16]) const noexcept;
union
{
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
struct { struct
{
__m128i k[28]; __m128i k[28];
__m128i h[4]; // h, hh, hhh, hhhh __m128i h[4]; // h, hh, hhh, hhhh
} ni; } ni;
#endif #endif
struct { struct
{
uint64_t h[2]; uint64_t h[2];
uint32_t ek[60]; uint32_t ek[60];
uint32_t dk[60]; uint32_t dk[60];
@ -519,47 +524,49 @@ private:
} _k; } _k;
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
void _init_aesni(const uint8_t key[32]) noexcept; void _init_aesni(const uint8_t key[32]) noexcept;
ZT_INLINE void _encrypt_aesni(const void *const in,void *const out) const noexcept ZT_INLINE void _encrypt_aesni(const void *const in, void *const out) const noexcept
{ {
__m128i tmp = _mm_loadu_si128((const __m128i *)in); __m128i tmp = _mm_loadu_si128((const __m128i *)in);
tmp = _mm_xor_si128(tmp,_k.ni.k[0]); tmp = _mm_xor_si128(tmp, _k.ni.k[0]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[1]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[1]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[2]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[2]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[3]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[3]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[4]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[4]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[5]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[5]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[6]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[6]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[7]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[7]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[8]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[8]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[9]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[9]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[10]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[10]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[11]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[11]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[12]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[12]);
tmp = _mm_aesenc_si128(tmp,_k.ni.k[13]); tmp = _mm_aesenc_si128(tmp, _k.ni.k[13]);
_mm_storeu_si128((__m128i *)out,_mm_aesenclast_si128(tmp,_k.ni.k[14])); _mm_storeu_si128((__m128i *)out, _mm_aesenclast_si128(tmp, _k.ni.k[14]));
} }
ZT_INLINE void _decrypt_aesni(const void *in,void *out) const noexcept ZT_INLINE void _decrypt_aesni(const void *in, void *out) const noexcept
{ {
__m128i tmp = _mm_loadu_si128((const __m128i *)in); __m128i tmp = _mm_loadu_si128((const __m128i *)in);
tmp = _mm_xor_si128(tmp,_k.ni.k[14]); tmp = _mm_xor_si128(tmp, _k.ni.k[14]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[15]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[15]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[16]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[16]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[17]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[17]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[18]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[18]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[19]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[19]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[20]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[20]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[21]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[21]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[22]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[22]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[23]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[23]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[24]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[24]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[25]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[25]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[26]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[26]);
tmp = _mm_aesdec_si128(tmp,_k.ni.k[27]); tmp = _mm_aesdec_si128(tmp, _k.ni.k[27]);
_mm_storeu_si128((__m128i *)out,_mm_aesdeclast_si128(tmp,_k.ni.k[0])); _mm_storeu_si128((__m128i *)out, _mm_aesdeclast_si128(tmp, _k.ni.k[0]));
} }
#endif #endif
}; };

View file

@ -40,7 +40,7 @@ public:
{} {}
explicit ZT_INLINE Address(const uint8_t b[5]) noexcept: explicit ZT_INLINE Address(const uint8_t b[5]) noexcept:
_a(((uint64_t) b[0] << 32U) | ((uint64_t) b[1] << 24U) | ((uint64_t) b[2] << 16U) | ((uint64_t) b[3] << 8U) | (uint64_t) b[4]) _a(((uint64_t)b[0] << 32U) | ((uint64_t)b[1] << 24U) | ((uint64_t)b[2] << 16U) | ((uint64_t)b[3] << 8U) | (uint64_t)b[4])
{} {}
ZT_INLINE Address &operator=(const uint64_t a) noexcept ZT_INLINE Address &operator=(const uint64_t a) noexcept
@ -55,7 +55,7 @@ public:
*/ */
ZT_INLINE void setTo(const uint8_t b[5]) noexcept ZT_INLINE void setTo(const uint8_t b[5]) noexcept
{ {
_a = ((uint64_t) b[0] << 32U) | ((uint64_t) b[1] << 24U) | ((uint64_t) b[2] << 16U) | ((uint64_t) b[3] << 8U) | (uint64_t) b[4]; _a = ((uint64_t)b[0] << 32U) | ((uint64_t)b[1] << 24U) | ((uint64_t)b[2] << 16U) | ((uint64_t)b[3] << 8U) | (uint64_t)b[4];
} }
/** /**
@ -65,11 +65,11 @@ public:
ZT_INLINE void copyTo(uint8_t b[5]) const noexcept ZT_INLINE void copyTo(uint8_t b[5]) const noexcept
{ {
const uint64_t a = _a; const uint64_t a = _a;
b[0] = (uint8_t) (a >> 32U); b[0] = (uint8_t)(a >> 32U);
b[1] = (uint8_t) (a >> 24U); b[1] = (uint8_t)(a >> 24U);
b[2] = (uint8_t) (a >> 16U); b[2] = (uint8_t)(a >> 16U);
b[3] = (uint8_t) (a >> 8U); b[3] = (uint8_t)(a >> 8U);
b[4] = (uint8_t) a; b[4] = (uint8_t)a;
} }
/** /**
@ -92,16 +92,16 @@ public:
{ {
const uint64_t a = _a; const uint64_t a = _a;
const unsigned int m = 0xf; const unsigned int m = 0xf;
s[0] = Utils::HEXCHARS[(unsigned int) (a >> 36U) & m]; s[0] = Utils::HEXCHARS[(unsigned int)(a >> 36U) & m];
s[1] = Utils::HEXCHARS[(unsigned int) (a >> 32U) & m]; s[1] = Utils::HEXCHARS[(unsigned int)(a >> 32U) & m];
s[2] = Utils::HEXCHARS[(unsigned int) (a >> 28U) & m]; s[2] = Utils::HEXCHARS[(unsigned int)(a >> 28U) & m];
s[3] = Utils::HEXCHARS[(unsigned int) (a >> 24U) & m]; s[3] = Utils::HEXCHARS[(unsigned int)(a >> 24U) & m];
s[4] = Utils::HEXCHARS[(unsigned int) (a >> 20U) & m]; s[4] = Utils::HEXCHARS[(unsigned int)(a >> 20U) & m];
s[5] = Utils::HEXCHARS[(unsigned int) (a >> 16U) & m]; s[5] = Utils::HEXCHARS[(unsigned int)(a >> 16U) & m];
s[6] = Utils::HEXCHARS[(unsigned int) (a >> 12U) & m]; s[6] = Utils::HEXCHARS[(unsigned int)(a >> 12U) & m];
s[7] = Utils::HEXCHARS[(unsigned int) (a >> 8U) & m]; s[7] = Utils::HEXCHARS[(unsigned int)(a >> 8U) & m];
s[8] = Utils::HEXCHARS[(unsigned int) (a >> 4U) & m]; s[8] = Utils::HEXCHARS[(unsigned int)(a >> 4U) & m];
s[9] = Utils::HEXCHARS[(unsigned int) a & m]; s[9] = Utils::HEXCHARS[(unsigned int)a & m];
s[10] = 0; s[10] = 0;
return s; return s;
} }
@ -126,7 +126,7 @@ public:
{ return ((!_a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); } { return ((!_a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); }
ZT_INLINE unsigned long hashCode() const noexcept ZT_INLINE unsigned long hashCode() const noexcept
{ return (unsigned long) _a; } { return (unsigned long)_a; }
ZT_INLINE operator bool() const noexcept ZT_INLINE operator bool() const noexcept
{ return (_a != 0); } { return (_a != 0); }

View file

@ -29,11 +29,11 @@
/** /**
* Version bit packed into four 16-bit fields in a 64-bit unsigned integer. * Version bit packed into four 16-bit fields in a 64-bit unsigned integer.
*/ */
#define ZT_VERSION_PACKED ( \ #define ZT_VERSION_PACKED ( \
((uint64_t)ZEROTIER_VERSION_MAJOR << 48U) | \ ((uint64_t)ZEROTIER_VERSION_MAJOR << 48U) | \
((uint64_t)ZEROTIER_VERSION_MINOR << 32U) | \ ((uint64_t)ZEROTIER_VERSION_MINOR << 32U) | \
((uint64_t)ZEROTIER_VERSION_REVISION << 16U) | \ ((uint64_t)ZEROTIER_VERSION_REVISION << 16U) | \
(uint64_t)ZEROTIER_VERSION_BUILD ) ((uint64_t)ZEROTIER_VERSION_BUILD) )
/** /**
* Length of a ZeroTier address in bytes * Length of a ZeroTier address in bytes
@ -91,7 +91,7 @@
#define ZT_SYMMETRIC_KEY_TTL 1800000 #define ZT_SYMMETRIC_KEY_TTL 1800000
/** /**
* Maximum number of messages over which a key should be considered usable. * Maximum number of messages per symmetric key.
*/ */
#define ZT_SYMMETRIC_KEY_TTL_MESSAGES 2147483648 #define ZT_SYMMETRIC_KEY_TTL_MESSAGES 2147483648
@ -178,7 +178,7 @@
#define ZT_PEER_PRIORITIZE_PATHS_INTERVAL 5000 #define ZT_PEER_PRIORITIZE_PATHS_INTERVAL 5000
/** /**
* Number of previous endpoints to cache for root-less re-establishment * Number of previous endpoints to cache in peer records.
*/ */
#define ZT_PEER_ENDPOINT_CACHE_SIZE 8 #define ZT_PEER_ENDPOINT_CACHE_SIZE 8
@ -201,11 +201,6 @@
*/ */
#define ZT_MAX_BRIDGE_ROUTES 16777216 #define ZT_MAX_BRIDGE_ROUTES 16777216
/**
* If there is no known L2 bridging route, spam to up to this many active bridges
*/
#define ZT_MAX_BRIDGE_SPAM 32
/** /**
* WHOIS rate limit (we allow these to be pretty fast) * WHOIS rate limit (we allow these to be pretty fast)
*/ */
@ -221,30 +216,11 @@
*/ */
#define ZT_PEER_PROBE_RESPONSE_RATE_LIMIT 5000 #define ZT_PEER_PROBE_RESPONSE_RATE_LIMIT 5000
/**
* 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
/** /**
* Size of a buffer to store either a C25519 or an ECC P-384 signature * Size of a buffer to store either a C25519 or an ECC P-384 signature
* *
* This must be large enough to hold all signature types. * This must be large enough to hold all signature types, which right now is
* Curve25519 EDDSA and NIST P-384 ECDSA.
*/ */
#define ZT_SIGNATURE_BUFFER_SIZE 96 #define ZT_SIGNATURE_BUFFER_SIZE 96

View file

@ -12,7 +12,6 @@
/****/ /****/
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "Identity.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -124,55 +123,6 @@ char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
return v; return v;
} }
bool Dictionary::sign(const Identity &signer)
{
Vector<uint8_t> data;
encode(data, true);
uint8_t sig[ZT_SIGNATURE_BUFFER_SIZE];
const unsigned int siglen = signer.sign(data.data(), (unsigned int) data.size(), sig, ZT_SIGNATURE_BUFFER_SIZE);
if (siglen == 0)
return false;
uint8_t fp[ZT_ADDRESS_LENGTH + ZT_FINGERPRINT_HASH_SIZE];
Address(signer.fingerprint().address).copyTo(fp);
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(fp + ZT_ADDRESS_LENGTH, signer.fingerprint().hash);
m_entries[s_signatureFingerprint].assign(fp, fp + ZT_ADDRESS_LENGTH + ZT_FINGERPRINT_HASH_SIZE);
m_entries[s_signatureData].assign(sig, sig + siglen);
return true;
}
Fingerprint Dictionary::signer() const
{
SortedMap<FCV<char, 8>, Vector<uint8_t> >::const_iterator sigfp(m_entries.find(s_signatureFingerprint));
Fingerprint fp;
if ((sigfp != m_entries.end()) && (sigfp->second.size() == (ZT_ADDRESS_LENGTH + ZT_FINGERPRINT_HASH_SIZE))) {
fp.address = Address(sigfp->second.data());
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(fp.hash, sigfp->second.data() + ZT_ADDRESS_LENGTH);
}
return fp;
}
bool Dictionary::verify(const Identity &signer) const
{
SortedMap< FCV<char, 8>, Vector<uint8_t> >::const_iterator sigfp(m_entries.find(s_signatureFingerprint));
if (
(sigfp == m_entries.end()) ||
(sigfp->second.size() != (ZT_ADDRESS_LENGTH + ZT_FINGERPRINT_HASH_SIZE)) ||
(Address(sigfp->second.data()) != signer.address()) ||
(memcmp(sigfp->second.data() + ZT_ADDRESS_LENGTH,signer.fingerprint().hash,ZT_FINGERPRINT_HASH_SIZE) != 0))
return false;
SortedMap< FCV<char, 8>, Vector<uint8_t> >::const_iterator sig(m_entries.find(s_signatureData));
if ((sig == m_entries.end()) || (sig->second.empty()))
return false;
Vector<uint8_t> data;
encode(data, true);
return signer.verify(data.data(),(unsigned int)data.size(),sig->second.data(),(unsigned int)sig->second.size());
}
void Dictionary::clear() void Dictionary::clear()
{ {
m_entries.clear(); m_entries.clear();

View file

@ -19,8 +19,6 @@
#include "Address.hpp" #include "Address.hpp"
#include "Buf.hpp" #include "Buf.hpp"
#include "FCV.hpp" #include "FCV.hpp"
#include "SHA512.hpp"
#include "Fingerprint.hpp"
#include "Containers.hpp" #include "Containers.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -141,33 +139,6 @@ public:
return (obj.unmarshal(d.data(),(unsigned int)d.size()) > 0); return (obj.unmarshal(d.data(),(unsigned int)d.size()) > 0);
} }
/**
* Sign this identity
*
* This adds two fields:
* "@Si" contains the fingerprint (address followed by hash) of the signer
* "@Ss" contains the signature
*
* @param signer Signing identity (must contain secret)
* @return True if signature was successful
*/
bool sign(const Identity &signer);
/**
* Get the signer's fingerprint for this dictionary or a NIL fingerprint if not signed.
*
* @return Signer
*/
Fingerprint signer() const;
/**
* Verify this identity's signature
*
* @param signer
* @return
*/
bool verify(const Identity &signer) const;
/** /**
* Erase all entries in dictionary * Erase all entries in dictionary
*/ */

View file

@ -52,7 +52,7 @@ public:
{ memoryZero(this); } { memoryZero(this); }
ZT_INLINE Endpoint(const ZT_Endpoint &ep) noexcept ZT_INLINE Endpoint(const ZT_Endpoint &ep) noexcept
{ *this = ep; } { Utils::copy< sizeof(ZT_Endpoint) >((ZT_Endpoint *)this, &ep); }
/** /**
* Create an endpoint for a type that uses an IP * Create an endpoint for a type that uses an IP
@ -64,7 +64,7 @@ public:
{ {
if (inaddr) { if (inaddr) {
this->type = et; this->type = et;
Utils::copy<sizeof(struct sockaddr_storage)>(&(this->value.ss), &(inaddr.as.ss)); Utils::copy< sizeof(struct sockaddr_storage) >(&(this->value.ss), &(inaddr.as.ss));
} else { } else {
memoryZero(this); memoryZero(this);
} }
@ -139,7 +139,7 @@ public:
case ZT_ENDPOINT_TYPE_IP_UDP: case ZT_ENDPOINT_TYPE_IP_UDP:
case ZT_ENDPOINT_TYPE_IP_TCP: case ZT_ENDPOINT_TYPE_IP_TCP:
case ZT_ENDPOINT_TYPE_IP_HTTP: case ZT_ENDPOINT_TYPE_IP_HTTP:
switch(ep.type) { switch (ep.type) {
case ZT_ENDPOINT_TYPE_IP: case ZT_ENDPOINT_TYPE_IP:
case ZT_ENDPOINT_TYPE_IP_UDP: case ZT_ENDPOINT_TYPE_IP_UDP:
case ZT_ENDPOINT_TYPE_IP_TCP: case ZT_ENDPOINT_TYPE_IP_TCP:
@ -200,7 +200,11 @@ public:
char *toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept; char *toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept;
ZT_INLINE String toString() const { char tmp[ZT_ENDPOINT_STRING_SIZE_MAX]; return String(toString(tmp)); } ZT_INLINE String toString() const
{
char tmp[ZT_ENDPOINT_STRING_SIZE_MAX];
return String(toString(tmp));
}
bool fromString(const char *s) noexcept; bool fromString(const char *s) noexcept;
@ -228,6 +232,8 @@ public:
{ return !(*this < ep); } { return !(*this < ep); }
}; };
static_assert(sizeof(Endpoint) == sizeof(ZT_Endpoint), "size mismatch");
} // namespace ZeroTier } // namespace ZeroTier
#endif #endif

View file

@ -419,7 +419,7 @@ void LinuxNetLink::_linkDeleted(struct nlmsghdr *nlp)
{ {
Mutex::Lock l(_if_m); Mutex::Lock l(_if_m);
if(_interfaces.contains(ifip->ifi_index)) { if(_interfaces.find(ifip->ifi_index) != _interfaces.end()) {
_interfaces.erase(ifip->ifi_index); _interfaces.erase(ifip->ifi_index);
} }
} }
@ -1057,12 +1057,9 @@ int LinuxNetLink::_indexForInterface(const char *iface)
{ {
Mutex::Lock l(_if_m); Mutex::Lock l(_if_m);
int interface_index = -1; int interface_index = -1;
Hashtable<int, iface_entry>::Iterator iter(_interfaces); for(std::map<int, iface_entry>::iterator i(_interfaces.begin());i!=_interfaces.end();++i) {
int *k = NULL; if (strcmp(iface, i->second.ifacename) == 0) {
iface_entry *v = NULL; interface_index = i->second.index;
while(iter.next(k,v)) {
if(strcmp(iface, v->ifacename) == 0) {
interface_index = v->index;
break; break;
} }
} }

View file

@ -29,10 +29,8 @@
#include "../core/InetAddress.hpp" #include "../core/InetAddress.hpp"
#include "../core/MAC.hpp" #include "../core/MAC.hpp"
#include "Thread.hpp" #include "Thread.hpp"
#include "../core/Hashtable.hpp"
#include "../core/Mutex.hpp" #include "../core/Mutex.hpp"
namespace ZeroTier { namespace ZeroTier {
struct route_entry { struct route_entry {
@ -107,7 +105,7 @@ private:
char mac_bin[6]; char mac_bin[6];
unsigned int mtu; unsigned int mtu;
}; };
Hashtable<int, iface_entry> _interfaces; std::map<int, iface_entry> _interfaces;
Mutex _if_m; Mutex _if_m;
// socket communication vars; // socket communication vars;

View file

@ -32,7 +32,9 @@
#include <ifaddrs.h> #include <ifaddrs.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#if __has_include(<netinet/in6_var.h>)
#include <netinet6/in6_var.h> #include <netinet6/in6_var.h>
#endif
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#ifdef __LINUX__ #ifdef __LINUX__
@ -689,7 +691,7 @@ extern "C" void ZT_GoTap_setMtu(ZT_GoTap *tap,unsigned int mtu)
extern "C" int ZT_isTemporaryV6Address(const char *ifname,const struct sockaddr_storage *a) extern "C" int ZT_isTemporaryV6Address(const char *ifname,const struct sockaddr_storage *a)
{ {
#ifndef __WINDOWS__ #ifdef IN6_IFF_TEMPORARY
static ZT_SOCKET s_tmpV6Socket = ZT_INVALID_SOCKET; static ZT_SOCKET s_tmpV6Socket = ZT_INVALID_SOCKET;
static std::mutex s_lock; static std::mutex s_lock;
std::lock_guard<std::mutex> l(s_lock); std::lock_guard<std::mutex> l(s_lock);