mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
ZeroTier standard .clang-format -- switch to spaces, match indentation of Rust, mostly based on LLVM format.
This commit is contained in:
parent
2698dab696
commit
12e7546ebc
111 changed files with 31629 additions and 26070 deletions
|
@ -57,7 +57,7 @@ SpacesInCStyleCastParentheses: 'false'
|
|||
SpacesInContainerLiterals: 'true'
|
||||
SpacesInParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
UseTab: ForIndentation
|
||||
UseTab: 'false'
|
||||
|
||||
---
|
||||
Language: Cpp
|
||||
|
|
388
core/AES.cpp
388
core/AES.cpp
|
@ -11,9 +11,10 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif
|
||||
|
@ -32,39 +33,48 @@ namespace ZeroTier {
|
|||
namespace {
|
||||
|
||||
#define s_bmul32(N, x, y, rh, rl) \
|
||||
uint32_t x0t_##N = (x) & 0x11111111U; \
|
||||
uint32_t x1t_##N = (x) & 0x22222222U; \
|
||||
uint32_t x2t_##N = (x) & 0x44444444U; \
|
||||
uint32_t x3t_##N = (x) & 0x88888888U; \
|
||||
uint32_t y0t_##N = (y) & 0x11111111U; \
|
||||
uint32_t y1t_##N = (y) & 0x22222222U; \
|
||||
uint32_t y2t_##N = (y) & 0x44444444U; \
|
||||
uint32_t y3t_##N = (y) & 0x88888888U; \
|
||||
uint64_t z0t_##N = (((uint64_t)x0t_##N * y0t_##N) ^ ((uint64_t)x1t_##N * y3t_##N) ^ ((uint64_t)x2t_##N * y2t_##N) ^ ((uint64_t)x3t_##N * y1t_##N)) & 0x1111111111111111ULL; \
|
||||
uint64_t z1t_##N = (((uint64_t)x0t_##N * y1t_##N) ^ ((uint64_t)x1t_##N * y0t_##N) ^ ((uint64_t)x2t_##N * y3t_##N) ^ ((uint64_t)x3t_##N * y2t_##N)) & 0x2222222222222222ULL; \
|
||||
uint64_t z2t_##N = (((uint64_t)x0t_##N * y2t_##N) ^ ((uint64_t)x1t_##N * y1t_##N) ^ ((uint64_t)x2t_##N * y0t_##N) ^ ((uint64_t)x3t_##N * y3t_##N)) & 0x4444444444444444ULL; \
|
||||
uint32_t x0t_##N = (x)&0x11111111U; \
|
||||
uint32_t x1t_##N = (x)&0x22222222U; \
|
||||
uint32_t x2t_##N = (x)&0x44444444U; \
|
||||
uint32_t x3t_##N = (x)&0x88888888U; \
|
||||
uint32_t y0t_##N = (y)&0x11111111U; \
|
||||
uint32_t y1t_##N = (y)&0x22222222U; \
|
||||
uint32_t y2t_##N = (y)&0x44444444U; \
|
||||
uint32_t y3t_##N = (y)&0x88888888U; \
|
||||
uint64_t z0t_##N = (((uint64_t)x0t_##N * y0t_##N) ^ ((uint64_t)x1t_##N * y3t_##N) ^ ((uint64_t)x2t_##N * y2t_##N) \
|
||||
^ ((uint64_t)x3t_##N * y1t_##N)) \
|
||||
& 0x1111111111111111ULL; \
|
||||
uint64_t z1t_##N = (((uint64_t)x0t_##N * y1t_##N) ^ ((uint64_t)x1t_##N * y0t_##N) ^ ((uint64_t)x2t_##N * y3t_##N) \
|
||||
^ ((uint64_t)x3t_##N * y2t_##N)) \
|
||||
& 0x2222222222222222ULL; \
|
||||
uint64_t z2t_##N = (((uint64_t)x0t_##N * y2t_##N) ^ ((uint64_t)x1t_##N * y1t_##N) ^ ((uint64_t)x2t_##N * y0t_##N) \
|
||||
^ ((uint64_t)x3t_##N * y3t_##N)) \
|
||||
& 0x4444444444444444ULL; \
|
||||
z0t_##N |= z1t_##N; \
|
||||
z2t_##N |= z0t_##N; \
|
||||
uint64_t zt_##N = z2t_##N | ((((uint64_t)x0t_##N * y3t_##N) ^ ((uint64_t)x1t_##N * y2t_##N) ^ ((uint64_t)x2t_##N * y1t_##N) ^ ((uint64_t)x3t_##N * y0t_##N)) & 0x8888888888888888ULL); \
|
||||
uint64_t zt_##N = z2t_##N \
|
||||
| ((((uint64_t)x0t_##N * y3t_##N) ^ ((uint64_t)x1t_##N * y2t_##N) \
|
||||
^ ((uint64_t)x2t_##N * y1t_##N) ^ ((uint64_t)x3t_##N * y0t_##N)) \
|
||||
& 0x8888888888888888ULL); \
|
||||
(rh) = (uint32_t)(zt_##N >> 32U); \
|
||||
(rl) = (uint32_t)zt_##N;
|
||||
|
||||
void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t &y0, uint64_t &y1) noexcept
|
||||
void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t& y0, uint64_t& y1) noexcept
|
||||
{
|
||||
uint32_t hhh = (uint32_t)(hh >> 32U);
|
||||
uint32_t hhl = (uint32_t)hh;
|
||||
uint32_t hlh = (uint32_t)(hl >> 32U);
|
||||
uint32_t hll = (uint32_t)hl;
|
||||
uint32_t hhXlh = hhh ^hlh;
|
||||
uint32_t hhXll = hhl ^hll;
|
||||
uint32_t hhXlh = hhh ^ hlh;
|
||||
uint32_t hhXll = hhl ^ hll;
|
||||
uint64_t yl = Utils::ntoh(y0);
|
||||
uint64_t yh = Utils::ntoh(y1);
|
||||
uint32_t cilh = (uint32_t)(yh >> 32U);
|
||||
uint32_t cill = (uint32_t)yh;
|
||||
uint32_t cihh = (uint32_t)(yl >> 32U);
|
||||
uint32_t cihl = (uint32_t)yl;
|
||||
uint32_t cihXlh = cihh ^cilh;
|
||||
uint32_t cihXll = cihl ^cill;
|
||||
uint32_t cihXlh = cihh ^ cilh;
|
||||
uint32_t cihXll = cihl ^ cill;
|
||||
uint32_t aah, aal, abh, abl, ach, acl;
|
||||
s_bmul32(M0, cihh, hhh, aah, aal);
|
||||
s_bmul32(M1, cihl, hhl, abh, abl);
|
||||
|
@ -94,8 +104,8 @@ void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t &y0, uint64_t &y1) n
|
|||
cbh ^= bbh ^ abh;
|
||||
cbl ^= bbl ^ abl;
|
||||
uint64_t zhh = ((uint64_t)aah << 32U) | aal;
|
||||
uint64_t zhl = (((uint64_t)abh << 32U) | abl) ^(((uint64_t)cah << 32U) | cal);
|
||||
uint64_t zlh = (((uint64_t)bah << 32U) | bal) ^(((uint64_t)cbh << 32U) | cbl);
|
||||
uint64_t zhl = (((uint64_t)abh << 32U) | abl) ^ (((uint64_t)cah << 32U) | cal);
|
||||
uint64_t zlh = (((uint64_t)bah << 32U) | bal) ^ (((uint64_t)cbh << 32U) | cbl);
|
||||
uint64_t zll = ((uint64_t)bbh << 32U) | bbl;
|
||||
zhh = zhh << 1U | zhl >> 63U;
|
||||
zhl = zhl << 1U | zlh >> 63U;
|
||||
|
@ -110,9 +120,9 @@ void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t &y0, uint64_t &y1) n
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
void AES::GMAC::update(const void *const data, unsigned int len) noexcept
|
||||
void AES::GMAC::update(const void* const data, unsigned int len) noexcept
|
||||
{
|
||||
const uint8_t *in = reinterpret_cast<const uint8_t *>(data);
|
||||
const uint8_t* in = reinterpret_cast<const uint8_t*>(data);
|
||||
_len += len;
|
||||
|
||||
#ifdef ZT_AES_AESNI
|
||||
|
@ -136,13 +146,13 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
|
|||
|
||||
if (_rp) {
|
||||
for (;;) {
|
||||
if (!len)
|
||||
if (! len)
|
||||
return;
|
||||
--len;
|
||||
_r[_rp++] = *(in++);
|
||||
if (_rp == 16) {
|
||||
y0 ^= Utils::loadMachineEndian< uint64_t >(_r);
|
||||
y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8);
|
||||
y0 ^= Utils::loadMachineEndian<uint64_t>(_r);
|
||||
y1 ^= Utils::loadMachineEndian<uint64_t>(_r + 8);
|
||||
s_gfmul(h0, h1, y0, y1);
|
||||
break;
|
||||
}
|
||||
|
@ -150,8 +160,8 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
|
|||
}
|
||||
|
||||
while (len >= 16) {
|
||||
y0 ^= Utils::loadMachineEndian< uint64_t >(in);
|
||||
y1 ^= Utils::loadMachineEndian< uint64_t >(in + 8);
|
||||
y0 ^= Utils::loadMachineEndian<uint64_t>(in);
|
||||
y1 ^= Utils::loadMachineEndian<uint64_t>(in + 8);
|
||||
in += 16;
|
||||
s_gfmul(h0, h1, y0, y1);
|
||||
len -= 16;
|
||||
|
@ -189,8 +199,8 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
|
|||
if (_rp) {
|
||||
while (_rp < 16)
|
||||
_r[_rp++] = 0;
|
||||
y0 ^= Utils::loadMachineEndian< uint64_t >(_r);
|
||||
y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8);
|
||||
y0 ^= Utils::loadMachineEndian<uint64_t>(_r);
|
||||
y1 ^= Utils::loadMachineEndian<uint64_t>(_r + 8);
|
||||
s_gfmul(h0, h1, y0, y1);
|
||||
}
|
||||
|
||||
|
@ -198,24 +208,24 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
|
|||
s_gfmul(h0, h1, y0, y1);
|
||||
|
||||
uint64_t iv2[2];
|
||||
Utils::copy< 12 >(iv2, _iv);
|
||||
Utils::copy<12>(iv2, _iv);
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
reinterpret_cast<uint32_t *>(iv2)[3] = 0x00000001;
|
||||
reinterpret_cast<uint32_t*>(iv2)[3] = 0x00000001;
|
||||
#else
|
||||
reinterpret_cast<uint32_t *>(iv2)[3] = 0x01000000;
|
||||
reinterpret_cast<uint32_t*>(iv2)[3] = 0x01000000;
|
||||
#endif
|
||||
_aes.encrypt(iv2, iv2);
|
||||
|
||||
Utils::storeMachineEndian< uint64_t >(tag, iv2[0] ^ y0);
|
||||
Utils::storeMachineEndian< uint64_t >(tag + 8, iv2[1] ^ y1);
|
||||
Utils::storeMachineEndian<uint64_t>(tag, iv2[0] ^ y0);
|
||||
Utils::storeMachineEndian<uint64_t>(tag + 8, iv2[1] ^ y1);
|
||||
}
|
||||
|
||||
// AES-CTR ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
||||
void AES::CTR::crypt(const void* const input, unsigned int len) noexcept
|
||||
{
|
||||
const uint8_t *in = reinterpret_cast<const uint8_t *>(input);
|
||||
uint8_t *out = _out;
|
||||
const uint8_t* in = reinterpret_cast<const uint8_t*>(input);
|
||||
uint8_t* out = _out;
|
||||
|
||||
#ifdef ZT_AES_AESNI
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
|
@ -232,23 +242,23 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
#endif // ZT_AES_NEON
|
||||
|
||||
uint64_t keyStream[2];
|
||||
uint32_t ctr = Utils::ntoh(reinterpret_cast<uint32_t *>(_ctr)[3]);
|
||||
uint32_t ctr = Utils::ntoh(reinterpret_cast<uint32_t*>(_ctr)[3]);
|
||||
|
||||
unsigned int totalLen = _len;
|
||||
if ((totalLen & 15U)) {
|
||||
for (;;) {
|
||||
if (!len) {
|
||||
if (! len) {
|
||||
_len = (totalLen + len);
|
||||
return;
|
||||
}
|
||||
--len;
|
||||
out[totalLen++] = *(in++);
|
||||
if (!(totalLen & 15U)) {
|
||||
_aes.p_encryptSW(reinterpret_cast<const uint8_t *>(_ctr), reinterpret_cast<uint8_t *>(keyStream));
|
||||
reinterpret_cast<uint32_t *>(_ctr)[3] = Utils::hton(++ctr);
|
||||
uint8_t *outblk = out + (totalLen - 16);
|
||||
if (! (totalLen & 15U)) {
|
||||
_aes.p_encryptSW(reinterpret_cast<const uint8_t*>(_ctr), reinterpret_cast<uint8_t*>(keyStream));
|
||||
reinterpret_cast<uint32_t*>(_ctr)[3] = Utils::hton(++ctr);
|
||||
uint8_t* outblk = out + (totalLen - 16);
|
||||
for (int i = 0; i < 16; ++i)
|
||||
outblk[i] ^= reinterpret_cast<uint8_t *>(keyStream)[i];
|
||||
outblk[i] ^= reinterpret_cast<uint8_t*>(keyStream)[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -258,10 +268,10 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
_len = (totalLen + len);
|
||||
|
||||
if (likely(len >= 16)) {
|
||||
const uint32_t *const restrict rk = _aes.p_k.sw.ek;
|
||||
const uint32_t ctr0rk0 = Utils::ntoh(reinterpret_cast<const uint32_t *>(_ctr)[0]) ^rk[0];
|
||||
const uint32_t ctr1rk1 = Utils::ntoh(reinterpret_cast<const uint32_t *>(_ctr)[1]) ^rk[1];
|
||||
const uint32_t ctr2rk2 = Utils::ntoh(reinterpret_cast<const uint32_t *>(_ctr)[2]) ^rk[2];
|
||||
const uint32_t* const restrict rk = _aes.p_k.sw.ek;
|
||||
const uint32_t ctr0rk0 = Utils::ntoh(reinterpret_cast<const uint32_t*>(_ctr)[0]) ^ rk[0];
|
||||
const uint32_t ctr1rk1 = Utils::ntoh(reinterpret_cast<const uint32_t*>(_ctr)[1]) ^ rk[1];
|
||||
const uint32_t ctr2rk2 = Utils::ntoh(reinterpret_cast<const uint32_t*>(_ctr)[2]) ^ rk[2];
|
||||
const uint32_t m8 = 0x000000ff;
|
||||
const uint32_t m8_8 = 0x0000ff00;
|
||||
const uint32_t m8_16 = 0x00ff0000;
|
||||
|
@ -274,8 +284,8 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
s2 = ctr2rk2;
|
||||
s3 = ctr++ ^ rk[3];
|
||||
|
||||
const uint64_t in0 = *reinterpret_cast<const uint64_t *>(in);
|
||||
const uint64_t in1 = *reinterpret_cast<const uint64_t *>(in + 8);
|
||||
const uint64_t in0 = *reinterpret_cast<const uint64_t*>(in);
|
||||
const uint64_t in1 = *reinterpret_cast<const uint64_t*>(in + 8);
|
||||
in += 16;
|
||||
|
||||
t0 = Te0[s0 >> 24U] ^ Te1_r((s1 >> 16U) & m8) ^ Te2_r((s2 >> 8U) & m8) ^ Te3_r(s3 & m8) ^ rk[4];
|
||||
|
@ -330,16 +340,21 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
t1 = Te0[s1 >> 24U] ^ Te1_r((s2 >> 16U) & m8) ^ Te2_r((s3 >> 8U) & m8) ^ Te3_r(s0 & m8) ^ rk[53];
|
||||
t2 = Te0[s2 >> 24U] ^ Te1_r((s3 >> 16U) & m8) ^ Te2_r((s0 >> 8U) & m8) ^ Te3_r(s1 & m8) ^ rk[54];
|
||||
t3 = Te0[s3 >> 24U] ^ Te1_r((s0 >> 16U) & m8) ^ Te2_r((s1 >> 8U) & m8) ^ Te3_r(s2 & m8) ^ rk[55];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8) ^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8) ^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
|
||||
*reinterpret_cast<uint64_t *>(out) = in0 ^ Utils::hton(((uint64_t)s0 << 32U) | (uint64_t)s1);
|
||||
*reinterpret_cast<uint64_t *>(out + 8) = in1 ^ Utils::hton(((uint64_t)s2 << 32U) | (uint64_t)s3);
|
||||
*reinterpret_cast<uint64_t*>(out) = in0 ^ Utils::hton(((uint64_t)s0 << 32U) | (uint64_t)s1);
|
||||
*reinterpret_cast<uint64_t*>(out + 8) = in1 ^ Utils::hton(((uint64_t)s2 << 32U) | (uint64_t)s3);
|
||||
out += 16;
|
||||
} while ((len -= 16) >= 16);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
do {
|
||||
uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
|
||||
s0 = ctr0rk0;
|
||||
|
@ -399,10 +414,14 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
t1 = Te0[s1 >> 24U] ^ Te1_r((s2 >> 16U) & m8) ^ Te2_r((s3 >> 8U) & m8) ^ Te3_r(s0 & m8) ^ rk[53];
|
||||
t2 = Te0[s2 >> 24U] ^ Te1_r((s3 >> 16U) & m8) ^ Te2_r((s0 >> 8U) & m8) ^ Te3_r(s1 & m8) ^ rk[54];
|
||||
t3 = Te0[s3 >> 24U] ^ Te1_r((s0 >> 16U) & m8) ^ Te2_r((s1 >> 8U) & m8) ^ Te3_r(s2 & m8) ^ rk[55];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8) ^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8) ^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
|
||||
out[0] = in[0] ^ (uint8_t)(s0 >> 24U);
|
||||
out[1] = in[1] ^ (uint8_t)(s0 >> 16U);
|
||||
|
@ -424,7 +443,7 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
in += 16;
|
||||
} while ((len -= 16) >= 16);
|
||||
}
|
||||
reinterpret_cast<uint32_t *>(_ctr)[3] = Utils::hton(ctr);
|
||||
reinterpret_cast<uint32_t*>(_ctr)[3] = Utils::hton(ctr);
|
||||
}
|
||||
|
||||
// Any remaining input is placed in _out. This will be picked up and crypted
|
||||
|
@ -449,65 +468,150 @@ void AES::CTR::finish() noexcept
|
|||
|
||||
// Software AES and AES key expansion ---------------------------------------------------------------------------------
|
||||
|
||||
const uint32_t AES::Te0[256] = {0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153,
|
||||
0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
|
||||
0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba,
|
||||
0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
|
||||
0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437,
|
||||
0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
|
||||
0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878,
|
||||
0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a};
|
||||
const uint32_t AES::Te4[256] = {0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676, 0xcacacaca, 0x82828282, 0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2, 0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0, 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626, 0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171, 0xd8d8d8d8, 0x31313131,
|
||||
0x15151515, 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696, 0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2, 0x75757575,
|
||||
0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0, 0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484, 0x53535353, 0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb, 0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf, 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa, 0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f, 0x50505050, 0x3c3c3c3c, 0x9f9f9f9f,
|
||||
0xa8a8a8a8, 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292, 0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff, 0xf3f3f3f3, 0xd2d2d2d2,
|
||||
0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444, 0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373, 0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646, 0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb, 0xe0e0e0e0, 0x32323232, 0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac, 0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4,
|
||||
0x79797979, 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d, 0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565, 0x7a7a7a7a, 0xaeaeaeae, 0x08080808,
|
||||
0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6, 0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b, 0x8a8a8a8a, 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e, 0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e, 0xe1e1e1e1, 0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e, 0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828,
|
||||
0xdfdfdfdf, 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989, 0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616};
|
||||
const uint32_t AES::Td0[256] = {0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c,
|
||||
0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
|
||||
0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1,
|
||||
0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
|
||||
0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e,
|
||||
0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
|
||||
0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14,
|
||||
0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742};
|
||||
const uint8_t AES::Td4[256] = {0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d,
|
||||
0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c,
|
||||
0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
|
||||
const uint32_t AES::rcon[15] = {0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000};
|
||||
const uint32_t AES::Te0[256] = {
|
||||
0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050,
|
||||
0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d,
|
||||
0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd,
|
||||
0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a,
|
||||
0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193,
|
||||
0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1,
|
||||
0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd,
|
||||
0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
|
||||
0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5,
|
||||
0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46,
|
||||
0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5,
|
||||
0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81,
|
||||
0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad,
|
||||
0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a,
|
||||
0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc,
|
||||
0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
|
||||
0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca,
|
||||
0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256,
|
||||
0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef,
|
||||
0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7,
|
||||
0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af,
|
||||
0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1,
|
||||
0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86,
|
||||
0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
|
||||
0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138,
|
||||
0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22,
|
||||
0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980,
|
||||
0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11,
|
||||
0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
|
||||
};
|
||||
const uint32_t AES::Te4[256] = {
|
||||
0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030,
|
||||
0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676, 0xcacacaca, 0x82828282,
|
||||
0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2,
|
||||
0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0, 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626,
|
||||
0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171,
|
||||
0xd8d8d8d8, 0x31313131, 0x15151515, 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696,
|
||||
0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2,
|
||||
0x75757575, 0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0,
|
||||
0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484, 0x53535353,
|
||||
0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb,
|
||||
0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf, 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa,
|
||||
0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f,
|
||||
0x50505050, 0x3c3c3c3c, 0x9f9f9f9f, 0xa8a8a8a8, 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292,
|
||||
0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff,
|
||||
0xf3f3f3f3, 0xd2d2d2d2, 0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444,
|
||||
0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373,
|
||||
0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646,
|
||||
0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb, 0xe0e0e0e0, 0x32323232,
|
||||
0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac,
|
||||
0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4, 0x79797979, 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d,
|
||||
0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565,
|
||||
0x7a7a7a7a, 0xaeaeaeae, 0x08080808, 0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6,
|
||||
0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b,
|
||||
0x8a8a8a8a, 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e,
|
||||
0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e, 0xe1e1e1e1,
|
||||
0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e,
|
||||
0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828, 0xdfdfdfdf, 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989,
|
||||
0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f,
|
||||
0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616
|
||||
};
|
||||
const uint32_t AES::Td0[256] = {
|
||||
0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55,
|
||||
0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67,
|
||||
0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb,
|
||||
0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd,
|
||||
0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0,
|
||||
0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2,
|
||||
0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba,
|
||||
0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
|
||||
0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9,
|
||||
0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997,
|
||||
0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9,
|
||||
0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927,
|
||||
0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f,
|
||||
0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad,
|
||||
0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5,
|
||||
0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
|
||||
0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c,
|
||||
0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1,
|
||||
0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b,
|
||||
0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3,
|
||||
0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65,
|
||||
0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331,
|
||||
0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e,
|
||||
0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
|
||||
0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c,
|
||||
0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f,
|
||||
0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c,
|
||||
0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190,
|
||||
0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742
|
||||
};
|
||||
const uint8_t AES::Td4[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39,
|
||||
0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2,
|
||||
0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76,
|
||||
0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc,
|
||||
0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d,
|
||||
0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c,
|
||||
0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f,
|
||||
0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
|
||||
0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62,
|
||||
0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd,
|
||||
0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60,
|
||||
0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
|
||||
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,
|
||||
0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
};
|
||||
const uint32_t AES::rcon[15] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
|
||||
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
|
||||
0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000 };
|
||||
|
||||
void AES::p_initSW(const uint8_t *key) noexcept
|
||||
void AES::p_initSW(const uint8_t* key) noexcept
|
||||
{
|
||||
uint32_t *rk = p_k.sw.ek;
|
||||
uint32_t* rk = p_k.sw.ek;
|
||||
|
||||
rk[0] = Utils::loadBigEndian< uint32_t >(key);
|
||||
rk[1] = Utils::loadBigEndian< uint32_t >(key + 4);
|
||||
rk[2] = Utils::loadBigEndian< uint32_t >(key + 8);
|
||||
rk[3] = Utils::loadBigEndian< uint32_t >(key + 12);
|
||||
rk[4] = Utils::loadBigEndian< uint32_t >(key + 16);
|
||||
rk[5] = Utils::loadBigEndian< uint32_t >(key + 20);
|
||||
rk[6] = Utils::loadBigEndian< uint32_t >(key + 24);
|
||||
rk[7] = Utils::loadBigEndian< uint32_t >(key + 28);
|
||||
rk[0] = Utils::loadBigEndian<uint32_t>(key);
|
||||
rk[1] = Utils::loadBigEndian<uint32_t>(key + 4);
|
||||
rk[2] = Utils::loadBigEndian<uint32_t>(key + 8);
|
||||
rk[3] = Utils::loadBigEndian<uint32_t>(key + 12);
|
||||
rk[4] = Utils::loadBigEndian<uint32_t>(key + 16);
|
||||
rk[5] = Utils::loadBigEndian<uint32_t>(key + 20);
|
||||
rk[6] = Utils::loadBigEndian<uint32_t>(key + 24);
|
||||
rk[7] = Utils::loadBigEndian<uint32_t>(key + 28);
|
||||
for (int i = 0;;) {
|
||||
uint32_t temp = rk[7];
|
||||
rk[8] = rk[0] ^ (Te2_r((temp >> 16U) & 0xffU) & 0xff000000U) ^ (Te3_r((temp >> 8U) & 0xffU) & 0x00ff0000U) ^ (Te0[(temp) & 0xffU] & 0x0000ff00U) ^ (Te1_r(temp >> 24U) & 0x000000ffU) ^ rcon[i];
|
||||
rk[8] = rk[0] ^ (Te2_r((temp >> 16U) & 0xffU) & 0xff000000U) ^ (Te3_r((temp >> 8U) & 0xffU) & 0x00ff0000U)
|
||||
^ (Te0[(temp)&0xffU] & 0x0000ff00U) ^ (Te1_r(temp >> 24U) & 0x000000ffU) ^ rcon[i];
|
||||
rk[9] = rk[1] ^ rk[8];
|
||||
rk[10] = rk[2] ^ rk[9];
|
||||
rk[11] = rk[3] ^ rk[10];
|
||||
if (++i == 7)
|
||||
break;
|
||||
temp = rk[11];
|
||||
rk[12] = rk[4] ^ (Te2_r(temp >> 24U) & 0xff000000U) ^ (Te3_r((temp >> 16U) & 0xffU) & 0x00ff0000U) ^ (Te0[(temp >> 8U) & 0xffU] & 0x0000ff00U) ^ (Te1_r((temp) & 0xffU) & 0x000000ffU);
|
||||
rk[12] = rk[4] ^ (Te2_r(temp >> 24U) & 0xff000000U) ^ (Te3_r((temp >> 16U) & 0xffU) & 0x00ff0000U)
|
||||
^ (Te0[(temp >> 8U) & 0xffU] & 0x0000ff00U) ^ (Te1_r((temp)&0xffU) & 0x000000ffU);
|
||||
rk[13] = rk[5] ^ rk[12];
|
||||
rk[14] = rk[6] ^ rk[13];
|
||||
rk[15] = rk[7] ^ rk[14];
|
||||
rk += 8;
|
||||
}
|
||||
|
||||
p_encryptSW((const uint8_t *)Utils::ZERO256, (uint8_t *)p_k.sw.h);
|
||||
p_encryptSW((const uint8_t*)Utils::ZERO256, (uint8_t*)p_k.sw.h);
|
||||
p_k.sw.h[0] = Utils::ntoh(p_k.sw.h[0]);
|
||||
p_k.sw.h[1] = Utils::ntoh(p_k.sw.h[1]);
|
||||
|
||||
|
@ -531,24 +635,28 @@ void AES::p_initSW(const uint8_t *key) noexcept
|
|||
}
|
||||
for (int i = 1; i < 14; ++i) {
|
||||
rk += 4;
|
||||
rk[0] = Td0[Te4[(rk[0] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[0] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[0] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[0]) & 0xffU] & 0xffU);
|
||||
rk[1] = Td0[Te4[(rk[1] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[1] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[1] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[1]) & 0xffU] & 0xffU);
|
||||
rk[2] = Td0[Te4[(rk[2] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[2] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[2] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[2]) & 0xffU] & 0xffU);
|
||||
rk[3] = Td0[Te4[(rk[3] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[3] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[3] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[3]) & 0xffU] & 0xffU);
|
||||
rk[0] = Td0[Te4[(rk[0] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[0] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[0] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[0]) & 0xffU] & 0xffU);
|
||||
rk[1] = Td0[Te4[(rk[1] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[1] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[1] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[1]) & 0xffU] & 0xffU);
|
||||
rk[2] = Td0[Te4[(rk[2] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[2] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[2] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[2]) & 0xffU] & 0xffU);
|
||||
rk[3] = Td0[Te4[(rk[3] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[3] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[3] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[3]) & 0xffU] & 0xffU);
|
||||
}
|
||||
}
|
||||
|
||||
void AES::p_encryptSW(const uint8_t *in, uint8_t *out) const noexcept
|
||||
void AES::p_encryptSW(const uint8_t* in, uint8_t* out) const noexcept
|
||||
{
|
||||
const uint32_t *const restrict rk = p_k.sw.ek;
|
||||
const uint32_t* const restrict rk = p_k.sw.ek;
|
||||
const uint32_t m8 = 0x000000ff;
|
||||
const uint32_t m8_8 = 0x0000ff00;
|
||||
const uint32_t m8_16 = 0x00ff0000;
|
||||
const uint32_t m8_24 = 0xff000000;
|
||||
uint32_t s0 = Utils::loadBigEndian< uint32_t >(in) ^rk[0];
|
||||
uint32_t s1 = Utils::loadBigEndian< uint32_t >(in + 4) ^rk[1];
|
||||
uint32_t s2 = Utils::loadBigEndian< uint32_t >(in + 8) ^rk[2];
|
||||
uint32_t s3 = Utils::loadBigEndian< uint32_t >(in + 12) ^rk[3];
|
||||
uint32_t s0 = Utils::loadBigEndian<uint32_t>(in) ^ rk[0];
|
||||
uint32_t s1 = Utils::loadBigEndian<uint32_t>(in + 4) ^ rk[1];
|
||||
uint32_t s2 = Utils::loadBigEndian<uint32_t>(in + 8) ^ rk[2];
|
||||
uint32_t s3 = Utils::loadBigEndian<uint32_t>(in + 12) ^ rk[3];
|
||||
|
||||
uint32_t t0, t1, t2, t3;
|
||||
t0 = Te0[s0 >> 24U] ^ Te1_r((s1 >> 16U) & m8) ^ Te2_r((s2 >> 8U) & m8) ^ Te3_r(s3 & m8) ^ rk[4];
|
||||
|
@ -603,25 +711,29 @@ void AES::p_encryptSW(const uint8_t *in, uint8_t *out) const noexcept
|
|||
t1 = Te0[s1 >> 24U] ^ Te1_r((s2 >> 16U) & m8) ^ Te2_r((s3 >> 8U) & m8) ^ Te3_r(s0 & m8) ^ rk[53];
|
||||
t2 = Te0[s2 >> 24U] ^ Te1_r((s3 >> 16U) & m8) ^ Te2_r((s0 >> 8U) & m8) ^ Te3_r(s1 & m8) ^ rk[54];
|
||||
t3 = Te0[s3 >> 24U] ^ Te1_r((s0 >> 16U) & m8) ^ Te2_r((s1 >> 8U) & m8) ^ Te3_r(s2 & m8) ^ rk[55];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8) ^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8) ^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
|
||||
Utils::storeBigEndian< uint32_t >(out, s0);
|
||||
Utils::storeBigEndian< uint32_t >(out + 4, s1);
|
||||
Utils::storeBigEndian< uint32_t >(out + 8, s2);
|
||||
Utils::storeBigEndian< uint32_t >(out + 12, s3);
|
||||
Utils::storeBigEndian<uint32_t>(out, s0);
|
||||
Utils::storeBigEndian<uint32_t>(out + 4, s1);
|
||||
Utils::storeBigEndian<uint32_t>(out + 8, s2);
|
||||
Utils::storeBigEndian<uint32_t>(out + 12, s3);
|
||||
}
|
||||
|
||||
void AES::p_decryptSW(const uint8_t *in, uint8_t *out) const noexcept
|
||||
void AES::p_decryptSW(const uint8_t* in, uint8_t* out) const noexcept
|
||||
{
|
||||
const uint32_t *restrict rk = p_k.sw.dk;
|
||||
const uint32_t* restrict rk = p_k.sw.dk;
|
||||
const uint32_t m8 = 0x000000ff;
|
||||
uint32_t s0 = Utils::loadBigEndian< uint32_t >(in) ^rk[0];
|
||||
uint32_t s1 = Utils::loadBigEndian< uint32_t >(in + 4) ^rk[1];
|
||||
uint32_t s2 = Utils::loadBigEndian< uint32_t >(in + 8) ^rk[2];
|
||||
uint32_t s3 = Utils::loadBigEndian< uint32_t >(in + 12) ^rk[3];
|
||||
uint32_t s0 = Utils::loadBigEndian<uint32_t>(in) ^ rk[0];
|
||||
uint32_t s1 = Utils::loadBigEndian<uint32_t>(in + 4) ^ rk[1];
|
||||
uint32_t s2 = Utils::loadBigEndian<uint32_t>(in + 8) ^ rk[2];
|
||||
uint32_t s3 = Utils::loadBigEndian<uint32_t>(in + 12) ^ rk[3];
|
||||
|
||||
uint32_t t0, t1, t2, t3;
|
||||
t0 = Td0[s0 >> 24U] ^ Td1_r((s3 >> 16U) & m8) ^ Td2_r((s2 >> 8U) & m8) ^ Td3_r(s1 & m8) ^ rk[4];
|
||||
|
@ -676,15 +788,19 @@ void AES::p_decryptSW(const uint8_t *in, uint8_t *out) const noexcept
|
|||
t1 = Td0[s1 >> 24U] ^ Td1_r((s0 >> 16U) & m8) ^ Td2_r((s3 >> 8U) & m8) ^ Td3_r(s2 & m8) ^ rk[53];
|
||||
t2 = Td0[s2 >> 24U] ^ Td1_r((s1 >> 16U) & m8) ^ Td2_r((s0 >> 8U) & m8) ^ Td3_r(s3 & m8) ^ rk[54];
|
||||
t3 = Td0[s3 >> 24U] ^ Td1_r((s2 >> 16U) & m8) ^ Td2_r((s1 >> 8U) & m8) ^ Td3_r(s0 & m8) ^ rk[55];
|
||||
s0 = (Td4[t0 >> 24U] << 24U) ^ (Td4[(t3 >> 16U) & m8] << 16U) ^ (Td4[(t2 >> 8U) & m8] << 8U) ^ (Td4[(t1) & m8]) ^ rk[56];
|
||||
s1 = (Td4[t1 >> 24U] << 24U) ^ (Td4[(t0 >> 16U) & m8] << 16U) ^ (Td4[(t3 >> 8U) & m8] << 8U) ^ (Td4[(t2) & m8]) ^ rk[57];
|
||||
s2 = (Td4[t2 >> 24U] << 24U) ^ (Td4[(t1 >> 16U) & m8] << 16U) ^ (Td4[(t0 >> 8U) & m8] << 8U) ^ (Td4[(t3) & m8]) ^ rk[58];
|
||||
s3 = (Td4[t3 >> 24U] << 24U) ^ (Td4[(t2 >> 16U) & m8] << 16U) ^ (Td4[(t1 >> 8U) & m8] << 8U) ^ (Td4[(t0) & m8]) ^ rk[59];
|
||||
s0 = (Td4[t0 >> 24U] << 24U) ^ (Td4[(t3 >> 16U) & m8] << 16U) ^ (Td4[(t2 >> 8U) & m8] << 8U) ^ (Td4[(t1)&m8])
|
||||
^ rk[56];
|
||||
s1 = (Td4[t1 >> 24U] << 24U) ^ (Td4[(t0 >> 16U) & m8] << 16U) ^ (Td4[(t3 >> 8U) & m8] << 8U) ^ (Td4[(t2)&m8])
|
||||
^ rk[57];
|
||||
s2 = (Td4[t2 >> 24U] << 24U) ^ (Td4[(t1 >> 16U) & m8] << 16U) ^ (Td4[(t0 >> 8U) & m8] << 8U) ^ (Td4[(t3)&m8])
|
||||
^ rk[58];
|
||||
s3 = (Td4[t3 >> 24U] << 24U) ^ (Td4[(t2 >> 16U) & m8] << 16U) ^ (Td4[(t1 >> 8U) & m8] << 8U) ^ (Td4[(t0)&m8])
|
||||
^ rk[59];
|
||||
|
||||
Utils::storeBigEndian< uint32_t >(out, s0);
|
||||
Utils::storeBigEndian< uint32_t >(out + 4, s1);
|
||||
Utils::storeBigEndian< uint32_t >(out + 8, s2);
|
||||
Utils::storeBigEndian< uint32_t >(out + 12, s3);
|
||||
Utils::storeBigEndian<uint32_t>(out, s0);
|
||||
Utils::storeBigEndian<uint32_t>(out + 4, s1);
|
||||
Utils::storeBigEndian<uint32_t>(out + 8, s2);
|
||||
Utils::storeBigEndian<uint32_t>(out + 12, s3);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
190
core/AES.hpp
190
core/AES.hpp
|
@ -15,16 +15,16 @@
|
|||
#define ZT_AES_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
// Uncomment to disable all hardware acceleration (usually for testing)
|
||||
//#define ZT_AES_NO_ACCEL
|
||||
|
||||
#if !defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_X64)
|
||||
#if ! defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_X64)
|
||||
#define ZT_AES_AESNI 1
|
||||
#endif
|
||||
#if !defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_ARM_HAS_NEON)
|
||||
#if ! defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_ARM_HAS_NEON)
|
||||
#define ZT_AES_NEON 1
|
||||
#endif
|
||||
|
||||
|
@ -40,9 +40,8 @@ namespace ZeroTier {
|
|||
* This includes hardware acceleration for certain processors. The software
|
||||
* mode is fallback and is significantly slower.
|
||||
*/
|
||||
class AES
|
||||
{
|
||||
public:
|
||||
class AES {
|
||||
public:
|
||||
/**
|
||||
* @return True if this system has hardware AES acceleration
|
||||
*/
|
||||
|
@ -64,39 +63,44 @@ public:
|
|||
* Create an un-initialized AES instance (must call init() before use)
|
||||
*/
|
||||
ZT_INLINE AES() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an AES instance with the given key
|
||||
*
|
||||
* @param key 256-bit key
|
||||
*/
|
||||
explicit ZT_INLINE AES(const void *const key) noexcept
|
||||
{ this->init(key); }
|
||||
explicit ZT_INLINE AES(const void* const key) noexcept
|
||||
{
|
||||
this->init(key);
|
||||
}
|
||||
|
||||
ZT_INLINE ~AES()
|
||||
{ Utils::burn(&p_k, sizeof(p_k)); }
|
||||
{
|
||||
Utils::burn(&p_k, sizeof(p_k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set (or re-set) this AES256 cipher's key
|
||||
*
|
||||
* @param key 256-bit / 32-byte key
|
||||
*/
|
||||
ZT_INLINE void init(const void *const key) noexcept
|
||||
ZT_INLINE void init(const void* const key) noexcept
|
||||
{
|
||||
#ifdef ZT_AES_AESNI
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
p_init_aesni(reinterpret_cast<const uint8_t *>(key));
|
||||
p_init_aesni(reinterpret_cast<const uint8_t*>(key));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef ZT_AES_NEON
|
||||
if (Utils::ARMCAP.aes) {
|
||||
p_init_armneon_crypto(reinterpret_cast<const uint8_t *>(key));
|
||||
p_init_armneon_crypto(reinterpret_cast<const uint8_t*>(key));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
p_initSW(reinterpret_cast<const uint8_t *>(key));
|
||||
p_initSW(reinterpret_cast<const uint8_t*>(key));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,7 +109,7 @@ public:
|
|||
* @param in Input block
|
||||
* @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
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
|
@ -119,7 +123,7 @@ public:
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
p_encryptSW(reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out));
|
||||
p_encryptSW(reinterpret_cast<const uint8_t*>(in), reinterpret_cast<uint8_t*>(out));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +132,7 @@ public:
|
|||
* @param in Input block
|
||||
* @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
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
|
@ -142,7 +146,7 @@ public:
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
p_decryptSW(reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out));
|
||||
p_decryptSW(reinterpret_cast<const uint8_t*>(in), reinterpret_cast<uint8_t*>(out));
|
||||
}
|
||||
|
||||
class GMACSIVEncryptor;
|
||||
|
@ -151,8 +155,7 @@ public:
|
|||
/**
|
||||
* Streaming GMAC calculator
|
||||
*/
|
||||
class GMAC
|
||||
{
|
||||
class GMAC {
|
||||
friend class GMACSIVEncryptor;
|
||||
friend class GMACSIVDecryptor;
|
||||
|
||||
|
@ -178,8 +181,9 @@ public:
|
|||
*
|
||||
* @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
|
||||
|
@ -195,9 +199,9 @@ public:
|
|||
// this would hold the counter, but we're not doing GCM just GMAC. That means the
|
||||
// counter always stays just 1.
|
||||
#ifdef ZT_AES_AESNI // also implies an x64 processor
|
||||
*reinterpret_cast<uint64_t *>(_iv) = *reinterpret_cast<const uint64_t *>(iv);
|
||||
*reinterpret_cast<uint32_t *>(_iv + 8) = *reinterpret_cast<const uint64_t *>(iv + 8);
|
||||
*reinterpret_cast<uint32_t *>(_iv + 12) = 0x01000000; // 0x00000001 in big-endian byte order
|
||||
*reinterpret_cast<uint64_t*>(_iv) = *reinterpret_cast<const uint64_t*>(iv);
|
||||
*reinterpret_cast<uint32_t*>(_iv + 8) = *reinterpret_cast<const uint64_t*>(iv + 8);
|
||||
*reinterpret_cast<uint32_t*>(_iv + 12) = 0x01000000; // 0x00000001 in big-endian byte order
|
||||
#else
|
||||
Utils::copy<12>(_iv, iv);
|
||||
_iv[12] = 0;
|
||||
|
@ -216,7 +220,7 @@ public:
|
|||
* @param data Bytes to process
|
||||
* @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
|
||||
|
@ -229,14 +233,14 @@ public:
|
|||
|
||||
private:
|
||||
#ifdef ZT_AES_AESNI
|
||||
void p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept;
|
||||
void p_aesNIUpdate(const uint8_t* in, unsigned int len) noexcept;
|
||||
void p_aesNIFinish(uint8_t tag[16]) noexcept;
|
||||
#endif
|
||||
#ifdef ZT_AES_NEON
|
||||
void p_armUpdate(const uint8_t *in, unsigned int len) noexcept;
|
||||
void p_armUpdate(const uint8_t* in, unsigned int len) noexcept;
|
||||
void p_armFinish(uint8_t tag[16]) noexcept;
|
||||
#endif
|
||||
const AES &_aes;
|
||||
const AES& _aes;
|
||||
unsigned int _rp;
|
||||
unsigned int _len;
|
||||
uint8_t _r[16]; // remainder
|
||||
|
@ -251,14 +255,14 @@ public:
|
|||
* We will never encrypt more than a tiny fraction of 2^32 blocks, so this is left out as
|
||||
* an optimization.
|
||||
*/
|
||||
class CTR
|
||||
{
|
||||
class CTR {
|
||||
friend class GMACSIVEncryptor;
|
||||
friend class GMACSIVDecryptor;
|
||||
|
||||
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
|
||||
|
@ -266,10 +270,10 @@ public:
|
|||
* @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!)
|
||||
*/
|
||||
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);
|
||||
_out = reinterpret_cast<uint8_t *>(output);
|
||||
Utils::copy<16>(_ctr, iv);
|
||||
_out = reinterpret_cast<uint8_t*>(output);
|
||||
_len = 0;
|
||||
}
|
||||
|
||||
|
@ -280,11 +284,11 @@ public:
|
|||
* @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!)
|
||||
*/
|
||||
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);
|
||||
reinterpret_cast<uint32_t *>(_ctr)[3] = ic;
|
||||
_out = reinterpret_cast<uint8_t *>(output);
|
||||
Utils::copy<12>(_ctr, iv);
|
||||
reinterpret_cast<uint32_t*>(_ctr)[3] = ic;
|
||||
_out = reinterpret_cast<uint8_t*>(output);
|
||||
_len = 0;
|
||||
}
|
||||
|
||||
|
@ -294,7 +298,7 @@ public:
|
|||
* @param input Input data
|
||||
* @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
|
||||
|
@ -305,14 +309,14 @@ public:
|
|||
|
||||
private:
|
||||
#ifdef ZT_AES_AESNI
|
||||
void p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) noexcept;
|
||||
void p_aesNICrypt(const uint8_t* in, uint8_t* out, unsigned int len) noexcept;
|
||||
#endif
|
||||
#ifdef ZT_AES_NEON
|
||||
void p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noexcept;
|
||||
void p_armCrypt(const uint8_t* in, uint8_t* out, unsigned int len) noexcept;
|
||||
#endif
|
||||
const AES &_aes;
|
||||
const AES& _aes;
|
||||
uint64_t _ctr[2];
|
||||
uint8_t *_out;
|
||||
uint8_t* _out;
|
||||
unsigned int _len;
|
||||
};
|
||||
|
||||
|
@ -327,8 +331,7 @@ public:
|
|||
* This supports encryption of a maximum of 2^31 bytes of data per
|
||||
* call to init().
|
||||
*/
|
||||
class GMACSIVEncryptor
|
||||
{
|
||||
class GMACSIVEncryptor {
|
||||
public:
|
||||
/**
|
||||
* Create a new AES-GMAC-SIV encryptor keyed with the provided AES instances
|
||||
|
@ -336,10 +339,11 @@ public:
|
|||
* @param k0 First of two AES instances keyed with K0
|
||||
* @param k1 Second of two AES instances keyed with K1
|
||||
*/
|
||||
ZT_INLINE GMACSIVEncryptor(const AES &k0, const AES &k1) noexcept :
|
||||
_gmac(k0),
|
||||
_ctr(k1)
|
||||
{}
|
||||
ZT_INLINE GMACSIVEncryptor(const AES& k0, const AES& k1) noexcept
|
||||
: _gmac(k0)
|
||||
, _ctr(k1)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize AES-GMAC-SIV
|
||||
|
@ -347,7 +351,7 @@ public:
|
|||
* @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!
|
||||
*/
|
||||
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 = output;
|
||||
|
@ -355,7 +359,7 @@ public:
|
|||
// Initialize GMAC with 64-bit IV (and remaining 32 bits padded to zero).
|
||||
_tag[0] = iv;
|
||||
_tag[1] = 0;
|
||||
_gmac.init(reinterpret_cast<const uint8_t *>(_tag));
|
||||
_gmac.init(reinterpret_cast<const uint8_t*>(_tag));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -368,7 +372,7 @@ public:
|
|||
* @param aad Additional authenticated data
|
||||
* @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
|
||||
_gmac.update(aad, len);
|
||||
|
@ -385,8 +389,10 @@ public:
|
|||
* @param input Plaintext chunk
|
||||
* @param len Length of plaintext chunk
|
||||
*/
|
||||
ZT_INLINE void update1(const void *const input, const unsigned int len) noexcept
|
||||
{ _gmac.update(input, len); }
|
||||
ZT_INLINE void update1(const void* const input, const unsigned int len) noexcept
|
||||
{
|
||||
_gmac.update(input, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish first pass, compute CTR IV, initialize second pass.
|
||||
|
@ -395,7 +401,7 @@ public:
|
|||
{
|
||||
// Compute 128-bit GMAC tag.
|
||||
uint64_t tmp[2];
|
||||
_gmac.finish(reinterpret_cast<uint8_t *>(tmp));
|
||||
_gmac.finish(reinterpret_cast<uint8_t*>(tmp));
|
||||
|
||||
// Shorten to 64 bits, concatenate with message IV, and encrypt with AES to
|
||||
// yield the CTR IV and opaque IV/MAC blob. In ZeroTier's use of GMAC-SIV
|
||||
|
@ -415,7 +421,7 @@ public:
|
|||
// and so 2^31 should be considered the input limit.
|
||||
tmp[0] = _tag[0];
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -428,8 +434,10 @@ public:
|
|||
* @param input Plaintext chunk
|
||||
* @param len Length of plaintext chunk
|
||||
*/
|
||||
ZT_INLINE void update2(const void *const input, const unsigned int len) noexcept
|
||||
{ _ctr.crypt(input, len); }
|
||||
ZT_INLINE void update2(const void* const input, const unsigned int len) noexcept
|
||||
{
|
||||
_ctr.crypt(input, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish second pass and return a pointer to the opaque 128-bit IV+MAC block
|
||||
|
@ -439,14 +447,14 @@ public:
|
|||
*
|
||||
* @return Pointer to 128-bit opaque IV+MAC (packed into two 64-bit integers)
|
||||
*/
|
||||
ZT_INLINE const uint64_t *finish2()
|
||||
ZT_INLINE const uint64_t* finish2()
|
||||
{
|
||||
_ctr.finish();
|
||||
return _tag;
|
||||
}
|
||||
|
||||
private:
|
||||
void *_output;
|
||||
void* _output;
|
||||
uint64_t _tag[2];
|
||||
AES::GMAC _gmac;
|
||||
AES::CTR _ctr;
|
||||
|
@ -457,13 +465,13 @@ public:
|
|||
*
|
||||
* GMAC-SIV decryption is single-pass. AAD (if any) must be processed first.
|
||||
*/
|
||||
class GMACSIVDecryptor
|
||||
{
|
||||
class GMACSIVDecryptor {
|
||||
public:
|
||||
ZT_INLINE GMACSIVDecryptor(const AES &k0, const AES &k1) noexcept:
|
||||
_ctr(k1),
|
||||
_gmac(k0)
|
||||
{}
|
||||
ZT_INLINE GMACSIVDecryptor(const AES& k0, const AES& k1) noexcept
|
||||
: _ctr(k1)
|
||||
, _gmac(k0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize decryptor for a new message
|
||||
|
@ -471,18 +479,18 @@ public:
|
|||
* @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!)
|
||||
*/
|
||||
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];
|
||||
tmp[0] = tag[0];
|
||||
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);
|
||||
|
||||
tmp[0] = _ivMac[0];
|
||||
tmp[1] = 0;
|
||||
_gmac.init(reinterpret_cast<const uint8_t *>(tmp));
|
||||
_gmac.init(reinterpret_cast<const uint8_t*>(tmp));
|
||||
|
||||
_output = output;
|
||||
_decryptedLen = 0;
|
||||
|
@ -494,7 +502,7 @@ public:
|
|||
* @param aad Additional authenticated data
|
||||
* @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);
|
||||
len &= 0xfU;
|
||||
|
@ -510,7 +518,7 @@ public:
|
|||
* @param input Input 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);
|
||||
_decryptedLen += len;
|
||||
|
@ -527,7 +535,7 @@ public:
|
|||
|
||||
uint64_t gmacTag[2];
|
||||
_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];
|
||||
}
|
||||
|
||||
|
@ -535,26 +543,24 @@ public:
|
|||
uint64_t _ivMac[2];
|
||||
AES::CTR _ctr;
|
||||
AES::GMAC _gmac;
|
||||
void *_output;
|
||||
void* _output;
|
||||
unsigned int _decryptedLen;
|
||||
};
|
||||
|
||||
private:
|
||||
private:
|
||||
static const uint32_t Te0[256];
|
||||
static const uint32_t Te4[256];
|
||||
static const uint32_t Td0[256];
|
||||
static const uint8_t Td4[256];
|
||||
static const uint32_t rcon[15];
|
||||
|
||||
void p_initSW(const uint8_t *key) noexcept;
|
||||
void p_encryptSW(const uint8_t *in, uint8_t *out) const noexcept;
|
||||
void p_decryptSW(const uint8_t *in, uint8_t *out) const noexcept;
|
||||
void p_initSW(const uint8_t* key) noexcept;
|
||||
void p_encryptSW(const uint8_t* in, uint8_t* out) const noexcept;
|
||||
void p_decryptSW(const uint8_t* in, uint8_t* out) const noexcept;
|
||||
|
||||
union
|
||||
{
|
||||
union {
|
||||
#ifdef ZT_AES_AESNI
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
__m128i k[28];
|
||||
__m128i h[4]; // h, hh, hhh, hhhh
|
||||
__m128i h2[4]; // _mm_xor_si128(_mm_shuffle_epi32(h, 78), h), etc.
|
||||
|
@ -562,8 +568,7 @@ private:
|
|||
#endif
|
||||
|
||||
#ifdef ZT_AES_NEON
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint64_t hsw[2]; // in case it has AES but not PMULL, not sure if that ever happens
|
||||
uint8x16_t ek[15];
|
||||
uint8x16_t dk[15];
|
||||
|
@ -571,8 +576,7 @@ private:
|
|||
} neon;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint64_t h[2];
|
||||
uint32_t ek[60];
|
||||
uint32_t dk[60];
|
||||
|
@ -580,15 +584,15 @@ private:
|
|||
} p_k;
|
||||
|
||||
#ifdef ZT_AES_AESNI
|
||||
void p_init_aesni(const uint8_t *key) noexcept;
|
||||
void p_encrypt_aesni(const void *in, void *out) const noexcept;
|
||||
void p_decrypt_aesni(const void *in, void *out) const noexcept;
|
||||
void p_init_aesni(const uint8_t* key) noexcept;
|
||||
void p_encrypt_aesni(const void* in, void* out) const noexcept;
|
||||
void p_decrypt_aesni(const void* in, void* out) const noexcept;
|
||||
#endif
|
||||
|
||||
#ifdef ZT_AES_NEON
|
||||
void p_init_armneon_crypto(const uint8_t *key) noexcept;
|
||||
void p_encrypt_armneon_crypto(const void *in, void *out) const noexcept;
|
||||
void p_decrypt_armneon_crypto(const void *in, void *out) const noexcept;
|
||||
void p_init_armneon_crypto(const uint8_t* key) noexcept;
|
||||
void p_encrypt_armneon_crypto(const void* in, void* out) const noexcept;
|
||||
void p_decrypt_armneon_crypto(const void* in, void* out) const noexcept;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
// AES for X64 AES-NI extensions (no 32-bit X86 support). Supports AVX2 and
|
||||
// AVX512 VAES for performance in excess of 10GiB/sec/core on newer chips.
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
#ifdef ZT_AES_AESNI
|
||||
|
||||
|
@ -32,7 +32,8 @@ const __m128i s_sseSwapBytes = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
|||
#ifdef __GNUC__
|
||||
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul")))
|
||||
#endif
|
||||
__m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
|
||||
__m128i
|
||||
p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
|
||||
{
|
||||
y = _mm_shuffle_epi8(y, s_sseSwapBytes);
|
||||
__m128i t1 = _mm_clmulepi64_si128(h, y, 0x00);
|
||||
|
@ -46,10 +47,16 @@ __m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
|
|||
t4 = _mm_xor_si128(t4, t2);
|
||||
__m128i t5 = _mm_srli_epi32(t1, 31);
|
||||
t1 = _mm_or_si128(_mm_slli_epi32(t1, 1), _mm_slli_si128(t5, 4));
|
||||
t4 = _mm_or_si128(_mm_or_si128(_mm_slli_epi32(t4, 1), _mm_slli_si128(_mm_srli_epi32(t4, 31), 4)), _mm_srli_si128(t5, 12));
|
||||
t4 = _mm_or_si128(
|
||||
_mm_or_si128(_mm_slli_epi32(t4, 1), _mm_slli_si128(_mm_srli_epi32(t4, 31), 4)),
|
||||
_mm_srli_si128(t5, 12));
|
||||
t5 = _mm_xor_si128(_mm_xor_si128(_mm_slli_epi32(t1, 31), _mm_slli_epi32(t1, 30)), _mm_slli_epi32(t1, 25));
|
||||
t1 = _mm_xor_si128(t1, _mm_slli_si128(t5, 12));
|
||||
t4 = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(t4, _mm_srli_si128(t5, 4)), t1), _mm_srli_epi32(t1, 2)), _mm_srli_epi32(t1, 7)), _mm_srli_epi32(t1, 1));
|
||||
t4 = _mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(t4, _mm_srli_si128(t5, 4)), t1), _mm_srli_epi32(t1, 2)),
|
||||
_mm_srli_epi32(t1, 7)),
|
||||
_mm_srli_epi32(t1, 1));
|
||||
return _mm_shuffle_epi8(t4, s_sseSwapBytes);
|
||||
}
|
||||
|
||||
|
@ -58,7 +65,7 @@ __m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
|
|||
* The performance gain can be significant but regular SSE is already so
|
||||
* fast it's highly unlikely to be a rate limiting factor except on massive
|
||||
* servers and network infrastructure stuff. */
|
||||
#if !defined(__WINDOWS__) && ((__GNUC__ >= 8) || (__clang_major__ >= 7))
|
||||
#if ! defined(__WINDOWS__) && ((__GNUC__ >= 8) || (__clang_major__ >= 7))
|
||||
|
||||
#define ZT_AES_VAES512 1
|
||||
|
||||
|
@ -83,12 +90,16 @@ void p_aesCtrInnerVAES512(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
const __m512i kk13 = _mm512_broadcast_i32x4(k[13]);
|
||||
const __m512i kk14 = _mm512_broadcast_i32x4(k[14]);
|
||||
do {
|
||||
__m512i p0 = _mm512_loadu_si512(reinterpret_cast<const __m512i *>(in));
|
||||
__m512i p0 = _mm512_loadu_si512(reinterpret_cast<const __m512i*>(in));
|
||||
__m512i d0 = _mm512_set_epi64(
|
||||
(long long)Utils::hton(c1 + 3ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1 + 1ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1), (long long)c0);
|
||||
(long long)Utils::hton(c1 + 3ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1 + 1ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1),
|
||||
(long long)c0);
|
||||
c1 += 4;
|
||||
in += 64;
|
||||
len -= 64;
|
||||
|
@ -107,7 +118,7 @@ void p_aesCtrInnerVAES512(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
d0 = _mm512_aesenc_epi128(d0, kk12);
|
||||
d0 = _mm512_aesenc_epi128(d0, kk13);
|
||||
d0 = _mm512_aesenclast_epi128(d0, kk14);
|
||||
_mm512_storeu_si512(reinterpret_cast<__m512i *>(out), _mm512_xor_si512(p0, d0));
|
||||
_mm512_storeu_si512(reinterpret_cast<__m512i*>(out), _mm512_xor_si512(p0, d0));
|
||||
out += 64;
|
||||
} while (likely(len >= 64));
|
||||
}
|
||||
|
@ -135,14 +146,18 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
const __m256i kk13 = _mm256_broadcastsi128_si256(k[13]);
|
||||
const __m256i kk14 = _mm256_broadcastsi128_si256(k[14]);
|
||||
do {
|
||||
__m256i p0 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in));
|
||||
__m256i p1 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in + 32));
|
||||
__m256i p0 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in));
|
||||
__m256i p1 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in + 32));
|
||||
__m256i d0 = _mm256_set_epi64x(
|
||||
(long long)Utils::hton(c1 + 1ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1), (long long)c0);
|
||||
(long long)Utils::hton(c1 + 1ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1),
|
||||
(long long)c0);
|
||||
__m256i d1 = _mm256_set_epi64x(
|
||||
(long long)Utils::hton(c1 + 3ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL), (long long)c0);
|
||||
(long long)Utils::hton(c1 + 3ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL),
|
||||
(long long)c0);
|
||||
c1 += 4;
|
||||
in += 64;
|
||||
len -= 64;
|
||||
|
@ -176,8 +191,8 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
d1 = _mm256_aesenc_epi128(d1, kk13);
|
||||
d0 = _mm256_aesenclast_epi128(d0, kk14);
|
||||
d1 = _mm256_aesenclast_epi128(d1, kk14);
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i *>(out), _mm256_xor_si256(d0, p0));
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i *>(out + 32), _mm256_xor_si256(d1, p1));
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(out), _mm256_xor_si256(d0, p0));
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(out + 32), _mm256_xor_si256(d1, p1));
|
||||
out += 64;
|
||||
} while (likely(len >= 64));
|
||||
}
|
||||
|
@ -187,7 +202,8 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
#ifdef __GNUC__
|
||||
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
|
||||
#endif
|
||||
__m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept
|
||||
__m128i
|
||||
p_init256_1_aesni(__m128i a, __m128i b) noexcept
|
||||
{
|
||||
__m128i x, y;
|
||||
b = _mm_shuffle_epi32(b, 0xff);
|
||||
|
@ -204,7 +220,8 @@ __m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept
|
|||
#ifdef __GNUC__
|
||||
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
|
||||
#endif
|
||||
__m128i p_init256_2_aesni(__m128i a, __m128i b) noexcept
|
||||
__m128i
|
||||
p_init256_2_aesni(__m128i a, __m128i b) noexcept
|
||||
{
|
||||
__m128i x, y, z;
|
||||
y = _mm_aeskeygenassist_si128(a, 0x00);
|
||||
|
@ -226,17 +243,19 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul")))
|
|||
#endif
|
||||
void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
|
||||
{
|
||||
__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i *>(_y));
|
||||
__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(_y));
|
||||
|
||||
// Handle anything left over from a previous run that wasn't a multiple of 16 bytes.
|
||||
if (_rp) {
|
||||
for (;;) {
|
||||
if (!len)
|
||||
if (! len)
|
||||
return;
|
||||
--len;
|
||||
_r[_rp++] = *(in++);
|
||||
if (_rp == 16) {
|
||||
y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i *>(_r))));
|
||||
y = p_gmacPCLMUL128(
|
||||
_aes.p_k.ni.h[0],
|
||||
_mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i*>(_r))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -252,36 +271,56 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
|
|||
const __m128i hh2 = _aes.p_k.ni.h2[1];
|
||||
const __m128i hhh2 = _aes.p_k.ni.h2[2];
|
||||
const __m128i hhhh2 = _aes.p_k.ni.h2[3];
|
||||
const uint8_t *const end64 = in + (len & ~((unsigned int)63));
|
||||
const uint8_t* const end64 = in + (len & ~((unsigned int)63));
|
||||
len &= 63U;
|
||||
do {
|
||||
__m128i d1 = _mm_shuffle_epi8(_mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i *>(in))), sb);
|
||||
__m128i d2 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 16)), sb);
|
||||
__m128i d3 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 32)), sb);
|
||||
__m128i d4 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 48)), sb);
|
||||
__m128i d1 = _mm_shuffle_epi8(_mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i*>(in))), sb);
|
||||
__m128i d2 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 16)), sb);
|
||||
__m128i d3 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 32)), sb);
|
||||
__m128i d4 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 48)), sb);
|
||||
in += 64;
|
||||
__m128i a = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x00), _mm_clmulepi64_si128(hhh, d2, 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x00), _mm_clmulepi64_si128(h, d4, 0x00)));
|
||||
__m128i b = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x11), _mm_clmulepi64_si128(hhh, d2, 0x11)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x11), _mm_clmulepi64_si128(h, d4, 0x11)));
|
||||
__m128i c = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00), _mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00), _mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))), _mm_xor_si128(a, b));
|
||||
__m128i a = _mm_xor_si128(
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x00), _mm_clmulepi64_si128(hhh, d2, 0x00)),
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x00), _mm_clmulepi64_si128(h, d4, 0x00)));
|
||||
__m128i b = _mm_xor_si128(
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x11), _mm_clmulepi64_si128(hhh, d2, 0x11)),
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x11), _mm_clmulepi64_si128(h, d4, 0x11)));
|
||||
__m128i c = _mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00),
|
||||
_mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)),
|
||||
_mm_xor_si128(
|
||||
_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00),
|
||||
_mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))),
|
||||
_mm_xor_si128(a, b));
|
||||
a = _mm_xor_si128(_mm_slli_si128(c, 8), a);
|
||||
b = _mm_xor_si128(_mm_srli_si128(c, 8), b);
|
||||
c = _mm_srli_epi32(a, 31);
|
||||
a = _mm_or_si128(_mm_slli_epi32(a, 1), _mm_slli_si128(c, 4));
|
||||
b = _mm_or_si128(_mm_or_si128(_mm_slli_epi32(b, 1), _mm_slli_si128(_mm_srli_epi32(b, 31), 4)), _mm_srli_si128(c, 12));
|
||||
b = _mm_or_si128(
|
||||
_mm_or_si128(_mm_slli_epi32(b, 1), _mm_slli_si128(_mm_srli_epi32(b, 31), 4)),
|
||||
_mm_srli_si128(c, 12));
|
||||
c = _mm_xor_si128(_mm_slli_epi32(a, 31), _mm_xor_si128(_mm_slli_epi32(a, 30), _mm_slli_epi32(a, 25)));
|
||||
a = _mm_xor_si128(a, _mm_slli_si128(c, 12));
|
||||
b = _mm_xor_si128(b, _mm_xor_si128(a, _mm_xor_si128(_mm_xor_si128(_mm_srli_epi32(a, 1), _mm_srli_si128(c, 4)), _mm_xor_si128(_mm_srli_epi32(a, 2), _mm_srli_epi32(a, 7)))));
|
||||
b = _mm_xor_si128(
|
||||
b,
|
||||
_mm_xor_si128(
|
||||
a,
|
||||
_mm_xor_si128(
|
||||
_mm_xor_si128(_mm_srli_epi32(a, 1), _mm_srli_si128(c, 4)),
|
||||
_mm_xor_si128(_mm_srli_epi32(a, 2), _mm_srli_epi32(a, 7)))));
|
||||
y = _mm_shuffle_epi8(b, sb);
|
||||
} while (likely(in != end64));
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i *>(in))));
|
||||
y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i*>(in))));
|
||||
in += 16;
|
||||
len -= 16;
|
||||
}
|
||||
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(_y), y);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(_y), y);
|
||||
|
||||
// Any overflow is cached for a later run or finish().
|
||||
for (unsigned int i = 0; i < len; ++i)
|
||||
|
@ -294,22 +333,22 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul,aes")))
|
|||
#endif
|
||||
void AES::GMAC::p_aesNIFinish(uint8_t tag[16]) noexcept
|
||||
{
|
||||
__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i *>(_y));
|
||||
__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(_y));
|
||||
|
||||
// Handle any remaining bytes, padding the last block with zeroes.
|
||||
if (_rp) {
|
||||
while (_rp < 16)
|
||||
_r[_rp++] = 0;
|
||||
y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i *>(_r))));
|
||||
y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i*>(_r))));
|
||||
}
|
||||
|
||||
// Interleave encryption of IV with the final GHASH of y XOR (length * 8).
|
||||
// Then XOR these together to get the final tag.
|
||||
const __m128i *const k = _aes.p_k.ni.k;
|
||||
const __m128i* const k = _aes.p_k.ni.k;
|
||||
const __m128i h = _aes.p_k.ni.h[0];
|
||||
y = _mm_xor_si128(y, _mm_set_epi64x(0LL, (long long)Utils::hton((uint64_t)_len << 3U)));
|
||||
y = _mm_shuffle_epi8(y, s_sseSwapBytes);
|
||||
__m128i encIV = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast<const __m128i *>(_iv)), k[0]);
|
||||
__m128i encIV = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast<const __m128i*>(_iv)), k[0]);
|
||||
__m128i t1 = _mm_clmulepi64_si128(h, y, 0x00);
|
||||
__m128i t2 = _mm_clmulepi64_si128(h, y, 0x01);
|
||||
__m128i t3 = _mm_clmulepi64_si128(h, y, 0x10);
|
||||
|
@ -359,7 +398,7 @@ void AES::GMAC::p_aesNIFinish(uint8_t tag[16]) noexcept
|
|||
t4 = _mm_xor_si128(t4, t3);
|
||||
encIV = _mm_aesenclast_si128(encIV, k[14]);
|
||||
t4 = _mm_xor_si128(t4, t5);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(tag), _mm_xor_si128(_mm_shuffle_epi8(t4, s_sseSwapBytes), encIV));
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(tag), _mm_xor_si128(_mm_shuffle_epi8(t4, s_sseSwapBytes), encIV));
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -370,7 +409,7 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
const __m128i dd = _mm_set_epi64x(0, (long long)_ctr[0]);
|
||||
uint64_t c1 = Utils::ntoh(_ctr[1]);
|
||||
|
||||
const __m128i *const k = _aes.p_k.ni.k;
|
||||
const __m128i* const k = _aes.p_k.ni.k;
|
||||
const __m128i k0 = k[0];
|
||||
const __m128i k1 = k[1];
|
||||
const __m128i k2 = k[2];
|
||||
|
@ -391,14 +430,14 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
unsigned int totalLen = _len;
|
||||
if ((totalLen & 15U)) {
|
||||
for (;;) {
|
||||
if (unlikely(!len)) {
|
||||
if (unlikely(! len)) {
|
||||
_ctr[1] = Utils::hton(c1);
|
||||
_len = totalLen;
|
||||
return;
|
||||
}
|
||||
--len;
|
||||
out[totalLen++] = *(in++);
|
||||
if (!(totalLen & 15U)) {
|
||||
if (! (totalLen & 15U)) {
|
||||
__m128i d0 = _mm_insert_epi64(dd, (long long)Utils::hton(c1++), 1);
|
||||
d0 = _mm_xor_si128(d0, k0);
|
||||
d0 = _mm_aesenc_si128(d0, k1);
|
||||
|
@ -411,7 +450,7 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
d0 = _mm_aesenc_si128(d0, k8);
|
||||
d0 = _mm_aesenc_si128(d0, k9);
|
||||
d0 = _mm_aesenc_si128(d0, k10);
|
||||
__m128i *const outblk = reinterpret_cast<__m128i *>(out + (totalLen - 16));
|
||||
__m128i* const outblk = reinterpret_cast<__m128i*>(out + (totalLen - 16));
|
||||
d0 = _mm_aesenc_si128(d0, k11);
|
||||
const __m128i p0 = _mm_loadu_si128(outblk);
|
||||
d0 = _mm_aesenc_si128(d0, k12);
|
||||
|
@ -427,26 +466,26 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
_len = totalLen + len;
|
||||
|
||||
if (likely(len >= 64)) {
|
||||
|
||||
#if defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
|
||||
if (Utils::CPUID.vaes) {
|
||||
if (Utils::CPUID.avx512f) {
|
||||
p_aesCtrInnerVAES512(len, _ctr[0], c1, in, out, k);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p_aesCtrInnerVAES256(len, _ctr[0], c1, in, out, k);
|
||||
}
|
||||
goto skip_conventional_aesni_64;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
|
||||
#if ! defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
|
||||
if (Utils::CPUID.vaes && (len >= 256)) {
|
||||
p_aesCtrInnerVAES256(len, _ctr[0], c1, in, out, k);
|
||||
goto skip_conventional_aesni_64;
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint8_t *const eof64 = in + (len & ~((unsigned int)63));
|
||||
const uint8_t* const eof64 = in + (len & ~((unsigned int)63));
|
||||
len &= 63;
|
||||
__m128i d0, d1, d2, d3;
|
||||
do {
|
||||
|
@ -515,21 +554,26 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
d1 = _mm_aesenc_si128(d1, k13);
|
||||
d2 = _mm_aesenc_si128(d2, k13);
|
||||
d3 = _mm_aesenc_si128(d3, k13);
|
||||
d0 = _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in)));
|
||||
d1 = _mm_xor_si128(_mm_aesenclast_si128(d1, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 16)));
|
||||
d2 = _mm_xor_si128(_mm_aesenclast_si128(d2, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 32)));
|
||||
d3 = _mm_xor_si128(_mm_aesenclast_si128(d3, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 48)));
|
||||
d0 = _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in)));
|
||||
d1 = _mm_xor_si128(
|
||||
_mm_aesenclast_si128(d1, k14),
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 16)));
|
||||
d2 = _mm_xor_si128(
|
||||
_mm_aesenclast_si128(d2, k14),
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 32)));
|
||||
d3 = _mm_xor_si128(
|
||||
_mm_aesenclast_si128(d3, k14),
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 48)));
|
||||
in += 64;
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(out), d0);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(out + 16), d1);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(out + 32), d2);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(out + 48), d3);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(out), d0);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 16), d1);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 32), d2);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 48), d3);
|
||||
out += 64;
|
||||
} while (likely(in != eof64));
|
||||
|
||||
}
|
||||
|
||||
skip_conventional_aesni_64:
|
||||
skip_conventional_aesni_64:
|
||||
while (len >= 16) {
|
||||
__m128i d0 = _mm_insert_epi64(dd, (long long)Utils::hton(c1++), 1);
|
||||
d0 = _mm_xor_si128(d0, k0);
|
||||
|
@ -546,7 +590,9 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
d0 = _mm_aesenc_si128(d0, k11);
|
||||
d0 = _mm_aesenc_si128(d0, k12);
|
||||
d0 = _mm_aesenc_si128(d0, k13);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(out), _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in))));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(out),
|
||||
_mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in))));
|
||||
in += 16;
|
||||
len -= 16;
|
||||
out += 16;
|
||||
|
@ -567,8 +613,8 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
|
|||
void AES::p_init_aesni(const uint8_t *key) noexcept
|
||||
{
|
||||
__m128i t1, t2, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13;
|
||||
p_k.ni.k[0] = t1 = _mm_loadu_si128((const __m128i *)key);
|
||||
p_k.ni.k[1] = k1 = t2 = _mm_loadu_si128((const __m128i *)(key + 16));
|
||||
p_k.ni.k[0] = t1 = _mm_loadu_si128((const __m128i*)key);
|
||||
p_k.ni.k[1] = k1 = t2 = _mm_loadu_si128((const __m128i*)(key + 16));
|
||||
p_k.ni.k[2] = k2 = t1 = p_init256_1_aesni(t1, _mm_aeskeygenassist_si128(t2, 0x01));
|
||||
p_k.ni.k[3] = k3 = t2 = p_init256_2_aesni(t1, t2);
|
||||
p_k.ni.k[4] = k4 = t1 = p_init256_1_aesni(t1, _mm_aeskeygenassist_si128(t2, 0x02));
|
||||
|
@ -630,7 +676,7 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
|
|||
#endif
|
||||
void AES::p_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, p_k.ni.k[0]);
|
||||
tmp = _mm_aesenc_si128(tmp, p_k.ni.k[1]);
|
||||
tmp = _mm_aesenc_si128(tmp, p_k.ni.k[2]);
|
||||
|
@ -645,7 +691,7 @@ void AES::p_encrypt_aesni(const void *const in, void *const out) const noexcept
|
|||
tmp = _mm_aesenc_si128(tmp, p_k.ni.k[11]);
|
||||
tmp = _mm_aesenc_si128(tmp, p_k.ni.k[12]);
|
||||
tmp = _mm_aesenc_si128(tmp, p_k.ni.k[13]);
|
||||
_mm_storeu_si128((__m128i *)out, _mm_aesenclast_si128(tmp, p_k.ni.k[14]));
|
||||
_mm_storeu_si128((__m128i*)out, _mm_aesenclast_si128(tmp, p_k.ni.k[14]));
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -653,7 +699,7 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
|
|||
#endif
|
||||
void AES::p_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, p_k.ni.k[14]);
|
||||
tmp = _mm_aesdec_si128(tmp, p_k.ni.k[15]);
|
||||
tmp = _mm_aesdec_si128(tmp, p_k.ni.k[16]);
|
||||
|
@ -668,7 +714,7 @@ void AES::p_decrypt_aesni(const void *in, void *out) const noexcept
|
|||
tmp = _mm_aesdec_si128(tmp, p_k.ni.k[25]);
|
||||
tmp = _mm_aesdec_si128(tmp, p_k.ni.k[26]);
|
||||
tmp = _mm_aesdec_si128(tmp, p_k.ni.k[27]);
|
||||
_mm_storeu_si128((__m128i *)out, _mm_aesdeclast_si128(tmp, p_k.ni.k[0]));
|
||||
_mm_storeu_si128((__m128i*)out, _mm_aesdeclast_si128(tmp, p_k.ni.k[0]));
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
|
||||
// AES for ARM crypto extensions and NEON.
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
#ifdef ZT_AES_NEON
|
||||
|
||||
|
@ -31,34 +31,34 @@ ZT_INLINE uint8x16_t s_clmul_armneon_crypto(uint8x16_t h, uint8x16_t y, const ui
|
|||
y = vrbitq_u8(y);
|
||||
const uint8x16_t p = vreinterpretq_u8_u64(vdupq_n_u64(0x0000000000000087));
|
||||
t0 = vextq_u8(y, y, 8);
|
||||
__asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t" : "=w" (r0) : "w" (h), "w" (y));
|
||||
__asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t" :"=w" (r1) : "w" (h), "w" (y));
|
||||
__asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t" : "=w" (t1) : "w" (h), "w" (t0));
|
||||
__asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t" :"=w" (t0) : "w" (h), "w" (t0));
|
||||
__asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t" : "=w"(r0) : "w"(h), "w"(y));
|
||||
__asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t" : "=w"(r1) : "w"(h), "w"(y));
|
||||
__asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t" : "=w"(t1) : "w"(h), "w"(t0));
|
||||
__asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t" : "=w"(t0) : "w"(h), "w"(t0));
|
||||
t0 = veorq_u8(t0, t1);
|
||||
t1 = vextq_u8(z, t0, 8);
|
||||
r0 = veorq_u8(r0, t1);
|
||||
t1 = vextq_u8(t0, z, 8);
|
||||
r1 = veorq_u8(r1, t1);
|
||||
__asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t" :"=w" (t0) : "w" (r1), "w" (p));
|
||||
__asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t" : "=w"(t0) : "w"(r1), "w"(p));
|
||||
t1 = vextq_u8(t0, z, 8);
|
||||
r1 = veorq_u8(r1, t1);
|
||||
t1 = vextq_u8(z, t0, 8);
|
||||
r0 = veorq_u8(r0, t1);
|
||||
__asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t" : "=w" (t0) : "w" (r1), "w" (p));
|
||||
__asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t" : "=w"(t0) : "w"(r1), "w"(p));
|
||||
return vrbitq_u8(veorq_u8(r0, t0));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void AES::GMAC::p_armUpdate(const uint8_t *in, unsigned int len) noexcept
|
||||
void AES::GMAC::p_armUpdate(const uint8_t* in, unsigned int len) noexcept
|
||||
{
|
||||
uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t *>(_y));
|
||||
uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t*>(_y));
|
||||
const uint8x16_t h = _aes.p_k.neon.h;
|
||||
|
||||
if (_rp) {
|
||||
for(;;) {
|
||||
if (!len)
|
||||
for (;;) {
|
||||
if (! len)
|
||||
return;
|
||||
--len;
|
||||
_r[_rp++] = *(in++);
|
||||
|
@ -75,7 +75,7 @@ void AES::GMAC::p_armUpdate(const uint8_t *in, unsigned int len) noexcept
|
|||
len -= 16;
|
||||
}
|
||||
|
||||
vst1q_u8(reinterpret_cast<uint8_t *>(_y), y);
|
||||
vst1q_u8(reinterpret_cast<uint8_t*>(_y), y);
|
||||
|
||||
for (unsigned int i = 0; i < len; ++i)
|
||||
_r[i] = in[i];
|
||||
|
@ -85,7 +85,7 @@ void AES::GMAC::p_armUpdate(const uint8_t *in, unsigned int len) noexcept
|
|||
void AES::GMAC::p_armFinish(uint8_t tag[16]) noexcept
|
||||
{
|
||||
uint64_t tmp[2];
|
||||
uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t *>(_y));
|
||||
uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t*>(_y));
|
||||
const uint8x16_t h = _aes.p_k.neon.h;
|
||||
|
||||
if (_rp) {
|
||||
|
@ -96,25 +96,25 @@ void AES::GMAC::p_armFinish(uint8_t tag[16]) noexcept
|
|||
|
||||
tmp[0] = Utils::hton((uint64_t)_len << 3U);
|
||||
tmp[1] = 0;
|
||||
y = s_clmul_armneon_crypto(h, y, reinterpret_cast<const uint8_t *>(tmp));
|
||||
y = s_clmul_armneon_crypto(h, y, reinterpret_cast<const uint8_t*>(tmp));
|
||||
|
||||
Utils::copy< 12 >(tmp, _iv);
|
||||
Utils::copy<12>(tmp, _iv);
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
reinterpret_cast<uint32_t *>(tmp)[3] = 0x00000001;
|
||||
reinterpret_cast<uint32_t*>(tmp)[3] = 0x00000001;
|
||||
#else
|
||||
reinterpret_cast<uint32_t *>(tmp)[3] = 0x01000000;
|
||||
reinterpret_cast<uint32_t*>(tmp)[3] = 0x01000000;
|
||||
#endif
|
||||
_aes.encrypt(tmp, tmp);
|
||||
|
||||
uint8x16_t yy = y;
|
||||
Utils::storeMachineEndian< uint64_t >(tag, tmp[0] ^ reinterpret_cast<const uint64_t *>(&yy)[0]);
|
||||
Utils::storeMachineEndian< uint64_t >(tag + 8, tmp[1] ^ reinterpret_cast<const uint64_t *>(&yy)[1]);
|
||||
Utils::storeMachineEndian<uint64_t>(tag, tmp[0] ^ reinterpret_cast<const uint64_t*>(&yy)[0]);
|
||||
Utils::storeMachineEndian<uint64_t>(tag + 8, tmp[1] ^ reinterpret_cast<const uint64_t*>(&yy)[1]);
|
||||
}
|
||||
|
||||
void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noexcept
|
||||
void AES::CTR::p_armCrypt(const uint8_t* in, uint8_t* out, unsigned int len) noexcept
|
||||
{
|
||||
uint8x16_t dd = vrev32q_u8(vld1q_u8(reinterpret_cast<uint8_t *>(_ctr)));
|
||||
const uint32x4_t one = {0,0,0,1};
|
||||
uint8x16_t dd = vrev32q_u8(vld1q_u8(reinterpret_cast<uint8_t*>(_ctr)));
|
||||
const uint32x4_t one = { 0, 0, 0, 1 };
|
||||
|
||||
uint8x16_t k0 = _aes.p_k.neon.ek[0];
|
||||
uint8x16_t k1 = _aes.p_k.neon.ek[1];
|
||||
|
@ -135,15 +135,15 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
|
|||
unsigned int totalLen = _len;
|
||||
if ((totalLen & 15U) != 0) {
|
||||
for (;;) {
|
||||
if (unlikely(!len)) {
|
||||
vst1q_u8(reinterpret_cast<uint8_t *>(_ctr), vrev32q_u8(dd));
|
||||
if (unlikely(! len)) {
|
||||
vst1q_u8(reinterpret_cast<uint8_t*>(_ctr), vrev32q_u8(dd));
|
||||
_len = totalLen;
|
||||
return;
|
||||
}
|
||||
--len;
|
||||
out[totalLen++] = *(in++);
|
||||
if ((totalLen & 15U) == 0) {
|
||||
uint8_t *const otmp = out + (totalLen - 16);
|
||||
uint8_t* const otmp = out + (totalLen - 16);
|
||||
uint8x16_t d0 = vrev32q_u8(dd);
|
||||
uint8x16_t pt = vld1q_u8(otmp);
|
||||
d0 = vaesmcq_u8(vaeseq_u8(d0, k0));
|
||||
|
@ -295,45 +295,65 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
|
|||
for (unsigned int i = 0; i < len; ++i)
|
||||
out[i] = in[i];
|
||||
|
||||
vst1q_u8(reinterpret_cast<uint8_t *>(_ctr), vrev32q_u8(dd));
|
||||
vst1q_u8(reinterpret_cast<uint8_t*>(_ctr), vrev32q_u8(dd));
|
||||
}
|
||||
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_SUBWORD(w) ((uint32_t)s_sbox[w & 0xffU] + ((uint32_t)s_sbox[(w >> 8U) & 0xffU] << 8U) + ((uint32_t)s_sbox[(w >> 16U) & 0xffU] << 16U) + ((uint32_t)s_sbox[(w >> 24U) & 0xffU] << 24U))
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_SUBWORD(w) \
|
||||
((uint32_t)s_sbox[w & 0xffU] + ((uint32_t)s_sbox[(w >> 8U) & 0xffU] << 8U) \
|
||||
+ ((uint32_t)s_sbox[(w >> 16U) & 0xffU] << 16U) + ((uint32_t)s_sbox[(w >> 24U) & 0xffU] << 24U))
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_ROTWORD(w) (((w) << 8U) | ((w) >> 24U))
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_NK 8
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_NB 4
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_NR 14
|
||||
|
||||
void AES::p_init_armneon_crypto(const uint8_t *key) noexcept
|
||||
void AES::p_init_armneon_crypto(const uint8_t* key) noexcept
|
||||
{
|
||||
static const uint8_t s_sbox[256] = {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c,
|
||||
0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea,
|
||||
0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
|
||||
static const uint8_t s_sbox[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82,
|
||||
0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96,
|
||||
0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb,
|
||||
0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff,
|
||||
0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32,
|
||||
0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
|
||||
0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e,
|
||||
0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
||||
0xb0, 0x54, 0xbb, 0x16
|
||||
};
|
||||
|
||||
uint64_t h[2];
|
||||
uint32_t *const w = reinterpret_cast<uint32_t *>(p_k.neon.ek);
|
||||
uint32_t* const w = reinterpret_cast<uint32_t*>(p_k.neon.ek);
|
||||
|
||||
for (unsigned int i=0;i<ZT_INIT_ARMNEON_CRYPTO_NK;++i) {
|
||||
for (unsigned int i = 0; i < ZT_INIT_ARMNEON_CRYPTO_NK; ++i) {
|
||||
const unsigned int j = i * 4;
|
||||
w[i] = ((uint32_t)key[j] << 24U) | ((uint32_t)key[j + 1] << 16U) | ((uint32_t)key[j + 2] << 8U) | (uint32_t)key[j + 3];
|
||||
w[i] = ((uint32_t)key[j] << 24U) | ((uint32_t)key[j + 1] << 16U) | ((uint32_t)key[j + 2] << 8U)
|
||||
| (uint32_t)key[j + 3];
|
||||
}
|
||||
|
||||
for (unsigned int i=ZT_INIT_ARMNEON_CRYPTO_NK;i<(ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));++i) {
|
||||
for (unsigned int i = ZT_INIT_ARMNEON_CRYPTO_NK; i < (ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));
|
||||
++i) {
|
||||
uint32_t t = w[i - 1];
|
||||
const unsigned int imod = i & (ZT_INIT_ARMNEON_CRYPTO_NK - 1);
|
||||
if (imod == 0) {
|
||||
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(ZT_INIT_ARMNEON_CRYPTO_ROTWORD(t)) ^ rcon[(i - 1) / ZT_INIT_ARMNEON_CRYPTO_NK];
|
||||
} else if (imod == 4) {
|
||||
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(ZT_INIT_ARMNEON_CRYPTO_ROTWORD(t))
|
||||
^ rcon[(i - 1) / ZT_INIT_ARMNEON_CRYPTO_NK];
|
||||
}
|
||||
else if (imod == 4) {
|
||||
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(t);
|
||||
}
|
||||
w[i] = w[i - ZT_INIT_ARMNEON_CRYPTO_NK] ^ t;
|
||||
}
|
||||
|
||||
for (unsigned int i=0;i<(ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));++i)
|
||||
for (unsigned int i = 0; i < (ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1)); ++i)
|
||||
w[i] = Utils::hton(w[i]);
|
||||
|
||||
p_k.neon.dk[0] = p_k.neon.ek[14];
|
||||
for (int i=1;i<14;++i)
|
||||
for (int i = 1; i < 14; ++i)
|
||||
p_k.neon.dk[i] = vaesimcq_u8(p_k.neon.ek[14 - i]);
|
||||
p_k.neon.dk[14] = p_k.neon.ek[0];
|
||||
|
||||
|
@ -344,9 +364,9 @@ void AES::p_init_armneon_crypto(const uint8_t *key) noexcept
|
|||
p_k.sw.h[1] = Utils::ntoh(h[1]);
|
||||
}
|
||||
|
||||
void AES::p_encrypt_armneon_crypto(const void *const in, void *const out) const noexcept
|
||||
void AES::p_encrypt_armneon_crypto(const void* const in, void* const out) const noexcept
|
||||
{
|
||||
uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t *>(in));
|
||||
uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t*>(in));
|
||||
tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[0]));
|
||||
tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[1]));
|
||||
tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[2]));
|
||||
|
@ -361,12 +381,12 @@ void AES::p_encrypt_armneon_crypto(const void *const in, void *const out) const
|
|||
tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[11]));
|
||||
tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[12]));
|
||||
tmp = veorq_u8(vaeseq_u8(tmp, p_k.neon.ek[13]), p_k.neon.ek[14]);
|
||||
vst1q_u8(reinterpret_cast<uint8_t *>(out), tmp);
|
||||
vst1q_u8(reinterpret_cast<uint8_t*>(out), tmp);
|
||||
}
|
||||
|
||||
void AES::p_decrypt_armneon_crypto(const void *const in, void *const out) const noexcept
|
||||
void AES::p_decrypt_armneon_crypto(const void* const in, void* const out) const noexcept
|
||||
{
|
||||
uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t *>(in));
|
||||
uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t*>(in));
|
||||
tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[0]));
|
||||
tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[1]));
|
||||
tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[2]));
|
||||
|
@ -381,7 +401,7 @@ void AES::p_decrypt_armneon_crypto(const void *const in, void *const out) const
|
|||
tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[11]));
|
||||
tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[12]));
|
||||
tmp = veorq_u8(vaesdq_u8(tmp, p_k.neon.dk[13]), p_k.neon.dk[14]);
|
||||
vst1q_u8(reinterpret_cast<uint8_t *>(out), tmp);
|
||||
vst1q_u8(reinterpret_cast<uint8_t*>(out), tmp);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
150
core/Address.hpp
150
core/Address.hpp
|
@ -15,9 +15,9 @@
|
|||
#define ZT_ADDRESS_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_ADDRESS_STRING_SIZE_MAX (ZT_ADDRESS_LENGTH_HEX + 1)
|
||||
|
||||
|
@ -28,28 +28,37 @@ namespace ZeroTier {
|
|||
*
|
||||
* This is merely a 40-bit short address packed into a uint64_t and wrapped with methods.
|
||||
*/
|
||||
class Address : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
ZT_INLINE Address() noexcept: _a(0)
|
||||
{}
|
||||
class Address : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE Address() noexcept : _a(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Address(const uint64_t a) noexcept: _a(a)
|
||||
{}
|
||||
ZT_INLINE Address(const uint64_t a) noexcept : _a(a)
|
||||
{
|
||||
}
|
||||
|
||||
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])
|
||||
{}
|
||||
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])
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Address &operator=(const uint64_t a) noexcept
|
||||
{ _a = a; return *this; }
|
||||
ZT_INLINE Address& operator=(const uint64_t a) noexcept
|
||||
{
|
||||
_a = a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits Raw address -- 5 bytes, big-endian byte order
|
||||
* @param len Length of array
|
||||
*/
|
||||
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];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits Buffer to hold 5-byte address in big-endian byte order
|
||||
|
@ -69,19 +78,23 @@ public:
|
|||
* @return Integer containing address (0 to 2^40)
|
||||
*/
|
||||
ZT_INLINE uint64_t toInt() const noexcept
|
||||
{ return _a; }
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set address to zero/NIL
|
||||
*/
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ _a = 0; }
|
||||
{
|
||||
_a = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s String with at least 11 characters of space available (10 + terminating NULL)
|
||||
* @return Hexadecimal string
|
||||
*/
|
||||
ZT_INLINE char *toString(char s[ZT_ADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||
ZT_INLINE char* toString(char s[ZT_ADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
const uint64_t a = _a;
|
||||
const unsigned int m = 0xf;
|
||||
|
@ -116,47 +129,90 @@ public:
|
|||
* @return True if address is reserved and may not be used
|
||||
*/
|
||||
ZT_INLINE bool isReserved() const noexcept
|
||||
{ return ((!_a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); }
|
||||
{
|
||||
return ((! _a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX));
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)_a; }
|
||||
{
|
||||
return (unsigned long)_a;
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (_a != 0); }
|
||||
{
|
||||
return (_a != 0);
|
||||
}
|
||||
|
||||
ZT_INLINE operator uint64_t() const noexcept
|
||||
{ return _a; }
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Address& a) const noexcept
|
||||
{
|
||||
return _a == a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Address& a) const noexcept
|
||||
{
|
||||
return _a != a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Address& a) const noexcept
|
||||
{
|
||||
return _a > a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Address& a) const noexcept
|
||||
{
|
||||
return _a < a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Address& a) const noexcept
|
||||
{
|
||||
return _a >= a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Address& a) const noexcept
|
||||
{
|
||||
return _a <= a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Address &a) const noexcept
|
||||
{ return _a == a._a; }
|
||||
ZT_INLINE bool operator!=(const Address &a) const noexcept
|
||||
{ return _a != a._a; }
|
||||
ZT_INLINE bool operator>(const Address &a) const noexcept
|
||||
{ return _a > a._a; }
|
||||
ZT_INLINE bool operator<(const Address &a) const noexcept
|
||||
{ return _a < a._a; }
|
||||
ZT_INLINE bool operator>=(const Address &a) const noexcept
|
||||
{ return _a >= a._a; }
|
||||
ZT_INLINE bool operator<=(const Address &a) const noexcept
|
||||
{ return _a <= a._a; }
|
||||
ZT_INLINE bool operator==(const uint64_t a) const noexcept
|
||||
{ return _a == a; }
|
||||
ZT_INLINE bool operator!=(const uint64_t a) const noexcept
|
||||
{ return _a != a; }
|
||||
ZT_INLINE bool operator>(const uint64_t a) const noexcept
|
||||
{ return _a > a; }
|
||||
ZT_INLINE bool operator<(const uint64_t a) const noexcept
|
||||
{ return _a < a; }
|
||||
ZT_INLINE bool operator>=(const uint64_t a) const noexcept
|
||||
{ return _a >= a; }
|
||||
ZT_INLINE bool operator<=(const uint64_t a) const noexcept
|
||||
{ return _a <= a; }
|
||||
{
|
||||
return _a == a;
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE bool operator!=(const uint64_t a) const noexcept
|
||||
{
|
||||
return _a != a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const uint64_t a) const noexcept
|
||||
{
|
||||
return _a > a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const uint64_t a) const noexcept
|
||||
{
|
||||
return _a < a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const uint64_t a) const noexcept
|
||||
{
|
||||
return _a >= a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const uint64_t a) const noexcept
|
||||
{
|
||||
return _a <= a;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t _a;
|
||||
};
|
||||
|
||||
static_assert(sizeof(Address) == sizeof(uint64_t),"Address has unnecessary extra padding");
|
||||
static_assert(sizeof(Address) == sizeof(uint64_t), "Address has unnecessary extra padding");
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
35
core/Buf.cpp
35
core/Buf.cpp
|
@ -12,56 +12,59 @@
|
|||
/****/
|
||||
|
||||
#include "Buf.hpp"
|
||||
|
||||
#include "Spinlock.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
static std::atomic< uintptr_t > s_pool(0);
|
||||
static std::atomic< long > s_allocated(0);
|
||||
static std::atomic<uintptr_t> s_pool(0);
|
||||
static std::atomic<long> s_allocated(0);
|
||||
|
||||
// uintptr_max can never be a valid pointer, so use it to indicate that s_pool is locked (very short duration spinlock)
|
||||
#define ZT_ATOMIC_PTR_LOCKED (~((uintptr_t)0))
|
||||
|
||||
void *Buf::operator new(std::size_t sz)
|
||||
void* Buf::operator new(std::size_t sz)
|
||||
{
|
||||
uintptr_t bb;
|
||||
for (;;) {
|
||||
bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire);
|
||||
|
||||
if (likely(bb != ZT_ATOMIC_PTR_LOCKED)) {
|
||||
Buf *b;
|
||||
Buf* b;
|
||||
if (likely(bb != 0)) {
|
||||
b = reinterpret_cast<Buf *>(bb);
|
||||
b = reinterpret_cast<Buf*>(bb);
|
||||
s_pool.store(b->__nextInPool, std::memory_order_release);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
s_pool.store(0, std::memory_order_release);
|
||||
b = reinterpret_cast<Buf *>(malloc(sz));
|
||||
if (!b)
|
||||
b = reinterpret_cast<Buf*>(malloc(sz));
|
||||
if (! b)
|
||||
throw Utils::BadAllocException;
|
||||
s_allocated.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
b->__refCount.store(0, std::memory_order_relaxed);
|
||||
|
||||
return reinterpret_cast<void *>(b);
|
||||
return reinterpret_cast<void*>(b);
|
||||
}
|
||||
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
|
||||
void Buf::operator delete(void *ptr)
|
||||
void Buf::operator delete(void* ptr)
|
||||
{
|
||||
if (likely(ptr != nullptr)) {
|
||||
if (s_allocated.load(std::memory_order_relaxed) > ZT_BUF_MAX_POOL_SIZE) {
|
||||
s_allocated.fetch_sub(1, std::memory_order_relaxed);
|
||||
free(ptr);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uintptr_t bb;
|
||||
for (;;) {
|
||||
bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire);
|
||||
if (likely(bb != ZT_ATOMIC_PTR_LOCKED)) {
|
||||
reinterpret_cast<Buf *>(ptr)->__nextInPool = bb;
|
||||
reinterpret_cast<Buf*>(ptr)->__nextInPool = bb;
|
||||
s_pool.store(reinterpret_cast<uintptr_t>(ptr), std::memory_order_release);
|
||||
return;
|
||||
}
|
||||
|
@ -81,9 +84,9 @@ void Buf::freePool() noexcept
|
|||
s_pool.store(0, std::memory_order_release);
|
||||
|
||||
while (bb != 0) {
|
||||
const uintptr_t next = reinterpret_cast<Buf *>(bb)->__nextInPool;
|
||||
const uintptr_t next = reinterpret_cast<Buf*>(bb)->__nextInPool;
|
||||
s_allocated.fetch_sub(1, std::memory_order_relaxed);
|
||||
free(reinterpret_cast<void *>(bb));
|
||||
free(reinterpret_cast<void*>(bb));
|
||||
bb = next;
|
||||
}
|
||||
|
||||
|
@ -95,6 +98,8 @@ void Buf::freePool() noexcept
|
|||
}
|
||||
|
||||
long Buf::poolAllocated() noexcept
|
||||
{ return s_allocated.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return s_allocated.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
274
core/Buf.hpp
274
core/Buf.hpp
|
@ -15,16 +15,16 @@
|
|||
#define ZT_BUF_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
// Buffers are 16384 bytes in size because this is the smallest size that can hold any packet
|
||||
// and is a power of two. It needs to be a power of two because masking is significantly faster
|
||||
|
@ -77,15 +77,14 @@ namespace ZeroTier {
|
|||
*
|
||||
* @tparam U Type to overlap with data bytes in data union (can't be larger than ZT_BUF_MEM_SIZE)
|
||||
*/
|
||||
class Buf
|
||||
{
|
||||
friend class SharedPtr< Buf >;
|
||||
class Buf {
|
||||
friend class SharedPtr<Buf>;
|
||||
|
||||
public:
|
||||
public:
|
||||
// New and delete operators that allocate Buf instances from a shared lock-free memory pool.
|
||||
static void *operator new(std::size_t sz);
|
||||
static void* operator new(std::size_t sz);
|
||||
|
||||
static void operator delete(void *ptr);
|
||||
static void operator delete(void* ptr);
|
||||
|
||||
/**
|
||||
* Raw data held in buffer
|
||||
|
@ -113,19 +112,30 @@ public:
|
|||
/**
|
||||
* Slice is almost exactly like the built-in slice data structure in Go
|
||||
*/
|
||||
struct Slice : TriviallyCopyable
|
||||
struct Slice : TriviallyCopyable {
|
||||
ZT_INLINE Slice(const SharedPtr<Buf>& b_, const unsigned int s_, const unsigned int e_) noexcept
|
||||
: b(b_)
|
||||
, s(s_)
|
||||
, e(e_)
|
||||
{
|
||||
ZT_INLINE Slice(const SharedPtr< Buf > &b_, const unsigned int s_, const unsigned int e_) noexcept: b(b_), s(s_), e(e_)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE Slice() noexcept: b(), s(0), e(0)
|
||||
{}
|
||||
ZT_INLINE Slice() noexcept
|
||||
: b()
|
||||
, s(0)
|
||||
, e(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (b); }
|
||||
{
|
||||
return (b);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return (e - s); }
|
||||
{
|
||||
return (e - s);
|
||||
}
|
||||
|
||||
ZT_INLINE void zero() noexcept
|
||||
{
|
||||
|
@ -137,7 +147,7 @@ public:
|
|||
/**
|
||||
* Buffer holding slice data
|
||||
*/
|
||||
SharedPtr< Buf > b;
|
||||
SharedPtr<Buf> b;
|
||||
|
||||
/**
|
||||
* Index of start of data in slice
|
||||
|
@ -153,11 +163,11 @@ public:
|
|||
/**
|
||||
* A vector of slices making up a packet that might span more than one buffer.
|
||||
*/
|
||||
class PacketVector : public ZeroTier::FCV< Slice, ZT_MAX_PACKET_FRAGMENTS >
|
||||
{
|
||||
class PacketVector : public ZeroTier::FCV<Slice, ZT_MAX_PACKET_FRAGMENTS> {
|
||||
public:
|
||||
ZT_INLINE PacketVector() : ZeroTier::FCV< Slice, ZT_MAX_PACKET_FRAGMENTS >()
|
||||
{}
|
||||
ZT_INLINE PacketVector() : ZeroTier::FCV<Slice, ZT_MAX_PACKET_FRAGMENTS>()
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int totalSize() const noexcept
|
||||
{
|
||||
|
@ -173,7 +183,7 @@ public:
|
|||
* @param b Destination buffer
|
||||
* @return Size of data in destination or -1 on error
|
||||
*/
|
||||
ZT_INLINE int mergeCopy(Buf &b) const noexcept
|
||||
ZT_INLINE int mergeCopy(Buf& b) const noexcept
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (PacketVector::const_iterator s(begin()); s != end(); ++s) {
|
||||
|
@ -182,7 +192,8 @@ public:
|
|||
if (likely((size + rem) <= ZT_BUF_MEM_SIZE)) {
|
||||
Utils::copy(b.unsafeData + size, s->b->unsafeData + start, rem);
|
||||
size += rem;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -200,8 +211,8 @@ public:
|
|||
* @tparam F Type of copyFunction (typically inferred)
|
||||
* @return Size of data in destination or -1 on error
|
||||
*/
|
||||
template< typename F >
|
||||
ZT_INLINE int mergeMap(Buf &b, const unsigned int simpleCopyBefore, F copyFunction) const noexcept
|
||||
template <typename F>
|
||||
ZT_INLINE int mergeMap(Buf& b, const unsigned int simpleCopyBefore, F copyFunction) const noexcept
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (PacketVector::const_iterator s(begin()); s != end(); ++s) {
|
||||
|
@ -221,7 +232,8 @@ public:
|
|||
copyFunction(b.unsafeData + size, s->b->unsafeData + start, rem);
|
||||
size += rem;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -232,29 +244,31 @@ public:
|
|||
/**
|
||||
* Create a new uninitialized buffer with undefined contents (use clear() to zero if needed)
|
||||
*/
|
||||
ZT_INLINE Buf() noexcept: __nextInPool(0), __refCount(0)
|
||||
{}
|
||||
ZT_INLINE Buf() noexcept
|
||||
: __nextInPool(0)
|
||||
, __refCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new buffer and copy data into it
|
||||
*/
|
||||
ZT_INLINE Buf(const void *const data, const unsigned int len) noexcept:
|
||||
__refCount(0)
|
||||
ZT_INLINE Buf(const void* const data, const unsigned int len) noexcept : __refCount(0)
|
||||
{
|
||||
Utils::copy(unsafeData, data, len);
|
||||
}
|
||||
|
||||
ZT_INLINE Buf(const Buf &b2) noexcept:
|
||||
__nextInPool(0),
|
||||
__refCount(0)
|
||||
ZT_INLINE Buf(const Buf& b2) noexcept
|
||||
: __nextInPool(0)
|
||||
, __refCount(0)
|
||||
{
|
||||
Utils::copy< ZT_BUF_MEM_SIZE >(unsafeData, b2.unsafeData);
|
||||
Utils::copy<ZT_BUF_MEM_SIZE>(unsafeData, b2.unsafeData);
|
||||
}
|
||||
|
||||
ZT_INLINE Buf &operator=(const Buf &b2) noexcept
|
||||
ZT_INLINE Buf& operator=(const Buf& b2) noexcept
|
||||
{
|
||||
if (this != &b2)
|
||||
Utils::copy< ZT_BUF_MEM_SIZE >(unsafeData, b2.unsafeData);
|
||||
Utils::copy<ZT_BUF_MEM_SIZE>(unsafeData, b2.unsafeData);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -267,8 +281,10 @@ public:
|
|||
* @param ii Iterator to check
|
||||
* @return True if iterator has read past the size of the buffer
|
||||
*/
|
||||
static ZT_INLINE bool writeOverflow(const int &ii) noexcept
|
||||
{ return ((ii - ZT_BUF_MEM_SIZE) > 0); }
|
||||
static ZT_INLINE bool writeOverflow(const int& ii) noexcept
|
||||
{
|
||||
return ((ii - ZT_BUF_MEM_SIZE) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for overflow beyond the size of the data that should be in the buffer
|
||||
|
@ -280,15 +296,17 @@ public:
|
|||
* @param size Size of data that should be in buffer
|
||||
* @return True if iterator has read past the size of the data
|
||||
*/
|
||||
static ZT_INLINE bool readOverflow(const int &ii, const unsigned int size) noexcept
|
||||
{ return ((ii - (int)size) > 0); }
|
||||
static ZT_INLINE bool readOverflow(const int& ii, const unsigned int size) noexcept
|
||||
{
|
||||
return ((ii - (int)size) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all memory to zero
|
||||
*/
|
||||
ZT_INLINE void clear() noexcept
|
||||
{
|
||||
Utils::zero< ZT_BUF_MEM_SIZE >(unsafeData);
|
||||
Utils::zero<ZT_BUF_MEM_SIZE>(unsafeData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -297,7 +315,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 1)
|
||||
* @return Byte (undefined on overflow)
|
||||
*/
|
||||
ZT_INLINE uint8_t rI8(int &ii) const noexcept
|
||||
ZT_INLINE uint8_t rI8(int& ii) const noexcept
|
||||
{
|
||||
const int s = ii++;
|
||||
return unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK];
|
||||
|
@ -309,16 +327,14 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 2)
|
||||
* @return Integer (undefined on overflow)
|
||||
*/
|
||||
ZT_INLINE uint16_t rI16(int &ii) const noexcept
|
||||
ZT_INLINE uint16_t rI16(int& ii) const noexcept
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
ii += 2;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint16_t)unsafeData[s] << 8U) |
|
||||
(uint16_t)unsafeData[s + 1]);
|
||||
return (((uint16_t)unsafeData[s] << 8U) | (uint16_t)unsafeData[s + 1]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t *>(unsafeData + s));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t*>(unsafeData + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -328,18 +344,16 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 4)
|
||||
* @return Integer (undefined on overflow)
|
||||
*/
|
||||
ZT_INLINE uint32_t rI32(int &ii) const noexcept
|
||||
ZT_INLINE uint32_t rI32(int& ii) const noexcept
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
ii += 4;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint32_t)unsafeData[s] << 24U) |
|
||||
((uint32_t)unsafeData[s + 1] << 16U) |
|
||||
((uint32_t)unsafeData[s + 2] << 8U) |
|
||||
(uint32_t)unsafeData[s + 3]);
|
||||
((uint32_t)unsafeData[s] << 24U) | ((uint32_t)unsafeData[s + 1] << 16U)
|
||||
| ((uint32_t)unsafeData[s + 2] << 8U) | (uint32_t)unsafeData[s + 3]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t *>(unsafeData + s));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t*>(unsafeData + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -349,22 +363,18 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 8)
|
||||
* @return Integer (undefined on overflow)
|
||||
*/
|
||||
ZT_INLINE uint64_t rI64(int &ii) const noexcept
|
||||
ZT_INLINE uint64_t rI64(int& ii) const noexcept
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
ii += 8;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint64_t)unsafeData[s] << 56U) |
|
||||
((uint64_t)unsafeData[s + 1] << 48U) |
|
||||
((uint64_t)unsafeData[s + 2] << 40U) |
|
||||
((uint64_t)unsafeData[s + 3] << 32U) |
|
||||
((uint64_t)unsafeData[s + 4] << 24U) |
|
||||
((uint64_t)unsafeData[s + 5] << 16U) |
|
||||
((uint64_t)unsafeData[s + 6] << 8U) |
|
||||
(uint64_t)unsafeData[s + 7]);
|
||||
((uint64_t)unsafeData[s] << 56U) | ((uint64_t)unsafeData[s + 1] << 48U)
|
||||
| ((uint64_t)unsafeData[s + 2] << 40U) | ((uint64_t)unsafeData[s + 3] << 32U)
|
||||
| ((uint64_t)unsafeData[s + 4] << 24U) | ((uint64_t)unsafeData[s + 5] << 16U)
|
||||
| ((uint64_t)unsafeData[s + 6] << 8U) | (uint64_t)unsafeData[s + 7]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t *>(unsafeData + s));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t*>(unsafeData + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -383,8 +393,7 @@ public:
|
|||
* @param obj Object to read
|
||||
* @return Bytes read or a negative value on unmarshal error (passed from object) or overflow
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE int rO(int &ii, T &obj) const noexcept
|
||||
template <typename T> ZT_INLINE int rO(int& ii, T& obj) const noexcept
|
||||
{
|
||||
if (likely(ii < ZT_BUF_MEM_SIZE)) {
|
||||
int ms = obj.unmarshal(unsafeData + ii, ZT_BUF_MEM_SIZE - ii);
|
||||
|
@ -406,9 +415,9 @@ public:
|
|||
* @param bufSize Capacity of buffer in bytes
|
||||
* @return Pointer to buf or NULL on overflow or error
|
||||
*/
|
||||
ZT_INLINE char *rS(int &ii, char *const buf, const unsigned int bufSize) const noexcept
|
||||
ZT_INLINE char* rS(int& ii, char* const buf, const unsigned int bufSize) const noexcept
|
||||
{
|
||||
const char *const s = (const char *)(unsafeData + ii);
|
||||
const char* const s = (const char*)(unsafeData + ii);
|
||||
const int sii = ii;
|
||||
while (ii < ZT_BUF_MEM_SIZE) {
|
||||
if (unsafeData[ii++] == 0) {
|
||||
|
@ -435,9 +444,9 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by length of string)
|
||||
* @return Pointer to null-terminated C-style string or NULL on overflow or error
|
||||
*/
|
||||
ZT_INLINE const char *rSnc(int &ii) const noexcept
|
||||
ZT_INLINE const char* rSnc(int& ii) const noexcept
|
||||
{
|
||||
const char *const s = (const char *)(unsafeData + ii);
|
||||
const char* const s = (const char*)(unsafeData + ii);
|
||||
while (ii < ZT_BUF_MEM_SIZE) {
|
||||
if (unsafeData[ii++] == 0)
|
||||
return s;
|
||||
|
@ -456,11 +465,11 @@ public:
|
|||
* @param len Length of buffer
|
||||
* @return Pointer to data or NULL on overflow or error
|
||||
*/
|
||||
ZT_INLINE uint8_t *rB(int &ii, void *const bytes, const unsigned int len) const noexcept
|
||||
ZT_INLINE uint8_t* rB(int& ii, void* const bytes, const unsigned int len) const noexcept
|
||||
{
|
||||
if (likely(((ii += (int)len) <= ZT_BUF_MEM_SIZE))) {
|
||||
Utils::copy(bytes, unsafeData + ii, len);
|
||||
return reinterpret_cast<uint8_t *>(bytes);
|
||||
return reinterpret_cast<uint8_t*>(bytes);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -478,9 +487,9 @@ public:
|
|||
* @param len Length of data field to obtain a pointer to
|
||||
* @return Pointer to field or NULL on overflow
|
||||
*/
|
||||
ZT_INLINE const uint8_t *rBnc(int &ii, unsigned int len) const noexcept
|
||||
ZT_INLINE const uint8_t* rBnc(int& ii, unsigned int len) const noexcept
|
||||
{
|
||||
const uint8_t *const b = unsafeData + ii;
|
||||
const uint8_t* const b = unsafeData + ii;
|
||||
return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr;
|
||||
}
|
||||
|
||||
|
@ -490,8 +499,7 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI8() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI8() const noexcept
|
||||
{
|
||||
static_assert(I < ZT_BUF_MEM_SIZE, "overflow");
|
||||
return unsafeData[I];
|
||||
|
@ -503,16 +511,13 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI16() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI16() const noexcept
|
||||
{
|
||||
static_assert((I + 1) < ZT_BUF_MEM_SIZE, "overflow");
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint16_t)unsafeData[I] << 8U) |
|
||||
(uint16_t)unsafeData[I + 1]);
|
||||
return (((uint16_t)unsafeData[I] << 8U) | (uint16_t)unsafeData[I + 1]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t *>(unsafeData + I));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t*>(unsafeData + I));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -522,18 +527,15 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI32() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI32() const noexcept
|
||||
{
|
||||
static_assert((I + 3) < ZT_BUF_MEM_SIZE, "overflow");
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint32_t)unsafeData[I] << 24U) |
|
||||
((uint32_t)unsafeData[I + 1] << 16U) |
|
||||
((uint32_t)unsafeData[I + 2] << 8U) |
|
||||
(uint32_t)unsafeData[I + 3]);
|
||||
((uint32_t)unsafeData[I] << 24U) | ((uint32_t)unsafeData[I + 1] << 16U)
|
||||
| ((uint32_t)unsafeData[I + 2] << 8U) | (uint32_t)unsafeData[I + 3]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t *>(unsafeData + I));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t*>(unsafeData + I));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -543,22 +545,17 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI64() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI64() const noexcept
|
||||
{
|
||||
static_assert((I + 7) < ZT_BUF_MEM_SIZE, "overflow");
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint64_t)unsafeData[I] << 56U) |
|
||||
((uint64_t)unsafeData[I + 1] << 48U) |
|
||||
((uint64_t)unsafeData[I + 2] << 40U) |
|
||||
((uint64_t)unsafeData[I + 3] << 32U) |
|
||||
((uint64_t)unsafeData[I + 4] << 24U) |
|
||||
((uint64_t)unsafeData[I + 5] << 16U) |
|
||||
((uint64_t)unsafeData[I + 6] << 8U) |
|
||||
(uint64_t)unsafeData[I + 7]);
|
||||
((uint64_t)unsafeData[I] << 56U) | ((uint64_t)unsafeData[I + 1] << 48U)
|
||||
| ((uint64_t)unsafeData[I + 2] << 40U) | ((uint64_t)unsafeData[I + 3] << 32U)
|
||||
| ((uint64_t)unsafeData[I + 4] << 24U) | ((uint64_t)unsafeData[I + 5] << 16U)
|
||||
| ((uint64_t)unsafeData[I + 6] << 8U) | (uint64_t)unsafeData[I + 7]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t *>(unsafeData + I));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t*>(unsafeData + I));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -585,11 +582,9 @@ public:
|
|||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint16_t)unsafeData[s] << 8U) |
|
||||
(uint16_t)unsafeData[s + 1]);
|
||||
return (((uint16_t)unsafeData[s] << 8U) | (uint16_t)unsafeData[s + 1]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t *>(unsafeData + s));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t*>(unsafeData + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -605,12 +600,10 @@ public:
|
|||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint32_t)unsafeData[s] << 24U) |
|
||||
((uint32_t)unsafeData[s + 1] << 16U) |
|
||||
((uint32_t)unsafeData[s + 2] << 8U) |
|
||||
(uint32_t)unsafeData[s + 3]);
|
||||
((uint32_t)unsafeData[s] << 24U) | ((uint32_t)unsafeData[s + 1] << 16U)
|
||||
| ((uint32_t)unsafeData[s + 2] << 8U) | (uint32_t)unsafeData[s + 3]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t *>(unsafeData + s));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t*>(unsafeData + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -626,16 +619,12 @@ public:
|
|||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint64_t)unsafeData[s] << 56U) |
|
||||
((uint64_t)unsafeData[s + 1] << 48U) |
|
||||
((uint64_t)unsafeData[s + 2] << 40U) |
|
||||
((uint64_t)unsafeData[s + 3] << 32U) |
|
||||
((uint64_t)unsafeData[s + 4] << 24U) |
|
||||
((uint64_t)unsafeData[s + 5] << 16U) |
|
||||
((uint64_t)unsafeData[s + 6] << 8U) |
|
||||
(uint64_t)unsafeData[s + 7]);
|
||||
((uint64_t)unsafeData[s] << 56U) | ((uint64_t)unsafeData[s + 1] << 48U)
|
||||
| ((uint64_t)unsafeData[s + 2] << 40U) | ((uint64_t)unsafeData[s + 3] << 32U)
|
||||
| ((uint64_t)unsafeData[s + 4] << 24U) | ((uint64_t)unsafeData[s + 5] << 16U)
|
||||
| ((uint64_t)unsafeData[s + 6] << 8U) | (uint64_t)unsafeData[s + 7]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t *>(unsafeData + s));
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t*>(unsafeData + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -645,7 +634,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 1)
|
||||
* @param n Byte
|
||||
*/
|
||||
ZT_INLINE void wI8(int &ii, const uint8_t n) noexcept
|
||||
ZT_INLINE void wI8(int& ii, const uint8_t n) noexcept
|
||||
{
|
||||
const int s = ii++;
|
||||
unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK] = n;
|
||||
|
@ -657,7 +646,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 2)
|
||||
* @param n Integer
|
||||
*/
|
||||
ZT_INLINE void wI16(int &ii, const uint16_t n) noexcept
|
||||
ZT_INLINE void wI16(int& ii, const uint16_t n) noexcept
|
||||
{
|
||||
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
|
||||
ii += 2;
|
||||
|
@ -665,7 +654,7 @@ public:
|
|||
unsafeData[s] = (uint8_t)(n >> 8U);
|
||||
unsafeData[s + 1] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint16_t *>(unsafeData + s) = Utils::hton(n);
|
||||
*reinterpret_cast<uint16_t*>(unsafeData + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -675,7 +664,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 4)
|
||||
* @param n Integer
|
||||
*/
|
||||
ZT_INLINE void wI32(int &ii, const uint32_t n) noexcept
|
||||
ZT_INLINE void wI32(int& ii, const uint32_t n) noexcept
|
||||
{
|
||||
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
|
||||
ii += 4;
|
||||
|
@ -685,7 +674,7 @@ public:
|
|||
unsafeData[s + 2] = (uint8_t)(n >> 8U);
|
||||
unsafeData[s + 3] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint32_t *>(unsafeData + s) = Utils::hton(n);
|
||||
*reinterpret_cast<uint32_t*>(unsafeData + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -695,7 +684,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by 8)
|
||||
* @param n Integer
|
||||
*/
|
||||
ZT_INLINE void wI64(int &ii, const uint64_t n) noexcept
|
||||
ZT_INLINE void wI64(int& ii, const uint64_t n) noexcept
|
||||
{
|
||||
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
|
||||
ii += 8;
|
||||
|
@ -709,7 +698,7 @@ public:
|
|||
unsafeData[s + 6] = (uint8_t)(n >> 8U);
|
||||
unsafeData[s + 7] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint64_t *>(unsafeData + s) = Utils::hton(n);
|
||||
*reinterpret_cast<uint64_t*>(unsafeData + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -720,15 +709,15 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by size of object)
|
||||
* @param t Object to write
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE void wO(int &ii, T &t) noexcept
|
||||
template <typename T> ZT_INLINE void wO(int& ii, T& t) noexcept
|
||||
{
|
||||
const int s = ii;
|
||||
if (likely((s + T::marshalSizeMax()) <= ZT_BUF_MEM_SIZE)) {
|
||||
int ms = t.marshal(unsafeData + s);
|
||||
if (ms > 0)
|
||||
ii += ms;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ii += T::marshalSizeMax(); // mark as overflowed even if we didn't do anything
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +728,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by length of string)
|
||||
* @param s String to write (writes an empty string if this is NULL)
|
||||
*/
|
||||
ZT_INLINE void wS(int &ii, const char *s) noexcept
|
||||
ZT_INLINE void wS(int& ii, const char* s) noexcept
|
||||
{
|
||||
if (s) {
|
||||
char c;
|
||||
|
@ -747,7 +736,8 @@ public:
|
|||
c = *(s++);
|
||||
wI8(ii, (uint8_t)c);
|
||||
} while (c);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
wI8(ii, 0);
|
||||
}
|
||||
}
|
||||
|
@ -759,7 +749,7 @@ public:
|
|||
* @param bytes Bytes to write
|
||||
* @param len Size of data in bytes
|
||||
*/
|
||||
ZT_INLINE void wB(int &ii, const void *const bytes, const unsigned int len) noexcept
|
||||
ZT_INLINE void wB(int& ii, const void* const bytes, const unsigned int len) noexcept
|
||||
{
|
||||
const int s = ii;
|
||||
if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE))
|
||||
|
@ -772,7 +762,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by len)
|
||||
* @param len Number of zero bytes to write
|
||||
*/
|
||||
ZT_INLINE void wZ(int &ii, const unsigned int len) noexcept
|
||||
ZT_INLINE void wZ(int& ii, const unsigned int len) noexcept
|
||||
{
|
||||
const int s = ii;
|
||||
if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE))
|
||||
|
@ -785,7 +775,7 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by len)
|
||||
* @param len Number of random bytes to write
|
||||
*/
|
||||
ZT_INLINE void wR(int &ii, const unsigned int len) noexcept
|
||||
ZT_INLINE void wR(int& ii, const unsigned int len) noexcept
|
||||
{
|
||||
const int s = ii;
|
||||
if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE))
|
||||
|
@ -810,7 +800,7 @@ public:
|
|||
unsafeData[s] = (uint8_t)(n >> 8U);
|
||||
unsafeData[s + 1] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint16_t *>(unsafeData + s) = Utils::hton(n);
|
||||
*reinterpret_cast<uint16_t*>(unsafeData + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -826,7 +816,7 @@ public:
|
|||
unsafeData[s + 2] = (uint8_t)(n >> 8U);
|
||||
unsafeData[s + 3] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint32_t *>(unsafeData + s) = Utils::hton(n);
|
||||
*reinterpret_cast<uint32_t*>(unsafeData + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -846,7 +836,7 @@ public:
|
|||
unsafeData[s + 6] = (uint8_t)(n >> 8U);
|
||||
unsafeData[s + 7] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint64_t *>(unsafeData + s) = Utils::hton(n);
|
||||
*reinterpret_cast<uint64_t*>(unsafeData + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -854,11 +844,13 @@ public:
|
|||
* @return Capacity of this buffer (usable size of data.bytes)
|
||||
*/
|
||||
static constexpr unsigned int capacity() noexcept
|
||||
{ return ZT_BUF_MEM_SIZE; }
|
||||
{
|
||||
return ZT_BUF_MEM_SIZE;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
volatile uintptr_t __nextInPool;
|
||||
std::atomic< int > __refCount;
|
||||
std::atomic<int> __refCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
3890
core/C25519.cpp
3890
core/C25519.cpp
File diff suppressed because it is too large
Load diff
|
@ -35,18 +35,20 @@ namespace ZeroTier {
|
|||
/**
|
||||
* A combined Curve25519 ECDH and Ed25519 signature engine
|
||||
*/
|
||||
class C25519
|
||||
{
|
||||
public:
|
||||
class C25519 {
|
||||
public:
|
||||
/**
|
||||
* Generate a set of two 25519 keys: a C25519 ECDH key pair and an Ed25519 EDDSA key pair.
|
||||
*/
|
||||
static void generateCombined(uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE]);
|
||||
static void generateCombined(
|
||||
uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE]);
|
||||
|
||||
/**
|
||||
* Generate a C25519 ECDH key pair only.
|
||||
*/
|
||||
static void generateC25519(uint8_t pub[ZT_C25519_ECDH_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_ECDH_PRIVATE_KEY_SIZE]);
|
||||
static void
|
||||
generateC25519(uint8_t pub[ZT_C25519_ECDH_PUBLIC_KEY_SIZE], uint8_t priv[ZT_C25519_ECDH_PRIVATE_KEY_SIZE]);
|
||||
|
||||
/**
|
||||
* Generate a key pair satisfying a condition
|
||||
|
@ -61,16 +63,19 @@ public:
|
|||
* @return Key pair where cond(kp) returns true
|
||||
* @tparam F Type of 'cond'
|
||||
*/
|
||||
template<typename F>
|
||||
static ZT_INLINE void generateSatisfying(F cond,uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE])
|
||||
template <typename F>
|
||||
static ZT_INLINE void generateSatisfying(
|
||||
F cond,
|
||||
uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE])
|
||||
{
|
||||
Utils::getSecureRandom(priv,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
Utils::getSecureRandom(priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
s_calcPubED(pub, priv); // do Ed25519 key -- bytes 32-63 of pub and priv
|
||||
do {
|
||||
++(((uint64_t *)priv)[1]);
|
||||
--(((uint64_t *)priv)[2]);
|
||||
++(((uint64_t*)priv)[1]);
|
||||
--(((uint64_t*)priv)[2]);
|
||||
s_calcPubDH(pub, priv); // keep regenerating bytes 0-31 until satisfied
|
||||
} while (!cond(pub));
|
||||
} while (! cond(pub));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +88,10 @@ public:
|
|||
* @param their Their public key
|
||||
* @param rawkey Buffer to receive raw (not hashed) agreed upon key
|
||||
*/
|
||||
static void agree(const uint8_t mine[ZT_C25519_ECDH_PRIVATE_KEY_SIZE],const uint8_t their[ZT_C25519_ECDH_PUBLIC_KEY_SIZE],uint8_t rawkey[ZT_C25519_ECDH_SHARED_SECRET_SIZE]);
|
||||
static void agree(
|
||||
const uint8_t mine[ZT_C25519_ECDH_PRIVATE_KEY_SIZE],
|
||||
const uint8_t their[ZT_C25519_ECDH_PUBLIC_KEY_SIZE],
|
||||
uint8_t rawkey[ZT_C25519_ECDH_SHARED_SECRET_SIZE]);
|
||||
|
||||
/**
|
||||
* Sign a message with a sender's key pair
|
||||
|
@ -102,7 +110,12 @@ public:
|
|||
* @param len Length of message in bytes
|
||||
* @param signature Buffer to fill with signature -- MUST be 96 bytes in length
|
||||
*/
|
||||
static void sign(const uint8_t myPrivate[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE],const uint8_t myPublic[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],const void *msg,unsigned int len,void *signature);
|
||||
static void sign(
|
||||
const uint8_t myPrivate[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE],
|
||||
const uint8_t myPublic[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
const void* msg,
|
||||
unsigned int len,
|
||||
void* signature);
|
||||
|
||||
/**
|
||||
* Verify a message's signature
|
||||
|
@ -114,16 +127,21 @@ public:
|
|||
* @param siglen Length of signature in bytes
|
||||
* @return True if signature is valid and the message is authentic and unmodified
|
||||
*/
|
||||
static bool verify(const uint8_t their[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],const void *msg,unsigned int len,const void *signature,unsigned int siglen);
|
||||
static bool verify(
|
||||
const uint8_t their[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
const void* msg,
|
||||
unsigned int len,
|
||||
const void* signature,
|
||||
unsigned int siglen);
|
||||
|
||||
private:
|
||||
private:
|
||||
// derive first 32 bytes of kp.pub from first 32 bytes of kp.priv
|
||||
// this is the ECDH key
|
||||
static void s_calcPubDH(uint8_t *pub, const uint8_t *priv);
|
||||
static void s_calcPubDH(uint8_t* pub, const uint8_t* priv);
|
||||
|
||||
// derive 2nd 32 bytes of kp.pub from 2nd 32 bytes of kp.priv
|
||||
// this is the Ed25519 sign/verify key
|
||||
static void s_calcPubED(uint8_t *pub, const uint8_t *priv);
|
||||
static void s_calcPubED(uint8_t* pub, const uint8_t* priv);
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
819
core/CAPI.cpp
819
core/CAPI.cpp
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required (VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(zt_core)
|
||||
|
||||
configure_file(
|
||||
|
@ -61,7 +61,7 @@ set(core_headers
|
|||
Utils.hpp
|
||||
VL1.hpp
|
||||
VL2.hpp
|
||||
)
|
||||
)
|
||||
|
||||
set(core_src
|
||||
AES.cpp
|
||||
|
@ -102,22 +102,22 @@ set(core_src
|
|||
Utils.cpp
|
||||
VL1.cpp
|
||||
VL2.cpp
|
||||
)
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${core_src} ${core_headers})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR})
|
||||
|
||||
if(WIN32)
|
||||
if (WIN32)
|
||||
set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi)
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
|
||||
else(WIN32)
|
||||
else (WIN32)
|
||||
set(libs ${libs} pthread)
|
||||
if (APPLE)
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
|
||||
else(APPLE)
|
||||
else (APPLE)
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
|
||||
endif(APPLE)
|
||||
endif(WIN32)
|
||||
endif (APPLE)
|
||||
endif (WIN32)
|
||||
|
||||
add_executable(zt_core_tests Tests.h Tests.cpp)
|
||||
target_compile_definitions(zt_core_tests PRIVATE ZT_ENABLE_TESTS=1 ZT_STANDALONE_TESTS=1)
|
||||
|
|
|
@ -25,14 +25,11 @@ namespace ZeroTier {
|
|||
* graph around from function to function as needed. It's cleaner and probably
|
||||
* faster than passing clock, ticks, and tPtr around everywhere.
|
||||
*/
|
||||
class CallContext
|
||||
{
|
||||
public:
|
||||
ZT_INLINE CallContext(const int64_t c, const int64_t t, void *const p) :
|
||||
clock(c),
|
||||
ticks(t),
|
||||
tPtr(p)
|
||||
{}
|
||||
class CallContext {
|
||||
public:
|
||||
ZT_INLINE CallContext(const int64_t c, const int64_t t, void* const p) : clock(c), ticks(t), tPtr(p)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Real world time in milliseconds since Unix epoch or -1 if unknown.
|
||||
|
@ -56,7 +53,7 @@ public:
|
|||
* By passing this back to callbacks state can be kept by the caller using
|
||||
* a mechanism that is faster (on most platforms) than thread-local storage.
|
||||
*/
|
||||
void *const tPtr;
|
||||
void* const tPtr;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -12,9 +12,10 @@
|
|||
/****/
|
||||
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -22,26 +23,26 @@ CapabilityCredential::CapabilityCredential(
|
|||
const uint32_t id,
|
||||
const uint64_t nwid,
|
||||
const int64_t timestamp,
|
||||
const ZT_VirtualNetworkRule *const rules,
|
||||
const unsigned int ruleCount) noexcept:
|
||||
m_nwid(nwid),
|
||||
m_timestamp(timestamp),
|
||||
m_id(id),
|
||||
m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES),
|
||||
m_signatureLength(0)
|
||||
const ZT_VirtualNetworkRule* const rules,
|
||||
const unsigned int ruleCount) noexcept
|
||||
: m_nwid(nwid)
|
||||
, m_timestamp(timestamp)
|
||||
, m_id(id)
|
||||
, m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES)
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
Utils::zero< sizeof(m_rules) >(m_rules);
|
||||
Utils::zero<sizeof(m_rules)>(m_rules);
|
||||
if (m_ruleCount > 0)
|
||||
Utils::copy(m_rules, rules, sizeof(ZT_VirtualNetworkRule) * m_ruleCount);
|
||||
Utils::zero< sizeof(m_signature) >(m_signature);
|
||||
Utils::zero<sizeof(m_signature)>(m_signature);
|
||||
}
|
||||
|
||||
bool CapabilityCredential::sign(const Identity &from, const Address &to) noexcept
|
||||
bool CapabilityCredential::sign(const Identity& from, const Address& to) noexcept
|
||||
{
|
||||
uint8_t buf[ZT_CAPABILITY_MARSHAL_SIZE_MAX + 16];
|
||||
m_issuedTo = to;
|
||||
m_signedBy = from.address();
|
||||
m_signatureLength = from.sign(buf, (unsigned int) marshal(buf, true), m_signature, sizeof(m_signature));
|
||||
m_signatureLength = from.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature));
|
||||
return m_signatureLength > 0;
|
||||
}
|
||||
|
||||
|
@ -50,16 +51,16 @@ int CapabilityCredential::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],
|
|||
int p = 0;
|
||||
|
||||
if (forSign) {
|
||||
for (int k = 0;k < 8;++k)
|
||||
for (int k = 0; k < 8; ++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
|
||||
Utils::storeBigEndian<uint64_t>(data + p, m_nwid);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, (uint64_t) m_timestamp);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, (uint64_t)m_timestamp);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 16, m_id);
|
||||
p += 20;
|
||||
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_ruleCount);
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_ruleCount);
|
||||
p += 2;
|
||||
p += CapabilityCredential::marshalVirtualNetworkRules(data + p, m_rules, m_ruleCount);
|
||||
|
||||
|
@ -67,18 +68,18 @@ int CapabilityCredential::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],
|
|||
// chain length. This is deprecated so set the max chain length to one.
|
||||
data[p++] = (uint8_t)1;
|
||||
|
||||
if (!forSign) {
|
||||
if (! forSign) {
|
||||
m_issuedTo.copyTo(data + p);
|
||||
m_signedBy.copyTo(data + p + ZT_ADDRESS_LENGTH);
|
||||
p += ZT_ADDRESS_LENGTH + ZT_ADDRESS_LENGTH;
|
||||
data[p++] = 1; // LEGACY: old versions require a reserved byte here
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_signatureLength);
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_signatureLength);
|
||||
p += 2;
|
||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||
p += (int)m_signatureLength;
|
||||
|
||||
// LEGACY: older versions supported more than one record terminated by a zero address.
|
||||
for (int k = 0;k < ZT_ADDRESS_LENGTH;++k)
|
||||
for (int k = 0; k < ZT_ADDRESS_LENGTH; ++k)
|
||||
data[p++] = 0;
|
||||
}
|
||||
|
||||
|
@ -86,20 +87,20 @@ int CapabilityCredential::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],
|
|||
data[p++] = 0; // uint16_t size of additional fields, currently 0
|
||||
|
||||
if (forSign) {
|
||||
for (int k = 0;k < 8;++k)
|
||||
for (int k = 0; k < 8; ++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
|
||||
int CapabilityCredential::unmarshal(const uint8_t* data, int len) noexcept
|
||||
{
|
||||
if (len < 22)
|
||||
return -1;
|
||||
|
||||
m_nwid = Utils::loadBigEndian<uint64_t>(data);
|
||||
m_timestamp = (int64_t) Utils::loadBigEndian<uint64_t>(data + 8);
|
||||
m_timestamp = (int64_t)Utils::loadBigEndian<uint64_t>(data + 8);
|
||||
m_id = Utils::loadBigEndian<uint32_t>(data + 16);
|
||||
|
||||
const unsigned int rc = Utils::loadBigEndian<uint16_t>(data + 20);
|
||||
|
@ -118,13 +119,13 @@ int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
// this feature was never used, just set the signature and issued to and other related
|
||||
// fields each time and we should only ever see one. If there's more than one and the
|
||||
// last is not the controller, this credential will just fail validity check.
|
||||
for (unsigned int i = 0;;++i) {
|
||||
for (unsigned int i = 0;; ++i) {
|
||||
if ((p + ZT_ADDRESS_LENGTH) > len)
|
||||
return -1;
|
||||
const Address to(data + p);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
|
||||
if (!to)
|
||||
if (! to)
|
||||
break;
|
||||
|
||||
m_issuedTo = to;
|
||||
|
@ -137,10 +138,10 @@ int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
return -1;
|
||||
m_signatureLength = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
if ((m_signatureLength > sizeof(m_signature)) || ((p + (int) m_signatureLength) > len))
|
||||
if ((m_signatureLength > sizeof(m_signature)) || ((p + (int)m_signatureLength) > len))
|
||||
return -1;
|
||||
Utils::copy(m_signature, data + p, m_signatureLength);
|
||||
p += (int) m_signatureLength;
|
||||
p += (int)m_signatureLength;
|
||||
}
|
||||
|
||||
if ((p + 2) > len)
|
||||
|
@ -153,12 +154,15 @@ int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
return p;
|
||||
}
|
||||
|
||||
int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept
|
||||
int CapabilityCredential::marshalVirtualNetworkRules(
|
||||
uint8_t* data,
|
||||
const ZT_VirtualNetworkRule* const rules,
|
||||
const unsigned int ruleCount) noexcept
|
||||
{
|
||||
int p = 0;
|
||||
for (unsigned int i = 0;i < ruleCount;++i) {
|
||||
for (unsigned int i = 0; i < ruleCount; ++i) {
|
||||
data[p++] = rules[i].t;
|
||||
switch ((ZT_VirtualNetworkRuleType) (rules[i].t & 0x3fU)) {
|
||||
switch ((ZT_VirtualNetworkRuleType)(rules[i].t & 0x3fU)) {
|
||||
default:
|
||||
data[p++] = 0;
|
||||
break;
|
||||
|
@ -201,10 +205,10 @@ int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_Vir
|
|||
case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
|
||||
case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
|
||||
data[p++] = 5;
|
||||
data[p++] = reinterpret_cast<const uint8_t *>(&(rules[i].v.ipv4.ip))[0];
|
||||
data[p++] = reinterpret_cast<const uint8_t *>(&(rules[i].v.ipv4.ip))[1];
|
||||
data[p++] = reinterpret_cast<const uint8_t *>(&(rules[i].v.ipv4.ip))[2];
|
||||
data[p++] = reinterpret_cast<const uint8_t *>(&(rules[i].v.ipv4.ip))[3];
|
||||
data[p++] = reinterpret_cast<const uint8_t*>(&(rules[i].v.ipv4.ip))[0];
|
||||
data[p++] = reinterpret_cast<const uint8_t*>(&(rules[i].v.ipv4.ip))[1];
|
||||
data[p++] = reinterpret_cast<const uint8_t*>(&(rules[i].v.ipv4.ip))[2];
|
||||
data[p++] = reinterpret_cast<const uint8_t*>(&(rules[i].v.ipv4.ip))[3];
|
||||
data[p++] = rules[i].v.ipv4.mask;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
|
||||
|
@ -277,7 +281,9 @@ int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_Vir
|
|||
data[p++] = 19;
|
||||
Utils::storeBigEndian<uint64_t>(data + p, rules[i].v.intRange.start);
|
||||
p += 8;
|
||||
Utils::storeBigEndian<uint64_t>(data + p, rules[i].v.intRange.start + (uint64_t) rules[i].v.intRange.end);
|
||||
Utils::storeBigEndian<uint64_t>(
|
||||
data + p,
|
||||
rules[i].v.intRange.start + (uint64_t)rules[i].v.intRange.end);
|
||||
p += 8;
|
||||
Utils::storeBigEndian<uint16_t>(data + p, rules[i].v.intRange.idx);
|
||||
p += 2;
|
||||
|
@ -288,7 +294,12 @@ int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_Vir
|
|||
return p;
|
||||
}
|
||||
|
||||
int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data, const int len, ZT_VirtualNetworkRule *const rules, unsigned int &ruleCount, const unsigned int maxRuleCount) noexcept
|
||||
int CapabilityCredential::unmarshalVirtualNetworkRules(
|
||||
const uint8_t* const data,
|
||||
const int len,
|
||||
ZT_VirtualNetworkRule* const rules,
|
||||
unsigned int& ruleCount,
|
||||
const unsigned int maxRuleCount) noexcept
|
||||
{
|
||||
int p = 0;
|
||||
unsigned int rc = 0;
|
||||
|
@ -296,16 +307,17 @@ int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data
|
|||
if (p >= len)
|
||||
return -1;
|
||||
rules[ruleCount].t = data[p++];
|
||||
const int fieldLen = (int) data[p++];
|
||||
const int fieldLen = (int)data[p++];
|
||||
if ((p + fieldLen) > len)
|
||||
return -1;
|
||||
switch ((ZT_VirtualNetworkRuleType) (rules[ruleCount].t & 0x3fU)) {
|
||||
switch ((ZT_VirtualNetworkRuleType)(rules[ruleCount].t & 0x3fU)) {
|
||||
default:
|
||||
break;
|
||||
case ZT_NETWORK_RULE_ACTION_TEE:
|
||||
case ZT_NETWORK_RULE_ACTION_WATCH:
|
||||
case ZT_NETWORK_RULE_ACTION_REDIRECT:
|
||||
if ((p + 14) > len) return -1;
|
||||
if ((p + 14) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.fwd.address = Utils::loadBigEndian<uint64_t>(data + p);
|
||||
p += 8;
|
||||
rules[ruleCount].v.fwd.flags = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
|
@ -315,86 +327,101 @@ int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data
|
|||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
|
||||
case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
|
||||
if ((p + ZT_ADDRESS_LENGTH) > len) return -1;
|
||||
if ((p + ZT_ADDRESS_LENGTH) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.zt = Address(data + p).toInt();
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_ID:
|
||||
if ((p + 2) > len) return -1;
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.vlanId = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_PCP:
|
||||
if ((p + 1) > len) return -1;
|
||||
if ((p + 1) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.vlanPcp = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
|
||||
if ((p + 1) > len) return -1;
|
||||
if ((p + 1) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.vlanDei = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
|
||||
case ZT_NETWORK_RULE_MATCH_MAC_DEST:
|
||||
if ((p + 6) > len) return -1;
|
||||
if ((p + 6) > len)
|
||||
return -1;
|
||||
Utils::copy<6>(rules[ruleCount].v.mac, data + p);
|
||||
p += 6;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
|
||||
case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
|
||||
if ((p + 5) > len) return -1;
|
||||
if ((p + 5) > len)
|
||||
return -1;
|
||||
Utils::copy<4>(&(rules[ruleCount].v.ipv4.ip), data + p);
|
||||
p += 4;
|
||||
rules[ruleCount].v.ipv4.mask = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
|
||||
case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
|
||||
if ((p + 17) > len) return -1;
|
||||
if ((p + 17) > len)
|
||||
return -1;
|
||||
Utils::copy<16>(rules[ruleCount].v.ipv6.ip, data + p);
|
||||
p += 16;
|
||||
rules[ruleCount].v.ipv6.mask = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_TOS:
|
||||
if ((p + 3) > len) return -1;
|
||||
if ((p + 3) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.ipTos.mask = data[p++];
|
||||
rules[ruleCount].v.ipTos.value[0] = data[p++];
|
||||
rules[ruleCount].v.ipTos.value[1] = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
|
||||
if ((p + 1) > len) return -1;
|
||||
if ((p + 1) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.ipProtocol = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
|
||||
if ((p + 2) > len) return -1;
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.etherType = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_ICMP:
|
||||
if ((p + 3) > len) return -1;
|
||||
if ((p + 3) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.icmp.type = data[p++];
|
||||
rules[ruleCount].v.icmp.code = data[p++];
|
||||
rules[ruleCount].v.icmp.flags = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
|
||||
case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.port[0] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
rules[ruleCount].v.port[1] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS:
|
||||
if ((p + 8) > len) return -1;
|
||||
if ((p + 8) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.characteristics = Utils::loadBigEndian<uint64_t>(data + p);
|
||||
p += 8;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.frameSize[0] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
rules[ruleCount].v.frameSize[1] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_RANDOM:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.randomProbability = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
p += 4;
|
||||
break;
|
||||
|
@ -405,17 +432,20 @@ int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data
|
|||
case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.tag.id = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
p += 4;
|
||||
rules[ruleCount].v.tag.value = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
p += 4;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE:
|
||||
if ((p + 19) > len) return -1;
|
||||
if ((p + 19) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.intRange.start = Utils::loadBigEndian<uint64_t>(data + p);
|
||||
p += 8;
|
||||
rules[ruleCount].v.intRange.end = (uint32_t) (Utils::loadBigEndian<uint64_t>(data + p) - rules[ruleCount].v.intRange.start);
|
||||
rules[ruleCount].v.intRange.end =
|
||||
(uint32_t)(Utils::loadBigEndian<uint64_t>(data + p) - rules[ruleCount].v.intRange.start);
|
||||
p += 8;
|
||||
rules[ruleCount].v.intRange.idx = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
|
|
|
@ -14,15 +14,17 @@
|
|||
#ifndef ZT_CAPABILITY_HPP
|
||||
#define ZT_CAPABILITY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX 21
|
||||
#define ZT_CAPABILITY_MARSHAL_SIZE_MAX (8 + 8 + 4 + 1 + 2 + (ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX * ZT_MAX_CAPABILITY_RULES) + 2 + (5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE))
|
||||
#define ZT_CAPABILITY_MARSHAL_SIZE_MAX \
|
||||
(8 + 8 + 4 + 1 + 2 + (ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX * ZT_MAX_CAPABILITY_RULES) + 2 \
|
||||
+ (5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE))
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -46,16 +48,19 @@ class Context;
|
|||
* Note that this is after evaluation of network scope rules and only if
|
||||
* network scope rules do not deliver an explicit match.
|
||||
*/
|
||||
class CapabilityCredential : public Credential
|
||||
{
|
||||
class CapabilityCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_CAPABILITY; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_CAPABILITY;
|
||||
}
|
||||
|
||||
ZT_INLINE CapabilityCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Capability ID
|
||||
|
@ -69,44 +74,64 @@ public:
|
|||
const uint32_t id,
|
||||
const uint64_t nwid,
|
||||
const int64_t timestamp,
|
||||
const ZT_VirtualNetworkRule *const rules,
|
||||
const ZT_VirtualNetworkRule* const rules,
|
||||
const unsigned int ruleCount) noexcept;
|
||||
|
||||
/**
|
||||
* @return Rules -- see ruleCount() for size of array
|
||||
*/
|
||||
ZT_INLINE const ZT_VirtualNetworkRule *rules() const noexcept
|
||||
{ return m_rules; }
|
||||
ZT_INLINE const ZT_VirtualNetworkRule* rules() const noexcept
|
||||
{
|
||||
return m_rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of rules in rules()
|
||||
*/
|
||||
ZT_INLINE unsigned int ruleCount() const noexcept
|
||||
{ return m_ruleCount; }
|
||||
{
|
||||
return m_ruleCount;
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_nwid; }
|
||||
{
|
||||
return m_nwid;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address &issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
ZT_INLINE const Address& issuedTo() const noexcept
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address &signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t *signature() const noexcept
|
||||
{ return m_signature; }
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign this capability and add signature to its chain of custody
|
||||
|
@ -121,21 +146,25 @@ public:
|
|||
* @param to Recipient of this signature
|
||||
* @return True if signature successful and chain of custody appended
|
||||
*/
|
||||
bool sign(const Identity &from, const Address &to) noexcept;
|
||||
bool sign(const Identity& from, const Address& to) noexcept;
|
||||
|
||||
/**
|
||||
* Verify this capability's chain of custody and signatures
|
||||
*
|
||||
* @param RR Runtime environment to provide for peer lookup, etc.
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context &ctx, const CallContext &cc) const noexcept
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const noexcept
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_CAPABILITY_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_CAPABILITY_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
||||
/**
|
||||
* Marshal a set of virtual network rules
|
||||
|
@ -145,7 +174,8 @@ public:
|
|||
* @param ruleCount Number of rules
|
||||
* @return Number of bytes written or -1 on error
|
||||
*/
|
||||
static int marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *rules, unsigned int ruleCount) noexcept;
|
||||
static int
|
||||
marshalVirtualNetworkRules(uint8_t* data, const ZT_VirtualNetworkRule* rules, unsigned int ruleCount) noexcept;
|
||||
|
||||
/**
|
||||
* Unmarshal a set of virtual network rules
|
||||
|
@ -157,19 +187,30 @@ public:
|
|||
* @param maxRuleCount Capacity of rules buffer
|
||||
* @return Number of bytes unmarshaled or -1 on error
|
||||
*/
|
||||
static int unmarshalVirtualNetworkRules(const uint8_t *data, int len, ZT_VirtualNetworkRule *rules, unsigned int &ruleCount, unsigned int maxRuleCount) noexcept;
|
||||
static int unmarshalVirtualNetworkRules(
|
||||
const uint8_t* data,
|
||||
int len,
|
||||
ZT_VirtualNetworkRule* rules,
|
||||
unsigned int& ruleCount,
|
||||
unsigned int maxRuleCount) noexcept;
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_INLINE bool operator<(const CapabilityCredential &c) const noexcept
|
||||
{ return (m_id < c.m_id); }
|
||||
ZT_INLINE bool operator<(const CapabilityCredential& c) const noexcept
|
||||
{
|
||||
return (m_id < c.m_id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const CapabilityCredential &c) const noexcept
|
||||
{ return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0); }
|
||||
ZT_INLINE bool operator==(const CapabilityCredential& c) const noexcept
|
||||
{
|
||||
return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const CapabilityCredential &c) const noexcept
|
||||
{ return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); }
|
||||
ZT_INLINE bool operator!=(const CapabilityCredential& c) const noexcept
|
||||
{
|
||||
return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
uint64_t m_nwid;
|
||||
int64_t m_timestamp;
|
||||
uint32_t m_id;
|
||||
|
|
|
@ -12,34 +12,38 @@
|
|||
/****/
|
||||
|
||||
#include "Certificate.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#include "ECC384.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Certificate::Certificate() noexcept
|
||||
{
|
||||
ZT_Certificate *const sup = this;
|
||||
Utils::zero< sizeof(ZT_Certificate) >(sup);
|
||||
ZT_Certificate* const sup = this;
|
||||
Utils::zero<sizeof(ZT_Certificate)>(sup);
|
||||
}
|
||||
|
||||
Certificate::Certificate(const ZT_Certificate &apiCert) :
|
||||
Certificate()
|
||||
{ *this = apiCert; }
|
||||
Certificate::Certificate(const ZT_Certificate& apiCert) : Certificate()
|
||||
{
|
||||
*this = apiCert;
|
||||
}
|
||||
|
||||
Certificate::Certificate(const Certificate &cert) :
|
||||
Certificate()
|
||||
{ *this = cert; }
|
||||
Certificate::Certificate(const Certificate& cert) : Certificate()
|
||||
{
|
||||
*this = cert;
|
||||
}
|
||||
|
||||
Certificate::~Certificate()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
||||
Certificate& Certificate::operator=(const ZT_Certificate& cert)
|
||||
{
|
||||
m_clear();
|
||||
|
||||
Utils::copy< sizeof(this->serialNo) >(this->serialNo, cert.serialNo);
|
||||
Utils::copy<sizeof(this->serialNo)>(this->serialNo, cert.serialNo);
|
||||
this->usageFlags = cert.usageFlags;
|
||||
this->timestamp = cert.timestamp;
|
||||
this->validity[0] = cert.validity[0];
|
||||
|
@ -51,9 +55,12 @@ Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
|||
for (unsigned int i = 0; i < cert.subject.identityCount; ++i) {
|
||||
if (cert.subject.identities[i].identity) {
|
||||
if (cert.subject.identities[i].locator) {
|
||||
addSubjectIdentity(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity), *reinterpret_cast<const Locator *>(cert.subject.identities[i].locator));
|
||||
} else {
|
||||
addSubjectIdentity(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity));
|
||||
addSubjectIdentity(
|
||||
*reinterpret_cast<const Identity*>(cert.subject.identities[i].identity),
|
||||
*reinterpret_cast<const Locator*>(cert.subject.identities[i].locator));
|
||||
}
|
||||
else {
|
||||
addSubjectIdentity(*reinterpret_cast<const Identity*>(cert.subject.identities[i].identity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,17 +86,19 @@ Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
|||
this->subject.networkCount = cert.subject.networkCount;
|
||||
this->subject.updateURLCount = cert.subject.updateURLCount;
|
||||
|
||||
Utils::copy< sizeof(ZT_Certificate_Name) >(&(this->subject.name), &(cert.subject.name));
|
||||
Utils::copy<sizeof(ZT_Certificate_Name)>(&(this->subject.name), &(cert.subject.name));
|
||||
|
||||
Utils::copy< sizeof(this->subject.uniqueId) >(this->subject.uniqueId, cert.subject.uniqueId);
|
||||
Utils::copy< sizeof(this->subject.uniqueIdSignature) >(this->subject.uniqueIdSignature, cert.subject.uniqueIdSignature);
|
||||
Utils::copy<sizeof(this->subject.uniqueId)>(this->subject.uniqueId, cert.subject.uniqueId);
|
||||
Utils::copy<sizeof(this->subject.uniqueIdSignature)>(
|
||||
this->subject.uniqueIdSignature,
|
||||
cert.subject.uniqueIdSignature);
|
||||
this->subject.uniqueIdSize = cert.subject.uniqueIdSize;
|
||||
this->subject.uniqueIdSignatureSize = cert.subject.uniqueIdSignatureSize;
|
||||
|
||||
Utils::copy< sizeof(this->issuer) >(this->issuer, cert.issuer);
|
||||
Utils::copy<sizeof(this->issuer)>(this->issuer, cert.issuer);
|
||||
|
||||
Utils::copy< sizeof(this->issuerPublicKey) >(this->issuerPublicKey, cert.issuerPublicKey);
|
||||
Utils::copy< sizeof(this->publicKey) >(this->publicKey, cert.publicKey);
|
||||
Utils::copy<sizeof(this->issuerPublicKey)>(this->issuerPublicKey, cert.issuerPublicKey);
|
||||
Utils::copy<sizeof(this->publicKey)>(this->publicKey, cert.publicKey);
|
||||
this->issuerPublicKeySize = cert.issuerPublicKeySize;
|
||||
this->publicKeySize = cert.publicKeySize;
|
||||
|
||||
|
@ -99,7 +108,7 @@ Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
|||
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||
}
|
||||
|
||||
Utils::copy< sizeof(this->signature) >(this->signature, cert.signature);
|
||||
Utils::copy<sizeof(this->signature)>(this->signature, cert.signature);
|
||||
this->signatureSize = cert.signatureSize;
|
||||
|
||||
this->maxPathLength = cert.maxPathLength;
|
||||
|
@ -107,7 +116,7 @@ Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
|||
return *this;
|
||||
}
|
||||
|
||||
ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id)
|
||||
ZT_Certificate_Identity* Certificate::addSubjectIdentity(const Identity& id)
|
||||
{
|
||||
// Store a local copy of the actual identity.
|
||||
m_identities.push_front(id);
|
||||
|
@ -124,10 +133,10 @@ ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id)
|
|||
return &(m_subjectIdentities.back());
|
||||
}
|
||||
|
||||
ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id, const Locator &loc)
|
||||
ZT_Certificate_Identity* Certificate::addSubjectIdentity(const Identity& id, const Locator& loc)
|
||||
{
|
||||
// Add identity as above.
|
||||
ZT_Certificate_Identity *const n = addSubjectIdentity(id);
|
||||
ZT_Certificate_Identity* const n = addSubjectIdentity(id);
|
||||
|
||||
// Store local copy of locator.
|
||||
m_locators.push_front(loc);
|
||||
|
@ -138,7 +147,7 @@ ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id, con
|
|||
return n;
|
||||
}
|
||||
|
||||
ZT_Certificate_Network *Certificate::addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller)
|
||||
ZT_Certificate_Network* Certificate::addSubjectNetwork(const uint64_t id, const ZT_Fingerprint& controller)
|
||||
{
|
||||
// Enlarge array of ZT_Certificate_Network and set pointer to potentially reallocated array.
|
||||
m_subjectNetworks.resize(++this->subject.networkCount);
|
||||
|
@ -146,12 +155,12 @@ ZT_Certificate_Network *Certificate::addSubjectNetwork(const uint64_t id, const
|
|||
|
||||
// Set fields in new ZT_Certificate_Network structure.
|
||||
m_subjectNetworks.back().id = id;
|
||||
Utils::copy< sizeof(ZT_Fingerprint) >(&(m_subjectNetworks.back().controller), &controller);
|
||||
Utils::copy<sizeof(ZT_Fingerprint)>(&(m_subjectNetworks.back().controller), &controller);
|
||||
|
||||
return &(m_subjectNetworks.back());
|
||||
}
|
||||
|
||||
void Certificate::addSubjectUpdateUrl(const char *url)
|
||||
void Certificate::addSubjectUpdateUrl(const char* url)
|
||||
{
|
||||
if ((url != nullptr) && (url[0] != 0)) {
|
||||
// Store local copy of URL.
|
||||
|
@ -165,9 +174,9 @@ void Certificate::addSubjectUpdateUrl(const char *url)
|
|||
}
|
||||
}
|
||||
|
||||
Vector< uint8_t > Certificate::encode(const bool omitSignature) const
|
||||
Vector<uint8_t> Certificate::encode(const bool omitSignature) const
|
||||
{
|
||||
Vector< uint8_t > enc;
|
||||
Vector<uint8_t> enc;
|
||||
Dictionary d;
|
||||
|
||||
/*
|
||||
|
@ -191,7 +200,7 @@ Vector< uint8_t > Certificate::encode(const bool omitSignature) const
|
|||
|
||||
m_encodeSubject(this->subject, d, false);
|
||||
|
||||
if (!Utils::allZero(this->issuer, sizeof(this->issuer)))
|
||||
if (! Utils::allZero(this->issuer, sizeof(this->issuer)))
|
||||
d.add("i", this->issuer, sizeof(this->issuer));
|
||||
|
||||
if (this->issuerPublicKeySize > 0)
|
||||
|
@ -203,7 +212,7 @@ Vector< uint8_t > Certificate::encode(const bool omitSignature) const
|
|||
if ((this->extendedAttributes != nullptr) && (this->extendedAttributesSize > 0))
|
||||
d["x"].assign(this->extendedAttributes, this->extendedAttributes + this->extendedAttributesSize);
|
||||
|
||||
if ((!omitSignature) && (this->signatureSize > 0))
|
||||
if ((! omitSignature) && (this->signatureSize > 0))
|
||||
d["si"].assign(this->signature, this->signature + this->signatureSize);
|
||||
|
||||
if (this->maxPathLength > 0)
|
||||
|
@ -213,12 +222,12 @@ Vector< uint8_t > Certificate::encode(const bool omitSignature) const
|
|||
return enc;
|
||||
}
|
||||
|
||||
bool Certificate::decode(const void *const data, const unsigned int len)
|
||||
bool Certificate::decode(const void* const data, const unsigned int len)
|
||||
{
|
||||
char tmp[32], tmp2[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||
|
||||
Dictionary d;
|
||||
if (!d.decode(data, len))
|
||||
if (! d.decode(data, len))
|
||||
return false;
|
||||
|
||||
m_clear();
|
||||
|
@ -232,8 +241,8 @@ bool Certificate::decode(const void *const data, const unsigned int len)
|
|||
|
||||
unsigned int cnt = (unsigned int)d.getUI("s.i$");
|
||||
for (unsigned int i = 0; i < cnt; ++i) {
|
||||
const Vector< uint8_t > &identityData = d[Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.i", i)];
|
||||
const Vector< uint8_t > &locatorData = d[Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.l", i)];
|
||||
const Vector<uint8_t>& identityData = d[Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.i", i)];
|
||||
const Vector<uint8_t>& locatorData = d[Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.l", i)];
|
||||
if (identityData.empty())
|
||||
return false;
|
||||
Identity id;
|
||||
|
@ -241,7 +250,8 @@ bool Certificate::decode(const void *const data, const unsigned int len)
|
|||
return false;
|
||||
if (locatorData.empty()) {
|
||||
this->addSubjectIdentity(id);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Locator loc;
|
||||
if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0)
|
||||
return false;
|
||||
|
@ -252,7 +262,7 @@ bool Certificate::decode(const void *const data, const unsigned int len)
|
|||
cnt = (unsigned int)d.getUI("s.nw$");
|
||||
for (unsigned int i = 0; i < cnt; ++i) {
|
||||
const uint64_t nwid = d.getUI(Dictionary::arraySubscript(tmp, sizeof(tmp), "s.nw$.i", i));
|
||||
const Vector< uint8_t > &fingerprintData = d[Dictionary::arraySubscript(tmp, sizeof(tmp), "s.nw$.c", i)];
|
||||
const Vector<uint8_t>& fingerprintData = d[Dictionary::arraySubscript(tmp, sizeof(tmp), "s.nw$.c", i)];
|
||||
if ((nwid == 0) || (fingerprintData.empty()))
|
||||
return false;
|
||||
Fingerprint fp;
|
||||
|
@ -278,72 +288,80 @@ bool Certificate::decode(const void *const data, const unsigned int len)
|
|||
d.getS("s.n.ur", this->subject.name.url, sizeof(this->subject.name.url));
|
||||
d.getS("s.n.h", this->subject.name.host, sizeof(this->subject.name.host));
|
||||
|
||||
const Vector< uint8_t > &uniqueId = d["s.uI"];
|
||||
if ((!uniqueId.empty()) && (uniqueId.size() <= sizeof(this->subject.uniqueId))) {
|
||||
const Vector<uint8_t>& uniqueId = d["s.uI"];
|
||||
if ((! uniqueId.empty()) && (uniqueId.size() <= sizeof(this->subject.uniqueId))) {
|
||||
Utils::copy(this->subject.uniqueId, uniqueId.data(), uniqueId.size());
|
||||
this->subject.uniqueIdSize = (unsigned int)uniqueId.size();
|
||||
}
|
||||
const Vector< uint8_t > &uniqueIdSignature = d["s.uS"];
|
||||
if ((!uniqueIdSignature.empty()) && (uniqueIdSignature.size() <= sizeof(this->subject.uniqueIdSignature))) {
|
||||
const Vector<uint8_t>& uniqueIdSignature = d["s.uS"];
|
||||
if ((! uniqueIdSignature.empty()) && (uniqueIdSignature.size() <= sizeof(this->subject.uniqueIdSignature))) {
|
||||
Utils::copy(this->subject.uniqueIdSignature, uniqueIdSignature.data(), uniqueIdSignature.size());
|
||||
this->subject.uniqueIdSignatureSize = (unsigned int)uniqueIdSignature.size();
|
||||
}
|
||||
|
||||
const Vector< uint8_t > &issuerData = d["i"];
|
||||
const Vector<uint8_t>& issuerData = d["i"];
|
||||
if (issuerData.size() == sizeof(this->issuer)) {
|
||||
Utils::copy< sizeof(this->issuer) >(this->issuer, issuerData.data());
|
||||
Utils::copy<sizeof(this->issuer)>(this->issuer, issuerData.data());
|
||||
}
|
||||
|
||||
const Vector< uint8_t > &issuerPublicKey = d["iPK"];
|
||||
if ((!issuerPublicKey.empty()) && (issuerPublicKey.size() <= sizeof(this->issuerPublicKey))) {
|
||||
const Vector<uint8_t>& issuerPublicKey = d["iPK"];
|
||||
if ((! issuerPublicKey.empty()) && (issuerPublicKey.size() <= sizeof(this->issuerPublicKey))) {
|
||||
Utils::copy(this->issuerPublicKey, issuerPublicKey.data(), issuerPublicKey.size());
|
||||
this->issuerPublicKeySize = (unsigned int)issuerPublicKey.size();
|
||||
}
|
||||
|
||||
const Vector< uint8_t > &publicKey = d["pK"];
|
||||
if ((!publicKey.empty()) && (publicKey.size() <= sizeof(this->publicKey))) {
|
||||
const Vector<uint8_t>& publicKey = d["pK"];
|
||||
if ((! publicKey.empty()) && (publicKey.size() <= sizeof(this->publicKey))) {
|
||||
Utils::copy(this->publicKey, publicKey.data(), publicKey.size());
|
||||
this->publicKeySize = (unsigned int)publicKey.size();
|
||||
}
|
||||
|
||||
m_extendedAttributes = d["x"];
|
||||
if (!m_extendedAttributes.empty()) {
|
||||
if (! m_extendedAttributes.empty()) {
|
||||
this->extendedAttributes = m_extendedAttributes.data();
|
||||
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||
}
|
||||
|
||||
const Vector< uint8_t > &signature = d["si"];
|
||||
if ((!signature.empty()) && (signature.size() <= sizeof(this->signature))) {
|
||||
const Vector<uint8_t>& signature = d["si"];
|
||||
if ((! signature.empty()) && (signature.size() <= sizeof(this->signature))) {
|
||||
Utils::copy(this->signature, signature.data(), signature.size());
|
||||
this->signatureSize = (unsigned int)signature.size();
|
||||
}
|
||||
|
||||
this->maxPathLength = (unsigned int)d.getUI("l");
|
||||
|
||||
const Vector< uint8_t > enc(encode(true));
|
||||
const Vector<uint8_t> enc(encode(true));
|
||||
SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Certificate::sign(const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE], const void *const issuerPrivateKey, const unsigned int issuerPrivateKeySize)
|
||||
bool Certificate::sign(
|
||||
const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE],
|
||||
const void* const issuerPrivateKey,
|
||||
const unsigned int issuerPrivateKeySize)
|
||||
{
|
||||
if ((!issuerPrivateKey) || (issuerPrivateKeySize == 0))
|
||||
if ((! issuerPrivateKey) || (issuerPrivateKeySize == 0))
|
||||
return false;
|
||||
|
||||
switch (reinterpret_cast<const uint8_t *>(issuerPrivateKey)[0]) {
|
||||
switch (reinterpret_cast<const uint8_t*>(issuerPrivateKey)[0]) {
|
||||
default:
|
||||
return false;
|
||||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
if (issuerPrivateKeySize == (1 + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE)) {
|
||||
Utils::copy< sizeof(this->issuer) >(this->issuer, issuer);
|
||||
Utils::copy< 1 + ZT_ECC384_PUBLIC_KEY_SIZE >(this->issuerPublicKey, issuerPrivateKey); // private is prefixed with public
|
||||
Utils::copy<sizeof(this->issuer)>(this->issuer, issuer);
|
||||
Utils::copy<1 + ZT_ECC384_PUBLIC_KEY_SIZE>(
|
||||
this->issuerPublicKey,
|
||||
issuerPrivateKey); // private is prefixed with public
|
||||
this->issuerPublicKeySize = 1 + ZT_ECC384_PUBLIC_KEY_SIZE;
|
||||
|
||||
const Vector< uint8_t > enc(encode(true));
|
||||
const Vector<uint8_t> enc(encode(true));
|
||||
SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
|
||||
|
||||
ECC384ECDSASign(reinterpret_cast<const uint8_t *>(issuerPrivateKey) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE, this->serialNo, this->signature);
|
||||
ECC384ECDSASign(
|
||||
reinterpret_cast<const uint8_t*>(issuerPrivateKey) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE,
|
||||
this->serialNo,
|
||||
this->signature);
|
||||
this->signatureSize = ZT_ECC384_SIGNATURE_SIZE;
|
||||
|
||||
return true;
|
||||
|
@ -364,19 +382,24 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
if (this->subject.identityCount > 0) {
|
||||
if (this->subject.identities) {
|
||||
for (unsigned int i = 0; i < this->subject.identityCount; ++i) {
|
||||
if (!this->subject.identities[i].identity) {
|
||||
if (! this->subject.identities[i].identity) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
if (checkSignatures) {
|
||||
if (!reinterpret_cast<const Identity *>(this->subject.identities[i].identity)->locallyValidate()) {
|
||||
if (! reinterpret_cast<const Identity*>(this->subject.identities[i].identity)
|
||||
->locallyValidate()) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_IDENTITY;
|
||||
}
|
||||
if ((this->subject.identities[i].locator) && (!reinterpret_cast<const Locator *>(this->subject.identities[i].locator)->verify(*reinterpret_cast<const Identity *>(this->subject.identities[i].identity)))) {
|
||||
if ((this->subject.identities[i].locator)
|
||||
&& (! reinterpret_cast<const Locator*>(this->subject.identities[i].locator)
|
||||
->verify(
|
||||
*reinterpret_cast<const Identity*>(this->subject.identities[i].identity)))) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_COMPONENT_SIGNATURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
@ -384,11 +407,12 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
if (this->subject.networkCount > 0) {
|
||||
if (this->subject.networks) {
|
||||
for (unsigned int i = 0; i < this->subject.networkCount; ++i) {
|
||||
if (!this->subject.networks[i].id) {
|
||||
if (! this->subject.networks[i].id) {
|
||||
return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
@ -396,23 +420,26 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
if (this->subject.updateURLCount > 0) {
|
||||
if (this->subject.updateURLs) {
|
||||
for (unsigned int i = 0; i < this->subject.updateURLCount; ++i) {
|
||||
if (!this->subject.updateURLs[i])
|
||||
if (! this->subject.updateURLs[i])
|
||||
return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
|
||||
}
|
||||
}
|
||||
|
||||
if ((this->subject.uniqueIdSize > sizeof(this->subject.uniqueId)) || (this->subject.uniqueIdSignatureSize > sizeof(this->subject.uniqueIdSignature))) {
|
||||
if ((this->subject.uniqueIdSize > sizeof(this->subject.uniqueId))
|
||||
|| (this->subject.uniqueIdSignatureSize > sizeof(this->subject.uniqueIdSignature))) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
if ((this->issuerPublicKeySize > sizeof(this->issuerPublicKey)) || (this->publicKeySize > sizeof(this->publicKey))) {
|
||||
if ((this->issuerPublicKeySize > sizeof(this->issuerPublicKey))
|
||||
|| (this->publicKeySize > sizeof(this->publicKey))) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
if ((this->extendedAttributesSize > 0) && (!this->extendedAttributes)) {
|
||||
if ((this->extendedAttributesSize > 0) && (! this->extendedAttributes)) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
|
@ -424,21 +451,25 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
// Signature check fails if main signature is not present or invalid.
|
||||
// Note that the serial number / SHA384 hash is computed on decode(), so
|
||||
// this value is not something we blindly trust from input.
|
||||
if ((this->issuerPublicKeySize > 0) && (this->issuerPublicKeySize <= (unsigned int)sizeof(this->issuerPublicKey))) {
|
||||
if ((this->issuerPublicKeySize > 0)
|
||||
&& (this->issuerPublicKeySize <= (unsigned int)sizeof(this->issuerPublicKey))) {
|
||||
switch (this->issuerPublicKey[0]) {
|
||||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
if ((this->issuerPublicKeySize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1)) && (this->signatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
if (!ECC384ECDSAVerify(this->issuerPublicKey + 1, this->serialNo, this->signature)) {
|
||||
if ((this->issuerPublicKeySize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1))
|
||||
&& (this->signatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
if (! ECC384ECDSAVerify(this->issuerPublicKey + 1, this->serialNo, this->signature)) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
|
||||
|
@ -451,52 +482,66 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_NONE:
|
||||
break;
|
||||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
if ((this->subject.uniqueIdSize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1)) && (this->subject.uniqueIdSignatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
if ((this->subject.uniqueIdSize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1))
|
||||
&& (this->subject.uniqueIdSignatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
Dictionary d;
|
||||
m_encodeSubject(this->subject, d, true);
|
||||
|
||||
Vector< uint8_t > enc;
|
||||
Vector<uint8_t> enc;
|
||||
enc.reserve(1024);
|
||||
d.encode(enc);
|
||||
|
||||
static_assert(ZT_ECC384_SIGNATURE_HASH_SIZE == ZT_SHA384_DIGEST_SIZE, "ECC384 should take 384-bit hash");
|
||||
static_assert(
|
||||
ZT_ECC384_SIGNATURE_HASH_SIZE == ZT_SHA384_DIGEST_SIZE,
|
||||
"ECC384 should take 384-bit hash");
|
||||
uint8_t h[ZT_SHA384_DIGEST_SIZE];
|
||||
SHA384(h, enc.data(), (unsigned int)enc.size());
|
||||
|
||||
if (!ECC384ECDSAVerify(this->subject.uniqueId + 1, h, this->subject.uniqueIdSignature)) {
|
||||
if (! ECC384ECDSAVerify(
|
||||
this->subject.uniqueId + 1,
|
||||
h,
|
||||
this->subject.uniqueIdSignature)) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clock >= 0) {
|
||||
if (!this->verifyTimeWindow(clock))
|
||||
if (! this->verifyTimeWindow(clock))
|
||||
return ZT_CERTIFICATE_ERROR_OUT_OF_VALID_TIME_WINDOW;
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
return ZT_CERTIFICATE_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool Certificate::newKeyPair(const ZT_CertificatePublicKeyAlgorithm type, uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE], int *const publicKeySize, uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE], int *const privateKeySize)
|
||||
bool Certificate::newKeyPair(
|
||||
const ZT_CertificatePublicKeyAlgorithm type,
|
||||
uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE],
|
||||
int* const publicKeySize,
|
||||
uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE],
|
||||
int* const privateKeySize)
|
||||
{
|
||||
switch (type) {
|
||||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
publicKey[0] = (uint8_t)ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384;
|
||||
ZeroTier::ECC384GenerateKey(publicKey + 1, privateKey + ZT_ECC384_PUBLIC_KEY_SIZE + 1);
|
||||
ZeroTier::Utils::copy< ZT_ECC384_PUBLIC_KEY_SIZE + 1 >(privateKey, publicKey);
|
||||
ZeroTier::Utils::copy<ZT_ECC384_PUBLIC_KEY_SIZE + 1>(privateKey, publicKey);
|
||||
*publicKeySize = ZT_ECC384_PUBLIC_KEY_SIZE + 1;
|
||||
*privateKeySize = ZT_ECC384_PUBLIC_KEY_SIZE + 1 + ZT_ECC384_PRIVATE_KEY_SIZE;
|
||||
return true;
|
||||
|
@ -506,12 +551,17 @@ bool Certificate::newKeyPair(const ZT_CertificatePublicKeyAlgorithm type, uint8_
|
|||
return false;
|
||||
}
|
||||
|
||||
Vector< uint8_t > Certificate::createCSR(const ZT_Certificate_Subject &s, const void *const certificatePublicKey, const unsigned int certificatePublicKeySize, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize)
|
||||
Vector<uint8_t> Certificate::createCSR(
|
||||
const ZT_Certificate_Subject& s,
|
||||
const void* const certificatePublicKey,
|
||||
const unsigned int certificatePublicKeySize,
|
||||
const void* uniqueIdPrivate,
|
||||
unsigned int uniqueIdPrivateSize)
|
||||
{
|
||||
Vector< uint8_t > enc;
|
||||
Vector<uint8_t> enc;
|
||||
|
||||
ZT_Certificate_Subject sc;
|
||||
Utils::copy< sizeof(ZT_Certificate_Subject) >(&sc, &s);
|
||||
Utils::copy<sizeof(ZT_Certificate_Subject)>(&sc, &s);
|
||||
|
||||
if (m_setSubjectUniqueId(sc, uniqueIdPrivate, uniqueIdPrivateSize)) {
|
||||
Dictionary d;
|
||||
|
@ -526,8 +576,8 @@ Vector< uint8_t > Certificate::createCSR(const ZT_Certificate_Subject &s, const
|
|||
|
||||
void Certificate::m_clear()
|
||||
{
|
||||
ZT_Certificate *const sup = this;
|
||||
Utils::zero< sizeof(ZT_Certificate) >(sup);
|
||||
ZT_Certificate* const sup = this;
|
||||
Utils::zero<sizeof(ZT_Certificate)>(sup);
|
||||
|
||||
m_identities.clear();
|
||||
m_locators.clear();
|
||||
|
@ -539,14 +589,20 @@ void Certificate::m_clear()
|
|||
m_extendedAttributes.clear();
|
||||
}
|
||||
|
||||
bool Certificate::m_setSubjectUniqueId(ZT_Certificate_Subject &s, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize)
|
||||
bool Certificate::m_setSubjectUniqueId(
|
||||
ZT_Certificate_Subject& s,
|
||||
const void* uniqueIdPrivate,
|
||||
unsigned int uniqueIdPrivateSize)
|
||||
{
|
||||
if (uniqueIdPrivateSize > 0) {
|
||||
if ((uniqueIdPrivate != nullptr) && (uniqueIdPrivateSize == (1 + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE)) && (reinterpret_cast<const uint8_t *>(uniqueIdPrivate)[0] == (uint8_t)ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384)) {
|
||||
Utils::copy< 1 + ZT_ECC384_PUBLIC_KEY_SIZE >(s.uniqueId, uniqueIdPrivate);
|
||||
if ((uniqueIdPrivate != nullptr)
|
||||
&& (uniqueIdPrivateSize == (1 + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE))
|
||||
&& (reinterpret_cast<const uint8_t*>(uniqueIdPrivate)[0]
|
||||
== (uint8_t)ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384)) {
|
||||
Utils::copy<1 + ZT_ECC384_PUBLIC_KEY_SIZE>(s.uniqueId, uniqueIdPrivate);
|
||||
s.uniqueIdSize = 1 + ZT_ECC384_PUBLIC_KEY_SIZE; // private is prefixed with public
|
||||
|
||||
Vector< uint8_t > enc;
|
||||
Vector<uint8_t> enc;
|
||||
Dictionary d;
|
||||
m_encodeSubject(s, d, true);
|
||||
d.encode(enc);
|
||||
|
@ -554,21 +610,26 @@ bool Certificate::m_setSubjectUniqueId(ZT_Certificate_Subject &s, const void *un
|
|||
uint8_t h[ZT_SHA384_DIGEST_SIZE];
|
||||
SHA384(h, enc.data(), (unsigned int)enc.size());
|
||||
|
||||
ECC384ECDSASign(reinterpret_cast<const uint8_t *>(uniqueIdPrivate) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE, h, s.uniqueIdSignature);
|
||||
ECC384ECDSASign(
|
||||
reinterpret_cast<const uint8_t*>(uniqueIdPrivate) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE,
|
||||
h,
|
||||
s.uniqueIdSignature);
|
||||
s.uniqueIdSignatureSize = ZT_ECC384_SIGNATURE_SIZE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Utils::zero< sizeof(s.uniqueId) >(s.uniqueId);
|
||||
}
|
||||
else {
|
||||
Utils::zero<sizeof(s.uniqueId)>(s.uniqueId);
|
||||
s.uniqueIdSize = 0;
|
||||
Utils::zero< sizeof(s.uniqueIdSignature) >(s.uniqueIdSignature);
|
||||
Utils::zero<sizeof(s.uniqueIdSignature)>(s.uniqueIdSignature);
|
||||
s.uniqueIdSignatureSize = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature)
|
||||
void Certificate::m_encodeSubject(const ZT_Certificate_Subject& s, Dictionary& d, bool omitUniqueIdProofSignature)
|
||||
{
|
||||
char tmp[32];
|
||||
|
||||
|
@ -578,9 +639,13 @@ void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d
|
|||
d.add("s.i$", (uint64_t)s.identityCount);
|
||||
for (unsigned int i = 0; i < s.identityCount; ++i) {
|
||||
if (s.identities[i].identity)
|
||||
d.addO(Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.i", i), *reinterpret_cast<const Identity *>(s.identities[i].identity));
|
||||
d.addO(
|
||||
Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.i", i),
|
||||
*reinterpret_cast<const Identity*>(s.identities[i].identity));
|
||||
if (s.identities[i].locator)
|
||||
d.addO(Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.l", i), *reinterpret_cast<const Locator *>(s.identities[i].locator));
|
||||
d.addO(
|
||||
Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.l", i),
|
||||
*reinterpret_cast<const Locator*>(s.identities[i].locator));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +691,7 @@ void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d
|
|||
|
||||
if (s.uniqueIdSize > 0)
|
||||
d["s.uI"].assign(s.uniqueId, s.uniqueId + s.uniqueIdSize);
|
||||
if ((!omitUniqueIdProofSignature) && (s.uniqueIdSignatureSize > 0))
|
||||
if ((! omitUniqueIdProofSignature) && (s.uniqueIdSignatureSize > 0))
|
||||
d["s.uS"].assign(s.uniqueIdSignature, s.uniqueIdSignature + s.uniqueIdSignatureSize);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
#ifndef ZT_CERTIFICATE_HPP
|
||||
#define ZT_CERTIFICATE_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Containers.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -43,27 +43,28 @@ namespace ZeroTier {
|
|||
* field, so these will not work correctly before sign() or decode() is
|
||||
* called.
|
||||
*/
|
||||
class Certificate : public ZT_Certificate
|
||||
{
|
||||
public:
|
||||
class Certificate : public ZT_Certificate {
|
||||
public:
|
||||
Certificate() noexcept;
|
||||
explicit Certificate(const ZT_Certificate &apiCert);
|
||||
Certificate(const Certificate &cert);
|
||||
explicit Certificate(const ZT_Certificate& apiCert);
|
||||
Certificate(const Certificate& cert);
|
||||
~Certificate();
|
||||
|
||||
Certificate &operator=(const ZT_Certificate &cert);
|
||||
Certificate& operator=(const ZT_Certificate& cert);
|
||||
|
||||
ZT_INLINE Certificate &operator=(const Certificate &cert) noexcept
|
||||
ZT_INLINE Certificate& operator=(const Certificate& cert) noexcept
|
||||
{
|
||||
if (likely(&cert != this)) {
|
||||
const ZT_Certificate *const sup = &cert;
|
||||
const ZT_Certificate* const sup = &cert;
|
||||
*this = *sup;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE H384 getSerialNo() const noexcept
|
||||
{ return H384(this->serialNo); }
|
||||
{
|
||||
return H384(this->serialNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subject node/identity without a locator
|
||||
|
@ -71,7 +72,7 @@ public:
|
|||
* @param id Identity
|
||||
* @return Pointer to C struct
|
||||
*/
|
||||
ZT_Certificate_Identity *addSubjectIdentity(const Identity &id);
|
||||
ZT_Certificate_Identity* addSubjectIdentity(const Identity& id);
|
||||
|
||||
/**
|
||||
* Add a subject node/identity with a locator
|
||||
|
@ -80,7 +81,7 @@ public:
|
|||
* @param loc Locator signed by identity (signature is NOT checked here)
|
||||
* @return Pointer to C struct
|
||||
*/
|
||||
ZT_Certificate_Identity *addSubjectIdentity(const Identity &id, const Locator &loc);
|
||||
ZT_Certificate_Identity* addSubjectIdentity(const Identity& id, const Locator& loc);
|
||||
|
||||
/**
|
||||
* Add a subject network
|
||||
|
@ -89,14 +90,14 @@ public:
|
|||
* @param controller Network controller's full fingerprint
|
||||
* @return Pointer to C struct
|
||||
*/
|
||||
ZT_Certificate_Network *addSubjectNetwork(uint64_t id, const ZT_Fingerprint &controller);
|
||||
ZT_Certificate_Network* addSubjectNetwork(uint64_t id, const ZT_Fingerprint& controller);
|
||||
|
||||
/**
|
||||
* Add an update URL to the updateUrls list
|
||||
*
|
||||
* @param url Update URL
|
||||
*/
|
||||
void addSubjectUpdateUrl(const char *url);
|
||||
void addSubjectUpdateUrl(const char* url);
|
||||
|
||||
/**
|
||||
* Sign subject with unique ID private key and set.
|
||||
|
@ -108,8 +109,10 @@ public:
|
|||
* @param uniqueIdPrivateSize Size of private key
|
||||
* @return True on success
|
||||
*/
|
||||
ZT_INLINE bool setSubjectUniqueId(const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize)
|
||||
{ return m_setSubjectUniqueId(this->subject, uniqueIdPrivate, uniqueIdPrivateSize); }
|
||||
ZT_INLINE bool setSubjectUniqueId(const void* uniqueIdPrivate, unsigned int uniqueIdPrivateSize)
|
||||
{
|
||||
return m_setSubjectUniqueId(this->subject, uniqueIdPrivate, uniqueIdPrivateSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshal this certificate in binary form
|
||||
|
@ -120,7 +123,7 @@ public:
|
|||
* @param omitSignature If true omit the signature field (for signing and verification, default is false)
|
||||
* @return Marshaled certificate
|
||||
*/
|
||||
Vector< uint8_t > encode(bool omitSignature = false) const;
|
||||
Vector<uint8_t> encode(bool omitSignature = false) const;
|
||||
|
||||
/**
|
||||
* Decode this certificate from marshaled bytes.
|
||||
|
@ -129,7 +132,7 @@ public:
|
|||
* @param len Length of marshalled certificate
|
||||
* @return True if input is valid and was unmarshalled (signature is NOT checked)
|
||||
*/
|
||||
bool decode(const void *data, unsigned int len);
|
||||
bool decode(const void* data, unsigned int len);
|
||||
|
||||
/**
|
||||
* Sign this certificate.
|
||||
|
@ -138,7 +141,10 @@ public:
|
|||
*
|
||||
* @return True on success
|
||||
*/
|
||||
bool sign(const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE], const void *issuerPrivateKey, unsigned int issuerPrivateKeySize);
|
||||
bool sign(
|
||||
const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE],
|
||||
const void* issuerPrivateKey,
|
||||
unsigned int issuerPrivateKeySize);
|
||||
|
||||
/**
|
||||
* Verify self-contained signatures and validity of certificate structure
|
||||
|
@ -159,7 +165,10 @@ public:
|
|||
* @return True if certificate is not expired or outside window
|
||||
*/
|
||||
ZT_INLINE bool verifyTimeWindow(int64_t clock) const noexcept
|
||||
{ return ((clock >= this->validity[0]) && (clock <= this->validity[1]) && (this->validity[0] <= this->validity[1])); }
|
||||
{
|
||||
return (
|
||||
(clock >= this->validity[0]) && (clock <= this->validity[1]) && (this->validity[0] <= this->validity[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new certificate public/private key pair
|
||||
|
@ -171,7 +180,12 @@ public:
|
|||
* @param privateKeySize Result parameter: set to size of private key
|
||||
* @return True on success
|
||||
*/
|
||||
static bool newKeyPair(const ZT_CertificatePublicKeyAlgorithm type, uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE], int *const publicKeySize, uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE], int *const privateKeySize);
|
||||
static bool newKeyPair(
|
||||
const ZT_CertificatePublicKeyAlgorithm type,
|
||||
uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE],
|
||||
int* const publicKeySize,
|
||||
uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE],
|
||||
int* const privateKeySize);
|
||||
|
||||
/**
|
||||
* Create a CSR that encodes the subject of this certificate
|
||||
|
@ -183,46 +197,66 @@ public:
|
|||
* @param uniqueIdPrivateSize Size of unique ID private key
|
||||
* @return Encoded subject (without any unique ID fields) or empty vector on error
|
||||
*/
|
||||
static Vector< uint8_t > createCSR(const ZT_Certificate_Subject &s, const void *certificatePublicKey, unsigned int certificatePublicKeySize, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
|
||||
static Vector<uint8_t> createCSR(
|
||||
const ZT_Certificate_Subject& s,
|
||||
const void* certificatePublicKey,
|
||||
unsigned int certificatePublicKeySize,
|
||||
const void* uniqueIdPrivate,
|
||||
unsigned int uniqueIdPrivateSize);
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)Utils::loadMachineEndian< uint32_t >(this->serialNo); }
|
||||
{
|
||||
return (unsigned long)Utils::loadMachineEndian<uint32_t>(this->serialNo);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const ZT_Certificate &c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0; }
|
||||
ZT_INLINE bool operator==(const ZT_Certificate& c) const noexcept
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const ZT_Certificate &c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0; }
|
||||
ZT_INLINE bool operator!=(const ZT_Certificate& c) const noexcept
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const ZT_Certificate &c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0; }
|
||||
ZT_INLINE bool operator<(const ZT_Certificate& c) const noexcept
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const ZT_Certificate &c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0; }
|
||||
ZT_INLINE bool operator<=(const ZT_Certificate& c) const noexcept
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const ZT_Certificate &c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0; }
|
||||
ZT_INLINE bool operator>(const ZT_Certificate& c) const noexcept
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const ZT_Certificate &c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; }
|
||||
ZT_INLINE bool operator>=(const ZT_Certificate& c) const noexcept
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
void m_clear();
|
||||
static bool m_setSubjectUniqueId(ZT_Certificate_Subject &s, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
|
||||
static void m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature);
|
||||
static bool
|
||||
m_setSubjectUniqueId(ZT_Certificate_Subject& s, const void* uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
|
||||
static void m_encodeSubject(const ZT_Certificate_Subject& s, Dictionary& d, bool omitUniqueIdProofSignature);
|
||||
|
||||
// These hold any identity or locator objects that are owned by and should
|
||||
// be deleted with this certificate. Lists are used so the pointers never
|
||||
// change.
|
||||
ForwardList< Identity > m_identities;
|
||||
ForwardList< Locator > m_locators;
|
||||
ForwardList< String > m_strings;
|
||||
ForwardList<Identity> m_identities;
|
||||
ForwardList<Locator> m_locators;
|
||||
ForwardList<String> m_strings;
|
||||
|
||||
// These are stored in a vector because the memory needs to be contiguous.
|
||||
Vector< ZT_Certificate_Identity > m_subjectIdentities;
|
||||
Vector< ZT_Certificate_Network > m_subjectNetworks;
|
||||
Vector< const char * > m_updateUrls;
|
||||
Vector< uint8_t > m_extendedAttributes;
|
||||
Vector<ZT_Certificate_Identity> m_subjectIdentities;
|
||||
Vector<ZT_Certificate_Network> m_subjectNetworks;
|
||||
Vector<const char*> m_updateUrls;
|
||||
Vector<uint8_t> m_extendedAttributes;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#define ZT_CORE 1
|
||||
|
||||
#include "OS.hpp"
|
||||
#include "zerotier.h"
|
||||
#include "version.h"
|
||||
#include "zerotier.h"
|
||||
|
||||
/**
|
||||
* Length of a ZeroTier address in bytes
|
||||
|
@ -190,7 +190,8 @@
|
|||
#define ZT_PEER_WHOIS_RATE_LIMIT 100
|
||||
|
||||
/**
|
||||
* General rate limit for other kinds of rate-limited packets (HELLO, credential request, etc.) both inbound and outbound
|
||||
* General rate limit for other kinds of rate-limited packets (HELLO, credential request, etc.) both inbound and
|
||||
* outbound
|
||||
*/
|
||||
#define ZT_PEER_GENERAL_RATE_LIMIT 500
|
||||
|
||||
|
|
|
@ -19,111 +19,104 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
||||
#include <atomic>
|
||||
#include <unordered_map>
|
||||
#include <forward_list>
|
||||
#include <unordered_map>
|
||||
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
template< typename V >
|
||||
class Vector : public std::vector< V >
|
||||
{
|
||||
public:
|
||||
ZT_INLINE Vector() :
|
||||
std::vector< V >()
|
||||
{}
|
||||
template <typename V> class Vector : public std::vector<V> {
|
||||
public:
|
||||
ZT_INLINE Vector() : std::vector<V>()
|
||||
{
|
||||
}
|
||||
|
||||
template< typename I >
|
||||
ZT_INLINE Vector(I begin, I end) :
|
||||
std::vector< V >(begin, end)
|
||||
{}
|
||||
template <typename I> ZT_INLINE Vector(I begin, I end) : std::vector<V>(begin, end)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template< typename V >
|
||||
class List : public std::list< V >
|
||||
{
|
||||
template <typename V> class List : public std::list<V> {
|
||||
};
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
||||
struct intl_MapHasher
|
||||
{
|
||||
template< typename O >
|
||||
std::size_t operator()(const O &obj) const noexcept
|
||||
{ return (std::size_t)obj.hashCode(); }
|
||||
struct intl_MapHasher {
|
||||
template <typename O> std::size_t operator()(const O& obj) const noexcept
|
||||
{
|
||||
return (std::size_t)obj.hashCode();
|
||||
}
|
||||
|
||||
std::size_t operator()(const Vector< uint8_t > &bytes) const noexcept
|
||||
{ return (std::size_t)Utils::fnv1a32(bytes.data(), (unsigned int)bytes.size()); }
|
||||
std::size_t operator()(const Vector<uint8_t>& bytes) const noexcept
|
||||
{
|
||||
return (std::size_t)Utils::fnv1a32(bytes.data(), (unsigned int)bytes.size());
|
||||
}
|
||||
|
||||
std::size_t operator()(const uint64_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash64(i ^ Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash64(i ^ Utils::s_mapNonce);
|
||||
}
|
||||
|
||||
std::size_t operator()(const int64_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash64((uint64_t)i ^ Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash64((uint64_t)i ^ Utils::s_mapNonce);
|
||||
}
|
||||
|
||||
std::size_t operator()(const uint32_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash32(i ^ (uint32_t)Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash32(i ^ (uint32_t)Utils::s_mapNonce);
|
||||
}
|
||||
|
||||
std::size_t operator()(const int32_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash32((uint32_t)i ^ (uint32_t)Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash32((uint32_t)i ^ (uint32_t)Utils::s_mapNonce);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename K, typename V >
|
||||
class Map : public std::unordered_map< K, V, intl_MapHasher >
|
||||
{
|
||||
template <typename K, typename V> class Map : public std::unordered_map<K, V, intl_MapHasher> {
|
||||
};
|
||||
|
||||
template< typename K, typename V >
|
||||
class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K > >
|
||||
{
|
||||
template <typename K, typename V>
|
||||
class MultiMap : public std::unordered_multimap<K, V, intl_MapHasher, std::equal_to<K> > {
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename K, typename V>
|
||||
class Map : public std::map< K, V >
|
||||
{};
|
||||
template <typename K, typename V> class Map : public std::map<K, V> {
|
||||
};
|
||||
|
||||
template<typename K, typename V>
|
||||
class MultiMap : public std::multimap< K, V >
|
||||
{};
|
||||
template <typename K, typename V> class MultiMap : public std::multimap<K, V> {
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template< typename K, typename V >
|
||||
class SortedMap : public std::map< K, V >
|
||||
{
|
||||
template <typename K, typename V> class SortedMap : public std::map<K, V> {
|
||||
};
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
||||
template< typename V >
|
||||
class ForwardList : public std::forward_list< V >
|
||||
{
|
||||
template <typename V> class ForwardList : public std::forward_list<V> {
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template< typename V >
|
||||
class ForwardList : public std::list< V >
|
||||
{};
|
||||
template <typename V> class ForwardList : public std::list<V> {
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template< typename V >
|
||||
class Set : public std::set< V, std::less< V > >
|
||||
{
|
||||
template <typename V> class Set : public std::set<V, std::less<V> > {
|
||||
};
|
||||
|
||||
typedef std::string String;
|
||||
|
@ -131,48 +124,72 @@ typedef std::string String;
|
|||
/**
|
||||
* A 384-bit hash
|
||||
*/
|
||||
struct H384
|
||||
{
|
||||
struct H384 {
|
||||
uint64_t data[6];
|
||||
|
||||
ZT_INLINE H384() noexcept
|
||||
{ Utils::zero< sizeof(data) >(data); }
|
||||
|
||||
ZT_INLINE H384(const H384 &b) noexcept
|
||||
{ Utils::copy< 48 >(data, b.data); }
|
||||
|
||||
explicit ZT_INLINE H384(const void *const d) noexcept
|
||||
{ Utils::copy< 48 >(data, d); }
|
||||
|
||||
ZT_INLINE H384 &operator=(const H384 &b) noexcept
|
||||
{
|
||||
Utils::copy< 48 >(data, b.data);
|
||||
Utils::zero<sizeof(data)>(data);
|
||||
}
|
||||
|
||||
ZT_INLINE H384(const H384& b) noexcept
|
||||
{
|
||||
Utils::copy<48>(data, b.data);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE H384(const void* const d) noexcept
|
||||
{
|
||||
Utils::copy<48>(data, d);
|
||||
}
|
||||
|
||||
ZT_INLINE H384& operator=(const H384& b) noexcept
|
||||
{
|
||||
Utils::copy<48>(data, b.data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)data[0]; }
|
||||
{
|
||||
return (unsigned long)data[0];
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return ((data[0] != 0) && (data[1] != 0) && (data[2] != 0) && (data[3] != 0) && (data[4] != 0) && (data[5] != 0)); }
|
||||
{
|
||||
return (
|
||||
(data[0] != 0) && (data[1] != 0) && (data[2] != 0) && (data[3] != 0) && (data[4] != 0) && (data[5] != 0));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const H384 &b) const noexcept
|
||||
{ return ((data[0] == b.data[0]) && (data[1] == b.data[1]) && (data[2] == b.data[2]) && (data[3] == b.data[3]) && (data[4] == b.data[4]) && (data[5] == b.data[5])); }
|
||||
ZT_INLINE bool operator==(const H384& b) const noexcept
|
||||
{
|
||||
return (
|
||||
(data[0] == b.data[0]) && (data[1] == b.data[1]) && (data[2] == b.data[2]) && (data[3] == b.data[3])
|
||||
&& (data[4] == b.data[4]) && (data[5] == b.data[5]));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const H384 &b) const noexcept
|
||||
{ return !(*this == b); }
|
||||
ZT_INLINE bool operator!=(const H384& b) const noexcept
|
||||
{
|
||||
return ! (*this == b);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const H384 &b) const noexcept
|
||||
{ return std::lexicographical_compare(data, data + 6, b.data, b.data + 6); }
|
||||
ZT_INLINE bool operator<(const H384& b) const noexcept
|
||||
{
|
||||
return std::lexicographical_compare(data, data + 6, b.data, b.data + 6);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const H384 &b) const noexcept
|
||||
{ return !(b < *this); }
|
||||
ZT_INLINE bool operator<=(const H384& b) const noexcept
|
||||
{
|
||||
return ! (b < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const H384 &b) const noexcept
|
||||
{ return (b < *this); }
|
||||
ZT_INLINE bool operator>(const H384& b) const noexcept
|
||||
{
|
||||
return (b < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const H384 &b) const noexcept
|
||||
{ return !(*this < b); }
|
||||
ZT_INLINE bool operator>=(const H384& b) const noexcept
|
||||
{
|
||||
return ! (*this < b);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(H384) == 48, "H384 contains unnecessary padding");
|
||||
|
@ -182,21 +199,25 @@ static_assert(sizeof(H384) == 48, "H384 contains unnecessary padding");
|
|||
*
|
||||
* @tparam S Size in bytes
|
||||
*/
|
||||
template< unsigned long S >
|
||||
struct Blob
|
||||
{
|
||||
template <unsigned long S> struct Blob {
|
||||
uint8_t data[S];
|
||||
|
||||
ZT_INLINE Blob() noexcept
|
||||
{ Utils::zero< S >(data); }
|
||||
{
|
||||
Utils::zero<S>(data);
|
||||
}
|
||||
|
||||
ZT_INLINE Blob(const Blob &b) noexcept
|
||||
{ Utils::copy< S >(data, b.data); }
|
||||
ZT_INLINE Blob(const Blob& b) noexcept
|
||||
{
|
||||
Utils::copy<S>(data, b.data);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE Blob(const void *const d) noexcept
|
||||
{ Utils::copy< S >(data, d); }
|
||||
explicit ZT_INLINE Blob(const void* const d) noexcept
|
||||
{
|
||||
Utils::copy<S>(data, d);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE Blob(const void *const d, const unsigned int l) noexcept
|
||||
explicit ZT_INLINE Blob(const void* const d, const unsigned int l) noexcept
|
||||
{
|
||||
Utils::copy(data, d, (l > (unsigned int)S) ? (unsigned int)S : l);
|
||||
if (l < S) {
|
||||
|
@ -204,37 +225,53 @@ struct Blob
|
|||
}
|
||||
}
|
||||
|
||||
ZT_INLINE Blob &operator=(const Blob &b) noexcept
|
||||
ZT_INLINE Blob& operator=(const Blob& b) noexcept
|
||||
{
|
||||
Utils::copy< S >(data, b.data);
|
||||
Utils::copy<S>(data, b.data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return Utils::fnv1a32(data, (unsigned int)S); }
|
||||
{
|
||||
return Utils::fnv1a32(data, (unsigned int)S);
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return Utils::allZero(data, (unsigned int)S); }
|
||||
{
|
||||
return Utils::allZero(data, (unsigned int)S);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Blob &b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) == 0); }
|
||||
ZT_INLINE bool operator==(const Blob& b) const noexcept
|
||||
{
|
||||
return (memcmp(data, b.data, S) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Blob &b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) != 0); }
|
||||
ZT_INLINE bool operator!=(const Blob& b) const noexcept
|
||||
{
|
||||
return (memcmp(data, b.data, S) != 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Blob &b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) < 0); }
|
||||
ZT_INLINE bool operator<(const Blob& b) const noexcept
|
||||
{
|
||||
return (memcmp(data, b.data, S) < 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Blob &b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) <= 0); }
|
||||
ZT_INLINE bool operator<=(const Blob& b) const noexcept
|
||||
{
|
||||
return (memcmp(data, b.data, S) <= 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Blob &b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) > 0); }
|
||||
ZT_INLINE bool operator>(const Blob& b) const noexcept
|
||||
{
|
||||
return (memcmp(data, b.data, S) > 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Blob &b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) >= 0); }
|
||||
ZT_INLINE bool operator>=(const Blob& b) const noexcept
|
||||
{
|
||||
return (memcmp(data, b.data, S) >= 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
#ifndef ZT_RUNTIMEENVIRONMENT_HPP
|
||||
#define ZT_RUNTIMEENVIRONMENT_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "TinyMap.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "TinyMap.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -38,55 +38,56 @@ class Network;
|
|||
/**
|
||||
* Node instance context
|
||||
*/
|
||||
class Context
|
||||
{
|
||||
public:
|
||||
ZT_INLINE Context(Node *const n) noexcept:
|
||||
instanceId(Utils::getSecureRandomU64()),
|
||||
node(n),
|
||||
uPtr(nullptr),
|
||||
localNetworkController(nullptr),
|
||||
store(nullptr),
|
||||
networks(nullptr),
|
||||
t(nullptr),
|
||||
expect(nullptr),
|
||||
vl2(nullptr),
|
||||
vl1(nullptr),
|
||||
topology(nullptr),
|
||||
sa(nullptr),
|
||||
ts(nullptr)
|
||||
class Context {
|
||||
public:
|
||||
ZT_INLINE Context(Node* const n) noexcept
|
||||
: instanceId(Utils::getSecureRandomU64())
|
||||
, node(n)
|
||||
, uPtr(nullptr)
|
||||
, localNetworkController(nullptr)
|
||||
, store(nullptr)
|
||||
, networks(nullptr)
|
||||
, t(nullptr)
|
||||
, expect(nullptr)
|
||||
, vl2(nullptr)
|
||||
, vl1(nullptr)
|
||||
, topology(nullptr)
|
||||
, sa(nullptr)
|
||||
, ts(nullptr)
|
||||
{
|
||||
publicIdentityStr[0] = 0;
|
||||
secretIdentityStr[0] = 0;
|
||||
}
|
||||
|
||||
ZT_INLINE ~Context() noexcept
|
||||
{ Utils::burn(secretIdentityStr, sizeof(secretIdentityStr)); }
|
||||
{
|
||||
Utils::burn(secretIdentityStr, sizeof(secretIdentityStr));
|
||||
}
|
||||
|
||||
// Unique ID generated on startup
|
||||
const uint64_t instanceId;
|
||||
|
||||
// Node instance that owns this RuntimeEnvironment
|
||||
Node *const restrict node;
|
||||
Node* const restrict node;
|
||||
|
||||
// Callbacks specified by caller who created node
|
||||
ZT_Node_Callbacks cb;
|
||||
|
||||
// User pointer specified by external code via API
|
||||
void *restrict uPtr;
|
||||
void* restrict uPtr;
|
||||
|
||||
// This is set externally to an instance of this base class
|
||||
NetworkController *restrict localNetworkController;
|
||||
NetworkController* restrict localNetworkController;
|
||||
|
||||
Store *restrict store;
|
||||
TinyMap< SharedPtr< Network > > *restrict networks;
|
||||
Trace *restrict t;
|
||||
Expect *restrict expect;
|
||||
VL2 *restrict vl2;
|
||||
VL1 *restrict vl1;
|
||||
Topology *restrict topology;
|
||||
SelfAwareness *restrict sa;
|
||||
TrustStore *restrict ts;
|
||||
Store* restrict store;
|
||||
TinyMap<SharedPtr<Network> >* restrict networks;
|
||||
Trace* restrict t;
|
||||
Expect* restrict expect;
|
||||
VL2* restrict vl2;
|
||||
VL1* restrict vl1;
|
||||
Topology* restrict topology;
|
||||
SelfAwareness* restrict sa;
|
||||
TrustStore* restrict ts;
|
||||
|
||||
// This node's identity and string representations thereof
|
||||
Identity identity;
|
||||
|
|
|
@ -11,15 +11,16 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Credential.hpp"
|
||||
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "OwnershipCredential.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "Topology.hpp"
|
||||
|
||||
// These are compile-time asserts to make sure temporary marshal buffers here and
|
||||
|
@ -42,57 +43,77 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
template< typename CRED >
|
||||
static ZT_INLINE Credential::VerifyResult p_credVerify(const Context &ctx, const CallContext &cc, CRED credential)
|
||||
template <typename CRED>
|
||||
static ZT_INLINE Credential::VerifyResult p_credVerify(const Context& ctx, const CallContext& cc, CRED credential)
|
||||
{
|
||||
uint8_t tmp[ZT_BUF_MEM_SIZE + 16];
|
||||
|
||||
const Address signedBy(credential.signer());
|
||||
const uint64_t networkId = credential.networkId();
|
||||
if ((!signedBy) || (signedBy != Network::controllerFor(networkId)))
|
||||
if ((! signedBy) || (signedBy != Network::controllerFor(networkId)))
|
||||
return Credential::VERIFY_BAD_SIGNATURE;
|
||||
|
||||
const SharedPtr< Peer > peer(ctx.topology->peer(cc, signedBy));
|
||||
if (!peer)
|
||||
const SharedPtr<Peer> peer(ctx.topology->peer(cc, signedBy));
|
||||
if (! peer)
|
||||
return Credential::VERIFY_NEED_IDENTITY;
|
||||
|
||||
try {
|
||||
int l = credential.marshal(tmp, true);
|
||||
if (l <= 0)
|
||||
return Credential::VERIFY_BAD_SIGNATURE;
|
||||
return (peer->identity().verify(tmp, (unsigned int)l, credential.signature(), credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE);
|
||||
} catch (...) {}
|
||||
return (
|
||||
peer->identity().verify(tmp, (unsigned int)l, credential.signature(), credential.signatureLength())
|
||||
? Credential::VERIFY_OK
|
||||
: Credential::VERIFY_BAD_SIGNATURE);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
return Credential::VERIFY_BAD_SIGNATURE;
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const RevocationCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const RevocationCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const TagCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const TagCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const CapabilityCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const CapabilityCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const OwnershipCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const OwnershipCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const MembershipCredential &credential)
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const MembershipCredential& credential)
|
||||
{
|
||||
// Sanity check network ID.
|
||||
if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId)))
|
||||
if ((! credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId)))
|
||||
return Credential::VERIFY_BAD_SIGNATURE;
|
||||
|
||||
// If we don't know the peer, get its identity. This shouldn't happen here but should be handled.
|
||||
const SharedPtr< Peer > peer(ctx.topology->peer(cc, credential.m_signedBy));
|
||||
if (!peer)
|
||||
const SharedPtr<Peer> peer(ctx.topology->peer(cc, credential.m_signedBy));
|
||||
if (! peer)
|
||||
return Credential::VERIFY_NEED_IDENTITY;
|
||||
|
||||
// Now verify the controller's signature.
|
||||
uint64_t buf[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX / 8];
|
||||
const unsigned int bufSize = credential.m_fillSigningBuf(buf);
|
||||
return peer->identity().verify(buf, bufSize, credential.m_signature, credential.m_signatureLength) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE;
|
||||
return peer->identity().verify(buf, bufSize, credential.m_signature, credential.m_signatureLength)
|
||||
? Credential::VERIFY_OK
|
||||
: Credential::VERIFY_BAD_SIGNATURE;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#ifndef ZT_CREDENTIAL_HPP
|
||||
#define ZT_CREDENTIAL_HPP
|
||||
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -35,25 +35,19 @@ class Context;
|
|||
* All credential verification methods are implemented in Credential.cpp as they share a lot
|
||||
* of common code and logic and grouping them makes auditing easier.
|
||||
*/
|
||||
class Credential : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
class Credential : public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Result of verify() operations
|
||||
*/
|
||||
enum VerifyResult
|
||||
{
|
||||
VERIFY_OK = 0,
|
||||
VERIFY_BAD_SIGNATURE = 1,
|
||||
VERIFY_NEED_IDENTITY = 2
|
||||
};
|
||||
enum VerifyResult { VERIFY_OK = 0, VERIFY_BAD_SIGNATURE = 1, VERIFY_NEED_IDENTITY = 2 };
|
||||
|
||||
protected:
|
||||
static VerifyResult s_verify(const Context &ctx, const CallContext &cc, const MembershipCredential &credential);
|
||||
static VerifyResult s_verify(const Context &ctx, const CallContext &cc, const RevocationCredential &credential);
|
||||
static VerifyResult s_verify(const Context &ctx, const CallContext &cc, const TagCredential &credential);
|
||||
static VerifyResult s_verify(const Context &ctx, const CallContext &cc, const OwnershipCredential &credential);
|
||||
static VerifyResult s_verify(const Context &ctx, const CallContext &cc, const CapabilityCredential &credential);
|
||||
protected:
|
||||
static VerifyResult s_verify(const Context& ctx, const CallContext& cc, const MembershipCredential& credential);
|
||||
static VerifyResult s_verify(const Context& ctx, const CallContext& cc, const RevocationCredential& credential);
|
||||
static VerifyResult s_verify(const Context& ctx, const CallContext& cc, const TagCredential& credential);
|
||||
static VerifyResult s_verify(const Context& ctx, const CallContext& cc, const OwnershipCredential& credential);
|
||||
static VerifyResult s_verify(const Context& ctx, const CallContext& cc, const CapabilityCredential& credential);
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
namespace ZeroTier {
|
||||
namespace Defaults {
|
||||
|
||||
const uint8_t *CERTIFICATE[DEFAULT_CERTIFICATE_COUNT] = {};
|
||||
const uint8_t* CERTIFICATE[DEFAULT_CERTIFICATE_COUNT] = {};
|
||||
|
||||
unsigned int CERTIFICATE_SIZE[DEFAULT_CERTIFICATE_COUNT] = {};
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Defaults {
|
|||
|
||||
#define DEFAULT_CERTIFICATE_COUNT 0
|
||||
|
||||
extern const uint8_t *CERTIFICATE[DEFAULT_CERTIFICATE_COUNT];
|
||||
extern const uint8_t* CERTIFICATE[DEFAULT_CERTIFICATE_COUNT];
|
||||
extern unsigned int CERTIFICATE_SIZE[DEFAULT_CERTIFICATE_COUNT];
|
||||
|
||||
} // namespace Defaults
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
#ifndef ZT_DEFRAGMENTER_HPP
|
||||
#define ZT_DEFRAGMENTER_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -40,25 +40,24 @@ namespace ZeroTier {
|
|||
* the ones used throughout the ZeroTier core.
|
||||
*
|
||||
* @tparam MF Maximum number of fragments that each message can possess (default: ZT_MAX_PACKET_FRAGMENTS)
|
||||
* @tparam MFP Maximum number of incoming fragments per path (if paths are specified) (default: ZT_MAX_INCOMING_FRAGMENTS_PER_PATH)
|
||||
* @tparam MFP Maximum number of incoming fragments per path (if paths are specified) (default:
|
||||
* ZT_MAX_INCOMING_FRAGMENTS_PER_PATH)
|
||||
* @tparam GCS Garbage collection target size for the incoming message queue (default: ZT_MAX_PACKET_FRAGMENTS * 2)
|
||||
* @tparam GCT Garbage collection trigger threshold, usually 2X GCS (default: ZT_MAX_PACKET_FRAGMENTS * 4)
|
||||
* @tparam P Type for pointer to a path object (default: SharedPtr<Path>)
|
||||
*/
|
||||
template<
|
||||
template <
|
||||
unsigned int MF = ZT_MAX_PACKET_FRAGMENTS,
|
||||
unsigned int MFP = ZT_MAX_INCOMING_FRAGMENTS_PER_PATH,
|
||||
unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2),
|
||||
unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4),
|
||||
typename P = SharedPtr< Path > >
|
||||
class Defragmenter
|
||||
{
|
||||
public:
|
||||
typename P = SharedPtr<Path> >
|
||||
class Defragmenter {
|
||||
public:
|
||||
/**
|
||||
* Return values from assemble()
|
||||
*/
|
||||
enum ResultCode
|
||||
{
|
||||
enum ResultCode {
|
||||
/**
|
||||
* No error occurred, fragment accepted
|
||||
*/
|
||||
|
@ -97,7 +96,8 @@ public:
|
|||
};
|
||||
|
||||
ZT_INLINE Defragmenter()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a fragment of a multi-part message
|
||||
|
@ -142,14 +142,14 @@ public:
|
|||
*/
|
||||
ZT_INLINE ResultCode assemble(
|
||||
const uint64_t messageId,
|
||||
FCV< Buf::Slice, MF > &message,
|
||||
SharedPtr< Buf > &fragment,
|
||||
FCV<Buf::Slice, MF>& message,
|
||||
SharedPtr<Buf>& fragment,
|
||||
const unsigned int fragmentDataIndex,
|
||||
const unsigned int fragmentDataSize,
|
||||
const unsigned int fragmentNo,
|
||||
const unsigned int totalFragmentsExpected,
|
||||
const int64_t ts,
|
||||
const P &via)
|
||||
const P& via)
|
||||
{
|
||||
// Sanity checks for malformed fragments or invalid input parameters.
|
||||
if ((fragmentNo >= totalFragmentsExpected) || (totalFragmentsExpected > MF) || (totalFragmentsExpected == 0))
|
||||
|
@ -167,34 +167,37 @@ public:
|
|||
// under the target size. This tries to minimize the amount of time the write
|
||||
// lock is held since many threads can hold the read lock but all threads must
|
||||
// wait if someone holds the write lock.
|
||||
std::vector< std::pair< int64_t, uint64_t > > messagesByLastUsedTime;
|
||||
std::vector<std::pair<int64_t, uint64_t> > messagesByLastUsedTime;
|
||||
messagesByLastUsedTime.reserve(m_messages.size());
|
||||
|
||||
for (typename Map< uint64_t, p_E >::const_iterator i(m_messages.begin()); i != m_messages.end(); ++i)
|
||||
messagesByLastUsedTime.push_back(std::pair< int64_t, uint64_t >(i->second.lastUsed, i->first));
|
||||
for (typename Map<uint64_t, p_E>::const_iterator i(m_messages.begin()); i != m_messages.end(); ++i)
|
||||
messagesByLastUsedTime.push_back(std::pair<int64_t, uint64_t>(i->second.lastUsed, i->first));
|
||||
std::sort(messagesByLastUsedTime.begin(), messagesByLastUsedTime.end());
|
||||
|
||||
ml.writing(); // acquire write lock on _messages
|
||||
for (unsigned long x = 0, y = (messagesByLastUsedTime.size() - GCS); x <= y; ++x)
|
||||
m_messages.erase(messagesByLastUsedTime[x].second);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Get or create message fragment.
|
||||
Defragmenter< MF, MFP, GCS, GCT, P >::p_E *e;
|
||||
Defragmenter<MF, MFP, GCS, GCT, P>::p_E* e;
|
||||
{
|
||||
typename Map< uint64_t, Defragmenter< MF, MFP, GCS, GCT, P >::p_E >::iterator ee(m_messages.find(messageId));
|
||||
typename Map<uint64_t, Defragmenter<MF, MFP, GCS, GCT, P>::p_E>::iterator ee(m_messages.find(messageId));
|
||||
if (ee == m_messages.end()) {
|
||||
ml.writing(); // acquire write lock on _messages if not already
|
||||
try {
|
||||
e = &(m_messages[messageId]);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
e->id = messageId;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
e = &(ee->second);
|
||||
}
|
||||
}
|
||||
|
@ -220,17 +223,19 @@ public:
|
|||
|
||||
// If there is a path associated with this fragment make sure we've registered
|
||||
// ourselves as in flight, check the limit, and abort if exceeded.
|
||||
if ((via) && (!e->via)) {
|
||||
if ((via) && (! e->via)) {
|
||||
e->via = via;
|
||||
bool tooManyPerPath = false;
|
||||
via->m_inboundFragmentedMessages_l.lock();
|
||||
try {
|
||||
if (via->m_inboundFragmentedMessages.size() < MFP) {
|
||||
via->m_inboundFragmentedMessages.insert(messageId);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
tooManyPerPath = true;
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
// This would indicate something like bad_alloc thrown by the set. Treat
|
||||
// it as limit exceeded.
|
||||
tooManyPerPath = true;
|
||||
|
@ -245,7 +250,7 @@ public:
|
|||
// data would just mean the transfer is corrupt and would be detected
|
||||
// later e.g. by packet MAC check. Other use cases of this code like
|
||||
// network configs check each fragment so this basically can't happen.
|
||||
Buf::Slice &s = e->message.at(fragmentNo);
|
||||
Buf::Slice& s = e->message.at(fragmentNo);
|
||||
if (s.b)
|
||||
return ERR_DUPLICATE_FRAGMENT;
|
||||
|
||||
|
@ -296,26 +301,27 @@ public:
|
|||
return m_messages.size();
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
// p_E is an entry in the message queue.
|
||||
struct p_E
|
||||
struct p_E {
|
||||
ZT_INLINE p_E() noexcept
|
||||
: id(0)
|
||||
, lastUsed(0)
|
||||
, totalFragmentsExpected(0)
|
||||
, fragmentsReceived(0)
|
||||
{
|
||||
ZT_INLINE p_E() noexcept:
|
||||
id(0),
|
||||
lastUsed(0),
|
||||
totalFragmentsExpected(0),
|
||||
fragmentsReceived(0)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE p_E(const p_E &e) noexcept:
|
||||
id(e.id),
|
||||
lastUsed(e.lastUsed),
|
||||
totalFragmentsExpected(e.totalFragmentsExpected),
|
||||
fragmentsReceived(e.fragmentsReceived),
|
||||
via(e.via),
|
||||
message(e.message),
|
||||
lock()
|
||||
{}
|
||||
ZT_INLINE p_E(const p_E& e) noexcept
|
||||
: id(e.id)
|
||||
, lastUsed(e.lastUsed)
|
||||
, totalFragmentsExpected(e.totalFragmentsExpected)
|
||||
, fragmentsReceived(e.fragmentsReceived)
|
||||
, via(e.via)
|
||||
, message(e.message)
|
||||
, lock()
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~p_E()
|
||||
{
|
||||
|
@ -326,7 +332,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
ZT_INLINE p_E &operator=(const p_E &e)
|
||||
ZT_INLINE p_E& operator=(const p_E& e)
|
||||
{
|
||||
if (this != &e) {
|
||||
id = e.id;
|
||||
|
@ -344,11 +350,11 @@ private:
|
|||
unsigned int totalFragmentsExpected;
|
||||
unsigned int fragmentsReceived;
|
||||
P via;
|
||||
FCV< Buf::Slice, MF > message;
|
||||
FCV<Buf::Slice, MF> message;
|
||||
Mutex lock;
|
||||
};
|
||||
|
||||
Map< uint64_t, Defragmenter< MF, MFP, GCS, GCT, P >::p_E > m_messages;
|
||||
Map<uint64_t, Defragmenter<MF, MFP, GCS, GCT, P>::p_E> m_messages;
|
||||
RWMutex m_messages_l;
|
||||
};
|
||||
|
||||
|
|
|
@ -15,44 +15,47 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
Vector< uint8_t > &Dictionary::operator[](const char *const k)
|
||||
{ return m_entries[k]; }
|
||||
|
||||
const Vector< uint8_t > &Dictionary::operator[](const char *const k) const
|
||||
Vector<uint8_t>& Dictionary::operator[](const char* const k)
|
||||
{
|
||||
static const Vector< uint8_t > s_emptyEntry;
|
||||
const SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(k));
|
||||
return m_entries[k];
|
||||
}
|
||||
|
||||
const Vector<uint8_t>& Dictionary::operator[](const char* const k) const
|
||||
{
|
||||
static const Vector<uint8_t> s_emptyEntry;
|
||||
const SortedMap<String, Vector<uint8_t> >::const_iterator e(m_entries.find(k));
|
||||
return (e == m_entries.end()) ? s_emptyEntry : e->second;
|
||||
}
|
||||
|
||||
void Dictionary::add(const char *k, const Address &v)
|
||||
void Dictionary::add(const char* k, const Address& v)
|
||||
{
|
||||
char tmp[ZT_ADDRESS_STRING_SIZE_MAX];
|
||||
v.toString(tmp);
|
||||
add(k, tmp);
|
||||
}
|
||||
|
||||
void Dictionary::add(const char *k, const char *v)
|
||||
void Dictionary::add(const char* k, const char* v)
|
||||
{
|
||||
Vector< uint8_t > &e = (*this)[k];
|
||||
Vector<uint8_t>& e = (*this)[k];
|
||||
e.clear();
|
||||
if (v) {
|
||||
while (*v)
|
||||
e.push_back((uint8_t)*(v++));
|
||||
e.push_back((uint8_t) * (v++));
|
||||
}
|
||||
}
|
||||
|
||||
void Dictionary::add(const char *k, const void *data, unsigned int len)
|
||||
void Dictionary::add(const char* k, const void* data, unsigned int len)
|
||||
{
|
||||
Vector< uint8_t > &e = (*this)[k];
|
||||
Vector<uint8_t>& e = (*this)[k];
|
||||
if (likely(len != 0)) {
|
||||
e.assign((const uint8_t *)data, (const uint8_t *)data + len);
|
||||
} else {
|
||||
e.assign((const uint8_t*)data, (const uint8_t*)data + len);
|
||||
}
|
||||
else {
|
||||
e.clear();
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const
|
||||
uint64_t Dictionary::getUI(const char* k, uint64_t dfl) const
|
||||
{
|
||||
char tmp[32];
|
||||
getS(k, tmp, sizeof(tmp));
|
||||
|
@ -61,12 +64,12 @@ uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const
|
|||
return dfl;
|
||||
}
|
||||
|
||||
char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
|
||||
char* Dictionary::getS(const char* k, char* v, const unsigned int cap) const
|
||||
{
|
||||
if (cap == 0) // sanity check
|
||||
return v;
|
||||
|
||||
const Vector< uint8_t > &e = (*this)[k];
|
||||
const Vector<uint8_t>& e = (*this)[k];
|
||||
if (e.empty()) {
|
||||
v[0] = 0;
|
||||
return v;
|
||||
|
@ -85,27 +88,29 @@ char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
|
|||
}
|
||||
|
||||
void Dictionary::clear()
|
||||
{ m_entries.clear(); }
|
||||
{
|
||||
m_entries.clear();
|
||||
}
|
||||
|
||||
void Dictionary::encode(Vector< uint8_t > &out) const
|
||||
void Dictionary::encode(Vector<uint8_t>& out) const
|
||||
{
|
||||
out.clear();
|
||||
for (SortedMap< String, Vector< uint8_t > >::const_iterator ti(m_entries.begin()); ti != m_entries.end(); ++ti) {
|
||||
for (SortedMap<String, Vector<uint8_t> >::const_iterator ti(m_entries.begin()); ti != m_entries.end(); ++ti) {
|
||||
s_appendKey(out, ti->first.data());
|
||||
for (Vector< uint8_t >::const_iterator i(ti->second.begin()); i != ti->second.end(); ++i)
|
||||
for (Vector<uint8_t>::const_iterator i(ti->second.begin()); i != ti->second.end(); ++i)
|
||||
s_appendValueByte(out, *i);
|
||||
out.push_back((uint8_t)'\n');
|
||||
}
|
||||
}
|
||||
|
||||
bool Dictionary::decode(const void *data, unsigned int len)
|
||||
bool Dictionary::decode(const void* data, unsigned int len)
|
||||
{
|
||||
clear();
|
||||
String k;
|
||||
Vector< uint8_t > *v = nullptr;
|
||||
Vector<uint8_t>* v = nullptr;
|
||||
bool escape = false;
|
||||
for (unsigned int di = 0; di < len; ++di) {
|
||||
const uint8_t c = reinterpret_cast<const uint8_t *>(data)[di];
|
||||
const uint8_t c = reinterpret_cast<const uint8_t*>(data)[di];
|
||||
if (c) {
|
||||
if (v) {
|
||||
if (escape) {
|
||||
|
@ -127,31 +132,37 @@ bool Dictionary::decode(const void *data, unsigned int len)
|
|||
v->push_back(c);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (c == (uint8_t)'\n') {
|
||||
k.clear();
|
||||
v = nullptr;
|
||||
} else if (c == 92) { // backslash
|
||||
}
|
||||
else if (c == 92) { // backslash
|
||||
escape = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
v->push_back(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (c == (uint8_t)'=') {
|
||||
v = &m_entries[k];
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
k.push_back(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *Dictionary::arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept
|
||||
char* Dictionary::arraySubscript(char* buf, unsigned int bufSize, const char* name, const unsigned long sub) noexcept
|
||||
{
|
||||
if (bufSize < 17) { // sanity check
|
||||
buf[0] = 0;
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#ifndef ZT_DICTIONARY_HPP
|
||||
#define ZT_DICTIONARY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,16 +37,17 @@ class Identity;
|
|||
* The fastest way to build a dictionary to send is to use the append
|
||||
* static functions, not to populate and then encode a Dictionary.
|
||||
*/
|
||||
class Dictionary
|
||||
{
|
||||
public:
|
||||
typedef SortedMap< String, Vector< uint8_t > >::const_iterator const_iterator;
|
||||
class Dictionary {
|
||||
public:
|
||||
typedef SortedMap<String, Vector<uint8_t> >::const_iterator const_iterator;
|
||||
|
||||
ZT_INLINE Dictionary()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~Dictionary()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
ZT_INLINE void dump() const
|
||||
|
@ -81,7 +82,7 @@ public:
|
|||
* @param k Key to look up
|
||||
* @return Reference to value
|
||||
*/
|
||||
Vector< uint8_t > &operator[](const char *k);
|
||||
Vector<uint8_t>& operator[](const char* k);
|
||||
|
||||
/**
|
||||
* Get a const reference to a value
|
||||
|
@ -89,19 +90,23 @@ public:
|
|||
* @param k Key to look up
|
||||
* @return Reference to value or to empty vector if not found
|
||||
*/
|
||||
const Vector< uint8_t > &operator[](const char *k) const;
|
||||
const Vector<uint8_t>& operator[](const char* k) const;
|
||||
|
||||
/**
|
||||
* @return Start of key->value pairs
|
||||
*/
|
||||
ZT_INLINE const_iterator begin() const noexcept
|
||||
{ return m_entries.begin(); }
|
||||
{
|
||||
return m_entries.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return End of key->value pairs
|
||||
*/
|
||||
ZT_INLINE const_iterator end() const noexcept
|
||||
{ return m_entries.end(); }
|
||||
{
|
||||
return m_entries.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an integer as a hexadecimal string value
|
||||
|
@ -109,7 +114,7 @@ public:
|
|||
* @param k Key to set
|
||||
* @param v Integer to set, will be cast to uint64_t and stored as hex
|
||||
*/
|
||||
ZT_INLINE void add(const char *const k, const uint64_t v)
|
||||
ZT_INLINE void add(const char* const k, const uint64_t v)
|
||||
{
|
||||
char buf[24];
|
||||
add(k, Utils::hex((uint64_t)(v), buf));
|
||||
|
@ -121,7 +126,7 @@ public:
|
|||
* @param k Key to set
|
||||
* @param v Integer to set, will be cast to uint64_t and stored as hex
|
||||
*/
|
||||
ZT_INLINE void add(const char *const k, const int64_t v)
|
||||
ZT_INLINE void add(const char* const k, const int64_t v)
|
||||
{
|
||||
char buf[24];
|
||||
add(k, Utils::hex((uint64_t)(v), buf));
|
||||
|
@ -130,17 +135,17 @@ public:
|
|||
/**
|
||||
* Add an address in 10-digit hex string format
|
||||
*/
|
||||
void add(const char *k, const Address &v);
|
||||
void add(const char* k, const Address& v);
|
||||
|
||||
/**
|
||||
* Add a C string as a value
|
||||
*/
|
||||
void add(const char *k, const char *v);
|
||||
void add(const char* k, const char* v);
|
||||
|
||||
/**
|
||||
* Add a binary blob as a value
|
||||
*/
|
||||
void add(const char *k, const void *data, unsigned int len);
|
||||
void add(const char* k, const void* data, unsigned int len);
|
||||
|
||||
/**
|
||||
* Get an integer
|
||||
|
@ -149,7 +154,7 @@ public:
|
|||
* @param dfl Default value (default: 0)
|
||||
* @return Value of key or default if not found
|
||||
*/
|
||||
uint64_t getUI(const char *k, uint64_t dfl = 0) const;
|
||||
uint64_t getUI(const char* k, uint64_t dfl = 0) const;
|
||||
|
||||
/**
|
||||
* Get a C string
|
||||
|
@ -161,7 +166,7 @@ public:
|
|||
* @param v Buffer to hold string
|
||||
* @param cap Maximum size of string (including terminating null)
|
||||
*/
|
||||
char *getS(const char *k, char *v, unsigned int cap) const;
|
||||
char* getS(const char* k, char* v, unsigned int cap) const;
|
||||
|
||||
/**
|
||||
* Get an object supporting the marshal/unmarshal interface pattern
|
||||
|
@ -171,10 +176,9 @@ public:
|
|||
* @param obj Object to unmarshal() into
|
||||
* @return True if unmarshal was successful
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE bool getO(const char *k, T &obj) const
|
||||
template <typename T> ZT_INLINE bool getO(const char* k, T& obj) const
|
||||
{
|
||||
const Vector< uint8_t > &d = (*this)[k];
|
||||
const Vector<uint8_t>& d = (*this)[k];
|
||||
if (d.empty())
|
||||
return false;
|
||||
return (obj.unmarshal(d.data(), (unsigned int)d.size()) > 0);
|
||||
|
@ -188,10 +192,9 @@ public:
|
|||
* @param obj Object to marshal() into vector
|
||||
* @return True if successful
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE bool addO(const char *k, T &obj)
|
||||
template <typename T> ZT_INLINE bool addO(const char* k, T& obj)
|
||||
{
|
||||
Vector< uint8_t > &d = (*this)[k];
|
||||
Vector<uint8_t>& d = (*this)[k];
|
||||
d.resize(T::marshalSizeMax());
|
||||
const int l = obj.marshal(d.data());
|
||||
if (l > 0) {
|
||||
|
@ -211,20 +214,24 @@ public:
|
|||
* @return Number of entries
|
||||
*/
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return (unsigned int)m_entries.size(); }
|
||||
{
|
||||
return (unsigned int)m_entries.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if dictionary is not empty
|
||||
*/
|
||||
ZT_INLINE bool empty() const noexcept
|
||||
{ return m_entries.empty(); }
|
||||
{
|
||||
return m_entries.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode to a string in the supplied vector
|
||||
*
|
||||
* @param out String encoded dictionary
|
||||
*/
|
||||
void encode(Vector< uint8_t > &out) const;
|
||||
void encode(Vector<uint8_t>& out) const;
|
||||
|
||||
/**
|
||||
* Decode a string encoded dictionary
|
||||
|
@ -236,7 +243,7 @@ public:
|
|||
* @param len Length of data
|
||||
* @return True if dictionary was formatted correctly and valid, false on error
|
||||
*/
|
||||
bool decode(const void *data, unsigned int len);
|
||||
bool decode(const void* data, unsigned int len);
|
||||
|
||||
/**
|
||||
* Append a key=value pair to a buffer (vector or FCV)
|
||||
|
@ -245,8 +252,7 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const bool v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const bool v)
|
||||
{
|
||||
s_appendKey(out, k);
|
||||
out.push_back((uint8_t)(v ? '1' : '0'));
|
||||
|
@ -260,8 +266,7 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const Address v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const Address v)
|
||||
{
|
||||
s_appendKey(out, k);
|
||||
const uint64_t a = v.toInt();
|
||||
|
@ -286,8 +291,7 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint64_t v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint64_t v)
|
||||
{
|
||||
s_appendKey(out, k);
|
||||
char buf[17];
|
||||
|
@ -298,33 +302,40 @@ public:
|
|||
out.push_back((uint8_t)'\n');
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int64_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int64_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint32_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint32_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int32_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int32_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint16_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint16_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int16_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int16_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint8_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint8_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int8_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int8_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a key=value pair to a buffer (vector or FCV)
|
||||
|
@ -333,13 +344,12 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const char *v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const char* v)
|
||||
{
|
||||
if ((v) && (*v)) {
|
||||
s_appendKey(out, k);
|
||||
while (*v)
|
||||
s_appendValueByte(out, (uint8_t)*(v++));
|
||||
s_appendValueByte(out, (uint8_t) * (v++));
|
||||
out.push_back((uint8_t)'\n');
|
||||
}
|
||||
}
|
||||
|
@ -352,12 +362,12 @@ public:
|
|||
* @param v Value
|
||||
* @param vlen Value length in bytes
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const void *const v, const unsigned int vlen)
|
||||
template <typename V>
|
||||
ZT_INLINE static void append(V& out, const char* const k, const void* const v, const unsigned int vlen)
|
||||
{
|
||||
s_appendKey(out, k);
|
||||
for (unsigned int i = 0; i < vlen; ++i)
|
||||
s_appendValueByte(out, reinterpret_cast<const uint8_t *>(v)[i]);
|
||||
s_appendValueByte(out, reinterpret_cast<const uint8_t*>(v)[i]);
|
||||
out.push_back((uint8_t)'\n');
|
||||
}
|
||||
|
||||
|
@ -368,9 +378,10 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param pid Packet ID
|
||||
*/
|
||||
template< typename V >
|
||||
static ZT_INLINE void appendPacketId(V &out, const char *const k, const uint64_t pid)
|
||||
{ append(out, k, &pid, 8); }
|
||||
template <typename V> static ZT_INLINE void appendPacketId(V& out, const char* const k, const uint64_t pid)
|
||||
{
|
||||
append(out, k, &pid, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append key=value with any object implementing the correct marshal interface
|
||||
|
@ -380,8 +391,7 @@ public:
|
|||
* @param v Marshal-able object
|
||||
* @return Bytes appended or negative on error (return value of marshal())
|
||||
*/
|
||||
template< typename V, typename T >
|
||||
static ZT_INLINE int appendObject(V &out, const char *const k, const T &v)
|
||||
template <typename V, typename T> static ZT_INLINE int appendObject(V& out, const char* const k, const T& v)
|
||||
{
|
||||
uint8_t tmp[2048]; // large enough for any current object
|
||||
if (T::marshalSizeMax() > sizeof(tmp))
|
||||
|
@ -400,11 +410,10 @@ public:
|
|||
* @param sub Subscript index
|
||||
* @return Pointer to 'buf'
|
||||
*/
|
||||
static char *arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept;
|
||||
static char* arraySubscript(char* buf, unsigned int bufSize, const char* name, const unsigned long sub) noexcept;
|
||||
|
||||
private:
|
||||
template< typename V >
|
||||
ZT_INLINE static void s_appendValueByte(V &out, const uint8_t c)
|
||||
private:
|
||||
template <typename V> ZT_INLINE static void s_appendValueByte(V& out, const uint8_t c)
|
||||
{
|
||||
switch (c) {
|
||||
case 0:
|
||||
|
@ -433,8 +442,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void s_appendKey(V &out, const char *k)
|
||||
template <typename V> ZT_INLINE static void s_appendKey(V& out, const char* k)
|
||||
{
|
||||
for (;;) {
|
||||
const char c = *(k++);
|
||||
|
@ -448,7 +456,7 @@ private:
|
|||
// Dictionary maps need to be sorted so that they always encode in the same order
|
||||
// to yield blobs that can be hashed and signed reproducibly. Other than for areas
|
||||
// where dictionaries are signed and verified the order doesn't matter.
|
||||
SortedMap< String, Vector< uint8_t > > m_entries;
|
||||
SortedMap<String, Vector<uint8_t> > m_entries;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
222
core/ECC384.cpp
222
core/ECC384.cpp
|
@ -2,8 +2,9 @@
|
|||
// https://github.com/esxgx/easy-ecc
|
||||
// This code is under the BSD 2-clause license, not ZeroTier's license
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "ECC384.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -14,47 +15,67 @@ namespace {
|
|||
#define secp384r1 48
|
||||
#define ECC_CURVE secp384r1
|
||||
#define ECC_BYTES ECC_CURVE
|
||||
#define NUM_ECC_DIGITS (ECC_BYTES/8)
|
||||
#define NUM_ECC_DIGITS (ECC_BYTES / 8)
|
||||
#define ECC_CREATE_KEY_MAX_ATTEMPTS 1024
|
||||
|
||||
#ifdef ZT_HAVE_UINT128
|
||||
#define SUPPORTS_INT128 1
|
||||
#else
|
||||
#define SUPPORTS_INT128 0
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint64_t m_low;
|
||||
uint64_t m_high;
|
||||
} uint128_t;
|
||||
#endif
|
||||
|
||||
typedef struct EccPoint
|
||||
{
|
||||
typedef struct EccPoint {
|
||||
uint64_t x[NUM_ECC_DIGITS];
|
||||
uint64_t y[NUM_ECC_DIGITS];
|
||||
} EccPoint;
|
||||
|
||||
#define CONCAT1(a, b) a##b
|
||||
#define CONCAT(a, b) CONCAT1(a, b)
|
||||
#define Curve_P_48 {0x00000000FFFFFFFF, 0xFFFFFFFF00000000, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}
|
||||
#define Curve_B_48 {0x2A85C8EDD3EC2AEF, 0xC656398D8A2ED19D, 0x0314088F5013875A, 0x181D9C6EFE814112, 0x988E056BE3F82D19, 0xB3312FA7E23EE7E4}
|
||||
#define Curve_G_48 {{0x3A545E3872760AB7, 0x5502F25DBF55296C, 0x59F741E082542A38, 0x6E1D3B628BA79B98, 0x8EB1C71EF320AD74, 0xAA87CA22BE8B0537}, {0x7A431D7C90EA0E5F, 0x0A60B1CE1D7E819D, 0xE9DA3113B5F0B8C0, 0xF8F41DBD289A147C, 0x5D9E98BF9292DC29, 0x3617DE4A96262C6F}}
|
||||
#define Curve_N_48 {0xECEC196ACCC52973, 0x581A0DB248B0A77A, 0xC7634D81F4372DDF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}
|
||||
#define Curve_P_48 \
|
||||
{ \
|
||||
0x00000000FFFFFFFF, 0xFFFFFFFF00000000, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, \
|
||||
0xFFFFFFFFFFFFFFFF \
|
||||
}
|
||||
#define Curve_B_48 \
|
||||
{ \
|
||||
0x2A85C8EDD3EC2AEF, 0xC656398D8A2ED19D, 0x0314088F5013875A, 0x181D9C6EFE814112, 0x988E056BE3F82D19, \
|
||||
0xB3312FA7E23EE7E4 \
|
||||
}
|
||||
#define Curve_G_48 \
|
||||
{ \
|
||||
{ 0x3A545E3872760AB7, 0x5502F25DBF55296C, 0x59F741E082542A38, \
|
||||
0x6E1D3B628BA79B98, 0x8EB1C71EF320AD74, 0xAA87CA22BE8B0537 }, \
|
||||
{ \
|
||||
0x7A431D7C90EA0E5F, 0x0A60B1CE1D7E819D, 0xE9DA3113B5F0B8C0, 0xF8F41DBD289A147C, 0x5D9E98BF9292DC29, \
|
||||
0x3617DE4A96262C6F \
|
||||
} \
|
||||
}
|
||||
#define Curve_N_48 \
|
||||
{ \
|
||||
0xECEC196ACCC52973, 0x581A0DB248B0A77A, 0xC7634D81F4372DDF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, \
|
||||
0xFFFFFFFFFFFFFFFF \
|
||||
}
|
||||
const uint64_t curve_p[NUM_ECC_DIGITS] = CONCAT(Curve_P_, ECC_CURVE);
|
||||
const uint64_t curve_b[NUM_ECC_DIGITS] = CONCAT(Curve_B_, ECC_CURVE);
|
||||
const EccPoint curve_G = CONCAT(Curve_G_, ECC_CURVE);
|
||||
const uint64_t curve_n[NUM_ECC_DIGITS] = CONCAT(Curve_N_, ECC_CURVE);
|
||||
|
||||
ZT_INLINE int getRandomNumber(uint64_t *p_vli)
|
||||
ZT_INLINE int getRandomNumber(uint64_t* p_vli)
|
||||
{
|
||||
Utils::getSecureRandom(p_vli, ECC_BYTES);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ZT_INLINE void vli_clear(uint64_t *p_vli)
|
||||
{ Utils::zero< sizeof(uint64_t) * NUM_ECC_DIGITS >(p_vli); }
|
||||
ZT_INLINE void vli_clear(uint64_t* p_vli)
|
||||
{
|
||||
Utils::zero<sizeof(uint64_t) * NUM_ECC_DIGITS>(p_vli);
|
||||
}
|
||||
|
||||
ZT_INLINE int vli_isZero(const uint64_t *p_vli)
|
||||
ZT_INLINE int vli_isZero(const uint64_t* p_vli)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < NUM_ECC_DIGITS; ++i) {
|
||||
|
@ -64,17 +85,19 @@ ZT_INLINE int vli_isZero(const uint64_t *p_vli)
|
|||
return 1;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t vli_testBit(const uint64_t *p_vli, uint p_bit)
|
||||
{ return (p_vli[p_bit / 64] & ((uint64_t)1 << (p_bit % 64))); }
|
||||
ZT_INLINE uint64_t vli_testBit(const uint64_t* p_vli, uint p_bit)
|
||||
{
|
||||
return (p_vli[p_bit / 64] & ((uint64_t)1 << (p_bit % 64)));
|
||||
}
|
||||
|
||||
ZT_INLINE uint vli_numDigits(const uint64_t *p_vli)
|
||||
ZT_INLINE uint vli_numDigits(const uint64_t* p_vli)
|
||||
{
|
||||
int i;
|
||||
for (i = NUM_ECC_DIGITS - 1; i >= 0 && p_vli[i] == 0; --i) {}
|
||||
return (uint)(i + 1);
|
||||
}
|
||||
|
||||
ZT_INLINE uint vli_numBits(const uint64_t *p_vli)
|
||||
ZT_INLINE uint vli_numBits(const uint64_t* p_vli)
|
||||
{
|
||||
uint i;
|
||||
uint64_t l_digit;
|
||||
|
@ -92,25 +115,26 @@ ZT_INLINE uint vli_numBits(const uint64_t *p_vli)
|
|||
return ((l_numDigits - 1) * 64 + i);
|
||||
}
|
||||
|
||||
ZT_INLINE void vli_set(uint64_t *p_dest, const uint64_t *p_src)
|
||||
ZT_INLINE void vli_set(uint64_t* p_dest, const uint64_t* p_src)
|
||||
{
|
||||
for (uint i = 0; i < NUM_ECC_DIGITS; ++i)
|
||||
p_dest[i] = p_src[i];
|
||||
}
|
||||
|
||||
ZT_INLINE int vli_cmp(const uint64_t *p_left, const uint64_t *p_right)
|
||||
ZT_INLINE int vli_cmp(const uint64_t* p_left, const uint64_t* p_right)
|
||||
{
|
||||
for (int i = NUM_ECC_DIGITS - 1; i >= 0; --i) {
|
||||
if (p_left[i] > p_right[i]) {
|
||||
return 1;
|
||||
} else if (p_left[i] < p_right[i]) {
|
||||
}
|
||||
else if (p_left[i] < p_right[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t vli_lshift(uint64_t *p_result, const uint64_t *p_in, uint p_shift)
|
||||
ZT_INLINE uint64_t vli_lshift(uint64_t* p_result, const uint64_t* p_in, uint p_shift)
|
||||
{
|
||||
uint64_t l_carry = 0;
|
||||
for (uint i = 0; i < NUM_ECC_DIGITS; ++i) {
|
||||
|
@ -121,9 +145,9 @@ ZT_INLINE uint64_t vli_lshift(uint64_t *p_result, const uint64_t *p_in, uint p_s
|
|||
return l_carry;
|
||||
}
|
||||
|
||||
ZT_INLINE void vli_rshift1(uint64_t *p_vli)
|
||||
ZT_INLINE void vli_rshift1(uint64_t* p_vli)
|
||||
{
|
||||
uint64_t *l_end = p_vli;
|
||||
uint64_t* l_end = p_vli;
|
||||
uint64_t l_carry = 0;
|
||||
p_vli += NUM_ECC_DIGITS;
|
||||
while (p_vli-- > l_end) {
|
||||
|
@ -133,7 +157,7 @@ ZT_INLINE void vli_rshift1(uint64_t *p_vli)
|
|||
}
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t vli_add(uint64_t *p_result, const uint64_t *p_left, const uint64_t *p_right)
|
||||
ZT_INLINE uint64_t vli_add(uint64_t* p_result, const uint64_t* p_left, const uint64_t* p_right)
|
||||
{
|
||||
uint64_t l_carry = 0;
|
||||
for (uint i = 0; i < NUM_ECC_DIGITS; ++i) {
|
||||
|
@ -146,7 +170,7 @@ ZT_INLINE uint64_t vli_add(uint64_t *p_result, const uint64_t *p_left, const uin
|
|||
return l_carry;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t vli_sub(uint64_t *p_result, const uint64_t *p_left, const uint64_t *p_right)
|
||||
ZT_INLINE uint64_t vli_sub(uint64_t* p_result, const uint64_t* p_left, const uint64_t* p_right)
|
||||
{
|
||||
uint64_t l_borrow = 0;
|
||||
for (uint i = 0; i < NUM_ECC_DIGITS; ++i) {
|
||||
|
@ -161,7 +185,7 @@ ZT_INLINE uint64_t vli_sub(uint64_t *p_result, const uint64_t *p_left, const uin
|
|||
|
||||
#if SUPPORTS_INT128 == 1
|
||||
|
||||
void vli_mult(uint64_t *p_result, const uint64_t *p_left, const uint64_t *p_right)
|
||||
void vli_mult(uint64_t* p_result, const uint64_t* p_left, const uint64_t* p_right)
|
||||
{
|
||||
uint128_t r01 = 0;
|
||||
uint64_t r2 = 0;
|
||||
|
@ -183,7 +207,7 @@ void vli_mult(uint64_t *p_result, const uint64_t *p_left, const uint64_t *p_righ
|
|||
p_result[NUM_ECC_DIGITS * 2 - 1] = (uint64_t)r01;
|
||||
}
|
||||
|
||||
void vli_square(uint64_t *p_result, const uint64_t *p_left)
|
||||
void vli_square(uint64_t* p_result, const uint64_t* p_left)
|
||||
{
|
||||
uint128_t r01 = 0;
|
||||
uint64_t r2 = 0;
|
||||
|
@ -244,9 +268,9 @@ ZT_INLINE uint128_t add_128_128(uint128_t a, uint128_t b)
|
|||
return l_result;
|
||||
}
|
||||
|
||||
void vli_mult(uint64_t *p_result, uint64_t *p_left, const uint64_t *p_right)
|
||||
void vli_mult(uint64_t* p_result, uint64_t* p_left, const uint64_t* p_right)
|
||||
{
|
||||
uint128_t r01 = {0, 0};
|
||||
uint128_t r01 = { 0, 0 };
|
||||
uint64_t r2 = 0;
|
||||
|
||||
uint i, k;
|
||||
|
@ -268,9 +292,9 @@ void vli_mult(uint64_t *p_result, uint64_t *p_left, const uint64_t *p_right)
|
|||
p_result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
|
||||
}
|
||||
|
||||
void vli_square(uint64_t *p_result, uint64_t *p_left)
|
||||
void vli_square(uint64_t* p_result, uint64_t* p_left)
|
||||
{
|
||||
uint128_t r01 = {0, 0};
|
||||
uint128_t r01 = { 0, 0 };
|
||||
uint64_t r2 = 0;
|
||||
|
||||
uint i, k;
|
||||
|
@ -297,7 +321,7 @@ void vli_square(uint64_t *p_result, uint64_t *p_left)
|
|||
|
||||
#endif /* SUPPORTS_INT128 */
|
||||
|
||||
void vli_modAdd(uint64_t *p_result, uint64_t *p_left, const uint64_t *p_right, const uint64_t *p_mod)
|
||||
void vli_modAdd(uint64_t* p_result, uint64_t* p_left, const uint64_t* p_right, const uint64_t* p_mod)
|
||||
{
|
||||
uint64_t l_carry = vli_add(p_result, p_left, p_right);
|
||||
if (l_carry || vli_cmp(p_result, p_mod) >= 0) {
|
||||
|
@ -305,7 +329,7 @@ void vli_modAdd(uint64_t *p_result, uint64_t *p_left, const uint64_t *p_right, c
|
|||
}
|
||||
}
|
||||
|
||||
void vli_modSub(uint64_t *p_result, uint64_t *p_left, const uint64_t *p_right, const uint64_t *p_mod)
|
||||
void vli_modSub(uint64_t* p_result, uint64_t* p_left, const uint64_t* p_right, const uint64_t* p_mod)
|
||||
{
|
||||
uint64_t l_borrow = vli_sub(p_result, p_left, p_right);
|
||||
if (l_borrow) {
|
||||
|
@ -313,7 +337,7 @@ void vli_modSub(uint64_t *p_result, uint64_t *p_left, const uint64_t *p_right, c
|
|||
}
|
||||
}
|
||||
|
||||
void omega_mult(uint64_t *p_result, uint64_t *p_right)
|
||||
void omega_mult(uint64_t* p_result, uint64_t* p_right)
|
||||
{
|
||||
uint64_t l_tmp[NUM_ECC_DIGITS];
|
||||
uint64_t l_carry, l_diff;
|
||||
|
@ -336,11 +360,11 @@ void omega_mult(uint64_t *p_result, uint64_t *p_right)
|
|||
p_result[NUM_ECC_DIGITS] = l_diff;
|
||||
}
|
||||
|
||||
void vli_mmod_fast(uint64_t *p_result, uint64_t *p_product)
|
||||
void vli_mmod_fast(uint64_t* p_result, uint64_t* p_product)
|
||||
{
|
||||
uint64_t l_tmp[2 * NUM_ECC_DIGITS];
|
||||
|
||||
while (!vli_isZero(p_product + NUM_ECC_DIGITS)) {
|
||||
while (! vli_isZero(p_product + NUM_ECC_DIGITS)) {
|
||||
uint64_t l_carry = 0;
|
||||
uint i;
|
||||
|
||||
|
@ -364,26 +388,26 @@ void vli_mmod_fast(uint64_t *p_result, uint64_t *p_product)
|
|||
vli_set(p_result, p_product);
|
||||
}
|
||||
|
||||
ZT_INLINE void vli_modMult_fast(uint64_t *p_result, uint64_t *p_left, const uint64_t *p_right)
|
||||
ZT_INLINE void vli_modMult_fast(uint64_t* p_result, uint64_t* p_left, const uint64_t* p_right)
|
||||
{
|
||||
uint64_t l_product[2 * NUM_ECC_DIGITS];
|
||||
vli_mult(l_product, p_left, p_right);
|
||||
vli_mmod_fast(p_result, l_product);
|
||||
}
|
||||
|
||||
ZT_INLINE void vli_modSquare_fast(uint64_t *p_result, uint64_t *p_left)
|
||||
ZT_INLINE void vli_modSquare_fast(uint64_t* p_result, uint64_t* p_left)
|
||||
{
|
||||
uint64_t l_product[2 * NUM_ECC_DIGITS];
|
||||
vli_square(l_product, p_left);
|
||||
vli_mmod_fast(p_result, l_product);
|
||||
}
|
||||
|
||||
#define vli_isEven(vli) (!(vli[0] & 1))
|
||||
#define vli_isEven(vli) (! (vli[0] & 1))
|
||||
|
||||
/* Computes p_result = (1 / p_input) % p_mod. All VLIs are the same size.
|
||||
See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
|
||||
https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf */
|
||||
void vli_modInv(uint64_t *p_result, uint64_t *p_input, const uint64_t *p_mod)
|
||||
void vli_modInv(uint64_t* p_result, uint64_t* p_input, const uint64_t* p_mod)
|
||||
{
|
||||
uint64_t a[NUM_ECC_DIGITS], b[NUM_ECC_DIGITS], u[NUM_ECC_DIGITS], v[NUM_ECC_DIGITS];
|
||||
uint64_t l_carry;
|
||||
|
@ -404,44 +428,47 @@ void vli_modInv(uint64_t *p_result, uint64_t *p_input, const uint64_t *p_mod)
|
|||
l_carry = 0;
|
||||
if (vli_isEven(a)) {
|
||||
vli_rshift1(a);
|
||||
if (!vli_isEven(u)) {
|
||||
if (! vli_isEven(u)) {
|
||||
l_carry = vli_add(u, u, p_mod);
|
||||
}
|
||||
vli_rshift1(u);
|
||||
if (l_carry) {
|
||||
u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
|
||||
}
|
||||
} else if (vli_isEven(b)) {
|
||||
}
|
||||
else if (vli_isEven(b)) {
|
||||
vli_rshift1(b);
|
||||
if (!vli_isEven(v)) {
|
||||
if (! vli_isEven(v)) {
|
||||
l_carry = vli_add(v, v, p_mod);
|
||||
}
|
||||
vli_rshift1(v);
|
||||
if (l_carry) {
|
||||
v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
|
||||
}
|
||||
} else if (l_cmpResult > 0) {
|
||||
}
|
||||
else if (l_cmpResult > 0) {
|
||||
vli_sub(a, a, b);
|
||||
vli_rshift1(a);
|
||||
if (vli_cmp(u, v) < 0) {
|
||||
vli_add(u, u, p_mod);
|
||||
}
|
||||
vli_sub(u, u, v);
|
||||
if (!vli_isEven(u)) {
|
||||
if (! vli_isEven(u)) {
|
||||
l_carry = vli_add(u, u, p_mod);
|
||||
}
|
||||
vli_rshift1(u);
|
||||
if (l_carry) {
|
||||
u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vli_sub(b, b, a);
|
||||
vli_rshift1(b);
|
||||
if (vli_cmp(v, u) < 0) {
|
||||
vli_add(v, v, p_mod);
|
||||
}
|
||||
vli_sub(v, v, u);
|
||||
if (!vli_isEven(v)) {
|
||||
if (! vli_isEven(v)) {
|
||||
l_carry = vli_add(v, v, p_mod);
|
||||
}
|
||||
vli_rshift1(v);
|
||||
|
@ -454,10 +481,12 @@ void vli_modInv(uint64_t *p_result, uint64_t *p_input, const uint64_t *p_mod)
|
|||
vli_set(p_result, u);
|
||||
}
|
||||
|
||||
ZT_INLINE int EccPoint_isZero(EccPoint *p_point)
|
||||
{ return (vli_isZero(p_point->x) && vli_isZero(p_point->y)); }
|
||||
ZT_INLINE int EccPoint_isZero(EccPoint* p_point)
|
||||
{
|
||||
return (vli_isZero(p_point->x) && vli_isZero(p_point->y));
|
||||
}
|
||||
|
||||
void EccPoint_double_jacobian(uint64_t *X1, uint64_t *Y1, uint64_t *Z1)
|
||||
void EccPoint_double_jacobian(uint64_t* X1, uint64_t* Y1, uint64_t* Z1)
|
||||
{
|
||||
/* t1 = X, t2 = Y, t3 = Z */
|
||||
uint64_t t4[NUM_ECC_DIGITS];
|
||||
|
@ -484,7 +513,8 @@ void EccPoint_double_jacobian(uint64_t *X1, uint64_t *Y1, uint64_t *Z1)
|
|||
uint64_t l_carry = vli_add(X1, X1, curve_p);
|
||||
vli_rshift1(X1);
|
||||
X1[NUM_ECC_DIGITS - 1] |= l_carry << 63U;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vli_rshift1(X1);
|
||||
}
|
||||
/* t1 = 3/2*(x1^2 - z1^4) = B */
|
||||
|
@ -501,7 +531,7 @@ void EccPoint_double_jacobian(uint64_t *X1, uint64_t *Y1, uint64_t *Z1)
|
|||
vli_set(Y1, t4);
|
||||
}
|
||||
|
||||
void apply_z(uint64_t *X1, uint64_t *Y1, uint64_t *Z)
|
||||
void apply_z(uint64_t* X1, uint64_t* Y1, uint64_t* Z)
|
||||
{
|
||||
uint64_t t1[NUM_ECC_DIGITS];
|
||||
|
||||
|
@ -511,7 +541,7 @@ void apply_z(uint64_t *X1, uint64_t *Y1, uint64_t *Z)
|
|||
vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
|
||||
}
|
||||
|
||||
void XYcZ_initial_double(uint64_t *X1, uint64_t *Y1, uint64_t *X2, uint64_t *Y2, uint64_t *p_initialZ)
|
||||
void XYcZ_initial_double(uint64_t* X1, uint64_t* Y1, uint64_t* X2, uint64_t* Y2, uint64_t* p_initialZ)
|
||||
{
|
||||
uint64_t z[NUM_ECC_DIGITS];
|
||||
|
||||
|
@ -531,7 +561,7 @@ void XYcZ_initial_double(uint64_t *X1, uint64_t *Y1, uint64_t *X2, uint64_t *Y2,
|
|||
apply_z(X2, Y2, z);
|
||||
}
|
||||
|
||||
void XYcZ_add(uint64_t *X1, uint64_t *Y1, uint64_t *X2, uint64_t *Y2)
|
||||
void XYcZ_add(uint64_t* X1, uint64_t* Y1, uint64_t* X2, uint64_t* Y2)
|
||||
{
|
||||
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
|
||||
uint64_t t5[NUM_ECC_DIGITS];
|
||||
|
@ -554,7 +584,7 @@ void XYcZ_add(uint64_t *X1, uint64_t *Y1, uint64_t *X2, uint64_t *Y2)
|
|||
vli_set(X2, t5);
|
||||
}
|
||||
|
||||
void XYcZ_addC(uint64_t *X1, uint64_t *Y1, uint64_t *X2, uint64_t *Y2)
|
||||
void XYcZ_addC(uint64_t* X1, uint64_t* Y1, uint64_t* X2, uint64_t* Y2)
|
||||
{
|
||||
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
|
||||
uint64_t t5[NUM_ECC_DIGITS];
|
||||
|
@ -587,7 +617,7 @@ void XYcZ_addC(uint64_t *X1, uint64_t *Y1, uint64_t *X2, uint64_t *Y2)
|
|||
vli_set(X1, t7);
|
||||
}
|
||||
|
||||
void EccPoint_mult(EccPoint *p_result, const EccPoint *p_point, uint64_t *p_scalar, uint64_t *p_initialZ)
|
||||
void EccPoint_mult(EccPoint* p_result, const EccPoint* p_point, uint64_t* p_scalar, uint64_t* p_initialZ)
|
||||
{
|
||||
/* R0 and R1 */
|
||||
uint64_t Rx[2][NUM_ECC_DIGITS];
|
||||
|
@ -602,12 +632,12 @@ void EccPoint_mult(EccPoint *p_result, const EccPoint *p_point, uint64_t *p_scal
|
|||
XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], p_initialZ);
|
||||
|
||||
for (i = (int)vli_numBits(p_scalar) - 2; i > 0; --i) {
|
||||
nb = !vli_testBit(p_scalar, i);
|
||||
nb = ! vli_testBit(p_scalar, i);
|
||||
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb]);
|
||||
XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb]);
|
||||
}
|
||||
|
||||
nb = !vli_testBit(p_scalar, 0);
|
||||
nb = ! vli_testBit(p_scalar, 0);
|
||||
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb]);
|
||||
|
||||
/* Find final 1/Z value. */
|
||||
|
@ -630,16 +660,17 @@ void EccPoint_mult(EccPoint *p_result, const EccPoint *p_point, uint64_t *p_scal
|
|||
ZT_INLINE void ecc_bytes2native(uint64_t p_native[NUM_ECC_DIGITS], const uint8_t p_bytes[ECC_BYTES])
|
||||
{
|
||||
for (uint i = 0; i < NUM_ECC_DIGITS; ++i) {
|
||||
const uint8_t *p_digit = p_bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
|
||||
p_native[i] = ((uint64_t)p_digit[0] << 56) | ((uint64_t)p_digit[1] << 48) | ((uint64_t)p_digit[2] << 40) | ((uint64_t)p_digit[3] << 32) |
|
||||
((uint64_t)p_digit[4] << 24) | ((uint64_t)p_digit[5] << 16) | ((uint64_t)p_digit[6] << 8) | (uint64_t)p_digit[7];
|
||||
const uint8_t* p_digit = p_bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
|
||||
p_native[i] = ((uint64_t)p_digit[0] << 56) | ((uint64_t)p_digit[1] << 48) | ((uint64_t)p_digit[2] << 40)
|
||||
| ((uint64_t)p_digit[3] << 32) | ((uint64_t)p_digit[4] << 24) | ((uint64_t)p_digit[5] << 16)
|
||||
| ((uint64_t)p_digit[6] << 8) | (uint64_t)p_digit[7];
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE void ecc_native2bytes(uint8_t p_bytes[ECC_BYTES], const uint64_t p_native[NUM_ECC_DIGITS])
|
||||
{
|
||||
for (uint i = 0; i < NUM_ECC_DIGITS; ++i) {
|
||||
uint8_t *p_digit = p_bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
|
||||
uint8_t* p_digit = p_bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
|
||||
p_digit[0] = p_native[i] >> 56;
|
||||
p_digit[1] = p_native[i] >> 48;
|
||||
p_digit[2] = p_native[i] >> 40;
|
||||
|
@ -653,8 +684,8 @@ ZT_INLINE void ecc_native2bytes(uint8_t p_bytes[ECC_BYTES], const uint64_t p_nat
|
|||
|
||||
void mod_sqrt(uint64_t a[NUM_ECC_DIGITS])
|
||||
{
|
||||
uint64_t p1[NUM_ECC_DIGITS] = {1};
|
||||
uint64_t l_result[NUM_ECC_DIGITS] = {1};
|
||||
uint64_t p1[NUM_ECC_DIGITS] = { 1 };
|
||||
uint64_t l_result[NUM_ECC_DIGITS] = { 1 };
|
||||
|
||||
vli_add(p1, curve_p, p1); /* p1 = curve_p + 1 */
|
||||
for (uint i = vli_numBits(p1) - 1; i > 1; --i) {
|
||||
|
@ -666,9 +697,9 @@ void mod_sqrt(uint64_t a[NUM_ECC_DIGITS])
|
|||
vli_set(a, l_result);
|
||||
}
|
||||
|
||||
void ecc_point_decompress(EccPoint *p_point, const uint8_t p_compressed[ECC_BYTES + 1])
|
||||
void ecc_point_decompress(EccPoint* p_point, const uint8_t p_compressed[ECC_BYTES + 1])
|
||||
{
|
||||
uint64_t _3[NUM_ECC_DIGITS] = {3}; /* -a = 3 */
|
||||
uint64_t _3[NUM_ECC_DIGITS] = { 3 }; /* -a = 3 */
|
||||
ecc_bytes2native(p_point->x, p_compressed + 1);
|
||||
|
||||
vli_modSquare_fast(p_point->y, p_point->x); /* y = x^2 */
|
||||
|
@ -690,7 +721,7 @@ ZT_INLINE int ecc_make_key(uint8_t p_publicKey[ECC_BYTES + 1], uint8_t p_private
|
|||
unsigned l_tries = 0;
|
||||
|
||||
do {
|
||||
if (!getRandomNumber(l_private) || (l_tries++ >= ECC_CREATE_KEY_MAX_ATTEMPTS)) {
|
||||
if (! getRandomNumber(l_private) || (l_tries++ >= ECC_CREATE_KEY_MAX_ATTEMPTS)) {
|
||||
return 0;
|
||||
}
|
||||
if (vli_isZero(l_private)) {
|
||||
|
@ -710,13 +741,16 @@ ZT_INLINE int ecc_make_key(uint8_t p_publicKey[ECC_BYTES + 1], uint8_t p_private
|
|||
return 1;
|
||||
}
|
||||
|
||||
ZT_INLINE int ecdh_shared_secret(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8_t p_privateKey[ECC_BYTES], uint8_t p_secret[ECC_BYTES])
|
||||
ZT_INLINE int ecdh_shared_secret(
|
||||
const uint8_t p_publicKey[ECC_BYTES + 1],
|
||||
const uint8_t p_privateKey[ECC_BYTES],
|
||||
uint8_t p_secret[ECC_BYTES])
|
||||
{
|
||||
EccPoint l_public;
|
||||
uint64_t l_private[NUM_ECC_DIGITS];
|
||||
uint64_t l_random[NUM_ECC_DIGITS];
|
||||
|
||||
if (!getRandomNumber(l_random)) {
|
||||
if (! getRandomNumber(l_random)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -728,11 +762,11 @@ ZT_INLINE int ecdh_shared_secret(const uint8_t p_publicKey[ECC_BYTES + 1], const
|
|||
|
||||
ecc_native2bytes(p_secret, l_product.x);
|
||||
|
||||
return !EccPoint_isZero(&l_product);
|
||||
return ! EccPoint_isZero(&l_product);
|
||||
}
|
||||
|
||||
/* Computes p_result = (p_left * p_right) % p_mod. */
|
||||
void vli_modMult(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, const uint64_t *p_mod)
|
||||
void vli_modMult(uint64_t* p_result, uint64_t* p_left, uint64_t* p_right, const uint64_t* p_mod)
|
||||
{
|
||||
uint64_t l_product[2 * NUM_ECC_DIGITS];
|
||||
uint64_t l_modMultiple[2 * NUM_ECC_DIGITS];
|
||||
|
@ -744,7 +778,8 @@ void vli_modMult(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, const
|
|||
l_productBits = vli_numBits(l_product + NUM_ECC_DIGITS);
|
||||
if (l_productBits) {
|
||||
l_productBits += NUM_ECC_DIGITS * 64;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
l_productBits = vli_numBits(l_product);
|
||||
}
|
||||
|
||||
|
@ -761,7 +796,8 @@ void vli_modMult(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, const
|
|||
l_bitShift = (l_productBits - l_modBits) % 64;
|
||||
if (l_bitShift) {
|
||||
l_modMultiple[l_digitShift + NUM_ECC_DIGITS] = vli_lshift(l_modMultiple + l_digitShift, p_mod, l_bitShift);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vli_set(l_modMultiple + l_digitShift, p_mod);
|
||||
}
|
||||
|
||||
|
@ -791,7 +827,8 @@ ZT_INLINE uint umax(uint a, uint b)
|
|||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
ZT_INLINE int ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_hash[ECC_BYTES], uint8_t p_signature[ECC_BYTES * 2])
|
||||
ZT_INLINE int
|
||||
ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_hash[ECC_BYTES], uint8_t p_signature[ECC_BYTES * 2])
|
||||
{
|
||||
uint64_t k[NUM_ECC_DIGITS];
|
||||
uint64_t l_tmp[NUM_ECC_DIGITS];
|
||||
|
@ -800,7 +837,7 @@ ZT_INLINE int ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_
|
|||
unsigned l_tries = 0;
|
||||
|
||||
do {
|
||||
if (!getRandomNumber(k) || (l_tries++ >= ECC_CREATE_KEY_MAX_ATTEMPTS)) {
|
||||
if (! getRandomNumber(k) || (l_tries++ >= ECC_CREATE_KEY_MAX_ATTEMPTS)) {
|
||||
return 0;
|
||||
}
|
||||
if (vli_isZero(k)) {
|
||||
|
@ -833,7 +870,10 @@ ZT_INLINE int ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_
|
|||
return 1;
|
||||
}
|
||||
|
||||
ZT_INLINE int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8_t p_hash[ECC_BYTES], const uint8_t p_signature[ECC_BYTES * 2])
|
||||
ZT_INLINE int ecdsa_verify(
|
||||
const uint8_t p_publicKey[ECC_BYTES + 1],
|
||||
const uint8_t p_hash[ECC_BYTES],
|
||||
const uint8_t p_signature[ECC_BYTES * 2])
|
||||
{
|
||||
uint64_t u1[NUM_ECC_DIGITS], u2[NUM_ECC_DIGITS];
|
||||
uint64_t z[NUM_ECC_DIGITS];
|
||||
|
@ -875,10 +915,11 @@ ZT_INLINE int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8
|
|||
apply_z(l_sum.x, l_sum.y, z);
|
||||
|
||||
/* Use Shamir's trick to calculate u1*G + u2*Q */
|
||||
const EccPoint *l_points[4] = {NULL, &curve_G, &l_public, &l_sum};
|
||||
const EccPoint* l_points[4] = { NULL, &curve_G, &l_public, &l_sum };
|
||||
uint l_numBits = umax(vli_numBits(u1), vli_numBits(u2));
|
||||
|
||||
const EccPoint *l_point = l_points[(!!vli_testBit(u1, l_numBits - 1)) | ((!!vli_testBit(u2, l_numBits - 1)) << 1)];
|
||||
const EccPoint* l_point =
|
||||
l_points[(! ! vli_testBit(u1, l_numBits - 1)) | ((! ! vli_testBit(u2, l_numBits - 1)) << 1)];
|
||||
vli_set(rx, l_point->x);
|
||||
vli_set(ry, l_point->y);
|
||||
vli_clear(z);
|
||||
|
@ -888,8 +929,8 @@ ZT_INLINE int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8
|
|||
for (i = l_numBits - 2; i >= 0; --i) {
|
||||
EccPoint_double_jacobian(rx, ry, z);
|
||||
|
||||
int l_index = (!!vli_testBit(u1, i)) | ((!!vli_testBit(u2, i)) << 1);
|
||||
const EccPoint *l_point = l_points[l_index];
|
||||
int l_index = (! ! vli_testBit(u1, i)) | ((! ! vli_testBit(u2, i)) << 1);
|
||||
const EccPoint* l_point = l_points[l_index];
|
||||
if (l_point) {
|
||||
vli_set(tx, l_point->x);
|
||||
vli_set(ty, l_point->y);
|
||||
|
@ -916,26 +957,35 @@ ZT_INLINE int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8
|
|||
|
||||
void ECC384GenerateKey(uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE], uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE])
|
||||
{
|
||||
if (!ecc_make_key(pub, priv)) {
|
||||
if (! ecc_make_key(pub, priv)) {
|
||||
fprintf(stderr, "FATAL: ecdsa_make_key() failed!" ZT_EOL_S);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE], const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE], uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
void ECC384ECDSASign(
|
||||
const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
{
|
||||
if (!ecdsa_sign(priv, hash, sig)) {
|
||||
if (! ecdsa_sign(priv, hash, sig)) {
|
||||
fprintf(stderr, "FATAL: ecdsa_sign() failed!" ZT_EOL_S);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
bool ECC384ECDSAVerify(const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE], const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE], const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
bool ECC384ECDSAVerify(
|
||||
const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
{
|
||||
return (ecdsa_verify(pub, hash, sig) != 0);
|
||||
}
|
||||
|
||||
bool ECC384ECDH(const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE], const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE], uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE])
|
||||
bool ECC384ECDH(
|
||||
const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE])
|
||||
{
|
||||
return (ecdh_shared_secret(theirPub, ourPriv, secret) != 0);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace ZeroTier {
|
|||
* @param pub Buffer to receive point compressed public key
|
||||
* @param priv Buffer to receiver private key
|
||||
*/
|
||||
void ECC384GenerateKey(uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE]);
|
||||
void ECC384GenerateKey(uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE], uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE]);
|
||||
|
||||
/**
|
||||
* Sign a hash with a NIST P-384 private key
|
||||
|
@ -77,7 +77,10 @@ void ECC384GenerateKey(uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],uint8_t priv[ZT_EC
|
|||
* @param hash 48-byte hash
|
||||
* @param sig Buffer to receive signature
|
||||
*/
|
||||
void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
void ECC384ECDSASign(
|
||||
const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
|
||||
/**
|
||||
* Verify a signature
|
||||
|
@ -87,7 +90,10 @@ void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],const uint8_
|
|||
* @param sig Signature to check
|
||||
* @return True if signature is valid
|
||||
*/
|
||||
bool ECC384ECDSAVerify(const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
bool ECC384ECDSAVerify(
|
||||
const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
|
||||
/**
|
||||
* Perform ECDH key agreement
|
||||
|
@ -99,7 +105,10 @@ bool ECC384ECDSAVerify(const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_
|
|||
* @param ourPriv Local private key
|
||||
* @param secret Buffer to receive 48-byte secret
|
||||
*/
|
||||
bool ECC384ECDH(const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE],uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE]);
|
||||
bool ECC384ECDH(
|
||||
const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE]);
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
|
@ -12,41 +12,60 @@
|
|||
/****/
|
||||
|
||||
#include "Endpoint.hpp"
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
static ZT_INLINE char s_endpointTypeChar(const ZT_EndpointType t)
|
||||
{
|
||||
switch(t) {
|
||||
default: return '0';
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER: return 'z';
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET: return 'e';
|
||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT: return 'd';
|
||||
case ZT_ENDPOINT_TYPE_BLUETOOTH: return 'b';
|
||||
case ZT_ENDPOINT_TYPE_IP: return 'i';
|
||||
case ZT_ENDPOINT_TYPE_IP_UDP: return 'u';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP: return 't';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP_WS: return 'w';
|
||||
switch (t) {
|
||||
default:
|
||||
return '0';
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
||||
return 'z';
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||
return 'e';
|
||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
||||
return 'd';
|
||||
case ZT_ENDPOINT_TYPE_BLUETOOTH:
|
||||
return 'b';
|
||||
case ZT_ENDPOINT_TYPE_IP:
|
||||
return 'i';
|
||||
case ZT_ENDPOINT_TYPE_IP_UDP:
|
||||
return 'u';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP:
|
||||
return 't';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP_WS:
|
||||
return 'w';
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_INLINE ZT_EndpointType s_charEndpointType(const char c)
|
||||
{
|
||||
switch(c) {
|
||||
default: return ZT_ENDPOINT_TYPE_NIL;
|
||||
case 'z': return ZT_ENDPOINT_TYPE_ZEROTIER;
|
||||
case 'e': return ZT_ENDPOINT_TYPE_ETHERNET;
|
||||
case 'd': return ZT_ENDPOINT_TYPE_WIFI_DIRECT;
|
||||
case 'b': return ZT_ENDPOINT_TYPE_BLUETOOTH;
|
||||
case 'i': return ZT_ENDPOINT_TYPE_IP;
|
||||
case 'u': return ZT_ENDPOINT_TYPE_IP_UDP;
|
||||
case 't': return ZT_ENDPOINT_TYPE_IP_TCP;
|
||||
case 'w': return ZT_ENDPOINT_TYPE_IP_TCP_WS;
|
||||
switch (c) {
|
||||
default:
|
||||
return ZT_ENDPOINT_TYPE_NIL;
|
||||
case 'z':
|
||||
return ZT_ENDPOINT_TYPE_ZEROTIER;
|
||||
case 'e':
|
||||
return ZT_ENDPOINT_TYPE_ETHERNET;
|
||||
case 'd':
|
||||
return ZT_ENDPOINT_TYPE_WIFI_DIRECT;
|
||||
case 'b':
|
||||
return ZT_ENDPOINT_TYPE_BLUETOOTH;
|
||||
case 'i':
|
||||
return ZT_ENDPOINT_TYPE_IP;
|
||||
case 'u':
|
||||
return ZT_ENDPOINT_TYPE_IP_UDP;
|
||||
case 't':
|
||||
return ZT_ENDPOINT_TYPE_IP_TCP;
|
||||
case 'w':
|
||||
return ZT_ENDPOINT_TYPE_IP_TCP_WS;
|
||||
}
|
||||
}
|
||||
|
||||
char *Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
||||
char* Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
static_assert(ZT_ENDPOINT_STRING_SIZE_MAX > (ZT_INETADDRESS_STRING_SIZE_MAX + 4), "overflow");
|
||||
static_assert(ZT_ENDPOINT_STRING_SIZE_MAX > (ZT_FINGERPRINT_STRING_SIZE_MAX + 4), "overflow");
|
||||
|
@ -78,26 +97,27 @@ char *Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
|||
return s;
|
||||
}
|
||||
|
||||
bool Endpoint::fromString(const char *s) noexcept
|
||||
bool Endpoint::fromString(const char* s) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if ((!s) || (!*s)) {
|
||||
if ((! s) || (! *s)) {
|
||||
// Empty strings are considered NIL endpoints.
|
||||
return true;
|
||||
} else if (s[1] == '/') {
|
||||
}
|
||||
else if (s[1] == '/') {
|
||||
// type/ADDRESS is a fully qualified endpoint.
|
||||
this->type = s_charEndpointType(s[0]);
|
||||
switch(this->type) {
|
||||
switch (this->type) {
|
||||
case ZT_ENDPOINT_TYPE_NIL:
|
||||
break;
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
||||
if (!s[2])
|
||||
if (! s[2])
|
||||
return false;
|
||||
break;
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
||||
case ZT_ENDPOINT_TYPE_BLUETOOTH: {
|
||||
if (!s[2])
|
||||
if (! s[2])
|
||||
return false;
|
||||
MAC tmpmac;
|
||||
tmpmac.fromString(s + 2);
|
||||
|
@ -107,13 +127,14 @@ bool Endpoint::fromString(const char *s) noexcept
|
|||
case ZT_ENDPOINT_TYPE_IP_UDP:
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP:
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP_WS: {
|
||||
if (!s[2])
|
||||
if (! s[2])
|
||||
return false;
|
||||
if (!asInetAddress(this->value.ss).fromString(s + 2))
|
||||
if (! asInetAddress(this->value.ss).fromString(s + 2))
|
||||
return false;
|
||||
} break;
|
||||
}
|
||||
} else if (strchr(s, '/') != nullptr) {
|
||||
}
|
||||
else if (strchr(s, '/') != nullptr) {
|
||||
// IP/port is parsed as an IP_UDP endpoint for backward compatibility.
|
||||
this->type = ZT_ENDPOINT_TYPE_IP_UDP;
|
||||
return asInetAddress(this->value.ss).fromString(s);
|
||||
|
@ -155,7 +176,7 @@ int Endpoint::marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept
|
|||
}
|
||||
}
|
||||
|
||||
int Endpoint::unmarshal(const uint8_t *restrict data, int len) noexcept
|
||||
int Endpoint::unmarshal(const uint8_t* restrict data, int len) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if (unlikely(len <= 0))
|
||||
|
@ -217,14 +238,14 @@ int Endpoint::unmarshal(const uint8_t *restrict data, int len) noexcept
|
|||
this->type = ZT_ENDPOINT_TYPE_NIL;
|
||||
if (len < 3)
|
||||
return -1;
|
||||
const int unrecLen = 1 + (int) Utils::loadBigEndian<uint16_t>(data + 1);
|
||||
const int unrecLen = 1 + (int)Utils::loadBigEndian<uint16_t>(data + 1);
|
||||
return (unrecLen > len) ? -1 : unrecLen;
|
||||
}
|
||||
|
||||
bool Endpoint::operator==(const Endpoint &ep) const noexcept
|
||||
bool Endpoint::operator==(const Endpoint& ep) const noexcept
|
||||
{
|
||||
if (this->type == ep.type) {
|
||||
switch(this->type) {
|
||||
switch (this->type) {
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
||||
return zt() == ep.zt();
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||
|
@ -243,10 +264,10 @@ bool Endpoint::operator==(const Endpoint &ep) const noexcept
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Endpoint::operator<(const Endpoint &ep) const noexcept
|
||||
bool Endpoint::operator<(const Endpoint& ep) const noexcept
|
||||
{
|
||||
if (this->type == ep.type) {
|
||||
switch(this->type) {
|
||||
switch (this->type) {
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
||||
return zt() < ep.zt();
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||
|
|
|
@ -14,24 +14,32 @@
|
|||
#ifndef ZT_ENDPOINT_HPP
|
||||
#define ZT_ENDPOINT_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_ENDPOINT_STRING_SIZE_MAX 256
|
||||
#define ZT_ENDPOINT_MARSHAL_SIZE_MAX 192
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > ZT_INETADDRESS_MARSHAL_SIZE_MAX, "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(ZT_Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(InetAddress), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > ZT_INETADDRESS_MARSHAL_SIZE_MAX,
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(ZT_Fingerprint),
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(InetAddress),
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(MAC), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint),
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
|
||||
/**
|
||||
* Endpoint variant specifying some form of network endpoint.
|
||||
|
@ -42,17 +50,22 @@ static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint), "ZT_ENDP
|
|||
* where InetAddress was used as long as only the UDP type is exchanged
|
||||
* with those nodes.
|
||||
*/
|
||||
class Endpoint : public ZT_Endpoint, public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
class Endpoint
|
||||
: public ZT_Endpoint
|
||||
, public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Create a NIL/empty endpoint
|
||||
*/
|
||||
ZT_INLINE Endpoint() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE Endpoint(const ZT_Endpoint &ep) noexcept
|
||||
{ Utils::copy< sizeof(ZT_Endpoint) >((ZT_Endpoint *)this, &ep); }
|
||||
ZT_INLINE Endpoint(const ZT_Endpoint& ep) noexcept
|
||||
{
|
||||
Utils::copy<sizeof(ZT_Endpoint)>((ZT_Endpoint*)this, &ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an endpoint for a type that uses an IP
|
||||
|
@ -60,12 +73,13 @@ public:
|
|||
* @param a IP/port
|
||||
* @param et Endpoint type (default: IP_UDP)
|
||||
*/
|
||||
ZT_INLINE Endpoint(const InetAddress &inaddr, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_IP_UDP) noexcept
|
||||
ZT_INLINE Endpoint(const InetAddress& inaddr, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_IP_UDP) noexcept
|
||||
{
|
||||
if (inaddr) {
|
||||
this->type = et;
|
||||
Utils::copy< sizeof(struct sockaddr_storage) >(&(this->value.ss), &(inaddr.as.ss));
|
||||
} else {
|
||||
Utils::copy<sizeof(struct sockaddr_storage)>(&(this->value.ss), &(inaddr.as.ss));
|
||||
}
|
||||
else {
|
||||
memoryZero(this);
|
||||
}
|
||||
}
|
||||
|
@ -75,12 +89,13 @@ public:
|
|||
*
|
||||
* @param zt_ ZeroTier identity fingerprint
|
||||
*/
|
||||
ZT_INLINE Endpoint(const Fingerprint &zt_) noexcept
|
||||
ZT_INLINE Endpoint(const Fingerprint& zt_) noexcept
|
||||
{
|
||||
if (zt_) {
|
||||
this->type = ZT_ENDPOINT_TYPE_ZEROTIER;
|
||||
this->value.fp = zt_;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
memoryZero(this);
|
||||
}
|
||||
}
|
||||
|
@ -91,12 +106,13 @@ public:
|
|||
* @param eth_ Ethernet address
|
||||
* @param et Endpoint type (default: ETHERNET)
|
||||
*/
|
||||
ZT_INLINE Endpoint(const MAC ð_, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_ETHERNET) noexcept
|
||||
ZT_INLINE Endpoint(const MAC& eth_, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_ETHERNET) noexcept
|
||||
{
|
||||
if (eth_) {
|
||||
this->type = et;
|
||||
this->value.mac = eth_.toInt();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
memoryZero(this);
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +121,9 @@ public:
|
|||
* @return True if endpoint type isn't NIL
|
||||
*/
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return this->type != ZT_ENDPOINT_TYPE_NIL; }
|
||||
{
|
||||
return this->type != ZT_ENDPOINT_TYPE_NIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this endpoint type has an InetAddress address type and thus ip() is valid
|
||||
|
@ -132,7 +150,7 @@ public:
|
|||
* @param ep Endpoint to check
|
||||
* @return True if endpoints seem to refer to the same address/host
|
||||
*/
|
||||
ZT_INLINE bool isSameAddress(const Endpoint &ep) const noexcept
|
||||
ZT_INLINE bool isSameAddress(const Endpoint& ep) const noexcept
|
||||
{
|
||||
switch (this->type) {
|
||||
case ZT_ENDPOINT_TYPE_IP:
|
||||
|
@ -160,8 +178,10 @@ public:
|
|||
*
|
||||
* @return InetAddress instance
|
||||
*/
|
||||
ZT_INLINE const InetAddress &ip() const noexcept
|
||||
{ return asInetAddress(this->value.ss); }
|
||||
ZT_INLINE const InetAddress& ip() const noexcept
|
||||
{
|
||||
return asInetAddress(this->value.ss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MAC if this is an Ethernet, WiFi direct, or Bluetooth type (undefined otherwise)
|
||||
|
@ -169,7 +189,9 @@ public:
|
|||
* @return Ethernet MAC
|
||||
*/
|
||||
ZT_INLINE MAC eth() const noexcept
|
||||
{ return MAC(this->value.mac); }
|
||||
{
|
||||
return MAC(this->value.mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fingerprint if this is a ZeroTier endpoint type (undefined otherwise)
|
||||
|
@ -177,7 +199,9 @@ public:
|
|||
* @return ZeroTier fingerprint
|
||||
*/
|
||||
ZT_INLINE Fingerprint zt() const noexcept
|
||||
{ return Fingerprint(this->value.fp); }
|
||||
{
|
||||
return Fingerprint(this->value.fp);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{
|
||||
|
@ -198,7 +222,7 @@ 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
|
||||
{
|
||||
|
@ -206,30 +230,40 @@ public:
|
|||
return String(toString(tmp));
|
||||
}
|
||||
|
||||
bool fromString(const char *s) noexcept;
|
||||
bool fromString(const char* s) noexcept;
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_ENDPOINT_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept;
|
||||
|
||||
int unmarshal(const uint8_t *restrict data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* restrict data, int len) noexcept;
|
||||
|
||||
bool operator==(const Endpoint &ep) const noexcept;
|
||||
bool operator==(const Endpoint& ep) const noexcept;
|
||||
|
||||
ZT_INLINE bool operator!=(const Endpoint &ep) const noexcept
|
||||
{ return !((*this) == ep); }
|
||||
ZT_INLINE bool operator!=(const Endpoint& ep) const noexcept
|
||||
{
|
||||
return ! ((*this) == ep);
|
||||
}
|
||||
|
||||
bool operator<(const Endpoint &ep) const noexcept;
|
||||
bool operator<(const Endpoint& ep) const noexcept;
|
||||
|
||||
ZT_INLINE bool operator>(const Endpoint &ep) const noexcept
|
||||
{ return (ep < *this); }
|
||||
ZT_INLINE bool operator>(const Endpoint& ep) const noexcept
|
||||
{
|
||||
return (ep < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Endpoint &ep) const noexcept
|
||||
{ return !(ep < *this); }
|
||||
ZT_INLINE bool operator<=(const Endpoint& ep) const noexcept
|
||||
{
|
||||
return ! (ep < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Endpoint &ep) const noexcept
|
||||
{ return !(*this < ep); }
|
||||
ZT_INLINE bool operator>=(const Endpoint& ep) const noexcept
|
||||
{
|
||||
return ! (*this < ep);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Endpoint) == sizeof(ZT_Endpoint), "size mismatch");
|
||||
|
|
|
@ -36,12 +36,11 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Tracker for expected OK replies to packet IDs of sent packets
|
||||
*/
|
||||
class Expect
|
||||
{
|
||||
public:
|
||||
ZT_INLINE Expect() :
|
||||
m_packetIdSent()
|
||||
{}
|
||||
class Expect {
|
||||
public:
|
||||
ZT_INLINE Expect() : m_packetIdSent()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by other code when something is sending a packet that could potentially receive an OK response
|
||||
|
@ -50,7 +49,10 @@ public:
|
|||
* @param now Current time
|
||||
*/
|
||||
ZT_INLINE void sending(const uint64_t packetId, const int64_t now) noexcept
|
||||
{ m_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS] = (uint32_t)(now / ZT_EXPECT_TTL); }
|
||||
{
|
||||
m_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS] =
|
||||
(uint32_t)(now / ZT_EXPECT_TTL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an OK is expected and if so reset the corresponding bucket.
|
||||
|
@ -64,11 +66,18 @@ public:
|
|||
* @return True if we're expecting a reply (and a reset occurred)
|
||||
*/
|
||||
ZT_INLINE bool expecting(const uint64_t inRePacketId, const int64_t now) noexcept
|
||||
{ return (((now / ZT_EXPECT_TTL) - (int64_t)m_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].exchange(0)) <= 1); }
|
||||
{
|
||||
return (
|
||||
((now / ZT_EXPECT_TTL)
|
||||
- (int64_t)
|
||||
m_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS]
|
||||
.exchange(0))
|
||||
<= 1);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
// Each bucket contains a timestamp in units of the max expect duration.
|
||||
std::atomic< uint32_t > m_packetIdSent[ZT_EXPECT_BUCKETS];
|
||||
std::atomic<uint32_t> m_packetIdSent[ZT_EXPECT_BUCKETS];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
177
core/FCV.hpp
177
core/FCV.hpp
|
@ -16,8 +16,8 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
|
@ -32,30 +32,28 @@ namespace ZeroTier {
|
|||
* @tparam T Type to contain
|
||||
* @tparam C Maximum capacity of vector
|
||||
*/
|
||||
template< typename T, unsigned int C >
|
||||
class FCV
|
||||
{
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
template <typename T, unsigned int C> class FCV {
|
||||
public:
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
ZT_INLINE FCV() noexcept: _s(0)
|
||||
{}
|
||||
ZT_INLINE FCV() noexcept : _s(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE FCV(const FCV &v) : _s(0)
|
||||
{ *this = v; }
|
||||
ZT_INLINE FCV(const FCV& v) : _s(0)
|
||||
{
|
||||
*this = v;
|
||||
}
|
||||
|
||||
ZT_INLINE FCV(const T *const contents, const unsigned int len) :
|
||||
_s(len)
|
||||
ZT_INLINE FCV(const T* const contents, const unsigned int len) : _s(len)
|
||||
{
|
||||
const unsigned int l = std::min(len, C);
|
||||
for (unsigned int i = 0; i < l; ++i)
|
||||
new(reinterpret_cast<T *>(_m) + i) T(contents[i]);
|
||||
new (reinterpret_cast<T*>(_m) + i) T(contents[i]);
|
||||
}
|
||||
|
||||
template< typename I >
|
||||
ZT_INLINE FCV(I i, I end) :
|
||||
_s(0)
|
||||
template <typename I> ZT_INLINE FCV(I i, I end) : _s(0)
|
||||
{
|
||||
while (i != end) {
|
||||
push_back(*i);
|
||||
|
@ -64,16 +62,18 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE ~FCV()
|
||||
{ this->clear(); }
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
ZT_INLINE FCV &operator=(const FCV &v)
|
||||
ZT_INLINE FCV& operator=(const FCV& v)
|
||||
{
|
||||
if (likely(&v != this)) {
|
||||
this->clear();
|
||||
const unsigned int s = v._s;
|
||||
_s = s;
|
||||
for (unsigned int i = 0; i < s; ++i)
|
||||
new(reinterpret_cast<T *>(_m) + i) T(*(reinterpret_cast<const T *>(v._m) + i));
|
||||
new (reinterpret_cast<T*>(_m) + i) T(*(reinterpret_cast<const T*>(v._m) + i));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public:
|
|||
const unsigned int s = _s;
|
||||
_s = 0;
|
||||
for (unsigned int i = 0; i < s; ++i)
|
||||
(reinterpret_cast<T *>(_m) + i)->~T();
|
||||
(reinterpret_cast<T*>(_m) + i)->~T();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,52 +94,70 @@ public:
|
|||
*
|
||||
* @param v Target vector
|
||||
*/
|
||||
ZT_INLINE void unsafeMoveTo(FCV &v) noexcept
|
||||
ZT_INLINE void unsafeMoveTo(FCV& v) noexcept
|
||||
{
|
||||
Utils::copy(v._m, _m, (v._s = _s) * sizeof(T));
|
||||
_s = 0;
|
||||
}
|
||||
|
||||
ZT_INLINE iterator begin() noexcept
|
||||
{ return reinterpret_cast<T *>(_m); }
|
||||
{
|
||||
return reinterpret_cast<T*>(_m);
|
||||
}
|
||||
|
||||
ZT_INLINE iterator end() noexcept
|
||||
{ return reinterpret_cast<T *>(_m) + _s; }
|
||||
{
|
||||
return reinterpret_cast<T*>(_m) + _s;
|
||||
}
|
||||
|
||||
ZT_INLINE const_iterator begin() const noexcept
|
||||
{ return reinterpret_cast<const T *>(_m); }
|
||||
{
|
||||
return reinterpret_cast<const T*>(_m);
|
||||
}
|
||||
|
||||
ZT_INLINE const_iterator end() const noexcept
|
||||
{ return reinterpret_cast<const T *>(_m) + _s; }
|
||||
{
|
||||
return reinterpret_cast<const T*>(_m) + _s;
|
||||
}
|
||||
|
||||
ZT_INLINE T &operator[](const unsigned int i)
|
||||
ZT_INLINE T& operator[](const unsigned int i)
|
||||
{
|
||||
if (likely(i < _s))
|
||||
return reinterpret_cast<T *>(_m)[i];
|
||||
return reinterpret_cast<T*>(_m)[i];
|
||||
throw Utils::OutOfRangeException;
|
||||
}
|
||||
|
||||
ZT_INLINE const T &operator[](const unsigned int i) const
|
||||
ZT_INLINE const T& operator[](const unsigned int i) const
|
||||
{
|
||||
if (likely(i < _s))
|
||||
return reinterpret_cast<const T *>(_m)[i];
|
||||
return reinterpret_cast<const T*>(_m)[i];
|
||||
throw Utils::OutOfRangeException;
|
||||
}
|
||||
|
||||
static constexpr unsigned int capacity() noexcept
|
||||
{ return C; }
|
||||
{
|
||||
return C;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return _s; }
|
||||
{
|
||||
return _s;
|
||||
}
|
||||
|
||||
ZT_INLINE bool empty() const noexcept
|
||||
{ return (_s == 0); }
|
||||
{
|
||||
return (_s == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE T *data() noexcept
|
||||
{ return reinterpret_cast<T *>(_m); }
|
||||
ZT_INLINE T* data() noexcept
|
||||
{
|
||||
return reinterpret_cast<T*>(_m);
|
||||
}
|
||||
|
||||
ZT_INLINE const T *data() const noexcept
|
||||
{ return reinterpret_cast<const T *>(_m); }
|
||||
ZT_INLINE const T* data() const noexcept
|
||||
{
|
||||
return reinterpret_cast<const T*>(_m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a value onto the back of this vector
|
||||
|
@ -148,11 +166,12 @@ public:
|
|||
*
|
||||
* @param v Value to push
|
||||
*/
|
||||
ZT_INLINE void push_back(const T &v)
|
||||
ZT_INLINE void push_back(const T& v)
|
||||
{
|
||||
if (likely(_s < C))
|
||||
new(reinterpret_cast<T *>(_m) + _s++) T(v);
|
||||
else throw Utils::OutOfRangeException;
|
||||
new (reinterpret_cast<T*>(_m) + _s++) T(v);
|
||||
else
|
||||
throw Utils::OutOfRangeException;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,12 +179,13 @@ public:
|
|||
*
|
||||
* @return Reference to new item
|
||||
*/
|
||||
ZT_INLINE T &push()
|
||||
ZT_INLINE T& push()
|
||||
{
|
||||
if (likely(_s < C)) {
|
||||
return *(new(reinterpret_cast<T *>(_m) + _s++) T());
|
||||
} else {
|
||||
return *(reinterpret_cast<T *>(_m) + (C - 1));
|
||||
return *(new (reinterpret_cast<T*>(_m) + _s++) T());
|
||||
}
|
||||
else {
|
||||
return *(reinterpret_cast<T*>(_m) + (C - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,12 +194,13 @@ public:
|
|||
*
|
||||
* @return Reference to new item
|
||||
*/
|
||||
ZT_INLINE T &push(const T &v)
|
||||
ZT_INLINE T& push(const T& v)
|
||||
{
|
||||
if (likely(_s < C)) {
|
||||
return *(new(reinterpret_cast<T *>(_m) + _s++) T(v));
|
||||
} else {
|
||||
T &tmp = *(reinterpret_cast<T *>(_m) + (C - 1));
|
||||
return *(new (reinterpret_cast<T*>(_m) + _s++) T(v));
|
||||
}
|
||||
else {
|
||||
T& tmp = *(reinterpret_cast<T*>(_m) + (C - 1));
|
||||
tmp = v;
|
||||
return tmp;
|
||||
}
|
||||
|
@ -191,7 +212,7 @@ public:
|
|||
ZT_INLINE void pop_back()
|
||||
{
|
||||
if (likely(_s != 0))
|
||||
(reinterpret_cast<T *>(_m) + --_s)->~T();
|
||||
(reinterpret_cast<T*>(_m) + --_s)->~T();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,9 +226,9 @@ public:
|
|||
throw Utils::OutOfRangeException;
|
||||
unsigned int s = _s;
|
||||
while (s < ns)
|
||||
new(reinterpret_cast<T *>(_m) + s++) T();
|
||||
new (reinterpret_cast<T*>(_m) + s++) T();
|
||||
while (s > ns)
|
||||
(reinterpret_cast<T *>(_m) + --s)->~T();
|
||||
(reinterpret_cast<T*>(_m) + --s)->~T();
|
||||
_s = s;
|
||||
}
|
||||
|
||||
|
@ -217,7 +238,9 @@ public:
|
|||
* @param ns New size
|
||||
*/
|
||||
ZT_INLINE void unsafeSetSize(unsigned int ns)
|
||||
{ _s = ns; }
|
||||
{
|
||||
_s = ns;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a bounds checked auto-resizing variant of the [] operator
|
||||
|
@ -228,16 +251,16 @@ public:
|
|||
* @param i Index to obtain as a reference, resizing if needed
|
||||
* @return Reference to value at this index
|
||||
*/
|
||||
ZT_INLINE T &at(unsigned int i)
|
||||
ZT_INLINE T& at(unsigned int i)
|
||||
{
|
||||
if (i >= _s) {
|
||||
if (unlikely(i >= C))
|
||||
i = C - 1;
|
||||
do {
|
||||
new(reinterpret_cast<T *>(_m) + _s++) T();
|
||||
new (reinterpret_cast<T*>(_m) + _s++) T();
|
||||
} while (i >= _s);
|
||||
}
|
||||
return *(reinterpret_cast<T *>(_m) + i);
|
||||
return *(reinterpret_cast<T*>(_m) + i);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,24 +272,24 @@ public:
|
|||
* @param start Starting iterator
|
||||
* @param end Ending iterator (must be greater than start)
|
||||
*/
|
||||
template< typename X >
|
||||
ZT_INLINE void assign(X start, const X &end)
|
||||
template <typename X> ZT_INLINE void assign(X start, const X& end)
|
||||
{
|
||||
const int l = std::min((int)std::distance(start, end), (int)C);
|
||||
if (l > 0) {
|
||||
this->resize((unsigned int)l);
|
||||
for (int i = 0; i < l; ++i)
|
||||
reinterpret_cast<T *>(_m)[i] = *(start++);
|
||||
} else {
|
||||
reinterpret_cast<T*>(_m)[i] = *(start++);
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const FCV &v) const noexcept
|
||||
ZT_INLINE bool operator==(const FCV& v) const noexcept
|
||||
{
|
||||
if (_s == v._s) {
|
||||
for (unsigned int i = 0; i < _s; ++i) {
|
||||
if (!(*(reinterpret_cast<const T *>(_m) + i) == *(reinterpret_cast<const T *>(v._m) + i)))
|
||||
if (! (*(reinterpret_cast<const T*>(_m) + i) == *(reinterpret_cast<const T*>(v._m) + i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -274,22 +297,32 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const FCV &v) const noexcept
|
||||
{ return *this != v; }
|
||||
ZT_INLINE bool operator!=(const FCV& v) const noexcept
|
||||
{
|
||||
return *this != v;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const FCV &v) const noexcept
|
||||
{ return std::lexicographical_compare(begin(), end(), v.begin(), v.end()); }
|
||||
ZT_INLINE bool operator<(const FCV& v) const noexcept
|
||||
{
|
||||
return std::lexicographical_compare(begin(), end(), v.begin(), v.end());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const FCV &v) const noexcept
|
||||
{ return (v < *this); }
|
||||
ZT_INLINE bool operator>(const FCV& v) const noexcept
|
||||
{
|
||||
return (v < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const FCV &v) const noexcept
|
||||
{ return v >= *this; }
|
||||
ZT_INLINE bool operator<=(const FCV& v) const noexcept
|
||||
{
|
||||
return v >= *this;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const FCV &v) const noexcept
|
||||
{ return *this >= v; }
|
||||
ZT_INLINE bool operator>=(const FCV& v) const noexcept
|
||||
{
|
||||
return *this >= v;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
#ifdef _MSC_VER
|
||||
uint8_t _m[sizeof(T) * C];
|
||||
#else
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#ifndef ZT_FINGERPRINT_HPP
|
||||
#define ZT_FINGERPRINT_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_FINGERPRINT_STRING_SIZE_MAX 128
|
||||
|
@ -30,32 +30,43 @@ namespace ZeroTier {
|
|||
* This is the same size as ZT_Fingerprint and should be cast-able back and forth.
|
||||
* This is checked in Tests.cpp.
|
||||
*/
|
||||
class Fingerprint : public ZT_Fingerprint, public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
class Fingerprint
|
||||
: public ZT_Fingerprint
|
||||
, public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE Fingerprint() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE Fingerprint(const ZT_Fingerprint &fp) noexcept
|
||||
{ Utils::copy< sizeof(ZT_Fingerprint) >(this, &fp); }
|
||||
ZT_INLINE Fingerprint(const ZT_Fingerprint& fp) noexcept
|
||||
{
|
||||
Utils::copy<sizeof(ZT_Fingerprint)>(this, &fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if hash is not all zero (missing/unspecified)
|
||||
*/
|
||||
ZT_INLINE bool haveHash() const noexcept
|
||||
{ return (!Utils::allZero(this->hash, ZT_FINGERPRINT_HASH_SIZE)); }
|
||||
{
|
||||
return (! Utils::allZero(this->hash, ZT_FINGERPRINT_HASH_SIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a base32-encoded representation of this fingerprint
|
||||
*
|
||||
* @param s Base32 string
|
||||
*/
|
||||
ZT_INLINE char *toString(char s[ZT_FINGERPRINT_STRING_SIZE_MAX]) const noexcept
|
||||
ZT_INLINE char* toString(char s[ZT_FINGERPRINT_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
Address(this->address).toString(s);
|
||||
if (haveHash()) {
|
||||
s[ZT_ADDRESS_LENGTH_HEX] = '-';
|
||||
Utils::b32e(this->hash, ZT_FINGERPRINT_HASH_SIZE, s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_FINGERPRINT_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
Utils::b32e(
|
||||
this->hash,
|
||||
ZT_FINGERPRINT_HASH_SIZE,
|
||||
s + (ZT_ADDRESS_LENGTH_HEX + 1),
|
||||
ZT_FINGERPRINT_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -72,71 +83,95 @@ public:
|
|||
* @param s String to decode
|
||||
* @return True if string appears to be valid and of the proper length (no other checking is done)
|
||||
*/
|
||||
ZT_INLINE bool fromString(const char *const s) noexcept
|
||||
ZT_INLINE bool fromString(const char* const s) noexcept
|
||||
{
|
||||
if (!s)
|
||||
if (! s)
|
||||
return false;
|
||||
const int l = (int)strlen(s);
|
||||
if (l < ZT_ADDRESS_LENGTH_HEX)
|
||||
return false;
|
||||
char a[ZT_ADDRESS_LENGTH_HEX + 1];
|
||||
Utils::copy< ZT_ADDRESS_LENGTH_HEX >(a, s);
|
||||
Utils::copy<ZT_ADDRESS_LENGTH_HEX>(a, s);
|
||||
a[ZT_ADDRESS_LENGTH_HEX] = 0;
|
||||
this->address = Utils::hexStrToU64(a) & ZT_ADDRESS_MASK;
|
||||
if (l > (ZT_ADDRESS_LENGTH_HEX + 1)) {
|
||||
if (Utils::b32d(s + (ZT_ADDRESS_LENGTH_HEX + 1), this->hash, ZT_FINGERPRINT_HASH_SIZE) != ZT_FINGERPRINT_HASH_SIZE)
|
||||
if (Utils::b32d(s + (ZT_ADDRESS_LENGTH_HEX + 1), this->hash, ZT_FINGERPRINT_HASH_SIZE)
|
||||
!= ZT_FINGERPRINT_HASH_SIZE)
|
||||
return false;
|
||||
} else {
|
||||
Utils::zero< ZT_FINGERPRINT_HASH_SIZE >(this->hash);
|
||||
}
|
||||
else {
|
||||
Utils::zero<ZT_FINGERPRINT_HASH_SIZE>(this->hash);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)this->address; }
|
||||
{
|
||||
return (unsigned long)this->address;
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return this->address != 0; }
|
||||
{
|
||||
return this->address != 0;
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_FINGERPRINT_MARSHAL_SIZE; }
|
||||
{
|
||||
return ZT_FINGERPRINT_MARSHAL_SIZE;
|
||||
}
|
||||
|
||||
ZT_INLINE int marshal(uint8_t data[ZT_FINGERPRINT_MARSHAL_SIZE]) const noexcept
|
||||
{
|
||||
Address(this->address).copyTo(data);
|
||||
Utils::copy< ZT_FINGERPRINT_HASH_SIZE >(data + ZT_ADDRESS_LENGTH, this->hash);
|
||||
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(data + ZT_ADDRESS_LENGTH, this->hash);
|
||||
return ZT_FINGERPRINT_MARSHAL_SIZE;
|
||||
}
|
||||
|
||||
ZT_INLINE int unmarshal(const uint8_t *const data, int len) noexcept
|
||||
ZT_INLINE int unmarshal(const uint8_t* const data, int len) noexcept
|
||||
{
|
||||
if (unlikely(len < ZT_FINGERPRINT_MARSHAL_SIZE))
|
||||
return -1;
|
||||
this->address = Address(data);
|
||||
Utils::copy< ZT_FINGERPRINT_HASH_SIZE >(hash, data + ZT_ADDRESS_LENGTH);
|
||||
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(hash, data + ZT_ADDRESS_LENGTH);
|
||||
return ZT_FINGERPRINT_MARSHAL_SIZE;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const ZT_Fingerprint &h) const noexcept
|
||||
{ return ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) == 0)); }
|
||||
ZT_INLINE bool operator==(const ZT_Fingerprint& h) const noexcept
|
||||
{
|
||||
return ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) == 0));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const ZT_Fingerprint &h) const noexcept
|
||||
{ return !(*this == h); }
|
||||
ZT_INLINE bool operator!=(const ZT_Fingerprint& h) const noexcept
|
||||
{
|
||||
return ! (*this == h);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const ZT_Fingerprint &h) const noexcept
|
||||
{ return ((this->address < h.address) || ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) < 0))); }
|
||||
ZT_INLINE bool operator<(const ZT_Fingerprint& h) const noexcept
|
||||
{
|
||||
return (
|
||||
(this->address < h.address)
|
||||
|| ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) < 0)));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const ZT_Fingerprint &h) const noexcept
|
||||
{ return (*reinterpret_cast<const Fingerprint *>(&h) < *this); }
|
||||
ZT_INLINE bool operator>(const ZT_Fingerprint& h) const noexcept
|
||||
{
|
||||
return (*reinterpret_cast<const Fingerprint*>(&h) < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const ZT_Fingerprint &h) const noexcept
|
||||
{ return !(*reinterpret_cast<const Fingerprint *>(&h) < *this); }
|
||||
ZT_INLINE bool operator<=(const ZT_Fingerprint& h) const noexcept
|
||||
{
|
||||
return ! (*reinterpret_cast<const Fingerprint*>(&h) < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const ZT_Fingerprint &h) const noexcept
|
||||
{ return !(*this < h); }
|
||||
ZT_INLINE bool operator>=(const ZT_Fingerprint& h) const noexcept
|
||||
{
|
||||
return ! (*this < h);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Fingerprint) == sizeof(ZT_Fingerprint), "size mismatch");
|
||||
|
|
|
@ -11,13 +11,14 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Identity.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "MIMC52.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "MIMC52.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
@ -29,7 +30,10 @@ namespace {
|
|||
// This is the memory-intensive hash function used to compute v0 identities from v0 public keys.
|
||||
#define ZT_V0_IDENTITY_GEN_MEMORY 2097152
|
||||
|
||||
void identityV0ProofOfWorkFrankenhash(const void *const restrict c25519CombinedPublicKey, void *const restrict digest, void *const restrict genmem) noexcept
|
||||
void identityV0ProofOfWorkFrankenhash(
|
||||
const void* const restrict c25519CombinedPublicKey,
|
||||
void* const restrict digest,
|
||||
void* const restrict genmem) noexcept
|
||||
{
|
||||
// Digest publicKey[] to obtain initial digest
|
||||
SHA512(digest, c25519CombinedPublicKey, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE);
|
||||
|
@ -37,37 +41,40 @@ void identityV0ProofOfWorkFrankenhash(const void *const restrict c25519CombinedP
|
|||
// Initialize genmem[] using Salsa20 in a CBC-like configuration since
|
||||
// ordinary Salsa20 is randomly seek-able. This is good for a cipher
|
||||
// but is not what we want for sequential memory-hardness.
|
||||
Utils::zero< ZT_V0_IDENTITY_GEN_MEMORY >(genmem);
|
||||
Salsa20 s20(digest, (char *)digest + 32);
|
||||
s20.crypt20((char *)genmem, (char *)genmem, 64);
|
||||
Utils::zero<ZT_V0_IDENTITY_GEN_MEMORY>(genmem);
|
||||
Salsa20 s20(digest, (char*)digest + 32);
|
||||
s20.crypt20((char*)genmem, (char*)genmem, 64);
|
||||
for (unsigned long i = 64; i < ZT_V0_IDENTITY_GEN_MEMORY; i += 64) {
|
||||
unsigned long k = i - 64;
|
||||
*((uint64_t *)((char *)genmem + i)) = *((uint64_t *)((char *)genmem + k));
|
||||
*((uint64_t *)((char *)genmem + i + 8)) = *((uint64_t *)((char *)genmem + k + 8));
|
||||
*((uint64_t *)((char *)genmem + i + 16)) = *((uint64_t *)((char *)genmem + k + 16));
|
||||
*((uint64_t *)((char *)genmem + i + 24)) = *((uint64_t *)((char *)genmem + k + 24));
|
||||
*((uint64_t *)((char *)genmem + i + 32)) = *((uint64_t *)((char *)genmem + k + 32));
|
||||
*((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.crypt20((char *)genmem + i, (char *)genmem + i, 64);
|
||||
*((uint64_t*)((char*)genmem + i)) = *((uint64_t*)((char*)genmem + k));
|
||||
*((uint64_t*)((char*)genmem + i + 8)) = *((uint64_t*)((char*)genmem + k + 8));
|
||||
*((uint64_t*)((char*)genmem + i + 16)) = *((uint64_t*)((char*)genmem + k + 16));
|
||||
*((uint64_t*)((char*)genmem + i + 24)) = *((uint64_t*)((char*)genmem + k + 24));
|
||||
*((uint64_t*)((char*)genmem + i + 32)) = *((uint64_t*)((char*)genmem + k + 32));
|
||||
*((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.crypt20((char*)genmem + i, (char*)genmem + i, 64);
|
||||
}
|
||||
|
||||
// Render final digest using genmem as a lookup table
|
||||
for (unsigned long i = 0; i < (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t));) {
|
||||
unsigned long idx1 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (64 / sizeof(uint64_t)));
|
||||
unsigned long idx2 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t)));
|
||||
uint64_t tmp = ((uint64_t *)genmem)[idx2];
|
||||
((uint64_t *)genmem)[idx2] = ((uint64_t *)digest)[idx1];
|
||||
((uint64_t *)digest)[idx1] = tmp;
|
||||
unsigned long idx1 = (unsigned long)(Utils::ntoh(((uint64_t*)genmem)[i++]) % (64 / sizeof(uint64_t)));
|
||||
unsigned long idx2 =
|
||||
(unsigned long)(Utils::ntoh(((uint64_t*)genmem)[i++]) % (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t)));
|
||||
uint64_t tmp = ((uint64_t*)genmem)[idx2];
|
||||
((uint64_t*)genmem)[idx2] = ((uint64_t*)digest)[idx1];
|
||||
((uint64_t*)digest)[idx1] = tmp;
|
||||
s20.crypt20(digest, digest, 64);
|
||||
}
|
||||
}
|
||||
|
||||
struct identityV0ProofOfWorkCriteria
|
||||
{
|
||||
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *restrict sb, char *restrict gm) noexcept: digest(sb), genmem(gm)
|
||||
{}
|
||||
struct identityV0ProofOfWorkCriteria {
|
||||
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char* restrict sb, char* restrict gm) noexcept
|
||||
: digest(sb)
|
||||
, genmem(gm)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]) const noexcept
|
||||
{
|
||||
|
@ -75,8 +82,8 @@ struct identityV0ProofOfWorkCriteria
|
|||
return (digest[0] < 17);
|
||||
}
|
||||
|
||||
unsigned char *restrict digest;
|
||||
char *restrict genmem;
|
||||
unsigned char* restrict digest;
|
||||
char* restrict genmem;
|
||||
};
|
||||
|
||||
void v1ChallengeFromPub(const uint8_t pub[ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE], uint64_t challenge[4])
|
||||
|
@ -85,17 +92,17 @@ void v1ChallengeFromPub(const uint8_t pub[ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_S
|
|||
// a hash, just different for different public keys. Public keys are basically kind of hashes of
|
||||
// private keys, so that's good enough. This is only used to seed a PRNG in MIMC52 for a proof of
|
||||
// sequential work. It's not used for authentication beyond checking PoW.
|
||||
Utils::copy< 32 >(challenge, pub + 7);
|
||||
challenge[0] ^= Utils::loadMachineEndian< uint64_t >(pub + 40);
|
||||
challenge[1] ^= Utils::loadMachineEndian< uint64_t >(pub + 48);
|
||||
challenge[2] ^= Utils::loadMachineEndian< uint64_t >(pub + 56);
|
||||
challenge[3] ^= Utils::loadMachineEndian< uint64_t >(pub + 64);
|
||||
challenge[0] ^= Utils::loadMachineEndian< uint64_t >(pub + 72);
|
||||
challenge[1] ^= Utils::loadMachineEndian< uint64_t >(pub + 80);
|
||||
challenge[2] ^= Utils::loadMachineEndian< uint64_t >(pub + 88);
|
||||
challenge[3] ^= Utils::loadMachineEndian< uint64_t >(pub + 96);
|
||||
challenge[0] ^= Utils::loadMachineEndian< uint64_t >(pub + 104);
|
||||
challenge[1] ^= Utils::loadMachineEndian< uint64_t >(pub + 112);
|
||||
Utils::copy<32>(challenge, pub + 7);
|
||||
challenge[0] ^= Utils::loadMachineEndian<uint64_t>(pub + 40);
|
||||
challenge[1] ^= Utils::loadMachineEndian<uint64_t>(pub + 48);
|
||||
challenge[2] ^= Utils::loadMachineEndian<uint64_t>(pub + 56);
|
||||
challenge[3] ^= Utils::loadMachineEndian<uint64_t>(pub + 64);
|
||||
challenge[0] ^= Utils::loadMachineEndian<uint64_t>(pub + 72);
|
||||
challenge[1] ^= Utils::loadMachineEndian<uint64_t>(pub + 80);
|
||||
challenge[2] ^= Utils::loadMachineEndian<uint64_t>(pub + 88);
|
||||
challenge[3] ^= Utils::loadMachineEndian<uint64_t>(pub + 96);
|
||||
challenge[0] ^= Utils::loadMachineEndian<uint64_t>(pub + 104);
|
||||
challenge[1] ^= Utils::loadMachineEndian<uint64_t>(pub + 112);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -108,12 +115,11 @@ bool Identity::generate(const Type t)
|
|||
m_hasPrivate = true;
|
||||
|
||||
switch (t) {
|
||||
|
||||
case C25519: {
|
||||
// Generate C25519/Ed25519 key pair whose hash satisfies a "hashcash" criterion and generate the
|
||||
// address from the last 40 bits of this hash. This is different from the fingerprint hash for V0.
|
||||
uint8_t digest[64];
|
||||
char *const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
||||
char* const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
||||
Address address;
|
||||
do {
|
||||
C25519::generateSatisfying(identityV0ProofOfWorkCriteria(digest, genmem), m_pub, m_priv);
|
||||
|
@ -122,17 +128,19 @@ bool Identity::generate(const Type t)
|
|||
delete[] genmem;
|
||||
m_fp.address = address; // address comes from PoW hash for type 0 identities
|
||||
m_computeHash();
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case P384:
|
||||
for (;;) {
|
||||
C25519::generateCombined(m_pub + 7, m_priv);
|
||||
ECC384GenerateKey(m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
ECC384GenerateKey(
|
||||
m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,
|
||||
m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
|
||||
uint64_t challenge[4];
|
||||
v1ChallengeFromPub(m_pub, challenge);
|
||||
const uint64_t proof = MIMC52::delay(reinterpret_cast<const uint8_t *>(challenge), ZT_IDENTITY_TYPE1_MIMC52_ROUNDS);
|
||||
const uint64_t proof =
|
||||
MIMC52::delay(reinterpret_cast<const uint8_t*>(challenge), ZT_IDENTITY_TYPE1_MIMC52_ROUNDS);
|
||||
m_pub[0] = (uint8_t)(proof >> 48U);
|
||||
m_pub[1] = (uint8_t)(proof >> 40U);
|
||||
m_pub[2] = (uint8_t)(proof >> 32U);
|
||||
|
@ -143,7 +151,7 @@ bool Identity::generate(const Type t)
|
|||
|
||||
m_computeHash();
|
||||
const Address addr(m_fp.hash);
|
||||
if (!addr.isReserved()) {
|
||||
if (! addr.isReserved()) {
|
||||
m_fp.address = addr;
|
||||
break;
|
||||
}
|
||||
|
@ -160,13 +168,12 @@ bool Identity::generate(const Type t)
|
|||
bool Identity::locallyValidate() const noexcept
|
||||
{
|
||||
try {
|
||||
if ((m_fp) && ((!Address(m_fp.address).isReserved()))) {
|
||||
if ((m_fp) && ((! Address(m_fp.address).isReserved()))) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519: {
|
||||
uint8_t digest[64];
|
||||
char *const genmem = (char *)malloc(ZT_V0_IDENTITY_GEN_MEMORY);
|
||||
if (!genmem)
|
||||
char* const genmem = (char*)malloc(ZT_V0_IDENTITY_GEN_MEMORY);
|
||||
if (! genmem)
|
||||
return false;
|
||||
identityV0ProofOfWorkFrankenhash(m_pub, digest, genmem);
|
||||
free(genmem);
|
||||
|
@ -177,13 +184,19 @@ bool Identity::locallyValidate() const noexcept
|
|||
if (Address(m_fp.hash) == m_fp.address) {
|
||||
uint64_t challenge[4];
|
||||
v1ChallengeFromPub(m_pub, challenge);
|
||||
return MIMC52::verify(reinterpret_cast<const uint8_t *>(challenge), ZT_IDENTITY_TYPE1_MIMC52_ROUNDS, ((uint64_t)m_pub[0] << 48U) | ((uint64_t)m_pub[1] << 40U) | ((uint64_t)m_pub[2] << 32U) | ((uint64_t)m_pub[3] << 24U) | ((uint64_t)m_pub[4] << 16U) | ((uint64_t)m_pub[5] << 8U) | (uint64_t)m_pub[6]);
|
||||
return MIMC52::verify(
|
||||
reinterpret_cast<const uint8_t*>(challenge),
|
||||
ZT_IDENTITY_TYPE1_MIMC52_ROUNDS,
|
||||
((uint64_t)m_pub[0] << 48U) | ((uint64_t)m_pub[1] << 40U) | ((uint64_t)m_pub[2] << 32U)
|
||||
| ((uint64_t)m_pub[3] << 24U) | ((uint64_t)m_pub[4] << 16U) | ((uint64_t)m_pub[5] << 8U)
|
||||
| (uint64_t)m_pub[6]);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -191,7 +204,6 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
|||
{
|
||||
if (m_hasPrivate) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
SHA384(h, m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
return;
|
||||
|
@ -199,17 +211,15 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
|||
case P384:
|
||||
SHA384(h, m_pub, sizeof(m_pub), m_priv, sizeof(m_priv));
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
Utils::zero< ZT_FINGERPRINT_HASH_SIZE >(h);
|
||||
Utils::zero<ZT_FINGERPRINT_HASH_SIZE>(h);
|
||||
}
|
||||
|
||||
unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsigned int siglen) const
|
||||
unsigned int Identity::sign(const void* data, unsigned int len, void* sig, unsigned int siglen) const
|
||||
{
|
||||
if (m_hasPrivate) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
|
||||
C25519::sign(m_priv, m_pub, data, len, sig);
|
||||
|
@ -222,20 +232,18 @@ unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsig
|
|||
static_assert(ZT_ECC384_SIGNATURE_HASH_SIZE == ZT_SHA384_DIGEST_SIZE, "weird!");
|
||||
uint8_t h[ZT_ECC384_SIGNATURE_HASH_SIZE];
|
||||
SHA384(h, data, len, m_pub, ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||
ECC384ECDSASign(m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, h, (uint8_t *)sig);
|
||||
ECC384ECDSASign(m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, h, (uint8_t*)sig);
|
||||
return ZT_ECC384_SIGNATURE_SIZE;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Identity::verify(const void *data, unsigned int len, const void *sig, unsigned int siglen) const
|
||||
bool Identity::verify(const void* data, unsigned int len, const void* sig, unsigned int siglen) const
|
||||
{
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
return C25519::verify(m_pub, data, len, sig, siglen);
|
||||
|
||||
|
@ -243,15 +251,14 @@ bool Identity::verify(const void *data, unsigned int len, const void *sig, unsig
|
|||
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
||||
uint8_t h[ZT_ECC384_SIGNATURE_HASH_SIZE];
|
||||
SHA384(h, data, len, m_pub, ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||
return ECC384ECDSAVerify(m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, h, (const uint8_t *)sig);
|
||||
return ECC384ECDSAVerify(m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, h, (const uint8_t*)sig);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const
|
||||
bool Identity::agree(const Identity& id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const
|
||||
{
|
||||
uint8_t rawkey[128], h[64];
|
||||
if (m_hasPrivate) {
|
||||
|
@ -260,16 +267,20 @@ bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) con
|
|||
// C25519 portion of a type 1 P-384 key.
|
||||
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||
SHA512(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
Utils::copy< ZT_SYMMETRIC_KEY_SIZE >(key, h);
|
||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key, h);
|
||||
return true;
|
||||
} else if ((m_type == P384) && (id.m_type == P384)) {
|
||||
}
|
||||
else if ((m_type == P384) && (id.m_type == P384)) {
|
||||
// For another P384 identity we execute DH agreement with BOTH keys and then
|
||||
// hash the results together. For those (cough FIPS cough) who only consider
|
||||
// P384 to be kosher, the C25519 secret can be considered a "salt"
|
||||
// or something. For those who don't trust P384 this means the privacy of
|
||||
// your traffic is also protected by C25519.
|
||||
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||
ECC384ECDH(id.m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
ECC384ECDH(
|
||||
id.m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,
|
||||
m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE,
|
||||
rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
SHA384(key, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
@ -277,9 +288,9 @@ bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) con
|
|||
return false;
|
||||
}
|
||||
|
||||
char *Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
|
||||
char* Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
|
||||
{
|
||||
char *p = buf;
|
||||
char* p = buf;
|
||||
Address(m_fp.address).toString(p);
|
||||
p += 10;
|
||||
*(p++) = ':';
|
||||
|
@ -301,13 +312,20 @@ char *Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER
|
|||
case P384: {
|
||||
*(p++) = '1';
|
||||
*(p++) = ':';
|
||||
int el = Utils::b32e(m_pub, sizeof(m_pub), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0) return nullptr;
|
||||
int el =
|
||||
Utils::b32e(m_pub, sizeof(m_pub), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0)
|
||||
return nullptr;
|
||||
p += el;
|
||||
if ((m_hasPrivate) && (includePrivate)) {
|
||||
*(p++) = ':';
|
||||
el = Utils::b32e(m_priv, sizeof(m_priv), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0) return nullptr;
|
||||
el = Utils::b32e(
|
||||
m_priv,
|
||||
sizeof(m_priv),
|
||||
p,
|
||||
(int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0)
|
||||
return nullptr;
|
||||
p += el;
|
||||
}
|
||||
*p = (char)0;
|
||||
|
@ -320,18 +338,17 @@ char *Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool Identity::fromString(const char *str)
|
||||
bool Identity::fromString(const char* str)
|
||||
{
|
||||
char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
||||
memoryZero(this);
|
||||
if ((!str) || (!Utils::scopy(tmp, sizeof(tmp), str)))
|
||||
if ((! str) || (! Utils::scopy(tmp, sizeof(tmp), str)))
|
||||
return false;
|
||||
|
||||
int fno = 0;
|
||||
char *saveptr = nullptr;
|
||||
for (char *f = Utils::stok(tmp, ":", &saveptr); ((f) && (fno < 4)); f = Utils::stok(nullptr, ":", &saveptr)) {
|
||||
char* saveptr = nullptr;
|
||||
for (char* f = Utils::stok(tmp, ":", &saveptr); ((f) && (fno < 4)); f = Utils::stok(nullptr, ":", &saveptr)) {
|
||||
switch (fno++) {
|
||||
|
||||
case 0:
|
||||
m_fp.address = Utils::hexStrToU64(f) & ZT_ADDRESS_MASK;
|
||||
if (Address(m_fp.address).isReserved())
|
||||
|
@ -339,20 +356,22 @@ bool Identity::fromString(const char *str)
|
|||
break;
|
||||
|
||||
case 1:
|
||||
if ((f[0] == '0') && (!f[1])) {
|
||||
if ((f[0] == '0') && (! f[1])) {
|
||||
m_type = C25519;
|
||||
} else if ((f[0] == '1') && (!f[1])) {
|
||||
}
|
||||
else if ((f[0] == '1') && (! f[1])) {
|
||||
m_type = P384;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f, strlen(f), m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) != ZT_C25519_COMBINED_PUBLIC_KEY_SIZE)
|
||||
if (Utils::unhex(f, strlen(f), m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE)
|
||||
!= ZT_C25519_COMBINED_PUBLIC_KEY_SIZE)
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
@ -360,18 +379,18 @@ bool Identity::fromString(const char *str)
|
|||
if (Utils::b32d(f, m_pub, sizeof(m_pub)) != sizeof(m_pub))
|
||||
return false;
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (strlen(f) > 1) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f, strlen(f), m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) != ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
if (Utils::unhex(f, strlen(f), m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE)
|
||||
!= ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_hasPrivate = true;
|
||||
}
|
||||
break;
|
||||
|
@ -379,15 +398,14 @@ bool Identity::fromString(const char *str)
|
|||
case P384:
|
||||
if (Utils::b32d(f, m_priv, sizeof(m_priv)) != sizeof(m_priv)) {
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_hasPrivate = true;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,41 +413,46 @@ bool Identity::fromString(const char *str)
|
|||
return false;
|
||||
|
||||
m_computeHash();
|
||||
return !((m_type == P384) && (Address(m_fp.hash) != m_fp.address));
|
||||
return ! ((m_type == P384) && (Address(m_fp.hash) != m_fp.address));
|
||||
}
|
||||
|
||||
int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], const bool includePrivate) const noexcept
|
||||
{
|
||||
Address(m_fp.address).copyTo(data);
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
|
||||
Utils::copy< ZT_C25519_COMBINED_PUBLIC_KEY_SIZE >(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||
if ((includePrivate) && (m_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
Utils::copy< ZT_C25519_COMBINED_PRIVATE_KEY_SIZE >(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1, m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1,
|
||||
m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = 0;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1;
|
||||
|
||||
case P384:
|
||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
|
||||
Utils::copy< ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE >(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||
if ((includePrivate) && (m_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
Utils::copy< ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE >(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1, m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] =
|
||||
ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,
|
||||
m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1;
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
||||
int Identity::unmarshal(const uint8_t* data, const int len) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
|
||||
|
@ -439,22 +462,27 @@ int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
|
||||
unsigned int privlen;
|
||||
switch ((m_type = (Type)data[ZT_ADDRESS_LENGTH])) {
|
||||
|
||||
case C25519:
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1))
|
||||
return -1;
|
||||
|
||||
Utils::copy< ZT_C25519_COMBINED_PUBLIC_KEY_SIZE >(m_pub, data + ZT_ADDRESS_LENGTH + 1);
|
||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(m_pub, data + ZT_ADDRESS_LENGTH + 1);
|
||||
m_computeHash();
|
||||
|
||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE];
|
||||
if (privlen == ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE))
|
||||
if (len
|
||||
< (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_C25519_COMBINED_PRIVATE_KEY_SIZE))
|
||||
return -1;
|
||||
m_hasPrivate = true;
|
||||
Utils::copy< ZT_C25519_COMBINED_PRIVATE_KEY_SIZE >(m_priv, data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
} else if (privlen == 0) {
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(
|
||||
m_priv,
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
else if (privlen == 0) {
|
||||
m_hasPrivate = false;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1;
|
||||
}
|
||||
|
@ -464,7 +492,7 @@ int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1))
|
||||
return -1;
|
||||
|
||||
Utils::copy< ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE >(m_pub, data + ZT_ADDRESS_LENGTH + 1);
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(m_pub, data + ZT_ADDRESS_LENGTH + 1);
|
||||
m_computeHash(); // this sets the address for P384
|
||||
if (Address(m_fp.hash) != m_fp.address) // this sanity check is possible with V1 identities
|
||||
return -1;
|
||||
|
@ -473,15 +501,20 @@ int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
if (privlen == 0) {
|
||||
m_hasPrivate = false;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1;
|
||||
} else if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE))
|
||||
}
|
||||
else if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
|
||||
if (len
|
||||
< (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE))
|
||||
return -1;
|
||||
m_hasPrivate = true;
|
||||
Utils::copy< ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE >(&m_priv, data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(
|
||||
&m_priv,
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
|
@ -14,20 +14,21 @@
|
|||
#ifndef ZT_IDENTITY_HPP
|
||||
#define ZT_IDENTITY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 1024
|
||||
#define ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE (7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + ZT_ECC384_PUBLIC_KEY_SIZE)
|
||||
#define ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE (ZT_C25519_COMBINED_PRIVATE_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE)
|
||||
#define ZT_IDENTITY_MARSHAL_SIZE_MAX (ZT_ADDRESS_LENGTH + 4 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE)
|
||||
#define ZT_IDENTITY_MARSHAL_SIZE_MAX \
|
||||
(ZT_ADDRESS_LENGTH + 4 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE)
|
||||
#define ZT_IDENTITY_TYPE1_MIMC52_ROUNDS 262144
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -44,14 +45,12 @@ namespace ZeroTier {
|
|||
* Type 1 identities are better in many ways but type 0 will remain the default until
|
||||
* 1.x nodes are pretty much dead in the wild.
|
||||
*/
|
||||
class Identity : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
class Identity : public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Identity type -- numeric values of these enums are protocol constants
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
enum Type {
|
||||
C25519 = ZT_IDENTITY_TYPE_C25519, // Type 0 -- Curve25519 and Ed25519 (1.x and 2.x, default)
|
||||
P384 = ZT_IDENTITY_TYPE_P384 // Type 1 -- NIST P-384 with linked Curve25519/Ed25519 secondaries (2.x+)
|
||||
};
|
||||
|
@ -62,10 +61,14 @@ public:
|
|||
static const Identity NIL;
|
||||
|
||||
ZT_INLINE Identity() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE Identity(const Identity &id) noexcept
|
||||
{ Utils::copy< sizeof(Identity) >(this, &id); }
|
||||
ZT_INLINE Identity(const Identity& id) noexcept
|
||||
{
|
||||
Utils::copy<sizeof(Identity)>(this, &id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct identity from string
|
||||
|
@ -75,16 +78,20 @@ public:
|
|||
*
|
||||
* @param str Identity in canonical string format
|
||||
*/
|
||||
explicit ZT_INLINE Identity(const char *str)
|
||||
{ fromString(str); }
|
||||
explicit ZT_INLINE Identity(const char* str)
|
||||
{
|
||||
fromString(str);
|
||||
}
|
||||
|
||||
ZT_INLINE ~Identity()
|
||||
{ Utils::burn(reinterpret_cast<void *>(&this->m_priv), sizeof(this->m_priv)); }
|
||||
{
|
||||
Utils::burn(reinterpret_cast<void*>(&this->m_priv), sizeof(this->m_priv));
|
||||
}
|
||||
|
||||
ZT_INLINE Identity &operator=(const Identity &id) noexcept
|
||||
ZT_INLINE Identity& operator=(const Identity& id) noexcept
|
||||
{
|
||||
if (likely(this != &id))
|
||||
Utils::copy< sizeof(Identity) >(this, &id);
|
||||
Utils::copy<sizeof(Identity)>(this, &id);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -92,13 +99,17 @@ public:
|
|||
* Set identity to NIL value (all zero)
|
||||
*/
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Identity type (undefined if identity is null or invalid)
|
||||
*/
|
||||
ZT_INLINE Type type() const noexcept
|
||||
{ return m_type; }
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new identity (address, key pair)
|
||||
|
@ -125,19 +136,25 @@ public:
|
|||
* @return True if this identity contains a private key
|
||||
*/
|
||||
ZT_INLINE bool hasPrivate() const noexcept
|
||||
{ return m_hasPrivate; }
|
||||
{
|
||||
return m_hasPrivate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This identity's address
|
||||
*/
|
||||
ZT_INLINE Address address() const noexcept
|
||||
{ return Address(m_fp.address); }
|
||||
{
|
||||
return Address(m_fp.address);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Full fingerprint of this identity (address plus SHA384 of keys)
|
||||
*/
|
||||
ZT_INLINE const Fingerprint &fingerprint() const noexcept
|
||||
{ return m_fp; }
|
||||
ZT_INLINE const Fingerprint& fingerprint() const noexcept
|
||||
{
|
||||
return m_fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a hash of this identity's public and private keys.
|
||||
|
@ -160,7 +177,7 @@ public:
|
|||
* @param siglen Length of buffer
|
||||
* @return Number of bytes actually written to sig or 0 on error
|
||||
*/
|
||||
unsigned int sign(const void *data, unsigned int len, void *sig, unsigned int siglen) const;
|
||||
unsigned int sign(const void* data, unsigned int len, void* sig, unsigned int siglen) const;
|
||||
|
||||
/**
|
||||
* Verify a message signature against this identity
|
||||
|
@ -171,7 +188,7 @@ public:
|
|||
* @param siglen Length of signature in bytes
|
||||
* @return True if signature validates and data integrity checks
|
||||
*/
|
||||
bool verify(const void *data, unsigned int len, const void *sig, unsigned int siglen) const;
|
||||
bool verify(const void* data, unsigned int len, const void* sig, unsigned int siglen) const;
|
||||
|
||||
/**
|
||||
* Shortcut method to perform key agreement with another identity
|
||||
|
@ -182,7 +199,7 @@ public:
|
|||
* @param key Result parameter to fill with key bytes
|
||||
* @return Was agreement successful?
|
||||
*/
|
||||
bool agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const;
|
||||
bool agree(const Identity& id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const;
|
||||
|
||||
/**
|
||||
* Serialize to a more human-friendly string
|
||||
|
@ -191,7 +208,7 @@ public:
|
|||
* @param buf Buffer to store string
|
||||
* @return ASCII string representation of identity (pointer to buf)
|
||||
*/
|
||||
char *toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
|
||||
char* toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
|
||||
|
||||
ZT_INLINE String toString(const bool includePrivate = false) const
|
||||
{
|
||||
|
@ -209,7 +226,7 @@ public:
|
|||
* @param str String to deserialize
|
||||
* @return True if deserialization appears successful
|
||||
*/
|
||||
bool fromString(const char *str);
|
||||
bool fromString(const char* str);
|
||||
|
||||
/**
|
||||
* Erase any private key in this identity object
|
||||
|
@ -224,36 +241,54 @@ public:
|
|||
* @return True if this identity contains something
|
||||
*/
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_fp); }
|
||||
{
|
||||
return (m_fp);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return m_fp.hashCode(); }
|
||||
{
|
||||
return m_fp.hashCode();
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Identity &id) const noexcept
|
||||
{ return (m_fp == id.m_fp); }
|
||||
ZT_INLINE bool operator==(const Identity& id) const noexcept
|
||||
{
|
||||
return (m_fp == id.m_fp);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Identity &id) const noexcept
|
||||
{ return !(*this == id); }
|
||||
ZT_INLINE bool operator!=(const Identity& id) const noexcept
|
||||
{
|
||||
return ! (*this == id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Identity &id) const noexcept
|
||||
{ return (m_fp < id.m_fp); }
|
||||
ZT_INLINE bool operator<(const Identity& id) const noexcept
|
||||
{
|
||||
return (m_fp < id.m_fp);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Identity &id) const noexcept
|
||||
{ return (id < *this); }
|
||||
ZT_INLINE bool operator>(const Identity& id) const noexcept
|
||||
{
|
||||
return (id < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Identity &id) const noexcept
|
||||
{ return !(id < *this); }
|
||||
ZT_INLINE bool operator<=(const Identity& id) const noexcept
|
||||
{
|
||||
return ! (id < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Identity &id) const noexcept
|
||||
{ return !(*this < id); }
|
||||
ZT_INLINE bool operator>=(const Identity& id) const noexcept
|
||||
{
|
||||
return ! (*this < id);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_IDENTITY_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], bool includePrivate = false) const noexcept;
|
||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
||||
private:
|
||||
private:
|
||||
void m_computeHash();
|
||||
|
||||
Fingerprint m_fp;
|
||||
|
|
|
@ -13,24 +13,31 @@
|
|||
|
||||
#define _WIN32_WINNT 0x06010000
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(sockaddr_storage), "ZT_SOCKADDR_STORAGE_SIZE is incorrect on this platform, must be size of sockaddr_storage");
|
||||
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(InetAddress), "ZT_SOCKADDR_STORAGE_SIZE should equal InetAddress, which should equal size of sockaddr_storage");
|
||||
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(ZT_InetAddress), "ZT_SOCKADDR_STORAGE_SIZE should equal ZT_InetAddress, which should equal size of sockaddr_storage");
|
||||
static_assert(
|
||||
ZT_SOCKADDR_STORAGE_SIZE == sizeof(sockaddr_storage),
|
||||
"ZT_SOCKADDR_STORAGE_SIZE is incorrect on this platform, must be size of sockaddr_storage");
|
||||
static_assert(
|
||||
ZT_SOCKADDR_STORAGE_SIZE == sizeof(InetAddress),
|
||||
"ZT_SOCKADDR_STORAGE_SIZE should equal InetAddress, which should equal size of sockaddr_storage");
|
||||
static_assert(
|
||||
ZT_SOCKADDR_STORAGE_SIZE == sizeof(ZT_InetAddress),
|
||||
"ZT_SOCKADDR_STORAGE_SIZE should equal ZT_InetAddress, which should equal size of sockaddr_storage");
|
||||
|
||||
const InetAddress InetAddress::LO4((const void *) ("\x7f\x00\x00\x01"), 4, 0);
|
||||
const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
|
||||
const InetAddress InetAddress::LO4((const void*)("\x7f\x00\x00\x01"), 4, 0);
|
||||
const InetAddress
|
||||
InetAddress::LO6((const void*)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
|
||||
const InetAddress InetAddress::NIL;
|
||||
|
||||
InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||
{
|
||||
switch (as.ss.ss_family) {
|
||||
|
||||
case AF_INET: {
|
||||
const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr);
|
||||
switch (ip >> 24U) {
|
||||
|
@ -40,38 +47,48 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
|||
return ZT_IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army)
|
||||
case 0x0a:
|
||||
return ZT_IP_SCOPE_PRIVATE; // 10.0.0.0/8
|
||||
case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||
case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||
case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense)
|
||||
case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
|
||||
case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
|
||||
case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
|
||||
case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
||||
case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||
case 0x15: // return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||
case 0x16: // return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||
case 0x19: // return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of
|
||||
// Defense)
|
||||
case 0x1a: // return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
|
||||
case 0x1c: // return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
|
||||
case 0x1d: // return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
|
||||
case 0x1e: // return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||
case 0x33: // return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of
|
||||
// Social Security)
|
||||
case 0x37: // return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||
case 0x38: // 56.0.0.0/8 (US Postal Service)
|
||||
return ZT_IP_SCOPE_PSEUDOPRIVATE;
|
||||
case 0x64:
|
||||
if ((ip & 0xffc00000) == 0x64400000) return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
||||
if ((ip & 0xffc00000) == 0x64400000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
||||
break;
|
||||
case 0x7f:
|
||||
return ZT_IP_SCOPE_LOOPBACK; // 127.0.0.0/8
|
||||
case 0xa9:
|
||||
if ((ip & 0xffff0000) == 0xa9fe0000) return ZT_IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
|
||||
if ((ip & 0xffff0000) == 0xa9fe0000)
|
||||
return ZT_IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
|
||||
break;
|
||||
case 0xac:
|
||||
if ((ip & 0xfff00000) == 0xac100000) return ZT_IP_SCOPE_PRIVATE; // 172.16.0.0/12
|
||||
if ((ip & 0xfff00000) == 0xac100000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 172.16.0.0/12
|
||||
break;
|
||||
case 0xc0:
|
||||
if ((ip & 0xffff0000) == 0xc0a80000) return ZT_IP_SCOPE_PRIVATE; // 192.168.0.0/16
|
||||
if ((ip & 0xffffff00) == 0xc0000200) return ZT_IP_SCOPE_PRIVATE; // 192.0.2.0/24
|
||||
if ((ip & 0xffff0000) == 0xc0a80000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 192.168.0.0/16
|
||||
if ((ip & 0xffffff00) == 0xc0000200)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 192.0.2.0/24
|
||||
break;
|
||||
case 0xc6:
|
||||
if ((ip & 0xfffe0000) == 0xc6120000) return ZT_IP_SCOPE_PRIVATE; // 198.18.0.0/15
|
||||
if ((ip & 0xffffff00) == 0xc6336400) return ZT_IP_SCOPE_PRIVATE; // 198.51.100.0/24
|
||||
if ((ip & 0xfffe0000) == 0xc6120000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 198.18.0.0/15
|
||||
if ((ip & 0xffffff00) == 0xc6336400)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 198.51.100.0/24
|
||||
break;
|
||||
case 0xcb:
|
||||
if ((ip & 0xffffff00) == 0xcb007100) return ZT_IP_SCOPE_PRIVATE; // 203.0.113.0/24
|
||||
if ((ip & 0xffffff00) == 0xcb007100)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 203.0.113.0/24
|
||||
break;
|
||||
case 0xff:
|
||||
return ZT_IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable)
|
||||
|
@ -86,41 +103,48 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
|||
}
|
||||
|
||||
case AF_INET6: {
|
||||
const uint8_t *const ip = as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t* const ip = as.sa_in6.sin6_addr.s6_addr;
|
||||
if ((ip[0] & 0xf0U) == 0xf0) {
|
||||
if (ip[0] == 0xff) return ZT_IP_SCOPE_MULTICAST; // ff00::/8
|
||||
if (ip[0] == 0xff)
|
||||
return ZT_IP_SCOPE_MULTICAST; // ff00::/8
|
||||
if ((ip[0] == 0xfe) && ((ip[1] & 0xc0U) == 0x80)) {
|
||||
unsigned int k = 2;
|
||||
while ((!ip[k]) && (k < 15)) ++k;
|
||||
while ((! ip[k]) && (k < 15))
|
||||
++k;
|
||||
if ((k == 15) && (ip[15] == 0x01))
|
||||
return ZT_IP_SCOPE_LOOPBACK; // fe80::1/128
|
||||
else return ZT_IP_SCOPE_LINK_LOCAL; // fe80::/10
|
||||
else
|
||||
return ZT_IP_SCOPE_LINK_LOCAL; // fe80::/10
|
||||
}
|
||||
if ((ip[0] & 0xfeU) == 0xfc) return ZT_IP_SCOPE_PRIVATE; // fc00::/7
|
||||
if ((ip[0] & 0xfeU) == 0xfc)
|
||||
return ZT_IP_SCOPE_PRIVATE; // fc00::/7
|
||||
}
|
||||
unsigned int k = 0;
|
||||
while ((!ip[k]) && (k < 15)) ++k;
|
||||
while ((! ip[k]) && (k < 15))
|
||||
++k;
|
||||
if (k == 15) { // all 0's except last byte
|
||||
if (ip[15] == 0x01) return ZT_IP_SCOPE_LOOPBACK; // ::1/128
|
||||
if (ip[15] == 0x00) return ZT_IP_SCOPE_NONE; // ::/128
|
||||
if (ip[15] == 0x01)
|
||||
return ZT_IP_SCOPE_LOOPBACK; // ::1/128
|
||||
if (ip[15] == 0x00)
|
||||
return ZT_IP_SCOPE_NONE; // ::/128
|
||||
}
|
||||
return ZT_IP_SCOPE_GLOBAL;
|
||||
}
|
||||
|
||||
}
|
||||
return ZT_IP_SCOPE_NONE;
|
||||
}
|
||||
|
||||
void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept
|
||||
void InetAddress::set(const void* ipBytes, unsigned int ipLen, unsigned int port) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if (ipLen == 4) {
|
||||
as.sa_in.sin_family = AF_INET;
|
||||
as.sa_in.sin_port = Utils::hton((uint16_t) port);
|
||||
as.sa_in.sin_addr.s_addr = Utils::loadMachineEndian< uint32_t >(ipBytes);
|
||||
} else if (ipLen == 16) {
|
||||
as.sa_in.sin_port = Utils::hton((uint16_t)port);
|
||||
as.sa_in.sin_addr.s_addr = Utils::loadMachineEndian<uint32_t>(ipBytes);
|
||||
}
|
||||
else if (ipLen == 16) {
|
||||
as.sa_in6.sin6_family = AF_INET6;
|
||||
as.sa_in6.sin6_port = Utils::hton((uint16_t) port);
|
||||
as.sa_in6.sin6_port = Utils::hton((uint16_t)port);
|
||||
Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr, ipBytes);
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +156,7 @@ bool InetAddress::isDefaultRoute() const noexcept
|
|||
return ((as.sa_in.sin_port == 0) && (as.sa_in.sin_addr.s_addr == 0));
|
||||
case AF_INET6:
|
||||
if (as.sa_in6.sin6_port == 0) {
|
||||
for (unsigned int i = 0;i < 16;++i) {
|
||||
for (unsigned int i = 0; i < 16; ++i) {
|
||||
if (as.sa_in6.sin6_addr.s6_addr[i])
|
||||
return false;
|
||||
}
|
||||
|
@ -144,20 +168,21 @@ bool InetAddress::isDefaultRoute() const noexcept
|
|||
}
|
||||
}
|
||||
|
||||
char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||
char* InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
char *p = toIpString(buf);
|
||||
char* p = toIpString(buf);
|
||||
if (*p) {
|
||||
while (*p) ++p;
|
||||
while (*p)
|
||||
++p;
|
||||
*(p++) = '/';
|
||||
Utils::decimal(port(), p);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||
char* InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
buf[0] = (char) 0;
|
||||
buf[0] = (char)0;
|
||||
switch (as.ss.ss_family) {
|
||||
case AF_INET:
|
||||
inet_ntop(AF_INET, &as.sa_in.sin_addr.s_addr, buf, INET_ADDRSTRLEN);
|
||||
|
@ -169,34 +194,35 @@ char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const no
|
|||
return buf;
|
||||
}
|
||||
|
||||
bool InetAddress::fromString(const char *ipSlashPort) noexcept
|
||||
bool InetAddress::fromString(const char* ipSlashPort) noexcept
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
memoryZero(this);
|
||||
|
||||
if (!*ipSlashPort)
|
||||
if (! *ipSlashPort)
|
||||
return true;
|
||||
if (!Utils::scopy(buf, sizeof(buf), ipSlashPort))
|
||||
if (! Utils::scopy(buf, sizeof(buf), ipSlashPort))
|
||||
return false;
|
||||
|
||||
char *portAt = buf;
|
||||
char* portAt = buf;
|
||||
while ((*portAt) && (*portAt != '/'))
|
||||
++portAt;
|
||||
unsigned int port = 0;
|
||||
if (*portAt) {
|
||||
*(portAt++) = (char) 0;
|
||||
*(portAt++) = (char)0;
|
||||
port = Utils::strToUInt(portAt) & 0xffffU;
|
||||
}
|
||||
|
||||
if (strchr(buf, ':')) {
|
||||
as.sa_in6.sin6_family = AF_INET6;
|
||||
as.sa_in6.sin6_port = Utils::hton((uint16_t) port);
|
||||
as.sa_in6.sin6_port = Utils::hton((uint16_t)port);
|
||||
inet_pton(AF_INET6, buf, as.sa_in6.sin6_addr.s6_addr);
|
||||
return true;
|
||||
} else if (strchr(buf, '.')) {
|
||||
}
|
||||
else if (strchr(buf, '.')) {
|
||||
as.sa_in.sin_family = AF_INET;
|
||||
as.sa_in.sin_port = Utils::hton((uint16_t) port);
|
||||
as.sa_in.sin_port = Utils::hton((uint16_t)port);
|
||||
inet_pton(AF_INET, buf, &as.sa_in.sin_addr.s_addr);
|
||||
return true;
|
||||
}
|
||||
|
@ -209,21 +235,22 @@ InetAddress InetAddress::netmask() const noexcept
|
|||
InetAddress r(*this);
|
||||
switch (r.as.ss.ss_family) {
|
||||
case AF_INET:
|
||||
r.as.sa_in.sin_addr.s_addr = Utils::hton((uint32_t) (0xffffffffU << (32 - netmaskBits())));
|
||||
r.as.sa_in.sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
const unsigned int bits = netmaskBits();
|
||||
if (bits) {
|
||||
nm[0] = Utils::hton((uint64_t) ((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] = Utils::hton((uint64_t) ((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
} else {
|
||||
nm[0] = Utils::hton(
|
||||
(uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
}
|
||||
else {
|
||||
nm[0] = 0;
|
||||
nm[1] = 0;
|
||||
}
|
||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, nm);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -232,7 +259,7 @@ InetAddress InetAddress::broadcast() const noexcept
|
|||
{
|
||||
if (as.ss.ss_family == AF_INET) {
|
||||
InetAddress r(*this);
|
||||
reinterpret_cast<sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t) (0xffffffffU >> netmaskBits()));
|
||||
reinterpret_cast<sockaddr_in*>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits()));
|
||||
return r;
|
||||
}
|
||||
return InetAddress();
|
||||
|
@ -243,33 +270,33 @@ InetAddress InetAddress::network() const noexcept
|
|||
InetAddress r(*this);
|
||||
switch (r.as.ss.ss_family) {
|
||||
case AF_INET:
|
||||
r.as.sa_in.sin_addr.s_addr &= Utils::hton((uint32_t) (0xffffffffU << (32 - netmaskBits())));
|
||||
r.as.sa_in.sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
const unsigned int bits = netmaskBits();
|
||||
Utils::copy<16>(nm, reinterpret_cast<sockaddr_in6 *>(&r)->sin6_addr.s6_addr);
|
||||
nm[0] &= Utils::hton((uint64_t) ((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] &= Utils::hton((uint64_t) ((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
Utils::copy<16>(nm, reinterpret_cast<sockaddr_in6*>(&r)->sin6_addr.s6_addr);
|
||||
nm[0] &=
|
||||
Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] &= Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, nm);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
||||
bool InetAddress::isEqualPrefix(const InetAddress& addr) const noexcept
|
||||
{
|
||||
if (addr.as.ss.ss_family == as.ss.ss_family) {
|
||||
switch (as.ss.ss_family) {
|
||||
case AF_INET6: {
|
||||
const InetAddress mask(netmask());
|
||||
InetAddress addr_mask(addr.netmask());
|
||||
const uint8_t *const n = addr_mask.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t *const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t *const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t *const b = as.sa_in6.sin6_addr.s6_addr;
|
||||
for (unsigned int i = 0;i < 16;++i) {
|
||||
const uint8_t* const n = addr_mask.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t* const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t* const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t* const b = as.sa_in6.sin6_addr.s6_addr;
|
||||
for (unsigned int i = 0; i < 16; ++i) {
|
||||
if ((a[i] & m[i]) != (b[i] & n[i]))
|
||||
return false;
|
||||
}
|
||||
|
@ -280,7 +307,7 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
|||
return false;
|
||||
}
|
||||
|
||||
bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
||||
bool InetAddress::containsAddress(const InetAddress& addr) const noexcept
|
||||
{
|
||||
if (addr.as.ss.ss_family == as.ss.ss_family) {
|
||||
switch (as.ss.ss_family) {
|
||||
|
@ -289,16 +316,15 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
|||
if (bits == 0)
|
||||
return true;
|
||||
return (
|
||||
(Utils::ntoh((uint32_t) addr.as.sa_in.sin_addr.s_addr) >> (32 - bits)) ==
|
||||
(Utils::ntoh((uint32_t) as.sa_in.sin_addr.s_addr) >> (32 - bits))
|
||||
);
|
||||
(Utils::ntoh((uint32_t)addr.as.sa_in.sin_addr.s_addr) >> (32 - bits))
|
||||
== (Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr) >> (32 - bits)));
|
||||
}
|
||||
case AF_INET6: {
|
||||
const InetAddress mask(netmask());
|
||||
const uint8_t *const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t *const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t *const b = as.sa_in6.sin6_addr.s6_addr;
|
||||
for (unsigned int i = 0;i < 16;++i) {
|
||||
const uint8_t* const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t* const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t* const b = as.sa_in6.sin6_addr.s6_addr;
|
||||
for (unsigned int i = 0; i < 16; ++i) {
|
||||
if ((a[i] & m[i]) != b[i])
|
||||
return false;
|
||||
}
|
||||
|
@ -318,7 +344,7 @@ bool InetAddress::isNetwork() const noexcept
|
|||
return false;
|
||||
if (bits >= 32)
|
||||
return false;
|
||||
const uint32_t ip = Utils::ntoh((uint32_t) as.sa_in.sin_addr.s_addr);
|
||||
const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr);
|
||||
return ((ip & (0xffffffffU >> bits)) == 0);
|
||||
}
|
||||
case AF_INET6: {
|
||||
|
@ -327,7 +353,7 @@ bool InetAddress::isNetwork() const noexcept
|
|||
return false;
|
||||
if (bits >= 128)
|
||||
return false;
|
||||
const uint8_t *const ip = as.sa_in6.sin6_addr.s6_addr;
|
||||
const uint8_t* const ip = as.sa_in6.sin6_addr.s6_addr;
|
||||
unsigned int p = bits / 8;
|
||||
if ((ip[p++] & (0xffU >> (bits % 8))) != 0)
|
||||
return false;
|
||||
|
@ -346,21 +372,21 @@ int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const no
|
|||
unsigned int port;
|
||||
switch (as.ss.ss_family) {
|
||||
case AF_INET:
|
||||
port = Utils::ntoh((uint16_t) reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||
port = Utils::ntoh((uint16_t) reinterpret_cast<const sockaddr_in*>(this)->sin_port);
|
||||
data[0] = 4;
|
||||
data[1] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[0];
|
||||
data[2] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[1];
|
||||
data[3] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[2];
|
||||
data[4] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[3];
|
||||
data[5] = (uint8_t) (port >> 8U);
|
||||
data[6] = (uint8_t) port;
|
||||
data[1] = reinterpret_cast<const uint8_t*>(&as.sa_in.sin_addr.s_addr)[0];
|
||||
data[2] = reinterpret_cast<const uint8_t*>(&as.sa_in.sin_addr.s_addr)[1];
|
||||
data[3] = reinterpret_cast<const uint8_t*>(&as.sa_in.sin_addr.s_addr)[2];
|
||||
data[4] = reinterpret_cast<const uint8_t*>(&as.sa_in.sin_addr.s_addr)[3];
|
||||
data[5] = (uint8_t)(port >> 8U);
|
||||
data[6] = (uint8_t)port;
|
||||
return 7;
|
||||
case AF_INET6:
|
||||
port = Utils::ntoh((uint16_t) as.sa_in6.sin6_port);
|
||||
port = Utils::ntoh((uint16_t)as.sa_in6.sin6_port);
|
||||
data[0] = 6;
|
||||
Utils::copy<16>(data + 1, as.sa_in6.sin6_addr.s6_addr);
|
||||
data[17] = (uint8_t) (port >> 8U);
|
||||
data[18] = (uint8_t) port;
|
||||
data[17] = (uint8_t)(port >> 8U);
|
||||
data[18] = (uint8_t)port;
|
||||
return 19;
|
||||
default:
|
||||
data[0] = 0;
|
||||
|
@ -368,7 +394,7 @@ int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const no
|
|||
}
|
||||
}
|
||||
|
||||
int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept
|
||||
int InetAddress::unmarshal(const uint8_t* restrict data, const int len) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if (unlikely(len <= 0))
|
||||
|
@ -380,14 +406,14 @@ int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept
|
|||
if (unlikely(len < 7))
|
||||
return -1;
|
||||
as.sa_in.sin_family = AF_INET;
|
||||
as.sa_in.sin_port = Utils::loadMachineEndian< uint16_t >(data + 5);
|
||||
as.sa_in.sin_addr.s_addr = Utils::loadMachineEndian< uint32_t >(data + 1);
|
||||
as.sa_in.sin_port = Utils::loadMachineEndian<uint16_t>(data + 5);
|
||||
as.sa_in.sin_addr.s_addr = Utils::loadMachineEndian<uint32_t>(data + 1);
|
||||
return 7;
|
||||
case 6:
|
||||
if (unlikely(len < 19))
|
||||
return -1;
|
||||
as.sa_in6.sin6_family = AF_INET6;
|
||||
as.sa_in6.sin6_port = Utils::loadMachineEndian< uint16_t >(data + 17);
|
||||
as.sa_in6.sin6_port = Utils::loadMachineEndian<uint16_t>(data + 17);
|
||||
Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr, data + 1);
|
||||
return 19;
|
||||
default:
|
||||
|
@ -395,7 +421,7 @@ int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept
|
||||
InetAddress InetAddress::makeIpv6LinkLocal(const MAC& mac) noexcept
|
||||
{
|
||||
InetAddress r;
|
||||
r.as.sa_in6.sin6_family = AF_INET6;
|
||||
|
@ -423,23 +449,24 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress
|
|||
{
|
||||
InetAddress r;
|
||||
r.as.sa_in6.sin6_family = AF_INET6;
|
||||
r.as.sa_in6.sin6_port = ZT_CONST_TO_BE_UINT16(88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
||||
r.as.sa_in6.sin6_port =
|
||||
ZT_CONST_TO_BE_UINT16(88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
||||
r.as.sa_in6.sin6_addr.s6_addr[0] = 0xfd;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t) (nwid >> 56U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t) (nwid >> 48U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t) (nwid >> 40U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t) (nwid >> 32U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t) (nwid >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t) (nwid >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t) (nwid >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t) nwid;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t)nwid;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[9] = 0x99;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[10] = 0x93;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[11] = (uint8_t) (zeroTierAddress >> 32U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[12] = (uint8_t) (zeroTierAddress >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[13] = (uint8_t) (zeroTierAddress >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[14] = (uint8_t) (zeroTierAddress >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[15] = (uint8_t) zeroTierAddress;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[15] = (uint8_t)zeroTierAddress;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -450,15 +477,15 @@ InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress)
|
|||
r.as.sa_in6.sin6_family = AF_INET6;
|
||||
r.as.sa_in6.sin6_port = ZT_CONST_TO_BE_UINT16(40);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[0] = 0xfc;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t) (nwid >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t) (nwid >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t) (nwid >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t) nwid;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t) (zeroTierAddress >> 32U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t) (zeroTierAddress >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t) (zeroTierAddress >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t) (zeroTierAddress >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[9] = (uint8_t) zeroTierAddress;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t)nwid;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[9] = (uint8_t)zeroTierAddress;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[15] = 0x01;
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#define ZT_INETADDRESS_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -33,9 +33,8 @@ namespace ZeroTier {
|
|||
* sockaddr_storage and used interchangeably. DO NOT change this by e.g.
|
||||
* adding non-static fields, since much code depends on this identity.
|
||||
*/
|
||||
struct InetAddress : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
struct InetAddress : public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Loopback IPv4 address (no port)
|
||||
*/
|
||||
|
@ -61,63 +60,88 @@ public:
|
|||
typedef ZT_InetAddress_IpScope IpScope;
|
||||
|
||||
ZT_INLINE InetAddress() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_storage &ss) noexcept
|
||||
{ *this = ss; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_storage& ss) noexcept
|
||||
{
|
||||
*this = ss;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_storage *const ss) noexcept
|
||||
{ *this = ss; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_storage* const ss) noexcept
|
||||
{
|
||||
*this = ss;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr &sa) noexcept
|
||||
{ *this = sa; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr& sa) noexcept
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr *const sa) noexcept
|
||||
{ *this = sa; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr* const sa) noexcept
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in &sa) noexcept
|
||||
{ *this = sa; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in& sa) noexcept
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in *const sa) noexcept
|
||||
{ *this = sa; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in* const sa) noexcept
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in6 &sa) noexcept
|
||||
{ *this = sa; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in6& sa) noexcept
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in6 *const sa) noexcept
|
||||
{ *this = sa; }
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in6* const sa) noexcept
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress(const void *const ipBytes, const unsigned int ipLen, const unsigned int port) noexcept
|
||||
{ this->set(ipBytes, ipLen, port); }
|
||||
ZT_INLINE InetAddress(const void* const ipBytes, const unsigned int ipLen, const unsigned int port) noexcept
|
||||
{
|
||||
this->set(ipBytes, ipLen, port);
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress(const uint32_t ipv4, const unsigned int port) noexcept
|
||||
{ this->set(&ipv4, 4, port); }
|
||||
{
|
||||
this->set(&ipv4, 4, port);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const char *const ipSlashPort) noexcept
|
||||
{ this->fromString(ipSlashPort); }
|
||||
explicit ZT_INLINE InetAddress(const char* const ipSlashPort) noexcept
|
||||
{
|
||||
this->fromString(ipSlashPort);
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr_storage &ss) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr_storage& ss) noexcept
|
||||
{
|
||||
as.ss = ss;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr_storage *ss) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr_storage* ss) noexcept
|
||||
{
|
||||
if (ss)
|
||||
as.ss = *ss;
|
||||
else memoryZero(this);
|
||||
else
|
||||
memoryZero(this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr_in &sa) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr_in& sa) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
as.sa_in = sa;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr_in *sa) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr_in* sa) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if (sa)
|
||||
|
@ -125,14 +149,14 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr_in6 &sa) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr_in6& sa) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
as.sa_in6 = sa;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr_in6 *sa) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr_in6* sa) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if (sa)
|
||||
|
@ -140,30 +164,32 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr &sa) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr& sa) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if (sa.sa_family == AF_INET)
|
||||
as.sa_in = *reinterpret_cast<const sockaddr_in *>(&sa);
|
||||
as.sa_in = *reinterpret_cast<const sockaddr_in*>(&sa);
|
||||
else if (sa.sa_family == AF_INET6)
|
||||
as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(&sa);
|
||||
as.sa_in6 = *reinterpret_cast<const sockaddr_in6*>(&sa);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress &operator=(const sockaddr *sa) noexcept
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr* sa) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
if (sa) {
|
||||
if (sa->sa_family == AF_INET)
|
||||
as.sa_in = *reinterpret_cast<const sockaddr_in *>(sa);
|
||||
as.sa_in = *reinterpret_cast<const sockaddr_in*>(sa);
|
||||
else if (sa->sa_family == AF_INET6)
|
||||
as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(sa);
|
||||
as.sa_in6 = *reinterpret_cast<const sockaddr_in6*>(sa);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE void clear() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IP scope classification (e.g. loopback, link-local, private, global)
|
||||
|
@ -177,7 +203,7 @@ public:
|
|||
* @param ipLen Length of IP address: 4 or 16
|
||||
* @param port Port number or 0 for none
|
||||
*/
|
||||
void set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept;
|
||||
void set(const void* ipBytes, unsigned int ipLen, unsigned int port) noexcept;
|
||||
|
||||
/**
|
||||
* Set the port component
|
||||
|
@ -204,7 +230,7 @@ public:
|
|||
/**
|
||||
* @return ASCII IP/port format representation
|
||||
*/
|
||||
char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
||||
char* toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
||||
|
||||
ZT_INLINE String toString() const
|
||||
{
|
||||
|
@ -216,7 +242,7 @@ public:
|
|||
/**
|
||||
* @return IP portion only, in ASCII string format
|
||||
*/
|
||||
char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
||||
char* toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
||||
|
||||
ZT_INLINE String toIpString() const
|
||||
{
|
||||
|
@ -229,7 +255,7 @@ public:
|
|||
* @param ipSlashPort IP/port (port is optional, will be 0 if not included)
|
||||
* @return True if address appeared to be valid
|
||||
*/
|
||||
bool fromString(const char *ipSlashPort) noexcept;
|
||||
bool fromString(const char* ipSlashPort) noexcept;
|
||||
|
||||
/**
|
||||
* @return Port or 0 if no port component defined
|
||||
|
@ -256,7 +282,9 @@ public:
|
|||
* @return Netmask bits
|
||||
*/
|
||||
ZT_INLINE unsigned int netmaskBits() const noexcept
|
||||
{ return port(); }
|
||||
{
|
||||
return port();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if netmask bits is valid for the address type
|
||||
|
@ -282,7 +310,9 @@ public:
|
|||
* @return Gateway metric
|
||||
*/
|
||||
ZT_INLINE unsigned int metric() const noexcept
|
||||
{ return port(); }
|
||||
{
|
||||
return port();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a full netmask as an InetAddress
|
||||
|
@ -314,7 +344,7 @@ public:
|
|||
* @param addr Address to check
|
||||
* @return True if this IPv6 prefix matches the prefix of a given IPv6 address
|
||||
*/
|
||||
bool isEqualPrefix(const InetAddress &addr) const noexcept;
|
||||
bool isEqualPrefix(const InetAddress& addr) const noexcept;
|
||||
|
||||
/**
|
||||
* Test whether this IP/netmask contains this address
|
||||
|
@ -322,30 +352,34 @@ public:
|
|||
* @param addr Address to check
|
||||
* @return True if this IP/netmask (route) contains this address
|
||||
*/
|
||||
bool containsAddress(const InetAddress &addr) const noexcept;
|
||||
bool containsAddress(const InetAddress& addr) const noexcept;
|
||||
|
||||
/**
|
||||
* @return True if this is an IPv4 address
|
||||
*/
|
||||
ZT_INLINE bool isV4() const noexcept
|
||||
{ return (as.ss.ss_family == AF_INET); }
|
||||
{
|
||||
return (as.ss.ss_family == AF_INET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this is an IPv6 address
|
||||
*/
|
||||
ZT_INLINE bool isV6() const noexcept
|
||||
{ return (as.ss.ss_family == AF_INET6); }
|
||||
{
|
||||
return (as.ss.ss_family == AF_INET6);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return pointer to raw address bytes or NULL if not available
|
||||
*/
|
||||
ZT_INLINE const void *rawIpData() const noexcept
|
||||
ZT_INLINE const void* rawIpData() const noexcept
|
||||
{
|
||||
switch (as.ss.ss_family) {
|
||||
case AF_INET:
|
||||
return reinterpret_cast<const void *>(&(as.sa_in.sin_addr.s_addr));
|
||||
return reinterpret_cast<const void*>(&(as.sa_in.sin_addr.s_addr));
|
||||
case AF_INET6:
|
||||
return reinterpret_cast<const void *>(as.sa_in6.sin6_addr.s6_addr);
|
||||
return reinterpret_cast<const void*>(as.sa_in6.sin6_addr.s6_addr);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -364,7 +398,7 @@ public:
|
|||
break;
|
||||
case AF_INET6:
|
||||
r.as.sa_in6.sin6_family = AF_INET6;
|
||||
Utils::copy< 16 >(r.as.sa_in6.sin6_addr.s6_addr, as.sa_in6.sin6_addr.s6_addr);
|
||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, as.sa_in6.sin6_addr.s6_addr);
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
|
@ -376,7 +410,7 @@ public:
|
|||
* @param a InetAddress to compare again
|
||||
* @return True if only IP portions are equal (false for non-IP or null addresses)
|
||||
*/
|
||||
ZT_INLINE bool ipsEqual(const InetAddress &a) const noexcept
|
||||
ZT_INLINE bool ipsEqual(const InetAddress& a) const noexcept
|
||||
{
|
||||
const uint8_t f = as.ss.ss_family;
|
||||
if (f == a.as.ss.ss_family) {
|
||||
|
@ -397,7 +431,7 @@ public:
|
|||
* @param a InetAddress to compare again
|
||||
* @return True if only IP portions are equal (false for non-IP or null addresses)
|
||||
*/
|
||||
ZT_INLINE bool ipsEqual2(const InetAddress &a) const noexcept
|
||||
ZT_INLINE bool ipsEqual2(const InetAddress& a) const noexcept
|
||||
{
|
||||
const uint8_t f = as.ss.ss_family;
|
||||
if (f == a.as.ss.ss_family) {
|
||||
|
@ -413,13 +447,14 @@ public:
|
|||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{
|
||||
if (as.ss.ss_family == AF_INET) {
|
||||
return (unsigned long)Utils::hash32(((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce);
|
||||
} else if (as.ss.ss_family == AF_INET6) {
|
||||
return (unsigned long)Utils::hash32(
|
||||
((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce);
|
||||
}
|
||||
else if (as.ss.ss_family == AF_INET6) {
|
||||
return (unsigned long)Utils::hash64(
|
||||
(Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr) +
|
||||
Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr + 8) +
|
||||
(uint64_t)as.sa_in6.sin6_port) ^
|
||||
Utils::s_mapNonce);
|
||||
(Utils::loadMachineEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr)
|
||||
+ Utils::loadMachineEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr + 8) + (uint64_t)as.sa_in6.sin6_port)
|
||||
^ Utils::s_mapNonce);
|
||||
}
|
||||
return Utils::fnv1a32(this, sizeof(InetAddress));
|
||||
}
|
||||
|
@ -438,35 +473,44 @@ public:
|
|||
* @return True if address family is non-zero
|
||||
*/
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return (as.ss.ss_family != 0); }
|
||||
{
|
||||
return (as.ss.ss_family != 0);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_INETADDRESS_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_INETADDRESS_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept;
|
||||
|
||||
int unmarshal(const uint8_t *restrict data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* restrict data, int len) noexcept;
|
||||
|
||||
ZT_INLINE bool operator==(const InetAddress &a) const noexcept
|
||||
ZT_INLINE bool operator==(const InetAddress& a) const noexcept
|
||||
{
|
||||
if (as.ss.ss_family == a.as.ss.ss_family) {
|
||||
if (as.ss.ss_family == AF_INET)
|
||||
return ((as.sa_in.sin_port == a.as.sa_in.sin_port) && (as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr));
|
||||
return (
|
||||
(as.sa_in.sin_port == a.as.sa_in.sin_port)
|
||||
&& (as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr));
|
||||
if (as.ss.ss_family == AF_INET6)
|
||||
return ((as.sa_in6.sin6_port == a.as.sa_in6.sin6_port) && (memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) == 0));
|
||||
return (
|
||||
(as.sa_in6.sin6_port == a.as.sa_in6.sin6_port)
|
||||
&& (memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) == 0));
|
||||
return memcmp(this, &a, sizeof(InetAddress)) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const InetAddress &a) const noexcept
|
||||
ZT_INLINE bool operator<(const InetAddress& a) const noexcept
|
||||
{
|
||||
if (as.ss.ss_family == a.as.ss.ss_family) {
|
||||
if (as.ss.ss_family == AF_INET) {
|
||||
const uint16_t p0 = Utils::ntoh((uint16_t)as.sa_in.sin_port);
|
||||
const uint16_t p1 = Utils::ntoh((uint16_t)a.as.sa_in.sin_port);
|
||||
if (p0 == p1)
|
||||
return Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr) < Utils::ntoh((uint32_t)a.as.sa_in.sin_addr.s_addr);
|
||||
return Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr)
|
||||
< Utils::ntoh((uint32_t)a.as.sa_in.sin_addr.s_addr);
|
||||
return p0 < p1;
|
||||
}
|
||||
if (as.ss.ss_family == AF_INET6) {
|
||||
|
@ -481,17 +525,25 @@ public:
|
|||
return as.ss.ss_family < a.as.ss.ss_family;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const InetAddress &a) const noexcept
|
||||
{ return !(*this == a); }
|
||||
ZT_INLINE bool operator!=(const InetAddress& a) const noexcept
|
||||
{
|
||||
return ! (*this == a);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const InetAddress &a) const noexcept
|
||||
{ return (a < *this); }
|
||||
ZT_INLINE bool operator>(const InetAddress& a) const noexcept
|
||||
{
|
||||
return (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const InetAddress &a) const noexcept
|
||||
{ return !(a < *this); }
|
||||
ZT_INLINE bool operator<=(const InetAddress& a) const noexcept
|
||||
{
|
||||
return ! (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const InetAddress &a) const noexcept
|
||||
{ return !(*this < a); }
|
||||
ZT_INLINE bool operator>=(const InetAddress& a) const noexcept
|
||||
{
|
||||
return ! (*this < a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute an IPv6 link-local address
|
||||
|
@ -499,7 +551,7 @@ public:
|
|||
* @param mac MAC address seed
|
||||
* @return IPv6 link-local address
|
||||
*/
|
||||
static InetAddress makeIpv6LinkLocal(const MAC &mac) noexcept;
|
||||
static InetAddress makeIpv6LinkLocal(const MAC& mac) noexcept;
|
||||
|
||||
/**
|
||||
* Compute private IPv6 unicast address from network ID and ZeroTier address
|
||||
|
@ -552,8 +604,7 @@ public:
|
|||
/**
|
||||
* Union allowing this to be accessed as a sockaddr of any supported type.
|
||||
*/
|
||||
union
|
||||
{
|
||||
union {
|
||||
sockaddr_storage ss;
|
||||
sockaddr sa;
|
||||
sockaddr_in sa_in;
|
||||
|
@ -561,65 +612,105 @@ public:
|
|||
} as;
|
||||
};
|
||||
|
||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr_in* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr_in6* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr_storage* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress *asInetAddress(ZT_InetAddress *const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_INLINE InetAddress* asInetAddress(ZT_InetAddress* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr_in* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr_in6* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr_storage* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress *asInetAddress(const ZT_InetAddress *const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const ZT_InetAddress* const p) noexcept
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr_in& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr_in6& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr_storage& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress &asInetAddress(ZT_InetAddress &p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
static ZT_INLINE InetAddress& asInetAddress(ZT_InetAddress& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr_in& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in6 &p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr_in6& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr_storage& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress &asInetAddress(const ZT_InetAddress &p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const ZT_InetAddress& p) noexcept
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
643
core/LZ4.cpp
643
core/LZ4.cpp
File diff suppressed because it is too large
Load diff
|
@ -19,10 +19,10 @@
|
|||
namespace ZeroTier {
|
||||
|
||||
#define LZ4_MAX_INPUT_SIZE 0x7E000000
|
||||
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize) / 255) + 16)
|
||||
|
||||
int LZ4_compress_fast(const char *source,char *dest,int inputSize,int maxOutputSize,int acceleration = 1) noexcept;
|
||||
int LZ4_decompress_safe(const char *source,char *dest,int compressedSize,int maxDecompressedSize) noexcept;
|
||||
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration = 1) noexcept;
|
||||
int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) noexcept;
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
|
@ -12,18 +12,19 @@
|
|||
/****/
|
||||
|
||||
#include "Locator.hpp"
|
||||
|
||||
#include "Identity.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
const SharedPtr< const Locator::EndpointAttributes > Locator::EndpointAttributes::DEFAULT(new Locator::EndpointAttributes());
|
||||
const SharedPtr<const Locator::EndpointAttributes>
|
||||
Locator::EndpointAttributes::DEFAULT(new Locator::EndpointAttributes());
|
||||
|
||||
Locator::Locator(const char *const str) noexcept :
|
||||
__refCount(0)
|
||||
Locator::Locator(const char* const str) noexcept : __refCount(0)
|
||||
{
|
||||
if (!fromString(str)) {
|
||||
if (! fromString(str)) {
|
||||
m_revision = 0;
|
||||
m_signer.zero();
|
||||
m_endpoints.clear();
|
||||
|
@ -31,22 +32,26 @@ Locator::Locator(const char *const str) noexcept :
|
|||
}
|
||||
}
|
||||
|
||||
bool Locator::add(const Endpoint &ep, const SharedPtr< const EndpointAttributes > &a)
|
||||
bool Locator::add(const Endpoint& ep, const SharedPtr<const EndpointAttributes>& a)
|
||||
{
|
||||
for (Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > >::iterator i(m_endpoints.begin());i!=m_endpoints.end();++i) {
|
||||
for (Vector<std::pair<Endpoint, SharedPtr<const EndpointAttributes> > >::iterator i(m_endpoints.begin());
|
||||
i != m_endpoints.end();
|
||||
++i) {
|
||||
if (i->first == ep) {
|
||||
i->second = ((a) && (a->data[0] != 0)) ? a : EndpointAttributes::DEFAULT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_endpoints.size() < ZT_LOCATOR_MAX_ENDPOINTS) {
|
||||
m_endpoints.push_back(std::pair<Endpoint, SharedPtr< const EndpointAttributes > >(ep, ((a) && (a->data[0] != 0)) ? a : EndpointAttributes::DEFAULT));
|
||||
m_endpoints.push_back(std::pair<Endpoint, SharedPtr<const EndpointAttributes> >(
|
||||
ep,
|
||||
((a) && (a->data[0] != 0)) ? a : EndpointAttributes::DEFAULT));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Locator::sign(const int64_t rev, const Identity &id) noexcept
|
||||
bool Locator::sign(const int64_t rev, const Identity& id) noexcept
|
||||
{
|
||||
m_revision = rev;
|
||||
m_signer = id.address();
|
||||
|
@ -64,7 +69,7 @@ bool Locator::sign(const int64_t rev, const Identity &id) noexcept
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Locator::verify(const Identity &id) const noexcept
|
||||
bool Locator::verify(const Identity& id) const noexcept
|
||||
{
|
||||
try {
|
||||
if ((m_revision > 0) && (m_signer == id.address())) {
|
||||
|
@ -72,23 +77,31 @@ bool Locator::verify(const Identity &id) const noexcept
|
|||
const unsigned int signlen = marshal(signdata, true);
|
||||
return id.verify(signdata, signlen, m_signature.data(), m_signature.size());
|
||||
}
|
||||
} catch (...) {} // fail verify on any unexpected exception
|
||||
}
|
||||
catch (...) {
|
||||
} // fail verify on any unexpected exception
|
||||
return false;
|
||||
}
|
||||
|
||||
char *Locator::toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept
|
||||
char* Locator::toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
static_assert(ZT_LOCATOR_STRING_SIZE_MAX > ((((ZT_LOCATOR_MARSHAL_SIZE_MAX / 5) + 1) * 8) + ZT_ADDRESS_LENGTH_HEX + 1), "overflow");
|
||||
static_assert(
|
||||
ZT_LOCATOR_STRING_SIZE_MAX > ((((ZT_LOCATOR_MARSHAL_SIZE_MAX / 5) + 1) * 8) + ZT_ADDRESS_LENGTH_HEX + 1),
|
||||
"overflow");
|
||||
uint8_t bin[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
m_signer.toString(s);
|
||||
s[ZT_ADDRESS_LENGTH_HEX] = '@';
|
||||
Utils::b32e(bin, marshal(bin, false), s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_LOCATOR_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
Utils::b32e(
|
||||
bin,
|
||||
marshal(bin, false),
|
||||
s + (ZT_ADDRESS_LENGTH_HEX + 1),
|
||||
ZT_LOCATOR_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
return s;
|
||||
}
|
||||
|
||||
bool Locator::fromString(const char *s) noexcept
|
||||
bool Locator::fromString(const char* s) noexcept
|
||||
{
|
||||
if (!s)
|
||||
if (! s)
|
||||
return false;
|
||||
if (strlen(s) < (ZT_ADDRESS_LENGTH_HEX + 1))
|
||||
return false;
|
||||
|
@ -101,13 +114,15 @@ bool Locator::fromString(const char *s) noexcept
|
|||
|
||||
int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept
|
||||
{
|
||||
Utils::storeBigEndian<uint64_t>(data, (uint64_t) m_revision);
|
||||
Utils::storeBigEndian<uint64_t>(data, (uint64_t)m_revision);
|
||||
m_signer.copyTo(data + 8);
|
||||
int p = 8 + ZT_ADDRESS_LENGTH;
|
||||
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_endpoints.size());
|
||||
p += 2;
|
||||
for (Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > >::const_iterator e(m_endpoints.begin());e != m_endpoints.end();++e) {
|
||||
for (Vector<std::pair<Endpoint, SharedPtr<const EndpointAttributes> > >::const_iterator e(m_endpoints.begin());
|
||||
e != m_endpoints.end();
|
||||
++e) {
|
||||
int l = e->first.marshal(data + p);
|
||||
if (l <= 0)
|
||||
return -1;
|
||||
|
@ -117,25 +132,26 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool exclu
|
|||
if (l > 0) {
|
||||
Utils::copy(data + p, e->second->data, (unsigned int)l);
|
||||
p += l;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data[p++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Utils::storeMachineEndian< uint16_t >(data + p, 0); // length of meta-data, currently always 0
|
||||
Utils::storeMachineEndian<uint16_t>(data + p, 0); // length of meta-data, currently always 0
|
||||
p += 2;
|
||||
|
||||
if (!excludeSignature) {
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_signature.size());
|
||||
if (! excludeSignature) {
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_signature.size());
|
||||
p += 2;
|
||||
Utils::copy(data + p, m_signature.data(), m_signature.size());
|
||||
p += (int) m_signature.size();
|
||||
p += (int)m_signature.size();
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
||||
int Locator::unmarshal(const uint8_t* data, const int len) noexcept
|
||||
{
|
||||
if (unlikely(len < (8 + ZT_ADDRESS_LENGTH)))
|
||||
return -1;
|
||||
|
@ -151,7 +167,7 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
return -1;
|
||||
m_endpoints.resize(endpointCount);
|
||||
m_endpoints.shrink_to_fit();
|
||||
for (unsigned int i = 0;i < endpointCount;++i) {
|
||||
for (unsigned int i = 0; i < endpointCount; ++i) {
|
||||
int l = m_endpoints[i].first.unmarshal(data + p, len - p);
|
||||
if (l <= 0)
|
||||
return -1;
|
||||
|
@ -163,9 +179,10 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
if (l <= 0) {
|
||||
m_endpoints[i].second = EndpointAttributes::DEFAULT;
|
||||
++p;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_endpoints[i].second.set(new EndpointAttributes());
|
||||
Utils::copy(const_cast< uint8_t * >(m_endpoints[i].second->data), data + p, (unsigned int)l);
|
||||
Utils::copy(const_cast<uint8_t*>(m_endpoints[i].second->data), data + p, (unsigned int)l);
|
||||
p += l;
|
||||
}
|
||||
}
|
||||
|
@ -191,15 +208,20 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
return p;
|
||||
}
|
||||
|
||||
struct p_SortByEndpoint
|
||||
{
|
||||
struct p_SortByEndpoint {
|
||||
// There can't be more than one of the same endpoint, so only need to sort
|
||||
// by endpoint.
|
||||
ZT_INLINE bool operator()(const std::pair< Endpoint, SharedPtr< const Locator::EndpointAttributes > > &a,const std::pair< Endpoint, SharedPtr< const Locator::EndpointAttributes > > &b) const noexcept
|
||||
{ return a.first < b.first; }
|
||||
ZT_INLINE bool operator()(
|
||||
const std::pair<Endpoint, SharedPtr<const Locator::EndpointAttributes> >& a,
|
||||
const std::pair<Endpoint, SharedPtr<const Locator::EndpointAttributes> >& b) const noexcept
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
void Locator::m_sortEndpoints() noexcept
|
||||
{ std::sort(m_endpoints.begin(), m_endpoints.end(), p_SortByEndpoint()); }
|
||||
{
|
||||
std::sort(m_endpoints.begin(), m_endpoints.end(), p_SortByEndpoint());
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
164
core/Locator.hpp
164
core/Locator.hpp
|
@ -15,13 +15,13 @@
|
|||
#define ZT_LOCATOR_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
|
||||
/**
|
||||
* Maximum size of endpoint attributes dictionary plus one byte for size.
|
||||
|
@ -35,7 +35,10 @@
|
|||
*/
|
||||
#define ZT_LOCATOR_MAX_ENDPOINTS 16
|
||||
|
||||
#define ZT_LOCATOR_MARSHAL_SIZE_MAX (8 + ZT_ADDRESS_LENGTH + 2 + (ZT_LOCATOR_MAX_ENDPOINTS * (ZT_ENDPOINT_MARSHAL_SIZE_MAX + ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE)) + 2 + 2 + ZT_SIGNATURE_BUFFER_SIZE)
|
||||
#define ZT_LOCATOR_MARSHAL_SIZE_MAX \
|
||||
(8 + ZT_ADDRESS_LENGTH + 2 \
|
||||
+ (ZT_LOCATOR_MAX_ENDPOINTS * (ZT_ENDPOINT_MARSHAL_SIZE_MAX + ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE)) + 2 + 2 \
|
||||
+ ZT_SIGNATURE_BUFFER_SIZE)
|
||||
|
||||
/**
|
||||
* Maximum size of a string format Locator (this is way larger than needed)
|
||||
|
@ -50,27 +53,25 @@ namespace ZeroTier {
|
|||
* A locator contains long-lived endpoints for a node such as IP/port pairs,
|
||||
* URLs, or other nodes, and is signed by the node it describes.
|
||||
*/
|
||||
class Locator
|
||||
{
|
||||
friend class SharedPtr< Locator >;
|
||||
friend class SharedPtr< const Locator >;
|
||||
class Locator {
|
||||
friend class SharedPtr<Locator>;
|
||||
friend class SharedPtr<const Locator>;
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Attributes of an endpoint in this locator
|
||||
*
|
||||
* This is specified for future use, but there are currently no attributes
|
||||
* defined. A Dictionary is used for serialization for extensibility.
|
||||
*/
|
||||
struct EndpointAttributes
|
||||
{
|
||||
friend class SharedPtr< Locator::EndpointAttributes >;
|
||||
friend class SharedPtr< const Locator::EndpointAttributes >;
|
||||
struct EndpointAttributes {
|
||||
friend class SharedPtr<Locator::EndpointAttributes>;
|
||||
friend class SharedPtr<const Locator::EndpointAttributes>;
|
||||
|
||||
/**
|
||||
* Default endpoint attributes
|
||||
*/
|
||||
static const SharedPtr< const Locator::EndpointAttributes > DEFAULT;
|
||||
static const SharedPtr<const Locator::EndpointAttributes> DEFAULT;
|
||||
|
||||
/**
|
||||
* Raw attributes data in the form of a dictionary prefixed by its size.
|
||||
|
@ -81,67 +82,90 @@ public:
|
|||
uint8_t data[ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE];
|
||||
|
||||
ZT_INLINE EndpointAttributes() noexcept
|
||||
{ Utils::zero< ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE >(data); }
|
||||
{
|
||||
Utils::zero<ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE>(data);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const EndpointAttributes &a) const noexcept
|
||||
{ return ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) == 0)); }
|
||||
ZT_INLINE bool operator==(const EndpointAttributes& a) const noexcept
|
||||
{
|
||||
return ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) == 0));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const EndpointAttributes &a) const noexcept
|
||||
{ return ((data[0] < a.data[0]) || ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) < 0))); }
|
||||
ZT_INLINE bool operator<(const EndpointAttributes& a) const noexcept
|
||||
{
|
||||
return ((data[0] < a.data[0]) || ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) < 0)));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const EndpointAttributes &a) const noexcept
|
||||
{ return !(*this == a); }
|
||||
ZT_INLINE bool operator!=(const EndpointAttributes& a) const noexcept
|
||||
{
|
||||
return ! (*this == a);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const EndpointAttributes &a) const noexcept
|
||||
{ return (a < *this); }
|
||||
ZT_INLINE bool operator>(const EndpointAttributes& a) const noexcept
|
||||
{
|
||||
return (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const EndpointAttributes &a) const noexcept
|
||||
{ return !(a < *this); }
|
||||
ZT_INLINE bool operator<=(const EndpointAttributes& a) const noexcept
|
||||
{
|
||||
return ! (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const EndpointAttributes &a) const noexcept
|
||||
{ return !(*this < a); }
|
||||
ZT_INLINE bool operator>=(const EndpointAttributes& a) const noexcept
|
||||
{
|
||||
return ! (*this < a);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic< int > __refCount;
|
||||
std::atomic<int> __refCount;
|
||||
};
|
||||
|
||||
ZT_INLINE Locator() noexcept:
|
||||
m_revision(0)
|
||||
{}
|
||||
ZT_INLINE Locator() noexcept : m_revision(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Locator(const Locator &l) noexcept:
|
||||
m_revision(l.m_revision),
|
||||
m_signer(l.m_signer),
|
||||
m_endpoints(l.m_endpoints),
|
||||
m_signature(l.m_signature),
|
||||
__refCount(0)
|
||||
{}
|
||||
ZT_INLINE Locator(const Locator& l) noexcept
|
||||
: m_revision(l.m_revision)
|
||||
, m_signer(l.m_signer)
|
||||
, m_endpoints(l.m_endpoints)
|
||||
, m_signature(l.m_signature)
|
||||
, __refCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Locator(const char *const str) noexcept;
|
||||
explicit Locator(const char* const str) noexcept;
|
||||
|
||||
/**
|
||||
* @return Timestamp (a.k.a. revision number) set by Location signer
|
||||
*/
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_revision; }
|
||||
{
|
||||
return m_revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ZeroTier address of signer
|
||||
*/
|
||||
ZT_INLINE Address signer() const noexcept
|
||||
{ return m_signer; }
|
||||
{
|
||||
return m_signer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Endpoints specified in locator
|
||||
*/
|
||||
ZT_INLINE const Vector <std::pair< Endpoint, SharedPtr< const EndpointAttributes > >> &endpoints() const noexcept
|
||||
{ return m_endpoints; }
|
||||
ZT_INLINE const Vector<std::pair<Endpoint, SharedPtr<const EndpointAttributes> > >& endpoints() const noexcept
|
||||
{
|
||||
return m_endpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Signature data
|
||||
*/
|
||||
ZT_INLINE const FCV< uint8_t, ZT_SIGNATURE_BUFFER_SIZE > &signature() const noexcept
|
||||
{ return m_signature; }
|
||||
ZT_INLINE const FCV<uint8_t, ZT_SIGNATURE_BUFFER_SIZE>& signature() const noexcept
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an endpoint to this locator
|
||||
|
@ -153,7 +177,7 @@ public:
|
|||
* @param a Endpoint attributes or NULL to use default
|
||||
* @return True if endpoint was added (or already present), false if locator is full
|
||||
*/
|
||||
bool add(const Endpoint &ep, const SharedPtr< const EndpointAttributes > &a);
|
||||
bool add(const Endpoint& ep, const SharedPtr<const EndpointAttributes>& a);
|
||||
|
||||
/**
|
||||
* Sign this locator
|
||||
|
@ -164,7 +188,7 @@ public:
|
|||
* @param id Identity that includes private key
|
||||
* @return True if signature successful
|
||||
*/
|
||||
bool sign(int64_t rev, const Identity &id) noexcept;
|
||||
bool sign(int64_t rev, const Identity& id) noexcept;
|
||||
|
||||
/**
|
||||
* Verify this Locator's validity and signature
|
||||
|
@ -172,7 +196,7 @@ public:
|
|||
* @param id Identity corresponding to hash
|
||||
* @return True if valid and signature checks out
|
||||
*/
|
||||
bool verify(const Identity &id) const noexcept;
|
||||
bool verify(const Identity& id) const noexcept;
|
||||
|
||||
/**
|
||||
* Convert this locator to a string
|
||||
|
@ -180,7 +204,7 @@ public:
|
|||
* @param s String buffer
|
||||
* @return Pointer to buffer
|
||||
*/
|
||||
char *toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept;
|
||||
char* toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept;
|
||||
|
||||
ZT_INLINE String toString() const
|
||||
{
|
||||
|
@ -194,29 +218,35 @@ public:
|
|||
* @param s Locator from toString()
|
||||
* @return True if format was valid
|
||||
*/
|
||||
bool fromString(const char *s) noexcept;
|
||||
bool fromString(const char* s) noexcept;
|
||||
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return m_revision > 0; }
|
||||
{
|
||||
return m_revision > 0;
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_LOCATOR_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], bool excludeSignature = false) const noexcept;
|
||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
||||
ZT_INLINE bool operator==(const Locator &l) const noexcept
|
||||
ZT_INLINE bool operator==(const Locator& l) const noexcept
|
||||
{
|
||||
const unsigned long es = (unsigned long)m_endpoints.size();
|
||||
if ((m_revision == l.m_revision) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size()) && (m_signature == l.m_signature)) {
|
||||
if ((m_revision == l.m_revision) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size())
|
||||
&& (m_signature == l.m_signature)) {
|
||||
for (unsigned long i = 0; i < es; ++i) {
|
||||
if (m_endpoints[i].first != l.m_endpoints[i].first)
|
||||
return false;
|
||||
if (!m_endpoints[i].second) {
|
||||
if (! m_endpoints[i].second) {
|
||||
if (l.m_endpoints[i].second)
|
||||
return false;
|
||||
} else {
|
||||
if ((!l.m_endpoints[i].second) || (*(m_endpoints[i].second) != *(l.m_endpoints[i].second)))
|
||||
}
|
||||
else {
|
||||
if ((! l.m_endpoints[i].second) || (*(m_endpoints[i].second) != *(l.m_endpoints[i].second)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -225,17 +255,19 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Locator &l) const noexcept
|
||||
{ return !(*this == l); }
|
||||
ZT_INLINE bool operator!=(const Locator& l) const noexcept
|
||||
{
|
||||
return ! (*this == l);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
void m_sortEndpoints() noexcept;
|
||||
|
||||
int64_t m_revision;
|
||||
Address m_signer;
|
||||
Vector <std::pair< Endpoint, SharedPtr< const EndpointAttributes > >> m_endpoints;
|
||||
FCV< uint8_t, ZT_SIGNATURE_BUFFER_SIZE > m_signature;
|
||||
std::atomic< int > __refCount;
|
||||
Vector<std::pair<Endpoint, SharedPtr<const EndpointAttributes> > > m_endpoints;
|
||||
FCV<uint8_t, ZT_SIGNATURE_BUFFER_SIZE> m_signature;
|
||||
std::atomic<int> __refCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
165
core/MAC.hpp
165
core/MAC.hpp
|
@ -14,55 +14,70 @@
|
|||
#ifndef ZT_MAC_HPP
|
||||
#define ZT_MAC_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* 48-byte Ethernet MAC address
|
||||
*/
|
||||
class MAC : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
ZT_INLINE MAC() noexcept: m_mac(0ULL)
|
||||
{}
|
||||
class MAC : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE MAC() noexcept : m_mac(0ULL)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE MAC(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d, const uint8_t e, const uint8_t f) noexcept:
|
||||
m_mac((((uint64_t)a) << 40U) | (((uint64_t)b) << 32U) | (((uint64_t)c) << 24U) | (((uint64_t)d) << 16U) | (((uint64_t)e) << 8U) | ((uint64_t)f))
|
||||
{}
|
||||
ZT_INLINE
|
||||
MAC(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d, const uint8_t e, const uint8_t f) noexcept
|
||||
: m_mac(
|
||||
(((uint64_t)a) << 40U) | (((uint64_t)b) << 32U) | (((uint64_t)c) << 24U) | (((uint64_t)d) << 16U)
|
||||
| (((uint64_t)e) << 8U) | ((uint64_t)f))
|
||||
{
|
||||
}
|
||||
|
||||
explicit ZT_INLINE MAC(const uint64_t m) noexcept:
|
||||
m_mac(m)
|
||||
{}
|
||||
explicit ZT_INLINE MAC(const uint64_t m) noexcept : m_mac(m)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ZT_INLINE MAC(const uint8_t b[6]) noexcept
|
||||
{ setTo(b); }
|
||||
{
|
||||
setTo(b);
|
||||
}
|
||||
|
||||
ZT_INLINE MAC(const Address &ztaddr, const uint64_t nwid) noexcept
|
||||
{ fromAddress(ztaddr, nwid); }
|
||||
ZT_INLINE MAC(const Address& ztaddr, const uint64_t nwid) noexcept
|
||||
{
|
||||
fromAddress(ztaddr, nwid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MAC in 64-bit integer
|
||||
*/
|
||||
ZT_INLINE uint64_t toInt() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set MAC to zero
|
||||
*/
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ m_mac = 0ULL; }
|
||||
{
|
||||
m_mac = 0ULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits Raw MAC in big-endian byte order
|
||||
* @param len Length, must be >= 6 or result is zero
|
||||
*/
|
||||
ZT_INLINE void setTo(const uint8_t b[6]) noexcept
|
||||
{ m_mac = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U) | ((uint64_t)b[4] << 8U) | (uint64_t)b[5]; }
|
||||
{
|
||||
m_mac = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U)
|
||||
| ((uint64_t)b[4] << 8U) | (uint64_t)b[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param buf Destination buffer for MAC in big-endian byte order
|
||||
|
@ -82,13 +97,17 @@ public:
|
|||
* @return True if this is broadcast (all 0xff)
|
||||
*/
|
||||
ZT_INLINE bool isBroadcast() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this is a multicast MAC
|
||||
*/
|
||||
ZT_INLINE bool isMulticast() const noexcept
|
||||
{ return ((m_mac & 0x010000000000ULL) != 0ULL); }
|
||||
{
|
||||
return ((m_mac & 0x010000000000ULL) != 0ULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this MAC to a MAC derived from an address and a network ID
|
||||
|
@ -96,7 +115,7 @@ public:
|
|||
* @param ztaddr ZeroTier address
|
||||
* @param nwid 64-bit network ID
|
||||
*/
|
||||
ZT_INLINE void fromAddress(const Address &ztaddr, uint64_t nwid) noexcept
|
||||
ZT_INLINE void fromAddress(const Address& ztaddr, uint64_t nwid) noexcept
|
||||
{
|
||||
uint64_t m = ((uint64_t)firstOctetForNetwork(nwid)) << 40U;
|
||||
m |= ztaddr.toInt(); // a is 40 bits
|
||||
|
@ -118,7 +137,8 @@ public:
|
|||
ZT_INLINE Address toAddress(uint64_t nwid) const noexcept
|
||||
{
|
||||
uint64_t a = m_mac & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address
|
||||
a ^= ((nwid >> 8U) & 0xffU) << 32U; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
|
||||
a ^= ((nwid >> 8U) & 0xffU)
|
||||
<< 32U; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
|
||||
a ^= ((nwid >> 16U) & 0xffU) << 24U;
|
||||
a ^= ((nwid >> 24U) & 0xffU) << 16U;
|
||||
a ^= ((nwid >> 32U) & 0xffU) << 8U;
|
||||
|
@ -132,8 +152,10 @@ public:
|
|||
*/
|
||||
static ZT_INLINE unsigned char firstOctetForNetwork(uint64_t nwid) noexcept
|
||||
{
|
||||
const uint8_t a = ((uint8_t)(nwid & 0xfeU) | 0x02U); // locally administered, not multicast, from LSB of network ID
|
||||
return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular virtualization engines... seems de-facto standard on Linux
|
||||
const uint8_t a =
|
||||
((uint8_t)(nwid & 0xfeU) | 0x02U); // locally administered, not multicast, from LSB of network ID
|
||||
return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular
|
||||
// virtualization engines... seems de-facto standard on Linux
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,22 +163,32 @@ public:
|
|||
* @return Byte at said position (address interpreted in big-endian order)
|
||||
*/
|
||||
ZT_INLINE uint8_t operator[](unsigned int i) const noexcept
|
||||
{ return (uint8_t)(m_mac >> (unsigned int)(40 - (i * 8))); }
|
||||
{
|
||||
return (uint8_t)(m_mac >> (unsigned int)(40 - (i * 8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 6, which is the number of bytes in a MAC, for container compliance
|
||||
*/
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return 6; }
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)Utils::hash64(m_mac); }
|
||||
{
|
||||
return (unsigned long)Utils::hash64(m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_mac != 0ULL); }
|
||||
{
|
||||
return (m_mac != 0ULL);
|
||||
}
|
||||
|
||||
ZT_INLINE operator uint64_t() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this MAC to a standard format colon-separated hex string
|
||||
|
@ -164,7 +196,7 @@ public:
|
|||
* @param buf Buffer to store string
|
||||
* @return Pointer to buf
|
||||
*/
|
||||
ZT_INLINE char *toString(char buf[18]) const noexcept
|
||||
ZT_INLINE char* toString(char buf[18]) const noexcept
|
||||
{
|
||||
buf[0] = Utils::HEXCHARS[(m_mac >> 44U) & 0xfU];
|
||||
buf[1] = Utils::HEXCHARS[(m_mac >> 40U) & 0xfU];
|
||||
|
@ -198,7 +230,7 @@ public:
|
|||
*
|
||||
* @param s String to parse
|
||||
*/
|
||||
ZT_INLINE void fromString(const char *s) noexcept
|
||||
ZT_INLINE void fromString(const char* s) noexcept
|
||||
{
|
||||
m_mac = 0;
|
||||
if (s) {
|
||||
|
@ -211,56 +243,81 @@ public:
|
|||
c = (uint64_t)hc - 87;
|
||||
else if ((hc >= 65) && (hc <= 70))
|
||||
c = (uint64_t)hc - 55;
|
||||
else continue;
|
||||
else
|
||||
continue;
|
||||
m_mac = (m_mac << 4U) | c;
|
||||
}
|
||||
m_mac &= 0xffffffffffffULL;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE MAC &operator=(const uint64_t m) noexcept
|
||||
ZT_INLINE MAC& operator=(const uint64_t m) noexcept
|
||||
{
|
||||
m_mac = m;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const MAC &m) const noexcept
|
||||
{ return (m_mac == m.m_mac); }
|
||||
ZT_INLINE bool operator==(const MAC& m) const noexcept
|
||||
{
|
||||
return (m_mac == m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const MAC &m) const noexcept
|
||||
{ return (m_mac != m.m_mac); }
|
||||
ZT_INLINE bool operator!=(const MAC& m) const noexcept
|
||||
{
|
||||
return (m_mac != m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const MAC &m) const noexcept
|
||||
{ return (m_mac < m.m_mac); }
|
||||
ZT_INLINE bool operator<(const MAC& m) const noexcept
|
||||
{
|
||||
return (m_mac < m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const MAC &m) const noexcept
|
||||
{ return (m_mac <= m.m_mac); }
|
||||
ZT_INLINE bool operator<=(const MAC& m) const noexcept
|
||||
{
|
||||
return (m_mac <= m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const MAC &m) const noexcept
|
||||
{ return (m_mac > m.m_mac); }
|
||||
ZT_INLINE bool operator>(const MAC& m) const noexcept
|
||||
{
|
||||
return (m_mac > m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const MAC &m) const noexcept
|
||||
{ return (m_mac >= m.m_mac); }
|
||||
ZT_INLINE bool operator>=(const MAC& m) const noexcept
|
||||
{
|
||||
return (m_mac >= m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const uint64_t m) const noexcept
|
||||
{ return (m_mac == m); }
|
||||
{
|
||||
return (m_mac == m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const uint64_t m) const noexcept
|
||||
{ return (m_mac != m); }
|
||||
{
|
||||
return (m_mac != m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const uint64_t m) const noexcept
|
||||
{ return (m_mac < m); }
|
||||
{
|
||||
return (m_mac < m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const uint64_t m) const noexcept
|
||||
{ return (m_mac <= m); }
|
||||
{
|
||||
return (m_mac <= m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const uint64_t m) const noexcept
|
||||
{ return (m_mac > m); }
|
||||
{
|
||||
return (m_mac > m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const uint64_t m) const noexcept
|
||||
{ return (m_mac >= m); }
|
||||
{
|
||||
return (m_mac >= m);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
uint64_t m_mac;
|
||||
};
|
||||
|
||||
|
|
151
core/MIMC52.cpp
151
core/MIMC52.cpp
|
@ -11,37 +11,131 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "MIMC52.hpp"
|
||||
|
||||
#include "AES.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
// Largest 1024 primes of form 6k + 5 and less than 2^52. Only the least significant 32
|
||||
// bits need to be here, as the most significant bits are all 1.
|
||||
const uint32_t ZT_MIMC52_PRIMES[1024] = {4294895267, 4294895477, 4294895513, 4294895519, 4294895543, 4294895567, 4294895657, 4294895711, 4294895777, 4294895861, 4294895909, 4294895921, 4294895969, 4294896011, 4294896149, 4294896227, 4294896401, 4294896473, 4294896527, 4294896563, 4294896653, 4294896731, 4294896863, 4294896899, 4294896983, 4294897037, 4294897103, 4294897331, 4294897349, 4294897451, 4294897571, 4294897661, 4294897703, 4294897757, 4294897793, 4294897811, 4294897817, 4294897829, 4294897877, 4294897919, 4294897991, 4294898027, 4294898129, 4294898153, 4294898231, 4294898273,
|
||||
4294898279, 4294898291, 4294898363, 4294898369, 4294898417, 4294898423, 4294898453, 4294898489, 4294898573, 4294898579, 4294898639, 4294898693, 4294898747, 4294898759, 4294898867, 4294898879, 4294898909, 4294898921, 4294898933, 4294899011, 4294899041, 4294899047, 4294899203, 4294899221, 4294899227, 4294899287, 4294899341, 4294899431, 4294899509, 4294899533, 4294899539, 4294899551, 4294899629, 4294899791, 4294899809, 4294899971, 4294900001, 4294900007, 4294900013, 4294900307, 4294900331, 4294900427, 4294900469, 4294900481, 4294900541, 4294900583,
|
||||
4294900781, 4294900853, 4294900931, 4294900991, 4294901033, 4294901087, 4294901159, 4294901267, 4294901393, 4294901411, 4294901489, 4294901657, 4294902011, 4294902071, 4294902101, 4294902107, 4294902353, 4294902377, 4294902599, 4294902647, 4294902743, 4294902869, 4294902977, 4294903067, 4294903103, 4294903259, 4294903289, 4294903397, 4294903421, 4294903493, 4294903577, 4294903631, 4294903637, 4294903733, 4294903799, 4294903823, 4294904003, 4294904033, 4294904081, 4294904129, 4294904279, 4294904297, 4294904303, 4294904333, 4294904351, 4294904381,
|
||||
4294904453, 4294904519, 4294904561, 4294904639, 4294904657, 4294904747, 4294904807, 4294904843, 4294905089, 4294905149, 4294905293, 4294905299, 4294905311, 4294905443, 4294905479, 4294905539, 4294905623, 4294905641, 4294905671, 4294905707, 4294905887, 4294905977, 4294906091, 4294906103, 4294906139, 4294906157, 4294906223, 4294906259, 4294906487, 4294906493, 4294906523, 4294906547, 4294906553, 4294906571, 4294906577, 4294906589, 4294906703, 4294906733, 4294906763, 4294906841, 4294906859, 4294906937, 4294907057, 4294907063, 4294907141, 4294907231,
|
||||
4294907249, 4294907261, 4294907267, 4294907387, 4294907417, 4294907567, 4294907603, 4294907699, 4294907789, 4294907849, 4294907873, 4294907879, 4294908023, 4294908071, 4294908119, 4294908209, 4294908227, 4294908329, 4294908491, 4294908503, 4294908569, 4294908653, 4294908713, 4294908719, 4294908791, 4294908839, 4294908869, 4294908989, 4294909031, 4294909067, 4294909109, 4294909253, 4294909529, 4294909589, 4294909643, 4294909739, 4294909799, 4294909811, 4294909853, 4294910003, 4294910039, 4294910189, 4294910201, 4294910219, 4294910273, 4294910333,
|
||||
4294910369, 4294910393, 4294910471, 4294910549, 4294910651, 4294910669, 4294910681, 4294910711, 4294910753, 4294910801, 4294910981, 4294911053, 4294911143, 4294911227, 4294911239, 4294911359, 4294911383, 4294911407, 4294911521, 4294911551, 4294911611, 4294911641, 4294911689, 4294911719, 4294911869, 4294912109, 4294912133, 4294912151, 4294912187, 4294912223, 4294912331, 4294912439, 4294912607, 4294912703, 4294912859, 4294912871, 4294912907, 4294912961, 4294913003, 4294913111, 4294913309, 4294913333, 4294913357, 4294913399, 4294913411, 4294913459,
|
||||
4294913501, 4294913531, 4294913591, 4294913609, 4294913663, 4294913783, 4294913819, 4294913903, 4294914137, 4294914413, 4294914473, 4294914497, 4294914527, 4294914551, 4294914593, 4294914611, 4294914659, 4294914671, 4294914743, 4294914863, 4294914917, 4294915061, 4294915103, 4294915139, 4294915217, 4294915223, 4294915253, 4294915283, 4294915373, 4294915433, 4294915607, 4294916069, 4294916213, 4294916267, 4294916303, 4294916393, 4294916441, 4294916477, 4294916507, 4294916573, 4294916633, 4294916687, 4294916783, 4294916837, 4294916897, 4294916921,
|
||||
4294917029, 4294917047, 4294917101, 4294917203, 4294917287, 4294917299, 4294917389, 4294917437, 4294917527, 4294917557, 4294917611, 4294917617, 4294917689, 4294917821, 4294917857, 4294917917, 4294917941, 4294918169, 4294918187, 4294918307, 4294918409, 4294918433, 4294918481, 4294918703, 4294918709, 4294918733, 4294918799, 4294918871, 4294919009, 4294919249, 4294919279, 4294919291, 4294919363, 4294919381, 4294919441, 4294919447, 4294919549, 4294919579, 4294919633, 4294919657, 4294919669, 4294919693, 4294919711, 4294920029, 4294920059, 4294920089,
|
||||
4294920197, 4294920239, 4294920257, 4294920263, 4294920269, 4294920341, 4294920353, 4294920407, 4294920503, 4294920599, 4294920647, 4294920743, 4294920803, 4294920809, 4294920881, 4294920899, 4294920983, 4294921043, 4294921139, 4294921151, 4294921181, 4294921229, 4294921289, 4294921331, 4294921343, 4294921391, 4294921469, 4294921709, 4294921721, 4294921823, 4294921847, 4294921889, 4294922057, 4294922171, 4294922201, 4294922237, 4294922309, 4294922399, 4294922447, 4294922507, 4294922513, 4294922549, 4294922609, 4294922663, 4294922861, 4294922933,
|
||||
4294923101, 4294923191, 4294923209, 4294923221, 4294923251, 4294923263, 4294923359, 4294923371, 4294923377, 4294923461, 4294923521, 4294923953, 4294924001, 4294924091, 4294924121, 4294924319, 4294924397, 4294924571, 4294924583, 4294924751, 4294924817, 4294924823, 4294924847, 4294924877, 4294925003, 4294925027, 4294925117, 4294925237, 4294925243, 4294925297, 4294925369, 4294925627, 4294925639, 4294925729, 4294925747, 4294925873, 4294925891, 4294925933, 4294926047, 4294926059, 4294926209, 4294926221, 4294926233, 4294926257, 4294926329, 4294926371,
|
||||
4294926401, 4294926413, 4294926437, 4294926563, 4294926569, 4294926917, 4294926923, 4294926947, 4294926971, 4294927067, 4294927073, 4294927151, 4294927349, 4294927367, 4294927403, 4294927481, 4294927523, 4294927553, 4294927589, 4294927649, 4294927673, 4294927727, 4294927739, 4294927763, 4294927889, 4294928183, 4294928207, 4294928249, 4294928327, 4294928351, 4294928399, 4294928483, 4294928489, 4294928543, 4294928597, 4294928951, 4294928963, 4294928981, 4294929017, 4294929059, 4294929161, 4294929197, 4294929233, 4294929269, 4294929311, 4294929323,
|
||||
4294929341, 4294929383, 4294929401, 4294929497, 4294929509, 4294929581, 4294929707, 4294929743, 4294930043, 4294930121, 4294930193, 4294930223, 4294930349, 4294930403, 4294930571, 4294930613, 4294930721, 4294930751, 4294930877, 4294930931, 4294930961, 4294930967, 4294930973, 4294931021, 4294931051, 4294931057, 4294931063, 4294931219, 4294931273, 4294931339, 4294931423, 4294931441, 4294931453, 4294931567, 4294931639, 4294931717, 4294931897, 4294931969, 4294932023, 4294932053, 4294932239, 4294932299, 4294932443, 4294932671, 4294932677, 4294932731,
|
||||
4294932743, 4294932767, 4294932773, 4294932779, 4294932881, 4294932899, 4294932929, 4294933067, 4294933277, 4294933307, 4294933343, 4294933451, 4294933523, 4294933763, 4294933793, 4294933829, 4294933847, 4294933871, 4294933997, 4294934033, 4294934111, 4294934207, 4294934243, 4294934267, 4294934279, 4294934291, 4294934327, 4294934363, 4294934423, 4294934489, 4294934561, 4294934867, 4294934921, 4294934969, 4294935137, 4294935239, 4294935299, 4294935431, 4294935539, 4294935629, 4294935701, 4294935791, 4294935797, 4294935803, 4294935959, 4294936001,
|
||||
4294936007, 4294936037, 4294936079, 4294936127, 4294936163, 4294936247, 4294936307, 4294936331, 4294936409, 4294936451, 4294936601, 4294936607, 4294936619, 4294936667, 4294936709, 4294936733, 4294936751, 4294936763, 4294936829, 4294936937, 4294936997, 4294937027, 4294937051, 4294937093, 4294937177, 4294937213, 4294937291, 4294937381, 4294937417, 4294937429, 4294937681, 4294937693, 4294937753, 4294937771, 4294937813, 4294937837, 4294937891, 4294937969, 4294938071, 4294938101, 4294938323, 4294938371, 4294938401, 4294938467, 4294938473, 4294938521,
|
||||
4294938599, 4294938731, 4294938779, 4294938833, 4294938899, 4294938977, 4294938983, 4294939067, 4294939127, 4294939223, 4294939277, 4294939331, 4294939337, 4294939391, 4294939457, 4294939559, 4294939673, 4294939691, 4294939901, 4294939991, 4294940087, 4294940093, 4294940189, 4294940213, 4294940417, 4294940657, 4294940699, 4294940753, 4294940801, 4294940873, 4294940951, 4294941047, 4294941143, 4294941161, 4294941227, 4294941281, 4294941377, 4294941509, 4294941551, 4294941701, 4294941731, 4294941767, 4294941911, 4294941923, 4294942043, 4294942139,
|
||||
4294942313, 4294942343, 4294942373, 4294942427, 4294942529, 4294942601, 4294942649, 4294942673, 4294942679, 4294942733, 4294942769, 4294942811, 4294942961, 4294943129, 4294943141, 4294943219, 4294943369, 4294943423, 4294943471, 4294943651, 4294943687, 4294943717, 4294943729, 4294943747, 4294943759, 4294943813, 4294943819, 4294943891, 4294944077, 4294944191, 4294944233, 4294944239, 4294944353, 4294944389, 4294944581, 4294944623, 4294944629, 4294944659, 4294944821, 4294945031, 4294945157, 4294945211, 4294945229, 4294945301, 4294945337, 4294945343,
|
||||
4294945511, 4294945547, 4294945667, 4294945709, 4294945757, 4294945841, 4294945991, 4294946033, 4294946099, 4294946153, 4294946477, 4294946687, 4294946747, 4294946957, 4294946993, 4294947023, 4294947131, 4294947167, 4294947287, 4294947311, 4294947413, 4294947581, 4294947599, 4294947671, 4294947851, 4294947959, 4294948067, 4294948073, 4294948193, 4294948259, 4294948421, 4294948451, 4294948613, 4294948673, 4294948883, 4294949027, 4294949057, 4294949069, 4294949519, 4294949531, 4294949603, 4294949609, 4294949627, 4294949693, 4294949729, 4294949741,
|
||||
4294949807, 4294949921, 4294949939, 4294949981, 4294949993, 4294950083, 4294950173, 4294950197, 4294950251, 4294950287, 4294950317, 4294950323, 4294950329, 4294950581, 4294950593, 4294950617, 4294950629, 4294950713, 4294950929, 4294951151, 4294951163, 4294951169, 4294951379, 4294951583, 4294951613, 4294951853, 4294951907, 4294951913, 4294951937, 4294951961, 4294952063, 4294952183, 4294952393, 4294952543, 4294952549, 4294952597, 4294952627, 4294952687, 4294952723, 4294952729, 4294952789, 4294952819, 4294952873, 4294952891, 4294952903, 4294952969,
|
||||
4294952999, 4294953023, 4294953107, 4294953173, 4294953281, 4294953341, 4294953431, 4294953599, 4294953689, 4294953719, 4294953827, 4294953887, 4294953977, 4294954073, 4294954079, 4294954157, 4294954217, 4294954283, 4294954607, 4294954667, 4294954859, 4294954901, 4294954973, 4294955081, 4294955237, 4294955273, 4294955327, 4294955441, 4294955507, 4294955591, 4294955789, 4294955831, 4294955837, 4294955927, 4294955963, 4294955969, 4294955987, 4294956041, 4294956047, 4294956197, 4294956323, 4294956359, 4294956551, 4294956593, 4294956623, 4294956629,
|
||||
4294956641, 4294956719, 4294956761, 4294956767, 4294956797, 4294956821, 4294956833, 4294957037, 4294957079, 4294957103, 4294957181, 4294957349, 4294957379, 4294957433, 4294957463, 4294957511, 4294957577, 4294957727, 4294957859, 4294957877, 4294958039, 4294958153, 4294958309, 4294958417, 4294958441, 4294958693, 4294958717, 4294958753, 4294958903, 4294958909, 4294959017, 4294959071, 4294959107, 4294959161, 4294959257, 4294959299, 4294959329, 4294959431, 4294959593, 4294959599, 4294959659, 4294959893, 4294959917, 4294959983, 4294960001, 4294960031,
|
||||
4294960061, 4294960079, 4294960097, 4294960271, 4294960283, 4294960349, 4294960367, 4294960421, 4294960529, 4294960541, 4294960583, 4294960613, 4294960673, 4294960691, 4294960697, 4294960787, 4294960919, 4294961003, 4294961039, 4294961153, 4294961159, 4294961171, 4294961321, 4294961411, 4294961471, 4294961507, 4294961537, 4294961669, 4294961717, 4294961741, 4294961873, 4294962059, 4294962137, 4294962167, 4294962263, 4294962281, 4294962311, 4294962341, 4294962413, 4294962521, 4294962563, 4294962761, 4294962893, 4294963103, 4294963163, 4294963223,
|
||||
4294963313, 4294963349, 4294963427, 4294963547, 4294963559, 4294963721, 4294963799, 4294963817, 4294963901, 4294963919, 4294964021, 4294964279, 4294964297, 4294964363, 4294964387, 4294964411, 4294964567, 4294964603, 4294964687, 4294964777, 4294965041, 4294965071, 4294965119, 4294965221, 4294965251, 4294965287, 4294965413, 4294965569, 4294965647, 4294965671, 4294965689, 4294965779, 4294965839, 4294965893, 4294966091, 4294966109, 4294966127, 4294966157, 4294966187, 4294966199, 4294966211, 4294966403, 4294966457, 4294966499, 4294966541, 4294966637,
|
||||
4294966661, 4294966739, 4294966823, 4294966883, 4294966901, 4294966961, 4294967027, 4294967087, 4294967099, 4294967123, 4294967153, 4294967249};
|
||||
const uint32_t ZT_MIMC52_PRIMES[1024] = {
|
||||
4294895267, 4294895477, 4294895513, 4294895519, 4294895543, 4294895567, 4294895657, 4294895711, 4294895777,
|
||||
4294895861, 4294895909, 4294895921, 4294895969, 4294896011, 4294896149, 4294896227, 4294896401, 4294896473,
|
||||
4294896527, 4294896563, 4294896653, 4294896731, 4294896863, 4294896899, 4294896983, 4294897037, 4294897103,
|
||||
4294897331, 4294897349, 4294897451, 4294897571, 4294897661, 4294897703, 4294897757, 4294897793, 4294897811,
|
||||
4294897817, 4294897829, 4294897877, 4294897919, 4294897991, 4294898027, 4294898129, 4294898153, 4294898231,
|
||||
4294898273, 4294898279, 4294898291, 4294898363, 4294898369, 4294898417, 4294898423, 4294898453, 4294898489,
|
||||
4294898573, 4294898579, 4294898639, 4294898693, 4294898747, 4294898759, 4294898867, 4294898879, 4294898909,
|
||||
4294898921, 4294898933, 4294899011, 4294899041, 4294899047, 4294899203, 4294899221, 4294899227, 4294899287,
|
||||
4294899341, 4294899431, 4294899509, 4294899533, 4294899539, 4294899551, 4294899629, 4294899791, 4294899809,
|
||||
4294899971, 4294900001, 4294900007, 4294900013, 4294900307, 4294900331, 4294900427, 4294900469, 4294900481,
|
||||
4294900541, 4294900583, 4294900781, 4294900853, 4294900931, 4294900991, 4294901033, 4294901087, 4294901159,
|
||||
4294901267, 4294901393, 4294901411, 4294901489, 4294901657, 4294902011, 4294902071, 4294902101, 4294902107,
|
||||
4294902353, 4294902377, 4294902599, 4294902647, 4294902743, 4294902869, 4294902977, 4294903067, 4294903103,
|
||||
4294903259, 4294903289, 4294903397, 4294903421, 4294903493, 4294903577, 4294903631, 4294903637, 4294903733,
|
||||
4294903799, 4294903823, 4294904003, 4294904033, 4294904081, 4294904129, 4294904279, 4294904297, 4294904303,
|
||||
4294904333, 4294904351, 4294904381, 4294904453, 4294904519, 4294904561, 4294904639, 4294904657, 4294904747,
|
||||
4294904807, 4294904843, 4294905089, 4294905149, 4294905293, 4294905299, 4294905311, 4294905443, 4294905479,
|
||||
4294905539, 4294905623, 4294905641, 4294905671, 4294905707, 4294905887, 4294905977, 4294906091, 4294906103,
|
||||
4294906139, 4294906157, 4294906223, 4294906259, 4294906487, 4294906493, 4294906523, 4294906547, 4294906553,
|
||||
4294906571, 4294906577, 4294906589, 4294906703, 4294906733, 4294906763, 4294906841, 4294906859, 4294906937,
|
||||
4294907057, 4294907063, 4294907141, 4294907231, 4294907249, 4294907261, 4294907267, 4294907387, 4294907417,
|
||||
4294907567, 4294907603, 4294907699, 4294907789, 4294907849, 4294907873, 4294907879, 4294908023, 4294908071,
|
||||
4294908119, 4294908209, 4294908227, 4294908329, 4294908491, 4294908503, 4294908569, 4294908653, 4294908713,
|
||||
4294908719, 4294908791, 4294908839, 4294908869, 4294908989, 4294909031, 4294909067, 4294909109, 4294909253,
|
||||
4294909529, 4294909589, 4294909643, 4294909739, 4294909799, 4294909811, 4294909853, 4294910003, 4294910039,
|
||||
4294910189, 4294910201, 4294910219, 4294910273, 4294910333, 4294910369, 4294910393, 4294910471, 4294910549,
|
||||
4294910651, 4294910669, 4294910681, 4294910711, 4294910753, 4294910801, 4294910981, 4294911053, 4294911143,
|
||||
4294911227, 4294911239, 4294911359, 4294911383, 4294911407, 4294911521, 4294911551, 4294911611, 4294911641,
|
||||
4294911689, 4294911719, 4294911869, 4294912109, 4294912133, 4294912151, 4294912187, 4294912223, 4294912331,
|
||||
4294912439, 4294912607, 4294912703, 4294912859, 4294912871, 4294912907, 4294912961, 4294913003, 4294913111,
|
||||
4294913309, 4294913333, 4294913357, 4294913399, 4294913411, 4294913459, 4294913501, 4294913531, 4294913591,
|
||||
4294913609, 4294913663, 4294913783, 4294913819, 4294913903, 4294914137, 4294914413, 4294914473, 4294914497,
|
||||
4294914527, 4294914551, 4294914593, 4294914611, 4294914659, 4294914671, 4294914743, 4294914863, 4294914917,
|
||||
4294915061, 4294915103, 4294915139, 4294915217, 4294915223, 4294915253, 4294915283, 4294915373, 4294915433,
|
||||
4294915607, 4294916069, 4294916213, 4294916267, 4294916303, 4294916393, 4294916441, 4294916477, 4294916507,
|
||||
4294916573, 4294916633, 4294916687, 4294916783, 4294916837, 4294916897, 4294916921, 4294917029, 4294917047,
|
||||
4294917101, 4294917203, 4294917287, 4294917299, 4294917389, 4294917437, 4294917527, 4294917557, 4294917611,
|
||||
4294917617, 4294917689, 4294917821, 4294917857, 4294917917, 4294917941, 4294918169, 4294918187, 4294918307,
|
||||
4294918409, 4294918433, 4294918481, 4294918703, 4294918709, 4294918733, 4294918799, 4294918871, 4294919009,
|
||||
4294919249, 4294919279, 4294919291, 4294919363, 4294919381, 4294919441, 4294919447, 4294919549, 4294919579,
|
||||
4294919633, 4294919657, 4294919669, 4294919693, 4294919711, 4294920029, 4294920059, 4294920089, 4294920197,
|
||||
4294920239, 4294920257, 4294920263, 4294920269, 4294920341, 4294920353, 4294920407, 4294920503, 4294920599,
|
||||
4294920647, 4294920743, 4294920803, 4294920809, 4294920881, 4294920899, 4294920983, 4294921043, 4294921139,
|
||||
4294921151, 4294921181, 4294921229, 4294921289, 4294921331, 4294921343, 4294921391, 4294921469, 4294921709,
|
||||
4294921721, 4294921823, 4294921847, 4294921889, 4294922057, 4294922171, 4294922201, 4294922237, 4294922309,
|
||||
4294922399, 4294922447, 4294922507, 4294922513, 4294922549, 4294922609, 4294922663, 4294922861, 4294922933,
|
||||
4294923101, 4294923191, 4294923209, 4294923221, 4294923251, 4294923263, 4294923359, 4294923371, 4294923377,
|
||||
4294923461, 4294923521, 4294923953, 4294924001, 4294924091, 4294924121, 4294924319, 4294924397, 4294924571,
|
||||
4294924583, 4294924751, 4294924817, 4294924823, 4294924847, 4294924877, 4294925003, 4294925027, 4294925117,
|
||||
4294925237, 4294925243, 4294925297, 4294925369, 4294925627, 4294925639, 4294925729, 4294925747, 4294925873,
|
||||
4294925891, 4294925933, 4294926047, 4294926059, 4294926209, 4294926221, 4294926233, 4294926257, 4294926329,
|
||||
4294926371, 4294926401, 4294926413, 4294926437, 4294926563, 4294926569, 4294926917, 4294926923, 4294926947,
|
||||
4294926971, 4294927067, 4294927073, 4294927151, 4294927349, 4294927367, 4294927403, 4294927481, 4294927523,
|
||||
4294927553, 4294927589, 4294927649, 4294927673, 4294927727, 4294927739, 4294927763, 4294927889, 4294928183,
|
||||
4294928207, 4294928249, 4294928327, 4294928351, 4294928399, 4294928483, 4294928489, 4294928543, 4294928597,
|
||||
4294928951, 4294928963, 4294928981, 4294929017, 4294929059, 4294929161, 4294929197, 4294929233, 4294929269,
|
||||
4294929311, 4294929323, 4294929341, 4294929383, 4294929401, 4294929497, 4294929509, 4294929581, 4294929707,
|
||||
4294929743, 4294930043, 4294930121, 4294930193, 4294930223, 4294930349, 4294930403, 4294930571, 4294930613,
|
||||
4294930721, 4294930751, 4294930877, 4294930931, 4294930961, 4294930967, 4294930973, 4294931021, 4294931051,
|
||||
4294931057, 4294931063, 4294931219, 4294931273, 4294931339, 4294931423, 4294931441, 4294931453, 4294931567,
|
||||
4294931639, 4294931717, 4294931897, 4294931969, 4294932023, 4294932053, 4294932239, 4294932299, 4294932443,
|
||||
4294932671, 4294932677, 4294932731, 4294932743, 4294932767, 4294932773, 4294932779, 4294932881, 4294932899,
|
||||
4294932929, 4294933067, 4294933277, 4294933307, 4294933343, 4294933451, 4294933523, 4294933763, 4294933793,
|
||||
4294933829, 4294933847, 4294933871, 4294933997, 4294934033, 4294934111, 4294934207, 4294934243, 4294934267,
|
||||
4294934279, 4294934291, 4294934327, 4294934363, 4294934423, 4294934489, 4294934561, 4294934867, 4294934921,
|
||||
4294934969, 4294935137, 4294935239, 4294935299, 4294935431, 4294935539, 4294935629, 4294935701, 4294935791,
|
||||
4294935797, 4294935803, 4294935959, 4294936001, 4294936007, 4294936037, 4294936079, 4294936127, 4294936163,
|
||||
4294936247, 4294936307, 4294936331, 4294936409, 4294936451, 4294936601, 4294936607, 4294936619, 4294936667,
|
||||
4294936709, 4294936733, 4294936751, 4294936763, 4294936829, 4294936937, 4294936997, 4294937027, 4294937051,
|
||||
4294937093, 4294937177, 4294937213, 4294937291, 4294937381, 4294937417, 4294937429, 4294937681, 4294937693,
|
||||
4294937753, 4294937771, 4294937813, 4294937837, 4294937891, 4294937969, 4294938071, 4294938101, 4294938323,
|
||||
4294938371, 4294938401, 4294938467, 4294938473, 4294938521, 4294938599, 4294938731, 4294938779, 4294938833,
|
||||
4294938899, 4294938977, 4294938983, 4294939067, 4294939127, 4294939223, 4294939277, 4294939331, 4294939337,
|
||||
4294939391, 4294939457, 4294939559, 4294939673, 4294939691, 4294939901, 4294939991, 4294940087, 4294940093,
|
||||
4294940189, 4294940213, 4294940417, 4294940657, 4294940699, 4294940753, 4294940801, 4294940873, 4294940951,
|
||||
4294941047, 4294941143, 4294941161, 4294941227, 4294941281, 4294941377, 4294941509, 4294941551, 4294941701,
|
||||
4294941731, 4294941767, 4294941911, 4294941923, 4294942043, 4294942139, 4294942313, 4294942343, 4294942373,
|
||||
4294942427, 4294942529, 4294942601, 4294942649, 4294942673, 4294942679, 4294942733, 4294942769, 4294942811,
|
||||
4294942961, 4294943129, 4294943141, 4294943219, 4294943369, 4294943423, 4294943471, 4294943651, 4294943687,
|
||||
4294943717, 4294943729, 4294943747, 4294943759, 4294943813, 4294943819, 4294943891, 4294944077, 4294944191,
|
||||
4294944233, 4294944239, 4294944353, 4294944389, 4294944581, 4294944623, 4294944629, 4294944659, 4294944821,
|
||||
4294945031, 4294945157, 4294945211, 4294945229, 4294945301, 4294945337, 4294945343, 4294945511, 4294945547,
|
||||
4294945667, 4294945709, 4294945757, 4294945841, 4294945991, 4294946033, 4294946099, 4294946153, 4294946477,
|
||||
4294946687, 4294946747, 4294946957, 4294946993, 4294947023, 4294947131, 4294947167, 4294947287, 4294947311,
|
||||
4294947413, 4294947581, 4294947599, 4294947671, 4294947851, 4294947959, 4294948067, 4294948073, 4294948193,
|
||||
4294948259, 4294948421, 4294948451, 4294948613, 4294948673, 4294948883, 4294949027, 4294949057, 4294949069,
|
||||
4294949519, 4294949531, 4294949603, 4294949609, 4294949627, 4294949693, 4294949729, 4294949741, 4294949807,
|
||||
4294949921, 4294949939, 4294949981, 4294949993, 4294950083, 4294950173, 4294950197, 4294950251, 4294950287,
|
||||
4294950317, 4294950323, 4294950329, 4294950581, 4294950593, 4294950617, 4294950629, 4294950713, 4294950929,
|
||||
4294951151, 4294951163, 4294951169, 4294951379, 4294951583, 4294951613, 4294951853, 4294951907, 4294951913,
|
||||
4294951937, 4294951961, 4294952063, 4294952183, 4294952393, 4294952543, 4294952549, 4294952597, 4294952627,
|
||||
4294952687, 4294952723, 4294952729, 4294952789, 4294952819, 4294952873, 4294952891, 4294952903, 4294952969,
|
||||
4294952999, 4294953023, 4294953107, 4294953173, 4294953281, 4294953341, 4294953431, 4294953599, 4294953689,
|
||||
4294953719, 4294953827, 4294953887, 4294953977, 4294954073, 4294954079, 4294954157, 4294954217, 4294954283,
|
||||
4294954607, 4294954667, 4294954859, 4294954901, 4294954973, 4294955081, 4294955237, 4294955273, 4294955327,
|
||||
4294955441, 4294955507, 4294955591, 4294955789, 4294955831, 4294955837, 4294955927, 4294955963, 4294955969,
|
||||
4294955987, 4294956041, 4294956047, 4294956197, 4294956323, 4294956359, 4294956551, 4294956593, 4294956623,
|
||||
4294956629, 4294956641, 4294956719, 4294956761, 4294956767, 4294956797, 4294956821, 4294956833, 4294957037,
|
||||
4294957079, 4294957103, 4294957181, 4294957349, 4294957379, 4294957433, 4294957463, 4294957511, 4294957577,
|
||||
4294957727, 4294957859, 4294957877, 4294958039, 4294958153, 4294958309, 4294958417, 4294958441, 4294958693,
|
||||
4294958717, 4294958753, 4294958903, 4294958909, 4294959017, 4294959071, 4294959107, 4294959161, 4294959257,
|
||||
4294959299, 4294959329, 4294959431, 4294959593, 4294959599, 4294959659, 4294959893, 4294959917, 4294959983,
|
||||
4294960001, 4294960031, 4294960061, 4294960079, 4294960097, 4294960271, 4294960283, 4294960349, 4294960367,
|
||||
4294960421, 4294960529, 4294960541, 4294960583, 4294960613, 4294960673, 4294960691, 4294960697, 4294960787,
|
||||
4294960919, 4294961003, 4294961039, 4294961153, 4294961159, 4294961171, 4294961321, 4294961411, 4294961471,
|
||||
4294961507, 4294961537, 4294961669, 4294961717, 4294961741, 4294961873, 4294962059, 4294962137, 4294962167,
|
||||
4294962263, 4294962281, 4294962311, 4294962341, 4294962413, 4294962521, 4294962563, 4294962761, 4294962893,
|
||||
4294963103, 4294963163, 4294963223, 4294963313, 4294963349, 4294963427, 4294963547, 4294963559, 4294963721,
|
||||
4294963799, 4294963817, 4294963901, 4294963919, 4294964021, 4294964279, 4294964297, 4294964363, 4294964387,
|
||||
4294964411, 4294964567, 4294964603, 4294964687, 4294964777, 4294965041, 4294965071, 4294965119, 4294965221,
|
||||
4294965251, 4294965287, 4294965413, 4294965569, 4294965647, 4294965671, 4294965689, 4294965779, 4294965839,
|
||||
4294965893, 4294966091, 4294966109, 4294966127, 4294966157, 4294966187, 4294966199, 4294966211, 4294966403,
|
||||
4294966457, 4294966499, 4294966541, 4294966637, 4294966661, 4294966739, 4294966823, 4294966883, 4294966901,
|
||||
4294966961, 4294967027, 4294967087, 4294967099, 4294967123, 4294967153, 4294967249
|
||||
};
|
||||
|
||||
#ifdef ZT_NO_IEEE_DOUBLE
|
||||
|
||||
|
@ -69,8 +163,8 @@ static uint64_t mulmod64(uint64_t a, uint64_t b, const uint64_t m)
|
|||
* performs fairly equally across CPUs. */
|
||||
ZT_INLINE uint64_t mulmod52(uint64_t a, const uint64_t b, const uint64_t m, const double mf)
|
||||
{
|
||||
a = ( ( a * b ) - ( ((uint64_t)(((double)a * (double)b) / mf) - 1) * m ) );
|
||||
//a -= m * (uint64_t)(a > m); // faster on some systems, but slower on newer cores
|
||||
a = ((a * b) - (((uint64_t)(((double)a * (double)b) / mf) - 1) * m));
|
||||
// a -= m * (uint64_t)(a > m); // faster on some systems, but slower on newer cores
|
||||
a %= m;
|
||||
return a;
|
||||
}
|
||||
|
@ -87,7 +181,8 @@ ZT_INLINE uint64_t modpow52(uint64_t a, uint64_t e, const uint64_t m, const doub
|
|||
}
|
||||
if (likely((e >>= 1U) != 0)) {
|
||||
a = mulmod52(a, a, m, mf);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,6 @@ uint64_t delay(const uint8_t challenge[32], unsigned long rounds);
|
|||
bool verify(const uint8_t challenge[32], unsigned long rounds, uint64_t proof);
|
||||
|
||||
} // namespace MIMC52
|
||||
} // namespcae ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
212
core/Member.cpp
212
core/Member.cpp
|
@ -11,26 +11,31 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Member.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Member::Member() :
|
||||
m_comRevocationThreshold(0),
|
||||
m_lastPushedCredentials(0),
|
||||
m_comAgreementLocalTimestamp(0),
|
||||
m_comAgreementRemoteTimestamp(0)
|
||||
Member::Member()
|
||||
: m_comRevocationThreshold(0)
|
||||
, m_lastPushedCredentials(0)
|
||||
, m_comAgreementLocalTimestamp(0)
|
||||
, m_comAgreementRemoteTimestamp(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Member::pushCredentials(const Context &ctx, const CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf)
|
||||
void Member::pushCredentials(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const SharedPtr<Peer>& to,
|
||||
const NetworkConfig& nconf)
|
||||
{
|
||||
if (!nconf.com) // sanity check
|
||||
if (! nconf.com) // sanity check
|
||||
return;
|
||||
|
||||
#if 0
|
||||
|
@ -115,29 +120,45 @@ void Member::pushCredentials(const Context &ctx, const CallContext &cc, const Sh
|
|||
m_lastPushedCredentials = cc.ticks;
|
||||
}
|
||||
|
||||
void Member::clean(const NetworkConfig &nconf)
|
||||
void Member::clean(const NetworkConfig& nconf)
|
||||
{
|
||||
m_cleanCredImpl< TagCredential >(nconf, m_remoteTags);
|
||||
m_cleanCredImpl< CapabilityCredential >(nconf, m_remoteCaps);
|
||||
m_cleanCredImpl< OwnershipCredential >(nconf, m_remoteCoos);
|
||||
m_cleanCredImpl<TagCredential>(nconf, m_remoteTags);
|
||||
m_cleanCredImpl<CapabilityCredential>(nconf, m_remoteCaps);
|
||||
m_cleanCredImpl<OwnershipCredential>(nconf, m_remoteCoos);
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context &ctx,
|
||||
const CallContext &cc,
|
||||
const Identity &sourcePeerIdentity,
|
||||
const NetworkConfig &nconf,
|
||||
const MembershipCredential &com)
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const MembershipCredential& com)
|
||||
{
|
||||
const int64_t newts = com.timestamp();
|
||||
if (newts <= m_comRevocationThreshold) {
|
||||
ctx.t->credentialRejected(cc, 0xd9992121, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0xd9992121,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
|
||||
const int64_t oldts = m_com.timestamp();
|
||||
if (newts < oldts) {
|
||||
ctx.t->credentialRejected(cc, 0xd9928192, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0xd9928192,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
if ((newts == oldts) && (m_com == com))
|
||||
|
@ -145,13 +166,29 @@ Member::AddCredentialResult Member::addCredential(
|
|||
|
||||
switch (com.verify(ctx, cc)) {
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x0f198241, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x0f198241,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return Member::ADD_REJECTED;
|
||||
case Credential::VERIFY_OK:
|
||||
m_com = com;
|
||||
return ADD_ACCEPTED_NEW;
|
||||
case Credential::VERIFY_BAD_SIGNATURE:
|
||||
ctx.t->credentialRejected(cc, 0xbaf0aaaa, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0xbaf0aaaa,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
|
||||
return ADD_REJECTED;
|
||||
case Credential::VERIFY_NEED_IDENTITY:
|
||||
return ADD_DEFERRED_FOR_WHOIS;
|
||||
|
@ -159,35 +196,60 @@ Member::AddCredentialResult Member::addCredential(
|
|||
}
|
||||
|
||||
// 3/5 of the credential types have identical addCredential() code
|
||||
template< typename C >
|
||||
template <typename C>
|
||||
static ZT_INLINE Member::AddCredentialResult _addCredImpl(
|
||||
Map< uint32_t, C > &remoteCreds,
|
||||
const Map< uint64_t, int64_t > &revocations,
|
||||
const Context &ctx,
|
||||
const CallContext &cc,
|
||||
const Identity &sourcePeerIdentity,
|
||||
const NetworkConfig &nconf,
|
||||
const C &cred)
|
||||
Map<uint32_t, C>& remoteCreds,
|
||||
const Map<uint64_t, int64_t>& revocations,
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const C& cred)
|
||||
{
|
||||
typename Map< uint32_t, C >::const_iterator rc(remoteCreds.find(cred.id()));
|
||||
typename Map<uint32_t, C>::const_iterator rc(remoteCreds.find(cred.id()));
|
||||
if (rc != remoteCreds.end()) {
|
||||
if (rc->second.revision() > cred.revision()) {
|
||||
ctx.t->credentialRejected(cc, 0x40000001, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x40000001,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
cred.id(),
|
||||
cred.revision(),
|
||||
C::credentialType(),
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
return Member::ADD_REJECTED;
|
||||
}
|
||||
if (rc->second == cred)
|
||||
return Member::ADD_ACCEPTED_REDUNDANT;
|
||||
}
|
||||
|
||||
typename Map< uint64_t, int64_t >::const_iterator rt(revocations.find(Member::credentialKey(C::credentialType(), cred.id())));
|
||||
typename Map<uint64_t, int64_t>::const_iterator rt(
|
||||
revocations.find(Member::credentialKey(C::credentialType(), cred.id())));
|
||||
if ((rt != revocations.end()) && (rt->second >= cred.revision())) {
|
||||
ctx.t->credentialRejected(cc, 0x24248124, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x24248124,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
cred.id(),
|
||||
cred.revision(),
|
||||
C::credentialType(),
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
return Member::ADD_REJECTED;
|
||||
}
|
||||
|
||||
switch (cred.verify(ctx, cc)) {
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x01feba012, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x01feba012,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
cred.id(),
|
||||
cred.revision(),
|
||||
C::credentialType(),
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return Member::ADD_REJECTED;
|
||||
case 0:
|
||||
if (rc == remoteCreds.end())
|
||||
|
@ -198,21 +260,55 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
|
|||
}
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag)
|
||||
{ return _addCredImpl< TagCredential >(m_remoteTags, m_revocations, ctx, cc, sourcePeerIdentity, nconf, tag); }
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap)
|
||||
{ return _addCredImpl< CapabilityCredential >(m_remoteCaps, m_revocations, ctx, cc, sourcePeerIdentity, nconf, cap); }
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo)
|
||||
{ return _addCredImpl< OwnershipCredential >(m_remoteCoos, m_revocations, ctx, cc, sourcePeerIdentity, nconf, coo); }
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev)
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const TagCredential& tag)
|
||||
{
|
||||
int64_t *rt;
|
||||
return _addCredImpl<TagCredential>(m_remoteTags, m_revocations, ctx, cc, sourcePeerIdentity, nconf, tag);
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const CapabilityCredential& cap)
|
||||
{
|
||||
return _addCredImpl<CapabilityCredential>(m_remoteCaps, m_revocations, ctx, cc, sourcePeerIdentity, nconf, cap);
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const OwnershipCredential& coo)
|
||||
{
|
||||
return _addCredImpl<OwnershipCredential>(m_remoteCoos, m_revocations, ctx, cc, sourcePeerIdentity, nconf, coo);
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const RevocationCredential& rev)
|
||||
{
|
||||
int64_t* rt;
|
||||
switch (rev.verify(ctx, cc)) {
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x938ff009, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x938ff009,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
rev.id(),
|
||||
0,
|
||||
ZT_CREDENTIAL_TYPE_REVOCATION,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return ADD_REJECTED;
|
||||
case 0: {
|
||||
const ZT_CredentialType ct = rev.typeBeingRevoked();
|
||||
|
@ -234,7 +330,15 @@ Member::AddCredentialResult Member::addCredential(const Context &ctx, const Call
|
|||
}
|
||||
return ADD_ACCEPTED_REDUNDANT;
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x0bbbb1a4, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x0bbbb1a4,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
rev.id(),
|
||||
0,
|
||||
ZT_CREDENTIAL_TYPE_REVOCATION,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
}
|
||||
|
@ -243,16 +347,12 @@ Member::AddCredentialResult Member::addCredential(const Context &ctx, const Call
|
|||
}
|
||||
}
|
||||
|
||||
bool Member::m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept
|
||||
bool Member::m_isUnspoofableAddress(const NetworkConfig& nconf, const InetAddress& ip) const noexcept
|
||||
{
|
||||
return (
|
||||
ip.isV6() &&
|
||||
nconf.ndpEmulation() &&
|
||||
(
|
||||
(ip == InetAddress::makeIpv66plane(nconf.networkId, m_com.issuedTo().address)) ||
|
||||
(ip == InetAddress::makeIpv6rfc4193(nconf.networkId, m_com.issuedTo().address))
|
||||
)
|
||||
);
|
||||
ip.isV6() && nconf.ndpEmulation()
|
||||
&& ((ip == InetAddress::makeIpv66plane(nconf.networkId, m_com.issuedTo().address))
|
||||
|| (ip == InetAddress::makeIpv6rfc4193(nconf.networkId, m_com.issuedTo().address))));
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
160
core/Member.hpp
160
core/Member.hpp
|
@ -14,14 +14,14 @@
|
|||
#ifndef ZT_MEMBERSHIP_HPP
|
||||
#define ZT_MEMBERSHIP_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -36,16 +36,9 @@ class Network;
|
|||
*
|
||||
* This class is not thread safe. It must be locked externally.
|
||||
*/
|
||||
class Member
|
||||
{
|
||||
public:
|
||||
enum AddCredentialResult
|
||||
{
|
||||
ADD_REJECTED,
|
||||
ADD_ACCEPTED_NEW,
|
||||
ADD_ACCEPTED_REDUNDANT,
|
||||
ADD_DEFERRED_FOR_WHOIS
|
||||
};
|
||||
class Member {
|
||||
public:
|
||||
enum AddCredentialResult { ADD_REJECTED, ADD_ACCEPTED_NEW, ADD_ACCEPTED_REDUNDANT, ADD_DEFERRED_FOR_WHOIS };
|
||||
|
||||
Member();
|
||||
|
||||
|
@ -55,13 +48,16 @@ public:
|
|||
* @param to Peer identity
|
||||
* @param nconf My network config
|
||||
*/
|
||||
void pushCredentials(const Context &ctx, const CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf);
|
||||
void
|
||||
pushCredentials(const Context& ctx, const CallContext& cc, const SharedPtr<Peer>& to, const NetworkConfig& nconf);
|
||||
|
||||
/**
|
||||
* @return Time we last pushed credentials to this member
|
||||
*/
|
||||
ZT_INLINE int64_t lastPushedCredentials() const noexcept
|
||||
{ return m_lastPushedCredentials; }
|
||||
{
|
||||
return m_lastPushedCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a remote member's tag (if we have it)
|
||||
|
@ -70,10 +66,12 @@ public:
|
|||
* @param id Tag ID
|
||||
* @return Pointer to tag or NULL if not found
|
||||
*/
|
||||
ZT_INLINE const TagCredential *getTag(const NetworkConfig &nconf, const uint32_t id) const noexcept
|
||||
ZT_INLINE const TagCredential* getTag(const NetworkConfig& nconf, const uint32_t id) const noexcept
|
||||
{
|
||||
Map< uint32_t, TagCredential >::const_iterator t(m_remoteTags.find(id));
|
||||
return (((t != m_remoteTags.end()) && (m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second) : (TagCredential *)0);
|
||||
Map<uint32_t, TagCredential>::const_iterator t(m_remoteTags.find(id));
|
||||
return (
|
||||
((t != m_remoteTags.end()) && (m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second)
|
||||
: (TagCredential*)0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,13 +79,15 @@ public:
|
|||
*
|
||||
* @param nconf Current network configuration
|
||||
*/
|
||||
void clean(const NetworkConfig &nconf);
|
||||
void clean(const NetworkConfig& nconf);
|
||||
|
||||
/**
|
||||
* Generates a key for internal use in indexing credentials by type and credential ID
|
||||
*/
|
||||
static ZT_INLINE uint64_t credentialKey(const ZT_CredentialType &t, const uint32_t i) noexcept
|
||||
{ return (((uint64_t)t << 32U) | (uint64_t)i); }
|
||||
static ZT_INLINE uint64_t credentialKey(const ZT_CredentialType& t, const uint32_t i) noexcept
|
||||
{
|
||||
return (((uint64_t)t << 32U) | (uint64_t)i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the peer represented by this Membership owns a given address
|
||||
|
@ -97,12 +97,11 @@ public:
|
|||
* @param r Resource to check
|
||||
* @return True if this peer has a certificate of ownership for the given resource
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf, const T &r) const noexcept
|
||||
template <typename T> ZT_INLINE bool peerOwnsAddress(const NetworkConfig& nconf, const T& r) const noexcept
|
||||
{
|
||||
if (m_isUnspoofableAddress(nconf, r))
|
||||
return true;
|
||||
for (Map< uint32_t, OwnershipCredential >::const_iterator i(m_remoteCoos.begin()); i != m_remoteCoos.end(); ++i) {
|
||||
for (Map<uint32_t, OwnershipCredential>::const_iterator i(m_remoteCoos.begin()); i != m_remoteCoos.end(); ++i) {
|
||||
if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r)))
|
||||
return true;
|
||||
}
|
||||
|
@ -114,9 +113,10 @@ public:
|
|||
*
|
||||
* @param localCom
|
||||
*/
|
||||
ZT_INLINE bool certificateOfMembershipAgress(const MembershipCredential &localCom, const Identity &remoteIdentity)
|
||||
ZT_INLINE bool certificateOfMembershipAgress(const MembershipCredential& localCom, const Identity& remoteIdentity)
|
||||
{
|
||||
if ((m_comAgreementLocalTimestamp == localCom.timestamp()) && (m_comAgreementRemoteTimestamp == m_com.timestamp()))
|
||||
if ((m_comAgreementLocalTimestamp == localCom.timestamp())
|
||||
&& (m_comAgreementRemoteTimestamp == m_com.timestamp()))
|
||||
return true;
|
||||
if (m_com.agreesWith(localCom)) {
|
||||
// SECURITY: newer network controllers embed the full fingerprint into the COM. If we are
|
||||
|
@ -129,7 +129,8 @@ public:
|
|||
if (localCom.issuedTo().haveHash()) {
|
||||
if (localCom.issuedTo() != m_com.issuedTo())
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// LEGACY: support networks run by old controllers.
|
||||
if (localCom.issuedTo().address != m_com.issuedTo().address)
|
||||
return false;
|
||||
|
@ -145,41 +146,70 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const MembershipCredential& com);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const TagCredential& tag);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const CapabilityCredential& cap);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const OwnershipCredential& coo);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const RevocationCredential& rev);
|
||||
|
||||
private:
|
||||
private:
|
||||
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
|
||||
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
|
||||
// always return true for them. A certificate is not required for these.
|
||||
ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept
|
||||
{ return false; }
|
||||
ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig& nconf, const MAC& m) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept;
|
||||
bool m_isUnspoofableAddress(const NetworkConfig& nconf, const InetAddress& ip) const noexcept;
|
||||
|
||||
// This compares the remote credential's timestamp to the timestamp in our network config
|
||||
// plus or minus the permitted maximum timestamp delta.
|
||||
template< typename C >
|
||||
ZT_INLINE bool m_isCredentialTimestampValid(const NetworkConfig &nconf, const C &remoteCredential) const noexcept
|
||||
template <typename C>
|
||||
ZT_INLINE bool m_isCredentialTimestampValid(const NetworkConfig& nconf, const C& remoteCredential) const noexcept
|
||||
{
|
||||
const int64_t ts = remoteCredential.revision();
|
||||
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) {
|
||||
Map< uint64_t, int64_t >::const_iterator threshold(m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id())));
|
||||
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts))
|
||||
<= nconf.credentialTimeMaxDelta) {
|
||||
Map<uint64_t, int64_t>::const_iterator threshold(
|
||||
m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id())));
|
||||
return ((threshold == m_revocations.end()) || (ts > threshold->second));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template< typename C >
|
||||
ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map< uint32_t, C > &remoteCreds)
|
||||
template <typename C> ZT_INLINE void m_cleanCredImpl(const NetworkConfig& nconf, Map<uint32_t, C>& remoteCreds)
|
||||
{
|
||||
for (typename Map< uint32_t, C >::iterator i(remoteCreds.begin()); i != remoteCreds.end();) {
|
||||
if (!m_isCredentialTimestampValid(nconf, i->second))
|
||||
for (typename Map<uint32_t, C>::iterator i(remoteCreds.begin()); i != remoteCreds.end();) {
|
||||
if (! m_isCredentialTimestampValid(nconf, i->second))
|
||||
remoteCreds.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,27 +226,27 @@ private:
|
|||
MembershipCredential m_com;
|
||||
|
||||
// Revocations by credentialKey()
|
||||
Map< uint64_t, int64_t > m_revocations;
|
||||
Map<uint64_t, int64_t> m_revocations;
|
||||
|
||||
// Remote credentials that we have received from this member (and that are valid)
|
||||
Map< uint32_t, TagCredential > m_remoteTags;
|
||||
Map< uint32_t, CapabilityCredential > m_remoteCaps;
|
||||
Map< uint32_t, OwnershipCredential > m_remoteCoos;
|
||||
Map<uint32_t, TagCredential> m_remoteTags;
|
||||
Map<uint32_t, CapabilityCredential> m_remoteCaps;
|
||||
Map<uint32_t, OwnershipCredential> m_remoteCoos;
|
||||
|
||||
public:
|
||||
class CapabilityIterator
|
||||
{
|
||||
public:
|
||||
ZT_INLINE CapabilityIterator(Member &m, const NetworkConfig &nconf) noexcept:
|
||||
m_hti(m.m_remoteCaps.begin()),
|
||||
m_parent(m),
|
||||
m_nconf(nconf)
|
||||
{}
|
||||
class CapabilityIterator {
|
||||
public:
|
||||
ZT_INLINE CapabilityIterator(Member& m, const NetworkConfig& nconf) noexcept
|
||||
: m_hti(m.m_remoteCaps.begin())
|
||||
, m_parent(m)
|
||||
, m_nconf(nconf)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE CapabilityCredential *next() noexcept
|
||||
ZT_INLINE CapabilityCredential* next() noexcept
|
||||
{
|
||||
while (m_hti != m_parent.m_remoteCaps.end()) {
|
||||
Map< uint32_t, CapabilityCredential >::iterator i(m_hti++);
|
||||
Map<uint32_t, CapabilityCredential>::iterator i(m_hti++);
|
||||
if (m_parent.m_isCredentialTimestampValid(m_nconf, i->second))
|
||||
return &(i->second);
|
||||
}
|
||||
|
@ -224,9 +254,9 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
Map< uint32_t, CapabilityCredential >::iterator m_hti;
|
||||
Member &m_parent;
|
||||
const NetworkConfig &m_nconf;
|
||||
Map<uint32_t, CapabilityCredential>::iterator m_hti;
|
||||
Member& m_parent;
|
||||
const NetworkConfig& m_nconf;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -15,15 +15,21 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
MembershipCredential::MembershipCredential(const int64_t timestamp, const int64_t timestampMaxDelta, const uint64_t nwid, const Identity &issuedTo) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_timestamp(timestamp),
|
||||
m_timestampMaxDelta(timestampMaxDelta),
|
||||
m_networkId(nwid),
|
||||
m_issuedTo(issuedTo.fingerprint()),
|
||||
m_signatureLength(0)
|
||||
{}
|
||||
MembershipCredential::MembershipCredential(
|
||||
const int64_t timestamp,
|
||||
const int64_t timestampMaxDelta,
|
||||
const uint64_t nwid,
|
||||
const Identity& issuedTo) noexcept
|
||||
: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_timestamp(timestamp)
|
||||
, m_timestampMaxDelta(timestampMaxDelta)
|
||||
, m_networkId(nwid)
|
||||
, m_issuedTo(issuedTo.fingerprint())
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool MembershipCredential::agreesWith(const MembershipCredential &other) const noexcept
|
||||
bool MembershipCredential::agreesWith(const MembershipCredential& other) const noexcept
|
||||
{
|
||||
// NOTE: we always do explicit absolute value with an if() since llabs() can have overflow
|
||||
// conditions that could introduce a vulnerability.
|
||||
|
@ -31,27 +37,35 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
|||
if (other.m_timestamp > m_timestamp) {
|
||||
if ((other.m_timestamp - m_timestamp) > std::min(m_timestampMaxDelta, other.m_timestampMaxDelta))
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((m_timestamp - other.m_timestamp) > std::min(m_timestampMaxDelta, other.m_timestampMaxDelta))
|
||||
return false;
|
||||
}
|
||||
|
||||
// us <> them
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin()); i != m_additionalQualifiers.end(); ++i) {
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(
|
||||
m_additionalQualifiers.begin());
|
||||
i != m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (i->delta != 0xffffffffffffffffULL) {
|
||||
const uint64_t *v2 = nullptr;
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(other.m_additionalQualifiers.begin()); j != other.m_additionalQualifiers.end(); ++i) {
|
||||
const uint64_t* v2 = nullptr;
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(
|
||||
other.m_additionalQualifiers.begin());
|
||||
j != other.m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (j->id == i->id) {
|
||||
v2 = &(j->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!v2)
|
||||
if (! v2)
|
||||
return false;
|
||||
if (*v2 > i->value) {
|
||||
if ((*v2 - i->value) > i->delta)
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((i->value - *v2) > i->delta)
|
||||
return false;
|
||||
}
|
||||
|
@ -59,21 +73,28 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
|||
}
|
||||
|
||||
// them <> us (we need a second pass in case they have qualifiers we don't or vice versa)
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(other.m_additionalQualifiers.begin()); i != other.m_additionalQualifiers.end(); ++i) {
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(
|
||||
other.m_additionalQualifiers.begin());
|
||||
i != other.m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (i->delta != 0xffffffffffffffffULL) {
|
||||
const uint64_t *v2 = nullptr;
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(m_additionalQualifiers.begin()); j != m_additionalQualifiers.end(); ++i) {
|
||||
const uint64_t* v2 = nullptr;
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(
|
||||
m_additionalQualifiers.begin());
|
||||
j != m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (j->id == i->id) {
|
||||
v2 = &(j->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!v2)
|
||||
if (! v2)
|
||||
return false;
|
||||
if (*v2 > i->value) {
|
||||
if ((*v2 - i->value) > i->delta)
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((i->value - *v2) > i->delta)
|
||||
return false;
|
||||
}
|
||||
|
@ -85,7 +106,7 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
|||
return (other.m_networkId == m_networkId) && (m_networkId != 0) && (other.m_issuedTo.address != m_issuedTo.address);
|
||||
}
|
||||
|
||||
bool MembershipCredential::sign(const Identity &with) noexcept
|
||||
bool MembershipCredential::sign(const Identity& with) noexcept
|
||||
{
|
||||
m_signedBy = with.address();
|
||||
uint64_t buf[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX / 8];
|
||||
|
@ -102,14 +123,14 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
|
|||
// equality compare, and the address of the issued-to node as an informational tuple.
|
||||
int p = 3;
|
||||
Utils::storeBigEndian<uint64_t>(data + p, 0);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, (uint64_t) m_timestamp);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 16, (uint64_t) m_timestampMaxDelta);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, (uint64_t)m_timestamp);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 16, (uint64_t)m_timestampMaxDelta);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 24, 1);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 32, m_networkId);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 40, 0);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 48, 2);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 56, m_issuedTo.address);
|
||||
Utils::storeMachineEndian< uint64_t >(data + p + 64, 0xffffffffffffffffULL);
|
||||
Utils::storeMachineEndian<uint64_t>(data + p + 64, 0xffffffffffffffffULL);
|
||||
p += 72;
|
||||
|
||||
if (v2) {
|
||||
|
@ -117,13 +138,16 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
|
|||
Utils::storeBigEndian<uint16_t>(data + 1, 3);
|
||||
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(data + p, m_issuedTo.hash);
|
||||
p += 48;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// V1 marshal format must shove everything into tuples, resulting in nine.
|
||||
Utils::storeBigEndian<uint16_t>(data + 1, 9);
|
||||
for (int k = 0;k < 6;++k) {
|
||||
Utils::storeBigEndian<uint64_t>(data + p, (uint64_t) k + 3);
|
||||
Utils::storeMachineEndian< uint64_t >(data + p + 8, Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + (k * 8)));
|
||||
Utils::storeMachineEndian< uint64_t >(data + p + 16, 0xffffffffffffffffULL);
|
||||
for (int k = 0; k < 6; ++k) {
|
||||
Utils::storeBigEndian<uint64_t>(data + p, (uint64_t)k + 3);
|
||||
Utils::storeMachineEndian<uint64_t>(
|
||||
data + p + 8,
|
||||
Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash + (k * 8)));
|
||||
Utils::storeMachineEndian<uint64_t>(data + p + 16, 0xffffffffffffffffULL);
|
||||
p += 24;
|
||||
}
|
||||
}
|
||||
|
@ -133,11 +157,12 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
|
|||
|
||||
if (v2) {
|
||||
// V2 marshal format prefixes signatures with a 16-bit length to support future signature types.
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_signatureLength);
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_signatureLength);
|
||||
p += 2;
|
||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||
p += (int)m_signatureLength;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// V1 only supports 96-byte signature fields.
|
||||
Utils::copy<96>(data + p, m_signature);
|
||||
p += 96;
|
||||
|
@ -146,7 +171,7 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
|
|||
return p;
|
||||
}
|
||||
|
||||
int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
||||
int MembershipCredential::unmarshal(const uint8_t* data, int len) noexcept
|
||||
{
|
||||
if (len < (1 + 2 + 72))
|
||||
return -1;
|
||||
|
@ -157,7 +182,7 @@ int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
if ((numq < 3) || (numq > (ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS + 3)))
|
||||
return -1;
|
||||
int p = 3;
|
||||
for (unsigned int q = 0;q < numq;++q) {
|
||||
for (unsigned int q = 0; q < numq; ++q) {
|
||||
if ((p + 24) > len)
|
||||
return -1;
|
||||
const uint64_t id = Utils::loadBigEndian<uint64_t>(data + p);
|
||||
|
@ -168,8 +193,8 @@ int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
switch (id) {
|
||||
case 0:
|
||||
m_timestamp = (int64_t) value;
|
||||
m_timestampMaxDelta = (int64_t) delta;
|
||||
m_timestamp = (int64_t)value;
|
||||
m_timestampMaxDelta = (int64_t)delta;
|
||||
break;
|
||||
case 1:
|
||||
m_networkId = value;
|
||||
|
@ -214,7 +239,8 @@ int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
m_signatureLength = 96;
|
||||
Utils::copy<96>(m_signature, data + p);
|
||||
return p + 96;
|
||||
} else if (data[0] == 2) {
|
||||
}
|
||||
else if (data[0] == 2) {
|
||||
if ((p + 48) > len)
|
||||
return -1;
|
||||
Utils::copy<48>(m_issuedTo.hash, data + p);
|
||||
|
@ -222,16 +248,16 @@ int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
if ((p + 2) > len)
|
||||
return -1;
|
||||
m_signatureLength = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
if ((m_signatureLength > (unsigned int) sizeof(m_signature)) || ((p + (int) m_signatureLength) > len))
|
||||
if ((m_signatureLength > (unsigned int)sizeof(m_signature)) || ((p + (int)m_signatureLength) > len))
|
||||
return -1;
|
||||
Utils::copy(m_signature, data + p, m_signatureLength);
|
||||
return p + (int) m_signatureLength;
|
||||
return p + (int)m_signatureLength;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int MembershipCredential::m_fillSigningBuf(uint64_t *buf) const noexcept
|
||||
unsigned int MembershipCredential::m_fillSigningBuf(uint64_t* buf) const noexcept
|
||||
{
|
||||
const uint64_t informational = 0xffffffffffffffffULL;
|
||||
|
||||
|
@ -243,8 +269,8 @@ unsigned int MembershipCredential::m_fillSigningBuf(uint64_t *buf) const noexcep
|
|||
|
||||
// The standard three tuples that must begin every COM.
|
||||
buf[0] = 0;
|
||||
buf[1] = Utils::hton((uint64_t) m_timestamp);
|
||||
buf[2] = Utils::hton((uint64_t) m_timestampMaxDelta);
|
||||
buf[1] = Utils::hton((uint64_t)m_timestamp);
|
||||
buf[2] = Utils::hton((uint64_t)m_timestampMaxDelta);
|
||||
buf[3] = ZT_CONST_TO_BE_UINT64(1);
|
||||
buf[4] = Utils::hton(m_networkId);
|
||||
buf[5] = 0;
|
||||
|
@ -258,26 +284,29 @@ unsigned int MembershipCredential::m_fillSigningBuf(uint64_t *buf) const noexcep
|
|||
// embeded as a series of informational tuples.
|
||||
if (m_issuedTo.haveHash()) {
|
||||
buf[p++] = ZT_CONST_TO_BE_UINT64(3);
|
||||
buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash);
|
||||
buf[p++] = Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash);
|
||||
buf[p++] = informational;
|
||||
buf[p++] = ZT_CONST_TO_BE_UINT64(4);
|
||||
buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 8);
|
||||
buf[p++] = Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash + 8);
|
||||
buf[p++] = informational;
|
||||
buf[p++] = ZT_CONST_TO_BE_UINT64(5);
|
||||
buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 16);
|
||||
buf[p++] = Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash + 16);
|
||||
buf[p++] = informational;
|
||||
buf[p++] = ZT_CONST_TO_BE_UINT64(6);
|
||||
buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 24);
|
||||
buf[p++] = Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash + 24);
|
||||
buf[p++] = informational;
|
||||
buf[p++] = ZT_CONST_TO_BE_UINT64(7);
|
||||
buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 32);
|
||||
buf[p++] = Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash + 32);
|
||||
buf[p++] = informational;
|
||||
buf[p++] = ZT_CONST_TO_BE_UINT64(8);
|
||||
buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 40);
|
||||
buf[p++] = Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash + 40);
|
||||
buf[p++] = informational;
|
||||
}
|
||||
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin()); i != m_additionalQualifiers.end(); ++i) { // NOLINT(modernize-loop-convert)
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(
|
||||
m_additionalQualifiers.begin());
|
||||
i != m_additionalQualifiers.end();
|
||||
++i) { // NOLINT(modernize-loop-convert)
|
||||
buf[p++] = Utils::hton(i->id);
|
||||
buf[p++] = Utils::hton(i->value);
|
||||
buf[p++] = Utils::hton(i->delta);
|
||||
|
|
|
@ -14,23 +14,24 @@
|
|||
#ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP
|
||||
#define ZT_CERTIFICATEOFMEMBERSHIP_HPP
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "FCV.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
// Maximum number of additional tuples beyond the standard always-present three.
|
||||
#define ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS 8
|
||||
|
||||
// version + qualifier count + three required qualifiers + additional qualifiers +
|
||||
#define ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX (1 + 2 + (3 * 3 * 8) + (ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS * 3 * 8) + 144 + 5 + 2 + 96)
|
||||
#define ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX \
|
||||
(1 + 2 + (3 * 3 * 8) + (ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS * 3 * 8) + 144 + 5 + 2 + 96)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -96,19 +97,22 @@ class Context;
|
|||
* order with the fingerprint hash being packed into tuple IDs 3-8 and this buffer is
|
||||
* then signed.
|
||||
*/
|
||||
class MembershipCredential : public Credential
|
||||
{
|
||||
class MembershipCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_COM; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_COM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty certificate of membership
|
||||
*/
|
||||
ZT_INLINE MembershipCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from required fields common to all networks
|
||||
|
@ -118,46 +122,61 @@ public:
|
|||
* @param nwid Network ID
|
||||
* @param issuedTo Certificate recipient
|
||||
*/
|
||||
MembershipCredential(int64_t timestamp, int64_t timestampMaxDelta, uint64_t nwid, const Identity &issuedTo) noexcept;
|
||||
MembershipCredential(int64_t timestamp, int64_t timestampMaxDelta, uint64_t nwid, const Identity& issuedTo)
|
||||
noexcept;
|
||||
|
||||
/**
|
||||
* @return True if there's something here
|
||||
*/
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_networkId != 0); }
|
||||
{
|
||||
return (m_networkId != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Credential ID, always 0 for COMs
|
||||
*/
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return 0; }
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Timestamp for this cert and maximum delta for timestamp
|
||||
*/
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum allowed difference between timestamps
|
||||
*/
|
||||
ZT_INLINE int64_t timestampMaxDelta() const noexcept
|
||||
{ return m_timestampMaxDelta; }
|
||||
{
|
||||
return m_timestampMaxDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Fingerprint of identity to which this cert was issued
|
||||
*/
|
||||
ZT_INLINE const Fingerprint &issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
ZT_INLINE const Fingerprint& issuedTo() const noexcept
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Network ID for which this cert was issued
|
||||
*/
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
{
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two certificates for parameter agreement
|
||||
|
@ -172,7 +191,7 @@ public:
|
|||
* @param other Cert to compare with
|
||||
* @return True if certs agree and 'other' may be communicated with
|
||||
*/
|
||||
bool agreesWith(const MembershipCredential &other) const noexcept;
|
||||
bool agreesWith(const MembershipCredential& other) const noexcept;
|
||||
|
||||
/**
|
||||
* Sign this certificate
|
||||
|
@ -180,7 +199,7 @@ public:
|
|||
* @param with Identity to sign with, must include private key
|
||||
* @return True if signature was successful
|
||||
*/
|
||||
bool sign(const Identity &with) noexcept;
|
||||
bool sign(const Identity& with) noexcept;
|
||||
|
||||
/**
|
||||
* Verify this COM and its signature
|
||||
|
@ -188,34 +207,47 @@ public:
|
|||
* @param RR Runtime environment for looking up peers
|
||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context &ctx, const CallContext &cc) const
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX], bool v2 = false) const noexcept;
|
||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
||||
private:
|
||||
unsigned int m_fillSigningBuf(uint64_t *buf) const noexcept;
|
||||
private:
|
||||
unsigned int m_fillSigningBuf(uint64_t* buf) const noexcept;
|
||||
|
||||
struct p_Qualifier
|
||||
struct p_Qualifier {
|
||||
ZT_INLINE p_Qualifier() noexcept
|
||||
: id(0)
|
||||
, value(0)
|
||||
, delta(0)
|
||||
{
|
||||
ZT_INLINE p_Qualifier() noexcept: id(0), value(0), delta(0)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE p_Qualifier(const uint64_t id_, const uint64_t value_, const uint64_t delta_) noexcept: id(id_), value(value_), delta(delta_)
|
||||
{}
|
||||
ZT_INLINE p_Qualifier(const uint64_t id_, const uint64_t value_, const uint64_t delta_) noexcept
|
||||
: id(id_)
|
||||
, value(value_)
|
||||
, delta(delta_)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t id;
|
||||
uint64_t value;
|
||||
uint64_t delta;
|
||||
ZT_INLINE bool operator<(const p_Qualifier &q) const noexcept
|
||||
{ return (id < q.id); } // sort order
|
||||
ZT_INLINE bool operator<(const p_Qualifier& q) const noexcept
|
||||
{
|
||||
return (id < q.id);
|
||||
} // sort order
|
||||
};
|
||||
|
||||
FCV< p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS > m_additionalQualifiers;
|
||||
FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS> m_additionalQualifiers;
|
||||
int64_t m_timestamp;
|
||||
int64_t m_timestampMaxDelta;
|
||||
uint64_t m_networkId;
|
||||
|
|
|
@ -34,17 +34,16 @@ namespace ZeroTier {
|
|||
* @tparam TUNIT Unit of time in milliseconds (default: 1000 for one second)
|
||||
* @tparam LSIZE Log size in units of time (default: 10 for 10s worth of data)
|
||||
*/
|
||||
template<int64_t TUNIT = 1000, unsigned long LSIZE = 10>
|
||||
class Meter
|
||||
{
|
||||
public:
|
||||
template <int64_t TUNIT = 1000, unsigned long LSIZE = 10> class Meter {
|
||||
public:
|
||||
/**
|
||||
* Create and initialize a new meter
|
||||
*
|
||||
* @param now Start time
|
||||
*/
|
||||
ZT_INLINE Meter() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a measurement
|
||||
|
@ -59,8 +58,11 @@ public:
|
|||
// to it.
|
||||
const unsigned long bucket = ((unsigned long)(ts / TUNIT)) % LSIZE;
|
||||
if (unlikely(m_bucket.exchange(bucket, std::memory_order_relaxed) != bucket)) {
|
||||
m_totalExclCounts.fetch_add(m_counts[bucket].exchange(count, std::memory_order_relaxed), std::memory_order_relaxed);
|
||||
} else {
|
||||
m_totalExclCounts.fetch_add(
|
||||
m_counts[bucket].exchange(count, std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
else {
|
||||
m_counts[bucket].fetch_add(count, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
@ -72,16 +74,16 @@ public:
|
|||
* @param rate Result parameter: rate in count/TUNIT
|
||||
* @param total Total count for life of object
|
||||
*/
|
||||
ZT_INLINE void rate(double &rate, uint64_t &total) const noexcept
|
||||
ZT_INLINE void rate(double& rate, uint64_t& total) const noexcept
|
||||
{
|
||||
total = 0;
|
||||
for (unsigned long i = 0;i < LSIZE;++i)
|
||||
for (unsigned long i = 0; i < LSIZE; ++i)
|
||||
total += m_counts[i].load(std::memory_order_relaxed);
|
||||
rate = (double) total / (double) LSIZE;
|
||||
rate = (double)total / (double)LSIZE;
|
||||
total += m_totalExclCounts.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
std::atomic<uint64_t> m_counts[LSIZE];
|
||||
std::atomic<uint64_t> m_totalExclCounts;
|
||||
std::atomic<unsigned long> m_bucket;
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#define ZT_MULTICASTGROUP_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,14 +37,19 @@ namespace ZeroTier {
|
|||
*
|
||||
* MulticastGroup behaves as an immutable value object.
|
||||
*/
|
||||
class MulticastGroup : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
ZT_INLINE MulticastGroup() noexcept: m_mac(), m_adi(0)
|
||||
{}
|
||||
class MulticastGroup : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE MulticastGroup() noexcept
|
||||
: m_mac()
|
||||
, m_adi(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE MulticastGroup(const MAC &m, uint32_t a) noexcept: m_mac(m), m_adi(a)
|
||||
{}
|
||||
ZT_INLINE MulticastGroup(const MAC& m, uint32_t a) noexcept
|
||||
: m_mac(m)
|
||||
, m_adi(a)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
||||
|
@ -52,20 +57,22 @@ public:
|
|||
* @param ip IP address (port field is ignored)
|
||||
* @return Multicast group for ARP/NDP
|
||||
*/
|
||||
static ZT_INLINE MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress &ip) noexcept
|
||||
static ZT_INLINE MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress& ip) noexcept
|
||||
{
|
||||
if (ip.isV4()) {
|
||||
// IPv4 wants broadcast MACs, so we shove the V4 address itself into
|
||||
// the Multicast Group ADI field. Making V4 ARP work is basically why
|
||||
// ADI was added, as well as handling other things that want mindless
|
||||
// Ethernet broadcast to all.
|
||||
return MulticastGroup(MAC(0xffffffffffffULL), Utils::ntoh(*((const uint32_t *)ip.rawIpData())));
|
||||
} else if (ip.isV6()) {
|
||||
return MulticastGroup(MAC(0xffffffffffffULL), Utils::ntoh(*((const uint32_t*)ip.rawIpData())));
|
||||
}
|
||||
else if (ip.isV6()) {
|
||||
// IPv6 is better designed in this respect. We can compute the IPv6
|
||||
// multicast address directly from the IP address, and it gives us
|
||||
// 24 bits of uniqueness. Collisions aren't likely to be common enough
|
||||
// to care about.
|
||||
const uint8_t *const a = reinterpret_cast<const uint8_t *>(ip.rawIpData()); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
const uint8_t* const a =
|
||||
reinterpret_cast<const uint8_t*>(ip.rawIpData()); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
return MulticastGroup(MAC(0x33, 0x33, 0xff, a[13], a[14], a[15]), 0);
|
||||
}
|
||||
return MulticastGroup(); // NOLINT(modernize-return-braced-init-list)
|
||||
|
@ -74,22 +81,31 @@ public:
|
|||
/**
|
||||
* @return Ethernet MAC portion of multicast group
|
||||
*/
|
||||
ZT_INLINE const MAC &mac() const noexcept
|
||||
{ return m_mac; }
|
||||
ZT_INLINE const MAC& mac() const noexcept
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Additional distinguishing information, which is normally zero except for IPv4 ARP where it's the IPv4 address
|
||||
* @return Additional distinguishing information, which is normally zero except for IPv4 ARP where it's the IPv4
|
||||
* address
|
||||
*/
|
||||
ZT_INLINE uint32_t adi() const
|
||||
{ return m_adi; }
|
||||
{
|
||||
return m_adi;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const MulticastGroup &g) const noexcept
|
||||
{ return ((m_mac == g.m_mac) && (m_adi == g.m_adi)); }
|
||||
ZT_INLINE bool operator==(const MulticastGroup& g) const noexcept
|
||||
{
|
||||
return ((m_mac == g.m_mac) && (m_adi == g.m_adi));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const MulticastGroup &g) const noexcept
|
||||
{ return ((m_mac != g.m_mac) || (m_adi != g.m_adi)); }
|
||||
ZT_INLINE bool operator!=(const MulticastGroup& g) const noexcept
|
||||
{
|
||||
return ((m_mac != g.m_mac) || (m_adi != g.m_adi));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const MulticastGroup &g) const noexcept
|
||||
ZT_INLINE bool operator<(const MulticastGroup& g) const noexcept
|
||||
{
|
||||
if (m_mac < g.m_mac)
|
||||
return true;
|
||||
|
@ -98,19 +114,27 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const MulticastGroup &g) const noexcept
|
||||
{ return (g < *this); }
|
||||
ZT_INLINE bool operator>(const MulticastGroup& g) const noexcept
|
||||
{
|
||||
return (g < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const MulticastGroup &g) const noexcept
|
||||
{ return !(g < *this); }
|
||||
ZT_INLINE bool operator<=(const MulticastGroup& g) const noexcept
|
||||
{
|
||||
return ! (g < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const MulticastGroup &g) const noexcept
|
||||
{ return !(*this < g); }
|
||||
ZT_INLINE bool operator>=(const MulticastGroup& g) const noexcept
|
||||
{
|
||||
return ! (*this < g);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (m_mac.hashCode() + (unsigned long)m_adi); }
|
||||
{
|
||||
return (m_mac.hashCode() + (unsigned long)m_adi);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
MAC m_mac;
|
||||
uint32_t m_adi;
|
||||
};
|
||||
|
|
234
core/Mutex.hpp
234
core/Mutex.hpp
|
@ -36,33 +36,66 @@ namespace ZeroTier {
|
|||
/**
|
||||
* A simple mutual exclusion lock.
|
||||
*/
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
class Mutex {
|
||||
public:
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
ZT_INLINE Mutex() noexcept { pthread_mutex_init(&_mh,nullptr); }
|
||||
ZT_INLINE ~Mutex() noexcept { pthread_mutex_destroy(&_mh); }
|
||||
ZT_INLINE void lock() const noexcept { pthread_mutex_lock(&((const_cast <Mutex *> (this))->_mh)); }
|
||||
ZT_INLINE void unlock() const noexcept { pthread_mutex_unlock(&((const_cast <Mutex *> (this))->_mh)); }
|
||||
ZT_INLINE Mutex() noexcept
|
||||
{
|
||||
pthread_mutex_init(&_mh, nullptr);
|
||||
}
|
||||
ZT_INLINE ~Mutex() noexcept
|
||||
{
|
||||
pthread_mutex_destroy(&_mh);
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
pthread_mutex_lock(&((const_cast<Mutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
pthread_mutex_unlock(&((const_cast<Mutex*>(this))->_mh));
|
||||
}
|
||||
#else
|
||||
ZT_INLINE Mutex() noexcept : _m() {}
|
||||
ZT_INLINE void lock() const noexcept { const_cast<Mutex *>(this)->_m.lock(); }
|
||||
ZT_INLINE void unlock() const noexcept { const_cast<Mutex *>(this)->_m.unlock(); }
|
||||
ZT_INLINE Mutex() noexcept : _m()
|
||||
{
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
const_cast<Mutex*>(this)->_m.lock();
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
const_cast<Mutex*>(this)->_m.unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
class Lock
|
||||
{
|
||||
class Lock {
|
||||
public:
|
||||
explicit ZT_INLINE Lock(Mutex &m) noexcept : _m(&m) { m.lock(); }
|
||||
explicit ZT_INLINE Lock(const Mutex &m) noexcept : _m(const_cast<Mutex *>(&m)) { _m->lock(); }
|
||||
ZT_INLINE ~Lock() { _m->unlock(); }
|
||||
explicit ZT_INLINE Lock(Mutex& m) noexcept : _m(&m)
|
||||
{
|
||||
m.lock();
|
||||
}
|
||||
explicit ZT_INLINE Lock(const Mutex& m) noexcept : _m(const_cast<Mutex*>(&m))
|
||||
{
|
||||
_m->lock();
|
||||
}
|
||||
ZT_INLINE ~Lock()
|
||||
{
|
||||
_m->unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex *const _m;
|
||||
Mutex* const _m;
|
||||
};
|
||||
|
||||
private:
|
||||
ZT_INLINE Mutex(const Mutex &) noexcept {}
|
||||
ZT_INLINE const Mutex &operator=(const Mutex &) noexcept { return *this; }
|
||||
private:
|
||||
ZT_INLINE Mutex(const Mutex&) noexcept
|
||||
{
|
||||
}
|
||||
ZT_INLINE const Mutex& operator=(const Mutex&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
pthread_mutex_t _mh;
|
||||
|
@ -74,48 +107,97 @@ private:
|
|||
/**
|
||||
* A lock allowing multiple threads to read but making all wait on any writing thread.
|
||||
*/
|
||||
class RWMutex
|
||||
{
|
||||
public:
|
||||
class RWMutex {
|
||||
public:
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
ZT_INLINE RWMutex() noexcept { pthread_rwlock_init(&_mh,nullptr); }
|
||||
ZT_INLINE ~RWMutex() noexcept { pthread_rwlock_destroy(&_mh); }
|
||||
ZT_INLINE void lock() const noexcept { pthread_rwlock_wrlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE void rlock() const noexcept { pthread_rwlock_rdlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE void unlock() const noexcept { pthread_rwlock_unlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE void runlock() const noexcept { pthread_rwlock_unlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE RWMutex() noexcept
|
||||
{
|
||||
pthread_rwlock_init(&_mh, nullptr);
|
||||
}
|
||||
ZT_INLINE ~RWMutex() noexcept
|
||||
{
|
||||
pthread_rwlock_destroy(&_mh);
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
pthread_rwlock_wrlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void rlock() const noexcept
|
||||
{
|
||||
pthread_rwlock_rdlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
pthread_rwlock_unlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void runlock() const noexcept
|
||||
{
|
||||
pthread_rwlock_unlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
#else
|
||||
ZT_INLINE RWMutex() noexcept : _m() {}
|
||||
ZT_INLINE void lock() const noexcept { const_cast<RWMutex *>(this)->_m.lock(); }
|
||||
ZT_INLINE void rlock() const noexcept { const_cast<RWMutex *>(this)->_m.lock_shared(); }
|
||||
ZT_INLINE void unlock() const noexcept { const_cast<RWMutex *>(this)->_m.unlock(); }
|
||||
ZT_INLINE void runlock() const noexcept { const_cast<RWMutex *>(this)->_m.unlock_shared(); }
|
||||
ZT_INLINE RWMutex() noexcept : _m()
|
||||
{
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.lock();
|
||||
}
|
||||
ZT_INLINE void rlock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.lock_shared();
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.unlock();
|
||||
}
|
||||
ZT_INLINE void runlock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.unlock_shared();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* RAAI locker that acquires only the read lock (shared read)
|
||||
*/
|
||||
class RLock
|
||||
{
|
||||
class RLock {
|
||||
public:
|
||||
explicit ZT_INLINE RLock(RWMutex &m) noexcept : _m(&m) { m.rlock(); }
|
||||
explicit ZT_INLINE RLock(const RWMutex &m) noexcept : _m(const_cast<RWMutex *>(&m)) { _m->rlock(); }
|
||||
ZT_INLINE ~RLock() { _m->runlock(); }
|
||||
explicit ZT_INLINE RLock(RWMutex& m) noexcept : _m(&m)
|
||||
{
|
||||
m.rlock();
|
||||
}
|
||||
explicit ZT_INLINE RLock(const RWMutex& m) noexcept : _m(const_cast<RWMutex*>(&m))
|
||||
{
|
||||
_m->rlock();
|
||||
}
|
||||
ZT_INLINE ~RLock()
|
||||
{
|
||||
_m->runlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWMutex *const _m;
|
||||
RWMutex* const _m;
|
||||
};
|
||||
|
||||
/**
|
||||
* RAAI locker that acquires the write lock (exclusive write, no readers)
|
||||
*/
|
||||
class Lock
|
||||
{
|
||||
class Lock {
|
||||
public:
|
||||
explicit ZT_INLINE Lock(RWMutex &m) noexcept : _m(&m) { m.lock(); }
|
||||
explicit ZT_INLINE Lock(const RWMutex &m) noexcept : _m(const_cast<RWMutex *>(&m)) { _m->lock(); }
|
||||
ZT_INLINE ~Lock() { _m->unlock(); }
|
||||
explicit ZT_INLINE Lock(RWMutex& m) noexcept : _m(&m)
|
||||
{
|
||||
m.lock();
|
||||
}
|
||||
explicit ZT_INLINE Lock(const RWMutex& m) noexcept : _m(const_cast<RWMutex*>(&m))
|
||||
{
|
||||
_m->lock();
|
||||
}
|
||||
ZT_INLINE ~Lock()
|
||||
{
|
||||
_m->unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWMutex *const _m;
|
||||
RWMutex* const _m;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -127,23 +209,61 @@ public:
|
|||
* transition, meaning protected variable states can change. Code must not assume
|
||||
* that the lock is held constantly if writing() is used to change mode.
|
||||
*/
|
||||
class RMaybeWLock
|
||||
{
|
||||
class RMaybeWLock {
|
||||
public:
|
||||
explicit ZT_INLINE RMaybeWLock(RWMutex &m) noexcept : _m(&m),_w(false) { m.rlock(); }
|
||||
explicit ZT_INLINE RMaybeWLock(const RWMutex &m) noexcept : _m(const_cast<RWMutex *>(&m)),_w(false) { _m->rlock(); }
|
||||
ZT_INLINE void writing() noexcept { if (!_w) { _w = true; _m->runlock(); _m->lock(); } }
|
||||
ZT_INLINE void reading() noexcept { if (_w) { _w = false; _m->unlock(); _m->rlock(); } }
|
||||
ZT_INLINE bool isWriting() const noexcept { return _w; }
|
||||
ZT_INLINE ~RMaybeWLock() { if (_w) _m->unlock(); else _m->runlock(); }
|
||||
explicit ZT_INLINE RMaybeWLock(RWMutex& m) noexcept
|
||||
: _m(&m)
|
||||
, _w(false)
|
||||
{
|
||||
m.rlock();
|
||||
}
|
||||
explicit ZT_INLINE RMaybeWLock(const RWMutex& m) noexcept
|
||||
: _m(const_cast<RWMutex*>(&m))
|
||||
, _w(false)
|
||||
{
|
||||
_m->rlock();
|
||||
}
|
||||
ZT_INLINE void writing() noexcept
|
||||
{
|
||||
if (! _w) {
|
||||
_w = true;
|
||||
_m->runlock();
|
||||
_m->lock();
|
||||
}
|
||||
}
|
||||
ZT_INLINE void reading() noexcept
|
||||
{
|
||||
if (_w) {
|
||||
_w = false;
|
||||
_m->unlock();
|
||||
_m->rlock();
|
||||
}
|
||||
}
|
||||
ZT_INLINE bool isWriting() const noexcept
|
||||
{
|
||||
return _w;
|
||||
}
|
||||
ZT_INLINE ~RMaybeWLock()
|
||||
{
|
||||
if (_w)
|
||||
_m->unlock();
|
||||
else
|
||||
_m->runlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWMutex *const _m;
|
||||
RWMutex* const _m;
|
||||
bool _w;
|
||||
};
|
||||
|
||||
private:
|
||||
ZT_INLINE RWMutex(const RWMutex &) noexcept {}
|
||||
ZT_INLINE const RWMutex &operator=(const RWMutex &) noexcept { return *this; }
|
||||
private:
|
||||
ZT_INLINE RWMutex(const RWMutex&) noexcept
|
||||
{
|
||||
}
|
||||
ZT_INLINE const RWMutex& operator=(const RWMutex&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
pthread_rwlock_t _mh;
|
||||
|
|
776
core/Network.cpp
776
core/Network.cpp
File diff suppressed because it is too large
Load diff
206
core/Network.hpp
206
core/Network.hpp
|
@ -14,19 +14,19 @@
|
|||
#ifndef ZT_NETWORK_HPP
|
||||
#define ZT_NETWORK_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Member.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Member.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
||||
#define ZT_NETWORK_MAX_INCOMING_UPDATES 3
|
||||
|
||||
|
@ -39,11 +39,10 @@ class Peer;
|
|||
/**
|
||||
* A virtual LAN
|
||||
*/
|
||||
class Network
|
||||
{
|
||||
friend class SharedPtr< Network >;
|
||||
class Network {
|
||||
friend class SharedPtr<Network>;
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Broadcast multicast group: ff:ff:ff:ff:ff:ff / 0
|
||||
*/
|
||||
|
@ -53,7 +52,9 @@ public:
|
|||
* Compute primary controller device ID from network ID
|
||||
*/
|
||||
static ZT_INLINE Address controllerFor(uint64_t nwid) noexcept
|
||||
{ return Address(nwid >> 24U); }
|
||||
{
|
||||
return Address(nwid >> 24U);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new network
|
||||
|
@ -67,38 +68,54 @@ public:
|
|||
* @param nconf Network config, if known
|
||||
*/
|
||||
Network(
|
||||
const Context &ctx,
|
||||
const CallContext &cc,
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
uint64_t nwid,
|
||||
const Fingerprint &controllerFingerprint,
|
||||
void *uptr,
|
||||
const NetworkConfig *nconf);
|
||||
const Fingerprint& controllerFingerprint,
|
||||
void* uptr,
|
||||
const NetworkConfig* nconf);
|
||||
|
||||
~Network();
|
||||
|
||||
ZT_INLINE uint64_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE Address controller() const noexcept
|
||||
{ return Address(m_id >> 24U); }
|
||||
{
|
||||
return Address(m_id >> 24U);
|
||||
}
|
||||
|
||||
ZT_INLINE bool multicastEnabled() const noexcept
|
||||
{ return (m_config.multicastLimit > 0); }
|
||||
{
|
||||
return (m_config.multicastLimit > 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool hasConfig() const noexcept
|
||||
{ return (m_config); }
|
||||
{
|
||||
return (m_config);
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t lastConfigUpdate() const noexcept
|
||||
{ return m_lastConfigUpdate; }
|
||||
{
|
||||
return m_lastConfigUpdate;
|
||||
}
|
||||
|
||||
ZT_INLINE ZT_VirtualNetworkStatus status() const noexcept
|
||||
{ return m_status(); }
|
||||
{
|
||||
return m_status();
|
||||
}
|
||||
|
||||
ZT_INLINE const NetworkConfig &config() const noexcept
|
||||
{ return m_config; }
|
||||
ZT_INLINE const NetworkConfig& config() const noexcept
|
||||
{
|
||||
return m_config;
|
||||
}
|
||||
|
||||
ZT_INLINE const MAC &mac() const noexcept
|
||||
{ return m_mac; }
|
||||
ZT_INLINE const MAC& mac() const noexcept
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters to an outgoing packet
|
||||
|
@ -120,17 +137,17 @@ public:
|
|||
* @return True if packet should be sent, false if dropped or redirected
|
||||
*/
|
||||
bool filterOutgoingPacket(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
bool noTee,
|
||||
const Address &ztSource,
|
||||
const Address &ztDest,
|
||||
const MAC &macSource,
|
||||
const MAC &macDest,
|
||||
const uint8_t *frameData,
|
||||
const Address& ztSource,
|
||||
const Address& ztDest,
|
||||
const MAC& macSource,
|
||||
const MAC& macDest,
|
||||
const uint8_t* frameData,
|
||||
unsigned int frameLen,
|
||||
unsigned int etherType,
|
||||
unsigned int vlanId,
|
||||
uint8_t &qosBucket);
|
||||
uint8_t& qosBucket);
|
||||
|
||||
/**
|
||||
* Apply filters to an incoming packet
|
||||
|
@ -151,12 +168,12 @@ public:
|
|||
* @return 0 == drop, 1 == accept, 2 == accept even if bridged
|
||||
*/
|
||||
int filterIncomingPacket(
|
||||
const CallContext &cc,
|
||||
const SharedPtr< Peer > &sourcePeer,
|
||||
const Address &ztDest,
|
||||
const MAC &macSource,
|
||||
const MAC &macDest,
|
||||
const uint8_t *frameData,
|
||||
const CallContext& cc,
|
||||
const SharedPtr<Peer>& sourcePeer,
|
||||
const Address& ztDest,
|
||||
const MAC& macSource,
|
||||
const MAC& macDest,
|
||||
const uint8_t* frameData,
|
||||
unsigned int frameLen,
|
||||
unsigned int etherType,
|
||||
unsigned int vlanId);
|
||||
|
@ -166,14 +183,14 @@ public:
|
|||
*
|
||||
* @param mg New multicast group
|
||||
*/
|
||||
void multicastSubscribe(const CallContext &cc, const MulticastGroup &mg);
|
||||
void multicastSubscribe(const CallContext& cc, const MulticastGroup& mg);
|
||||
|
||||
/**
|
||||
* Unsubscribe from a multicast group
|
||||
*
|
||||
* @param mg Multicast group
|
||||
*/
|
||||
void multicastUnsubscribe(const MulticastGroup &mg);
|
||||
void multicastUnsubscribe(const MulticastGroup& mg);
|
||||
|
||||
/**
|
||||
* Parse, verify, and handle an inbound network config chunk
|
||||
|
@ -191,10 +208,10 @@ public:
|
|||
* @return Update ID if update was fully assembled and accepted or 0 otherwise
|
||||
*/
|
||||
uint64_t handleConfigChunk(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
uint64_t packetId,
|
||||
const SharedPtr< Peer > &source,
|
||||
const Buf &chunk,
|
||||
const SharedPtr<Peer>& source,
|
||||
const Buf& chunk,
|
||||
int ptr,
|
||||
int size);
|
||||
|
||||
|
@ -209,22 +226,23 @@ public:
|
|||
* @param saveToDisk Save to disk? Used during loading, should usually be true otherwise.
|
||||
* @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new
|
||||
*/
|
||||
int setConfiguration(
|
||||
const CallContext &cc,
|
||||
const NetworkConfig &nconf,
|
||||
bool saveToDisk);
|
||||
int setConfiguration(const CallContext& cc, const NetworkConfig& nconf, bool saveToDisk);
|
||||
|
||||
/**
|
||||
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
|
||||
*/
|
||||
ZT_INLINE void setAccessDenied() noexcept
|
||||
{ _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED; }
|
||||
{
|
||||
_netconfFailure = NETCONF_FAILURE_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set netconf failure to 'not found' -- called by IncomingPacket when controller reports this
|
||||
*/
|
||||
ZT_INLINE void setNotFound() noexcept
|
||||
{ _netconfFailure = NETCONF_FAILURE_NOT_FOUND; }
|
||||
{
|
||||
_netconfFailure = NETCONF_FAILURE_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this peer is permitted to communicate on this network
|
||||
|
@ -232,12 +250,12 @@ public:
|
|||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
* @param peer Peer to check
|
||||
*/
|
||||
bool gate(void *tPtr, const SharedPtr< Peer > &peer) noexcept;
|
||||
bool gate(void* tPtr, const SharedPtr<Peer>& peer) noexcept;
|
||||
|
||||
/**
|
||||
* Do periodic cleanup and housekeeping tasks
|
||||
*/
|
||||
void doPeriodicTasks(const CallContext &cc);
|
||||
void doPeriodicTasks(const CallContext& cc);
|
||||
|
||||
/**
|
||||
* Find the node on this network that has this MAC behind it (if any)
|
||||
|
@ -245,10 +263,10 @@ public:
|
|||
* @param mac MAC address
|
||||
* @return ZeroTier address of bridge to this MAC
|
||||
*/
|
||||
ZT_INLINE Address findBridgeTo(const MAC &mac) const
|
||||
ZT_INLINE Address findBridgeTo(const MAC& mac) const
|
||||
{
|
||||
Mutex::Lock _l(m_remoteBridgeRoutes_l);
|
||||
Map< MAC, Address >::const_iterator br(m_remoteBridgeRoutes.find(mac));
|
||||
Map<MAC, Address>::const_iterator br(m_remoteBridgeRoutes.find(mac));
|
||||
return ((br == m_remoteBridgeRoutes.end()) ? Address() : br->second);
|
||||
}
|
||||
|
||||
|
@ -258,7 +276,7 @@ public:
|
|||
* @param mac MAC address of destination
|
||||
* @param addr Bridge this MAC is reachable behind
|
||||
*/
|
||||
void learnBridgeRoute(const MAC &mac, const Address &addr);
|
||||
void learnBridgeRoute(const MAC& mac, const Address& addr);
|
||||
|
||||
/**
|
||||
* Learn a multicast group that is bridged to our tap device
|
||||
|
@ -267,7 +285,7 @@ public:
|
|||
* @param mg Multicast group
|
||||
* @param now Current time
|
||||
*/
|
||||
ZT_INLINE void learnBridgedMulticastGroup(const MulticastGroup &mg, int64_t now)
|
||||
ZT_INLINE void learnBridgedMulticastGroup(const MulticastGroup& mg, int64_t now)
|
||||
{
|
||||
Mutex::Lock l(m_myMulticastGroups_l);
|
||||
m_multicastGroupsBehindMe[mg] = now;
|
||||
|
@ -276,34 +294,39 @@ public:
|
|||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const MembershipCredential &com);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const MembershipCredential& com);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const CapabilityCredential &cap);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const CapabilityCredential& cap);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const TagCredential &tag);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const TagCredential& tag);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const RevocationCredential &rev);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const RevocationCredential& rev);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const OwnershipCredential &coo);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const OwnershipCredential& coo);
|
||||
|
||||
/**
|
||||
* Push credentials to a peer if timeouts indicate that we should do so
|
||||
*
|
||||
* @param to Destination peer
|
||||
*/
|
||||
void pushCredentials(const CallContext &cc, const SharedPtr< Peer > &to);
|
||||
void pushCredentials(const CallContext& cc, const SharedPtr<Peer>& to);
|
||||
|
||||
/**
|
||||
* Destroy this network
|
||||
|
@ -318,19 +341,19 @@ public:
|
|||
*
|
||||
* @param ec Buffer to fill with externally-visible network configuration
|
||||
*/
|
||||
void externalConfig(ZT_VirtualNetworkConfig *ec) const;
|
||||
void externalConfig(ZT_VirtualNetworkConfig* ec) const;
|
||||
|
||||
/**
|
||||
* Iterate through memberships
|
||||
*
|
||||
* @param f Function of (const Address,const Membership)
|
||||
*/
|
||||
template< typename F >
|
||||
ZT_INLINE void eachMember(F f)
|
||||
template <typename F> ZT_INLINE void eachMember(F f)
|
||||
{
|
||||
Mutex::Lock ml(m_memberships_l);
|
||||
for (Map< Address, Member >::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
|
||||
if (!f(i->first, i->second))
|
||||
for (Map<Address, Member>::iterator i(m_memberships.begin()); i != m_memberships.end();
|
||||
++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
|
||||
if (! f(i->first, i->second))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -338,48 +361,51 @@ public:
|
|||
/**
|
||||
* @return Externally usable pointer-to-pointer exported via the core API
|
||||
*/
|
||||
ZT_INLINE void **userPtr() noexcept
|
||||
{ return &m_uPtr; }
|
||||
ZT_INLINE void** userPtr() noexcept
|
||||
{
|
||||
return &m_uPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
void m_requestConfiguration(const CallContext &cc);
|
||||
private:
|
||||
void m_requestConfiguration(const CallContext& cc);
|
||||
ZT_VirtualNetworkStatus m_status() const;
|
||||
void m_externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||
void m_announceMulticastGroups(void *tPtr, bool force);
|
||||
void m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector< MulticastGroup > &allMulticastGroups);
|
||||
Vector< MulticastGroup > m_allMulticastGroups() const;
|
||||
void m_externalConfig(ZT_VirtualNetworkConfig* ec) const; // assumes _lock is locked
|
||||
void m_announceMulticastGroups(void* tPtr, bool force);
|
||||
void m_announceMulticastGroupsTo(void* tPtr, const Address& peer, const Vector<MulticastGroup>& allMulticastGroups);
|
||||
Vector<MulticastGroup> m_allMulticastGroups() const;
|
||||
|
||||
const Context &m_ctx;
|
||||
void *m_uPtr;
|
||||
const Context& m_ctx;
|
||||
void* m_uPtr;
|
||||
const uint64_t m_id;
|
||||
Fingerprint m_controllerFingerprint;
|
||||
MAC m_mac; // local MAC address
|
||||
bool m_portInitialized;
|
||||
std::atomic< bool > m_destroyed;
|
||||
std::atomic<bool> m_destroyed;
|
||||
|
||||
Vector< MulticastGroup > m_myMulticastGroups; // multicast groups that we belong to (according to tap)
|
||||
Map< MulticastGroup, int64_t > m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
|
||||
Map< MAC, Address > m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
|
||||
Vector<MulticastGroup> m_myMulticastGroups; // multicast groups that we belong to (according to tap)
|
||||
Map<MulticastGroup, int64_t> m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we
|
||||
// last saw them (if we are a bridge)
|
||||
Map<MAC, Address> m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices
|
||||
// behind remote bridges)
|
||||
|
||||
NetworkConfig m_config;
|
||||
std::atomic< int64_t > m_lastConfigUpdate;
|
||||
std::atomic<int64_t> m_lastConfigUpdate;
|
||||
|
||||
volatile enum
|
||||
{
|
||||
volatile enum {
|
||||
NETCONF_FAILURE_NONE,
|
||||
NETCONF_FAILURE_ACCESS_DENIED,
|
||||
NETCONF_FAILURE_NOT_FOUND,
|
||||
NETCONF_FAILURE_INIT_FAILED
|
||||
} _netconfFailure;
|
||||
|
||||
Map< Address, Member > m_memberships;
|
||||
Map<Address, Member> m_memberships;
|
||||
|
||||
Mutex m_myMulticastGroups_l;
|
||||
Mutex m_remoteBridgeRoutes_l;
|
||||
Mutex m_config_l;
|
||||
Mutex m_memberships_l;
|
||||
|
||||
std::atomic< int > __refCount;
|
||||
std::atomic<int> __refCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -11,44 +11,47 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <cstdint>
|
||||
#include "NetworkConfig.hpp"
|
||||
|
||||
#include "Buf.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool NetworkConfig::toDictionary(Dictionary &d) const
|
||||
bool NetworkConfig::toDictionary(Dictionary& d) const
|
||||
{
|
||||
uint8_t tmp[ZT_BUF_MEM_SIZE];
|
||||
try {
|
||||
d.clear();
|
||||
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,this->networkId);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString((char *)tmp));
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH,this->issuedToFingerprintHash,ZT_FINGERPRINT_HASH_SIZE);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID, this->networkId);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP, this->timestamp);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA, this->credentialTimeMaxDelta);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION, this->revision);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO, this->issuedTo.toString((char*)tmp));
|
||||
d.add(
|
||||
ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH,
|
||||
this->issuedToFingerprintHash,
|
||||
ZT_FINGERPRINT_HASH_SIZE);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS, this->flags);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT, (uint64_t)this->multicastLimit);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE, (uint64_t)this->type);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME, this->name);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU, (uint64_t)this->mtu);
|
||||
|
||||
if (this->com) {
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,tmp,this->com.marshal(tmp));
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_COM, tmp, this->com.marshal(tmp));
|
||||
}
|
||||
|
||||
Vector<uint8_t> *blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES]);
|
||||
Vector<uint8_t>* blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES]);
|
||||
for (unsigned int i = 0; i < this->capabilityCount; ++i) {
|
||||
int l = this->capabilities[i].marshal(tmp);
|
||||
if (l < 0)
|
||||
return false;
|
||||
blob->insert(blob->end(),tmp,tmp + l);
|
||||
blob->insert(blob->end(), tmp, tmp + l);
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_TAGS]);
|
||||
|
@ -56,7 +59,7 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
|
|||
int l = this->tags[i].marshal(tmp);
|
||||
if (l < 0)
|
||||
return false;
|
||||
blob->insert(blob->end(),tmp,tmp + l);
|
||||
blob->insert(blob->end(), tmp, tmp + l);
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP]);
|
||||
|
@ -64,13 +67,13 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
|
|||
int l = this->certificatesOfOwnership[i].marshal(tmp);
|
||||
if (l < 0)
|
||||
return false;
|
||||
blob->insert(blob->end(),tmp,tmp + l);
|
||||
blob->insert(blob->end(), tmp, tmp + l);
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS]);
|
||||
for (unsigned int i = 0; i < this->specialistCount; ++i) {
|
||||
Utils::storeBigEndian<uint64_t>(tmp,this->specialists[i]);
|
||||
blob->insert(blob->end(),tmp,tmp + 8);
|
||||
Utils::storeBigEndian<uint64_t>(tmp, this->specialists[i]);
|
||||
blob->insert(blob->end(), tmp, tmp + 8);
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ROUTES]);
|
||||
|
@ -78,11 +81,11 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
|
|||
int l = asInetAddress(this->routes[i].target).marshal(tmp);
|
||||
if (l < 0)
|
||||
return false;
|
||||
blob->insert(blob->end(),tmp,tmp + l);
|
||||
blob->insert(blob->end(), tmp, tmp + l);
|
||||
l = asInetAddress(this->routes[i].via).marshal(tmp);
|
||||
if (l < 0)
|
||||
return false;
|
||||
blob->insert(blob->end(),tmp,tmp + l);
|
||||
blob->insert(blob->end(), tmp, tmp + l);
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS]);
|
||||
|
@ -90,7 +93,7 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
|
|||
int l = this->staticIps[i].marshal(tmp);
|
||||
if (l < 0)
|
||||
return false;
|
||||
blob->insert(blob->end(),tmp,tmp + l);
|
||||
blob->insert(blob->end(), tmp, tmp + l);
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_RULES]);
|
||||
|
@ -102,140 +105,157 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
|
|||
}
|
||||
|
||||
return true;
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkConfig::fromDictionary(const Dictionary &d)
|
||||
bool NetworkConfig::fromDictionary(const Dictionary& d)
|
||||
{
|
||||
static const NetworkConfig NIL_NC;
|
||||
try {
|
||||
*this = NIL_NC;
|
||||
|
||||
this->networkId = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,0);
|
||||
if (!this->networkId)
|
||||
this->networkId = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID, 0);
|
||||
if (! this->networkId)
|
||||
return false;
|
||||
this->timestamp = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,0);
|
||||
this->timestamp = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP, 0);
|
||||
if (this->timestamp <= 0)
|
||||
return false;
|
||||
this->credentialTimeMaxDelta = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,0);
|
||||
this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION,0);
|
||||
this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0);
|
||||
const Vector<uint8_t> *blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH]);
|
||||
this->credentialTimeMaxDelta = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA, 0);
|
||||
this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION, 0);
|
||||
this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO, 0);
|
||||
const Vector<uint8_t>* blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH]);
|
||||
if (blob->size() == ZT_FINGERPRINT_HASH_SIZE) {
|
||||
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(this->issuedToFingerprintHash,blob->data());
|
||||
} else {
|
||||
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(this->issuedToFingerprintHash, blob->data());
|
||||
}
|
||||
else {
|
||||
Utils::zero<ZT_FINGERPRINT_HASH_SIZE>(this->issuedToFingerprintHash);
|
||||
}
|
||||
if (!this->issuedTo)
|
||||
if (! this->issuedTo)
|
||||
return false;
|
||||
this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0);
|
||||
d.getS(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name));
|
||||
this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU,ZT_DEFAULT_MTU);
|
||||
this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT, 0);
|
||||
d.getS(ZT_NETWORKCONFIG_DICT_KEY_NAME, this->name, sizeof(this->name));
|
||||
this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU, ZT_DEFAULT_MTU);
|
||||
if (this->mtu < 1280)
|
||||
this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others
|
||||
else if (this->mtu > ZT_MAX_MTU)
|
||||
this->mtu = ZT_MAX_MTU;
|
||||
|
||||
if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) {
|
||||
if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION, 0) < 6) {
|
||||
return false;
|
||||
} else {
|
||||
this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,0);
|
||||
this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)ZT_NETWORK_TYPE_PRIVATE);
|
||||
}
|
||||
else {
|
||||
this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS, 0);
|
||||
this->type =
|
||||
(ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE, (uint64_t)ZT_NETWORK_TYPE_PRIVATE);
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_COM]);
|
||||
if (!blob->empty()) {
|
||||
if (this->com.unmarshal(blob->data(),(int)(blob->size()) < 0))
|
||||
if (! blob->empty()) {
|
||||
if (this->com.unmarshal(blob->data(), (int)(blob->size()) < 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES]);
|
||||
if (!blob->empty()) {
|
||||
if (! blob->empty()) {
|
||||
try {
|
||||
unsigned int p = 0;
|
||||
while (p < blob->size()) {
|
||||
CapabilityCredential cap;
|
||||
int l = cap.unmarshal(blob->data() + p,(int)(blob->size() - p));
|
||||
int l = cap.unmarshal(blob->data() + p, (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
if (this->capabilityCount < ZT_MAX_NETWORK_CAPABILITIES)
|
||||
this->capabilities[this->capabilityCount++] = cap;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
std::sort(&(this->capabilities[0]),&(this->capabilities[this->capabilityCount]));
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
std::sort(&(this->capabilities[0]), &(this->capabilities[this->capabilityCount]));
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_TAGS]);
|
||||
if (!blob->empty()) {
|
||||
if (! blob->empty()) {
|
||||
try {
|
||||
unsigned int p = 0;
|
||||
while (p < blob->size()) {
|
||||
TagCredential tag;
|
||||
int l = tag.unmarshal(blob->data() + p,(int)(blob->size() - p));
|
||||
int l = tag.unmarshal(blob->data() + p, (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
if (this->tagCount < ZT_MAX_NETWORK_TAGS)
|
||||
this->tags[this->tagCount++] = tag;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
std::sort(&(this->tags[0]),&(this->tags[this->tagCount]));
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
std::sort(&(this->tags[0]), &(this->tags[this->tagCount]));
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP]);
|
||||
if (!blob->empty()) {
|
||||
if (! blob->empty()) {
|
||||
try {
|
||||
unsigned int p = 0;
|
||||
while (p < blob->size()) {
|
||||
OwnershipCredential coo;
|
||||
int l = coo.unmarshal(blob->data() + p,(int)(blob->size() - p));
|
||||
int l = coo.unmarshal(blob->data() + p, (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
if (this->certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP)
|
||||
this->certificatesOfOwnership[certificateOfOwnershipCount++] = coo;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
std::sort(&(this->certificatesOfOwnership[0]),&(this->certificatesOfOwnership[this->certificateOfOwnershipCount]));
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
std::sort(
|
||||
&(this->certificatesOfOwnership[0]),
|
||||
&(this->certificatesOfOwnership[this->certificateOfOwnershipCount]));
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS]);
|
||||
if (!blob->empty()) {
|
||||
if (! blob->empty()) {
|
||||
unsigned int p = 0;
|
||||
while (((p + 8) <= blob->size())&&(specialistCount < ZT_MAX_NETWORK_SPECIALISTS)) {
|
||||
while (((p + 8) <= blob->size()) && (specialistCount < ZT_MAX_NETWORK_SPECIALISTS)) {
|
||||
this->specialists[this->specialistCount++] = Utils::loadBigEndian<uint64_t>(blob->data() + p);
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ROUTES]);
|
||||
if (!blob->empty()) {
|
||||
if (! blob->empty()) {
|
||||
unsigned int p = 0;
|
||||
while ((p < blob->size())&&(routeCount < ZT_MAX_NETWORK_ROUTES)) {
|
||||
int l = asInetAddress(this->routes[this->routeCount].target).unmarshal(blob->data(),(int)(blob->size() - p));
|
||||
while ((p < blob->size()) && (routeCount < ZT_MAX_NETWORK_ROUTES)) {
|
||||
int l = asInetAddress(this->routes[this->routeCount].target)
|
||||
.unmarshal(blob->data(), (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
if (p >= blob->size())
|
||||
return false;
|
||||
l = asInetAddress(this->routes[this->routeCount].via).unmarshal(blob->data(),(int)(blob->size() - p));
|
||||
l = asInetAddress(this->routes[this->routeCount].via)
|
||||
.unmarshal(blob->data(), (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
if ((p + 4) > blob->size())
|
||||
return false;
|
||||
this->routes[this->routeCount].flags = Utils::loadBigEndian<uint16_t>(blob->data() + p); p += 2;
|
||||
this->routes[this->routeCount].metric = Utils::loadBigEndian<uint16_t>(blob->data() + p); p += 2;
|
||||
this->routes[this->routeCount].flags = Utils::loadBigEndian<uint16_t>(blob->data() + p);
|
||||
p += 2;
|
||||
this->routes[this->routeCount].metric = Utils::loadBigEndian<uint16_t>(blob->data() + p);
|
||||
p += 2;
|
||||
++this->routeCount;
|
||||
}
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS]);
|
||||
if (!blob->empty()) {
|
||||
if (! blob->empty()) {
|
||||
unsigned int p = 0;
|
||||
while ((p < blob->size())&&(staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) {
|
||||
int l = this->staticIps[this->staticIpCount].unmarshal(blob->data() + p,(int)(blob->size() - p));
|
||||
while ((p < blob->size()) && (staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) {
|
||||
int l = this->staticIps[this->staticIpCount].unmarshal(blob->data() + p, (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
|
@ -244,22 +264,30 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_RULES]);
|
||||
if (!blob->empty()) {
|
||||
if (! blob->empty()) {
|
||||
this->ruleCount = 0;
|
||||
if (CapabilityCredential::unmarshalVirtualNetworkRules(blob->data(), (int)blob->size(), this->rules, this->ruleCount, ZT_MAX_NETWORK_RULES) < 0)
|
||||
if (CapabilityCredential::unmarshalVirtualNetworkRules(
|
||||
blob->data(),
|
||||
(int)blob->size(),
|
||||
this->rules,
|
||||
this->ruleCount,
|
||||
ZT_MAX_NETWORK_RULES)
|
||||
< 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkConfig::addSpecialist(const Address &a,const uint64_t f) noexcept
|
||||
bool NetworkConfig::addSpecialist(const Address& a, const uint64_t f) noexcept
|
||||
{
|
||||
const uint64_t aint = a.toInt();
|
||||
for(unsigned int i=0;i<specialistCount;++i) {
|
||||
for (unsigned int i = 0; i < specialistCount; ++i) {
|
||||
if ((specialists[i] & 0xffffffffffULL) == aint) {
|
||||
specialists[i] |= f;
|
||||
return true;
|
||||
|
|
|
@ -14,23 +14,23 @@
|
|||
#ifndef ZT_NETWORKCONFIG_HPP
|
||||
#define ZT_NETWORKCONFIG_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "OwnershipCredential.hpp"
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "OwnershipCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -144,10 +144,11 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Network configuration received from network controller nodes
|
||||
*/
|
||||
struct NetworkConfig : TriviallyCopyable
|
||||
{
|
||||
struct NetworkConfig : TriviallyCopyable {
|
||||
ZT_INLINE NetworkConfig() noexcept
|
||||
{ memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
{
|
||||
memoryZero(this);
|
||||
} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
||||
/**
|
||||
* Write this network config to a dictionary for transport
|
||||
|
@ -155,7 +156,7 @@ struct NetworkConfig : TriviallyCopyable
|
|||
* @param d Dictionary
|
||||
* @return True if dictionary was successfully created, false if e.g. overflow
|
||||
*/
|
||||
bool toDictionary(Dictionary &d) const;
|
||||
bool toDictionary(Dictionary& d) const;
|
||||
|
||||
/**
|
||||
* Read this network config from a dictionary
|
||||
|
@ -163,52 +164,67 @@ struct NetworkConfig : TriviallyCopyable
|
|||
* @param d Dictionary (non-const since it might be modified during parse, should not be used after call)
|
||||
* @return True if dictionary was valid and network config successfully initialized
|
||||
*/
|
||||
bool fromDictionary(const Dictionary &d);
|
||||
bool fromDictionary(const Dictionary& d);
|
||||
|
||||
/**
|
||||
* @return True if broadcast (ff:ff:ff:ff:ff:ff) address should work on this network
|
||||
*/
|
||||
ZT_INLINE bool enableBroadcast() const noexcept
|
||||
{ return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0); }
|
||||
{
|
||||
return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if IPv6 NDP emulation should be allowed for certain "magic" IPv6 address patterns
|
||||
*/
|
||||
ZT_INLINE bool ndpEmulation() const noexcept
|
||||
{ return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0); }
|
||||
{
|
||||
return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Network type is public (no access control)
|
||||
*/
|
||||
ZT_INLINE bool isPublic() const noexcept
|
||||
{ return (this->type == ZT_NETWORK_TYPE_PUBLIC); }
|
||||
{
|
||||
return (this->type == ZT_NETWORK_TYPE_PUBLIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Network type is private (certificate access control)
|
||||
*/
|
||||
ZT_INLINE bool isPrivate() const noexcept
|
||||
{ return (this->type == ZT_NETWORK_TYPE_PRIVATE); }
|
||||
{
|
||||
return (this->type == ZT_NETWORK_TYPE_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fromPeer Peer attempting to bridge other Ethernet peers onto network
|
||||
* @return True if this network allows bridging
|
||||
*/
|
||||
ZT_INLINE bool permitsBridging(const Address &fromPeer) const noexcept
|
||||
ZT_INLINE bool permitsBridging(const Address& fromPeer) const noexcept
|
||||
{
|
||||
for (unsigned int i = 0;i < specialistCount;++i) {
|
||||
if ((fromPeer.toInt() == (specialists[i] & ZT_ADDRESS_MASK)) && ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0))
|
||||
for (unsigned int i = 0; i < specialistCount; ++i) {
|
||||
if ((fromPeer.toInt() == (specialists[i] & ZT_ADDRESS_MASK))
|
||||
&& ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (networkId != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
ZT_INLINE bool operator==(const NetworkConfig &nc) const noexcept
|
||||
{ return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0); }
|
||||
{
|
||||
return (networkId != 0);
|
||||
} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
ZT_INLINE bool operator==(const NetworkConfig& nc) const noexcept
|
||||
{
|
||||
return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const NetworkConfig &nc) const noexcept
|
||||
{ return (!(*this == nc)); }
|
||||
ZT_INLINE bool operator!=(const NetworkConfig& nc) const noexcept
|
||||
{
|
||||
return (! (*this == nc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a specialist or mask flags if already present
|
||||
|
@ -220,20 +236,20 @@ struct NetworkConfig : TriviallyCopyable
|
|||
* @param f Flags (OR of specialist role/type flags)
|
||||
* @return True if successfully masked or added
|
||||
*/
|
||||
bool addSpecialist(const Address &a, uint64_t f) noexcept;
|
||||
bool addSpecialist(const Address& a, uint64_t f) noexcept;
|
||||
|
||||
ZT_INLINE const CapabilityCredential *capability(const uint32_t id) const
|
||||
ZT_INLINE const CapabilityCredential* capability(const uint32_t id) const
|
||||
{
|
||||
for (unsigned int i = 0;i < capabilityCount;++i) {
|
||||
for (unsigned int i = 0; i < capabilityCount; ++i) {
|
||||
if (capabilities[i].id() == id)
|
||||
return &(capabilities[i]);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZT_INLINE const TagCredential *tag(const uint32_t id) const
|
||||
ZT_INLINE const TagCredential* tag(const uint32_t id) const
|
||||
{
|
||||
for (unsigned int i = 0;i < tagCount;++i) {
|
||||
for (unsigned int i = 0; i < tagCount; ++i) {
|
||||
if (tags[i].id() == id)
|
||||
return &(tags[i]);
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#ifndef ZT_NETWORKCONFIGMASTER_HPP
|
||||
#define ZT_NETWORKCONFIGMASTER_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "Address.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -28,11 +28,9 @@ struct InetAddress;
|
|||
/**
|
||||
* Interface for network controller implementations
|
||||
*/
|
||||
class NetworkController
|
||||
{
|
||||
public:
|
||||
enum ErrorCode
|
||||
{
|
||||
class NetworkController {
|
||||
public:
|
||||
enum ErrorCode {
|
||||
NC_ERROR_NONE = 0,
|
||||
NC_ERROR_OBJECT_NOT_FOUND = 1,
|
||||
NC_ERROR_ACCESS_DENIED = 2,
|
||||
|
@ -42,19 +40,27 @@ public:
|
|||
/**
|
||||
* Interface for sender used to send pushes and replies
|
||||
*/
|
||||
class Sender
|
||||
{
|
||||
class Sender {
|
||||
public:
|
||||
/**
|
||||
* Send a configuration to a remote peer
|
||||
*
|
||||
* @param nwid Network ID
|
||||
* @param requestPacketId Request packet ID to send OK(NETWORK_CONFIG_REQUEST) or 0 to send NETWORK_CONFIG (push)
|
||||
* @param requestPacketId Request packet ID to send OK(NETWORK_CONFIG_REQUEST) or 0 to send NETWORK_CONFIG
|
||||
* (push)
|
||||
* @param destination Destination peer Address
|
||||
* @param nc Network configuration to send
|
||||
* @param sendLegacyFormatConfig If true, send an old-format network config
|
||||
*/
|
||||
virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig) = 0;
|
||||
virtual void ncSendConfig(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
const NetworkConfig& nc,
|
||||
bool sendLegacyFormatConfig) = 0;
|
||||
|
||||
/**
|
||||
* Send revocation to a node
|
||||
|
@ -62,7 +68,12 @@ public:
|
|||
* @param destination Destination node address
|
||||
* @param rev Revocation to send
|
||||
*/
|
||||
virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev) = 0;
|
||||
virtual void ncSendRevocation(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
const Address& destination,
|
||||
const RevocationCredential& rev) = 0;
|
||||
|
||||
/**
|
||||
* Send a network configuration request error
|
||||
|
@ -72,11 +83,22 @@ public:
|
|||
* @param destination Destination peer Address
|
||||
* @param errorCode Error code
|
||||
*/
|
||||
virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode) = 0;
|
||||
virtual void ncSendError(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
NetworkController::ErrorCode errorCode) = 0;
|
||||
};
|
||||
|
||||
NetworkController() {}
|
||||
virtual ~NetworkController() {}
|
||||
NetworkController()
|
||||
{
|
||||
}
|
||||
virtual ~NetworkController()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this is added to a Node to initialize and supply info
|
||||
|
@ -84,7 +106,7 @@ public:
|
|||
* @param signingId Identity for signing of network configurations, certs, etc.
|
||||
* @param sender Sender implementation for sending replies or config pushes
|
||||
*/
|
||||
virtual void init(const Identity &signingId, Sender *sender) = 0;
|
||||
virtual void init(const Identity& signingId, Sender* sender) = 0;
|
||||
|
||||
/**
|
||||
* Handle a network configuration request
|
||||
|
@ -98,10 +120,10 @@ public:
|
|||
*/
|
||||
virtual void request(
|
||||
uint64_t nwid,
|
||||
const InetAddress &fromAddr,
|
||||
const InetAddress& fromAddr,
|
||||
uint64_t requestPacketId,
|
||||
const Identity &identity,
|
||||
const Dictionary &metaData) = 0;
|
||||
const Identity& identity,
|
||||
const Dictionary& metaData) = 0;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
439
core/Node.cpp
439
core/Node.cpp
|
@ -11,39 +11,39 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Topology.hpp"
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Expect.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Store.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
#include "VL1.hpp"
|
||||
#include "VL2.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
#include "Store.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
namespace {
|
||||
|
||||
struct _NodeObjects
|
||||
{
|
||||
ZT_INLINE _NodeObjects(Context &ctx, const CallContext &cc) :
|
||||
networks(),
|
||||
t(ctx),
|
||||
expect(),
|
||||
vl2(ctx),
|
||||
vl1(ctx),
|
||||
topology(ctx, cc),
|
||||
sa(ctx),
|
||||
ts()
|
||||
struct _NodeObjects {
|
||||
ZT_INLINE _NodeObjects(Context& ctx, const CallContext& cc)
|
||||
: networks()
|
||||
, t(ctx)
|
||||
, expect()
|
||||
, vl2(ctx)
|
||||
, vl1(ctx)
|
||||
, topology(ctx, cc)
|
||||
, sa(ctx)
|
||||
, ts()
|
||||
{
|
||||
ctx.networks = &networks;
|
||||
ctx.t = &t;
|
||||
|
@ -55,7 +55,7 @@ struct _NodeObjects
|
|||
ctx.ts = &ts;
|
||||
}
|
||||
|
||||
TinyMap< SharedPtr< Network > > networks;
|
||||
TinyMap<SharedPtr<Network> > networks;
|
||||
Trace t;
|
||||
Expect expect;
|
||||
VL2 vl2;
|
||||
|
@ -67,27 +67,27 @@ struct _NodeObjects
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
Node::Node(void *uPtr, const struct ZT_Node_Callbacks *callbacks, const CallContext &cc) :
|
||||
m_ctx(this),
|
||||
m_store(m_ctx),
|
||||
m_objects(nullptr),
|
||||
m_lastPeerPulse(0),
|
||||
m_lastHousekeepingRun(0),
|
||||
m_lastNetworkHousekeepingRun(0),
|
||||
m_lastTrustStoreUpdate(0),
|
||||
m_online(false)
|
||||
Node::Node(void* uPtr, const struct ZT_Node_Callbacks* callbacks, const CallContext& cc)
|
||||
: m_ctx(this)
|
||||
, m_store(m_ctx)
|
||||
, m_objects(nullptr)
|
||||
, m_lastPeerPulse(0)
|
||||
, m_lastHousekeepingRun(0)
|
||||
, m_lastNetworkHousekeepingRun(0)
|
||||
, m_lastTrustStoreUpdate(0)
|
||||
, m_online(false)
|
||||
{
|
||||
ZT_SPEW("Node starting up!");
|
||||
|
||||
Utils::copy< sizeof(ZT_Node_Callbacks) >(&m_ctx.cb, callbacks);
|
||||
Utils::copy<sizeof(ZT_Node_Callbacks)>(&m_ctx.cb, callbacks);
|
||||
m_ctx.uPtr = uPtr;
|
||||
m_ctx.store = &m_store;
|
||||
|
||||
Vector< uint8_t > data(m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0));
|
||||
Vector<uint8_t> data(m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0));
|
||||
bool haveIdentity = false;
|
||||
if (!data.empty()) {
|
||||
if (! data.empty()) {
|
||||
data.push_back(0); // zero-terminate string
|
||||
if (m_ctx.identity.fromString((const char *)data.data())) {
|
||||
if (m_ctx.identity.fromString((const char*)data.data())) {
|
||||
m_ctx.identity.toString(false, m_ctx.publicIdentityStr);
|
||||
m_ctx.identity.toString(true, m_ctx.secretIdentityStr);
|
||||
haveIdentity = true;
|
||||
|
@ -95,17 +95,36 @@ Node::Node(void *uPtr, const struct ZT_Node_Callbacks *callbacks, const CallCont
|
|||
}
|
||||
}
|
||||
|
||||
if (!haveIdentity) {
|
||||
if (! haveIdentity) {
|
||||
m_ctx.identity.generate(Identity::C25519);
|
||||
m_ctx.identity.toString(false, m_ctx.publicIdentityStr);
|
||||
m_ctx.identity.toString(true, m_ctx.secretIdentityStr);
|
||||
m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0, m_ctx.secretIdentityStr, (unsigned int)strlen(m_ctx.secretIdentityStr));
|
||||
m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_ctx.publicIdentityStr, (unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
m_store.put(
|
||||
cc,
|
||||
ZT_STATE_OBJECT_IDENTITY_SECRET,
|
||||
Utils::ZERO256,
|
||||
0,
|
||||
m_ctx.secretIdentityStr,
|
||||
(unsigned int)strlen(m_ctx.secretIdentityStr));
|
||||
m_store.put(
|
||||
cc,
|
||||
ZT_STATE_OBJECT_IDENTITY_PUBLIC,
|
||||
Utils::ZERO256,
|
||||
0,
|
||||
m_ctx.publicIdentityStr,
|
||||
(unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
ZT_SPEW("no pre-existing identity found, created %s", m_ctx.identity.toString().c_str());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data = m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0);
|
||||
if ((data.empty()) || (memcmp(data.data(), m_ctx.publicIdentityStr, strlen(m_ctx.publicIdentityStr)) != 0))
|
||||
m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_ctx.publicIdentityStr, (unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
m_store.put(
|
||||
cc,
|
||||
ZT_STATE_OBJECT_IDENTITY_PUBLIC,
|
||||
Utils::ZERO256,
|
||||
0,
|
||||
m_ctx.publicIdentityStr,
|
||||
(unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
}
|
||||
|
||||
uint8_t localSecretCipherKey[ZT_FINGERPRINT_HASH_SIZE];
|
||||
|
@ -142,7 +161,7 @@ Node::~Node()
|
|||
m_allNetworks.clear();
|
||||
m_allNetworks_l.unlock();
|
||||
|
||||
delete reinterpret_cast<_NodeObjects *>(m_objects);
|
||||
delete reinterpret_cast<_NodeObjects*>(m_objects);
|
||||
|
||||
// Let go of cached Buf objects. If other nodes happen to be running in this
|
||||
// same process space new Bufs will be allocated as needed, but this is almost
|
||||
|
@ -151,7 +170,7 @@ Node::~Node()
|
|||
Buf::freePool();
|
||||
}
|
||||
|
||||
void Node::shutdown(const CallContext &cc)
|
||||
void Node::shutdown(const CallContext& cc)
|
||||
{
|
||||
m_allNetworks_l.lock();
|
||||
m_ctx.networks->clear();
|
||||
|
@ -164,7 +183,7 @@ void Node::shutdown(const CallContext &cc)
|
|||
m_ctx.topology->saveAll(cc);
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::processBackgroundTasks(const CallContext &cc, volatile int64_t *nextBackgroundTaskDeadline)
|
||||
ZT_ResultCode Node::processBackgroundTasks(const CallContext& cc, volatile int64_t* nextBackgroundTaskDeadline)
|
||||
{
|
||||
Mutex::Lock bl(m_backgroundTasksLock);
|
||||
|
||||
|
@ -183,7 +202,7 @@ ZT_ResultCode Node::processBackgroundTasks(const CallContext &cc, volatile int64
|
|||
m_lastNetworkHousekeepingRun = cc.ticks;
|
||||
ZT_SPEW("running networking housekeeping...");
|
||||
Mutex::Lock l(m_allNetworks_l);
|
||||
for (Vector< SharedPtr< Network > >::const_iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n)
|
||||
for (Vector<SharedPtr<Network> >::const_iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n)
|
||||
(*n)->doPeriodicTasks(cc);
|
||||
}
|
||||
|
||||
|
@ -203,15 +222,17 @@ ZT_ResultCode Node::processBackgroundTasks(const CallContext &cc, volatile int64
|
|||
m_lastPeerPulse = cc.ticks;
|
||||
ZT_SPEW("running pulse() on each peer...");
|
||||
try {
|
||||
Vector< SharedPtr< Peer > > allPeers, rootPeers;
|
||||
Vector<SharedPtr<Peer> > allPeers, rootPeers;
|
||||
m_ctx.topology->allPeers(allPeers, rootPeers);
|
||||
std::sort(rootPeers.begin(), rootPeers.end());
|
||||
|
||||
bool online = false;
|
||||
for (Vector< SharedPtr< Peer > >::iterator p(allPeers.begin()); p != allPeers.end(); ++p) {
|
||||
for (Vector<SharedPtr<Peer> >::iterator p(allPeers.begin()); p != allPeers.end(); ++p) {
|
||||
(*p)->pulse(m_ctx, cc);
|
||||
if (!online) {
|
||||
online = ((std::binary_search(rootPeers.begin(), rootPeers.end(), *p) || rootPeers.empty()) && (*p)->directlyConnected());
|
||||
if (! online) {
|
||||
online =
|
||||
((std::binary_search(rootPeers.begin(), rootPeers.end(), *p) || rootPeers.empty())
|
||||
&& (*p)->directlyConnected());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,20 +241,22 @@ ZT_ResultCode Node::processBackgroundTasks(const CallContext &cc, volatile int64
|
|||
|
||||
ZT_SPEW("ranking roots...");
|
||||
m_ctx.topology->rankRoots(cc);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
*nextBackgroundTaskDeadline = cc.ticks + ZT_TIMER_TASK_INTERVAL;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::join(uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, const CallContext &cc)
|
||||
ZT_ResultCode Node::join(uint64_t nwid, const ZT_Fingerprint* controllerFingerprint, void* uptr, const CallContext& cc)
|
||||
{
|
||||
Mutex::Lock l(m_allNetworks_l);
|
||||
|
||||
|
@ -241,31 +264,32 @@ ZT_ResultCode Node::join(uint64_t nwid, const ZT_Fingerprint *controllerFingerpr
|
|||
if (controllerFingerprint) {
|
||||
fp = *controllerFingerprint;
|
||||
ZT_SPEW("joining network %.16llx with controller fingerprint %s", nwid, fp.toString().c_str());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ZT_SPEW("joining network %.16llx", nwid);
|
||||
}
|
||||
|
||||
for (Vector< SharedPtr< Network > >::iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n) {
|
||||
for (Vector<SharedPtr<Network> >::iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n) {
|
||||
if ((*n)->id() == nwid)
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
SharedPtr< Network > network(new Network(m_ctx, cc, nwid, fp, uptr, nullptr));
|
||||
SharedPtr<Network> network(new Network(m_ctx, cc, nwid, fp, uptr, nullptr));
|
||||
m_allNetworks.push_back(network);
|
||||
m_ctx.networks->set(nwid, network);
|
||||
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::leave(uint64_t nwid, void **uptr, const CallContext &cc)
|
||||
ZT_ResultCode Node::leave(uint64_t nwid, void** uptr, const CallContext& cc)
|
||||
{
|
||||
Mutex::Lock l(m_allNetworks_l);
|
||||
|
||||
ZT_SPEW("leaving network %.16llx", nwid);
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
|
||||
SharedPtr< Network > network;
|
||||
SharedPtr<Network> network;
|
||||
m_ctx.networks->erase(nwid);
|
||||
for (Vector< SharedPtr< Network > >::iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n) {
|
||||
for (Vector<SharedPtr<Network> >::iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n) {
|
||||
if ((*n)->id() == nwid) {
|
||||
network.move(*n);
|
||||
m_allNetworks.erase(n);
|
||||
|
@ -282,88 +306,100 @@ ZT_ResultCode Node::leave(uint64_t nwid, void **uptr, const CallContext &cc)
|
|||
if (uptr)
|
||||
*uptr = *network->userPtr();
|
||||
network->externalConfig(&ctmp);
|
||||
m_ctx.cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, cc.tPtr, nwid, network->userPtr(), ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY, &ctmp);
|
||||
m_ctx.cb.virtualNetworkConfigFunction(
|
||||
reinterpret_cast<ZT_Node*>(this),
|
||||
m_ctx.uPtr,
|
||||
cc.tPtr,
|
||||
nwid,
|
||||
network->userPtr(),
|
||||
ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,
|
||||
&ctmp);
|
||||
network->destroy();
|
||||
return ZT_RESULT_OK;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::multicastSubscribe(const CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
ZT_ResultCode
|
||||
Node::multicastSubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
{
|
||||
ZT_SPEW("multicast subscribe to %s:%lu", MAC(multicastGroup).toString().c_str(), multicastAdi);
|
||||
const SharedPtr< Network > nw(m_ctx.networks->get(nwid));
|
||||
const SharedPtr<Network> nw(m_ctx.networks->get(nwid));
|
||||
if (nw) {
|
||||
nw->multicastSubscribe(cc, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
|
||||
return ZT_RESULT_OK;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::multicastUnsubscribe(const CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
ZT_ResultCode
|
||||
Node::multicastUnsubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
{
|
||||
ZT_SPEW("multicast unsubscribe from %s:%lu", MAC(multicastGroup).toString().c_str(), multicastAdi);
|
||||
const SharedPtr< Network > nw(m_ctx.networks->get(nwid));
|
||||
const SharedPtr<Network> nw(m_ctx.networks->get(nwid));
|
||||
if (nw) {
|
||||
nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
|
||||
return ZT_RESULT_OK;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
void Node::status(ZT_NodeStatus *status) const
|
||||
void Node::status(ZT_NodeStatus* status) const
|
||||
{
|
||||
status->address = m_ctx.identity.address().toInt();
|
||||
status->identity = reinterpret_cast<const ZT_Identity *>(&m_ctx.identity);
|
||||
status->identity = reinterpret_cast<const ZT_Identity*>(&m_ctx.identity);
|
||||
status->publicIdentity = m_ctx.publicIdentityStr;
|
||||
status->secretIdentity = m_ctx.secretIdentityStr;
|
||||
status->online = m_online ? 1 : 0;
|
||||
}
|
||||
|
||||
struct p_ZT_PeerListPrivate : public ZT_PeerList
|
||||
{
|
||||
struct p_ZT_PeerListPrivate : public ZT_PeerList {
|
||||
// Actual containers for the memory, hidden from external users.
|
||||
Vector< ZT_Peer > p_peers;
|
||||
ForwardList< Vector< ZT_Path > > p_paths;
|
||||
ForwardList< Identity > p_identities;
|
||||
ForwardList< Blob< ZT_LOCATOR_MARSHAL_SIZE_MAX > > p_locators;
|
||||
Vector<ZT_Peer> p_peers;
|
||||
ForwardList<Vector<ZT_Path> > p_paths;
|
||||
ForwardList<Identity> p_identities;
|
||||
ForwardList<Blob<ZT_LOCATOR_MARSHAL_SIZE_MAX> > p_locators;
|
||||
};
|
||||
|
||||
static void p_peerListFreeFunction(const void *pl)
|
||||
static void p_peerListFreeFunction(const void* pl)
|
||||
{
|
||||
if (pl)
|
||||
delete reinterpret_cast<p_ZT_PeerListPrivate *>(const_cast<void *>(pl));
|
||||
delete reinterpret_cast<p_ZT_PeerListPrivate*>(const_cast<void*>(pl));
|
||||
}
|
||||
|
||||
struct p_sortPeerPtrsByAddress
|
||||
{
|
||||
ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const noexcept
|
||||
{ return (a->address() < b->address()); }
|
||||
struct p_sortPeerPtrsByAddress {
|
||||
ZT_INLINE bool operator()(const SharedPtr<Peer>& a, const SharedPtr<Peer>& b) const noexcept
|
||||
{
|
||||
return (a->address() < b->address());
|
||||
}
|
||||
};
|
||||
|
||||
ZT_PeerList *Node::peers(const CallContext &cc) const
|
||||
ZT_PeerList* Node::peers(const CallContext& cc) const
|
||||
{
|
||||
p_ZT_PeerListPrivate *pl = nullptr;
|
||||
p_ZT_PeerListPrivate* pl = nullptr;
|
||||
try {
|
||||
pl = new p_ZT_PeerListPrivate;
|
||||
pl->freeFunction = p_peerListFreeFunction;
|
||||
|
||||
Vector< SharedPtr< Peer > > peers, rootPeers;
|
||||
Vector<SharedPtr<Peer> > peers, rootPeers;
|
||||
m_ctx.topology->allPeers(peers, rootPeers);
|
||||
std::sort(peers.begin(), peers.end(), p_sortPeerPtrsByAddress());
|
||||
std::sort(rootPeers.begin(), rootPeers.end());
|
||||
|
||||
for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) {
|
||||
for (Vector<SharedPtr<Peer> >::iterator pi(peers.begin()); pi != peers.end(); ++pi) {
|
||||
pl->p_peers.push_back(ZT_Peer());
|
||||
ZT_Peer &p = pl->p_peers.back();
|
||||
Peer &pp = **pi;
|
||||
ZT_Peer& p = pl->p_peers.back();
|
||||
Peer& pp = **pi;
|
||||
|
||||
p.address = pp.address();
|
||||
pl->p_identities.push_front(pp.identity());
|
||||
p.identity = reinterpret_cast<const ZT_Identity *>(&(pl->p_identities.front()));
|
||||
p.identity = reinterpret_cast<const ZT_Identity*>(&(pl->p_identities.front()));
|
||||
p.fingerprint = &(pl->p_identities.front().fingerprint());
|
||||
uint16_t vProto, vMajor, vMinor, vRevision;
|
||||
if (pp.remoteVersion(vProto, vMajor, vMinor, vRevision)) {
|
||||
|
@ -371,7 +407,8 @@ ZT_PeerList *Node::peers(const CallContext &cc) const
|
|||
p.versionMinor = (int)vMinor;
|
||||
p.versionRev = (int)vRevision;
|
||||
p.versionProto = (int)vProto;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.versionMajor = -1;
|
||||
p.versionMinor = -1;
|
||||
p.versionRev = -1;
|
||||
|
@ -383,17 +420,17 @@ ZT_PeerList *Node::peers(const CallContext &cc) const
|
|||
p.networks = nullptr;
|
||||
p.networkCount = 0; // TODO: networks this peer belongs to
|
||||
|
||||
Vector< SharedPtr< Path > > ztPaths;
|
||||
Vector<SharedPtr<Path> > ztPaths;
|
||||
pp.getAllPaths(ztPaths);
|
||||
if (ztPaths.empty()) {
|
||||
pl->p_paths.push_front(Vector< ZT_Path >());
|
||||
std::vector< ZT_Path > &apiPaths = pl->p_paths.front();
|
||||
pl->p_paths.push_front(Vector<ZT_Path>());
|
||||
std::vector<ZT_Path>& apiPaths = pl->p_paths.front();
|
||||
apiPaths.resize(ztPaths.size());
|
||||
for (unsigned long i = 0; i < (unsigned long)ztPaths.size(); ++i) {
|
||||
SharedPtr< Path > &ztp = ztPaths[i];
|
||||
ZT_Path &apip = apiPaths[i];
|
||||
SharedPtr<Path>& ztp = ztPaths[i];
|
||||
ZT_Path& apip = apiPaths[i];
|
||||
apip.endpoint.type = ZT_ENDPOINT_TYPE_IP_UDP;
|
||||
Utils::copy< sizeof(struct sockaddr_storage) >(&(apip.endpoint.value.ss), &(ztp->address().as.ss));
|
||||
Utils::copy<sizeof(struct sockaddr_storage)>(&(apip.endpoint.value.ss), &(ztp->address().as.ss));
|
||||
apip.lastSend = ztp->lastOut();
|
||||
apip.lastReceive = ztp->lastIn();
|
||||
apip.alive = ztp->alive(cc) ? 1 : 0;
|
||||
|
@ -401,16 +438,17 @@ ZT_PeerList *Node::peers(const CallContext &cc) const
|
|||
}
|
||||
p.paths = apiPaths.data();
|
||||
p.pathCount = (unsigned int)apiPaths.size();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.paths = nullptr;
|
||||
p.pathCount = 0;
|
||||
}
|
||||
|
||||
const SharedPtr< const Locator > loc(pp.locator());
|
||||
const SharedPtr<const Locator> loc(pp.locator());
|
||||
if (loc) {
|
||||
pl->p_locators.push_front(Blob< ZT_LOCATOR_MARSHAL_SIZE_MAX >());
|
||||
Blob< ZT_LOCATOR_MARSHAL_SIZE_MAX > &lb = pl->p_locators.front();
|
||||
Utils::zero< ZT_LOCATOR_MARSHAL_SIZE_MAX >(lb.data);
|
||||
pl->p_locators.push_front(Blob<ZT_LOCATOR_MARSHAL_SIZE_MAX>());
|
||||
Blob<ZT_LOCATOR_MARSHAL_SIZE_MAX>& lb = pl->p_locators.front();
|
||||
Utils::zero<ZT_LOCATOR_MARSHAL_SIZE_MAX>(lb.data);
|
||||
const int ls = loc->marshal(lb.data);
|
||||
if (ls > 0) {
|
||||
p.locatorSize = (unsigned int)ls;
|
||||
|
@ -423,47 +461,48 @@ ZT_PeerList *Node::peers(const CallContext &cc) const
|
|||
pl->peerCount = (unsigned long)pl->p_peers.size();
|
||||
|
||||
return pl;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
delete pl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
|
||||
ZT_VirtualNetworkConfig* Node::networkConfig(uint64_t nwid) const
|
||||
{
|
||||
const SharedPtr< Network > nw(m_ctx.networks->get(nwid));
|
||||
const SharedPtr<Network> nw(m_ctx.networks->get(nwid));
|
||||
if (nw) {
|
||||
ZT_VirtualNetworkConfig *const nc = (ZT_VirtualNetworkConfig *)::malloc(sizeof(ZT_VirtualNetworkConfig));
|
||||
ZT_VirtualNetworkConfig* const nc = (ZT_VirtualNetworkConfig*)::malloc(sizeof(ZT_VirtualNetworkConfig));
|
||||
nw->externalConfig(nc);
|
||||
return nc;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_VirtualNetworkList *Node::networks() const
|
||||
ZT_VirtualNetworkList* Node::networks() const
|
||||
{
|
||||
Mutex::Lock l(m_allNetworks_l);
|
||||
|
||||
char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_allNetworks.size()));
|
||||
if (!buf)
|
||||
char* const buf =
|
||||
(char*)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_allNetworks.size()));
|
||||
if (! buf)
|
||||
return nullptr;
|
||||
ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf;
|
||||
nl->freeFunction = reinterpret_cast<void (*)(const void *)>(free);
|
||||
nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList));
|
||||
ZT_VirtualNetworkList* nl = (ZT_VirtualNetworkList*)buf;
|
||||
nl->freeFunction = reinterpret_cast<void (*)(const void*)>(free);
|
||||
nl->networks = (ZT_VirtualNetworkConfig*)(buf + sizeof(ZT_VirtualNetworkList));
|
||||
|
||||
nl->networkCount = 0;
|
||||
for (Vector< SharedPtr< Network > >::const_iterator i(m_allNetworks.begin()); i != m_allNetworks.end(); ++i)
|
||||
for (Vector<SharedPtr<Network> >::const_iterator i(m_allNetworks.begin()); i != m_allNetworks.end(); ++i)
|
||||
(*i)->externalConfig(&(nl->networks[nl->networkCount++]));
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
void Node::setNetworkUserPtr(
|
||||
uint64_t nwid,
|
||||
void *ptr)
|
||||
void Node::setNetworkUserPtr(uint64_t nwid, void* ptr)
|
||||
{
|
||||
SharedPtr< Network > nw(m_ctx.networks->get(nwid));
|
||||
SharedPtr<Network> nw(m_ctx.networks->get(nwid));
|
||||
if (nw) {
|
||||
m_allNetworks_l.lock(); // ensure no concurrent modification of user PTR in network
|
||||
*(nw->userPtr()) = ptr;
|
||||
|
@ -471,86 +510,89 @@ void Node::setNetworkUserPtr(
|
|||
}
|
||||
}
|
||||
|
||||
void Node::setInterfaceAddresses(
|
||||
const ZT_InterfaceAddress *addrs,
|
||||
unsigned int addrCount)
|
||||
void Node::setInterfaceAddresses(const ZT_InterfaceAddress* addrs, unsigned int addrCount)
|
||||
{
|
||||
Mutex::Lock _l(m_localInterfaceAddresses_m);
|
||||
m_localInterfaceAddresses.clear();
|
||||
for (unsigned int i = 0; i < addrCount; ++i) {
|
||||
bool dupe = false;
|
||||
for (unsigned int j = 0; j < i; ++j) {
|
||||
if (*(reinterpret_cast<const InetAddress *>(&addrs[j].address)) == *(reinterpret_cast<const InetAddress *>(&addrs[i].address))) {
|
||||
if (*(reinterpret_cast<const InetAddress*>(&addrs[j].address))
|
||||
== *(reinterpret_cast<const InetAddress*>(&addrs[i].address))) {
|
||||
dupe = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dupe)
|
||||
if (! dupe)
|
||||
m_localInterfaceAddresses.push_back(addrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ZT_CertificateError Node::addCertificate(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
unsigned int localTrust,
|
||||
const ZT_Certificate *cert,
|
||||
const void *certData,
|
||||
const ZT_Certificate* cert,
|
||||
const void* certData,
|
||||
unsigned int certSize)
|
||||
{
|
||||
Certificate c;
|
||||
if (cert) {
|
||||
c = *cert;
|
||||
} else {
|
||||
if ((!certData) || (!certSize))
|
||||
}
|
||||
else {
|
||||
if ((! certData) || (! certSize))
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
if (!c.decode(certData, certSize))
|
||||
if (! c.decode(certData, certSize))
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
m_ctx.ts->add(c, localTrust);
|
||||
m_ctx.ts->update(cc.clock, nullptr);
|
||||
SharedPtr< TrustStore::Entry > ent(m_ctx.ts->get(c.getSerialNo()));
|
||||
return (ent) ? ent->error() : ZT_CERTIFICATE_ERROR_INVALID_FORMAT; // should never be null, but if so it means invalid
|
||||
SharedPtr<TrustStore::Entry> ent(m_ctx.ts->get(c.getSerialNo()));
|
||||
return (ent) ? ent->error()
|
||||
: ZT_CERTIFICATE_ERROR_INVALID_FORMAT; // should never be null, but if so it means invalid
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::deleteCertificate(
|
||||
const CallContext &cc,
|
||||
const void *serialNo)
|
||||
ZT_ResultCode Node::deleteCertificate(const CallContext& cc, const void* serialNo)
|
||||
{
|
||||
if (!serialNo)
|
||||
if (! serialNo)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
m_ctx.ts->erase(H384(serialNo));
|
||||
m_ctx.ts->update(-1, nullptr);
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
struct p_certificateListInternal
|
||||
{
|
||||
Vector< SharedPtr< TrustStore::Entry > > entries;
|
||||
Vector< const ZT_Certificate * > c;
|
||||
Vector< unsigned int > t;
|
||||
struct p_certificateListInternal {
|
||||
Vector<SharedPtr<TrustStore::Entry> > entries;
|
||||
Vector<const ZT_Certificate*> c;
|
||||
Vector<unsigned int> t;
|
||||
};
|
||||
|
||||
static void p_freeCertificateList(const void *cl)
|
||||
static void p_freeCertificateList(const void* cl)
|
||||
{
|
||||
if (cl) {
|
||||
reinterpret_cast<const p_certificateListInternal *>(reinterpret_cast<const uint8_t *>(cl) + sizeof(ZT_CertificateList))->~p_certificateListInternal();
|
||||
free(const_cast<void *>(cl));
|
||||
reinterpret_cast<const p_certificateListInternal*>(
|
||||
reinterpret_cast<const uint8_t*>(cl) + sizeof(ZT_CertificateList))
|
||||
->~p_certificateListInternal();
|
||||
free(const_cast<void*>(cl));
|
||||
}
|
||||
}
|
||||
|
||||
ZT_CertificateList *Node::listCertificates()
|
||||
ZT_CertificateList* Node::listCertificates()
|
||||
{
|
||||
ZT_CertificateList *const cl = (ZT_CertificateList *)malloc(sizeof(ZT_CertificateList) + sizeof(p_certificateListInternal));
|
||||
if (!cl)
|
||||
ZT_CertificateList* const cl =
|
||||
(ZT_CertificateList*)malloc(sizeof(ZT_CertificateList) + sizeof(p_certificateListInternal));
|
||||
if (! cl)
|
||||
return nullptr;
|
||||
|
||||
p_certificateListInternal *const clint = reinterpret_cast<p_certificateListInternal *>(reinterpret_cast<uint8_t *>(cl) + sizeof(ZT_CertificateList));
|
||||
new(clint) p_certificateListInternal;
|
||||
p_certificateListInternal* const clint =
|
||||
reinterpret_cast<p_certificateListInternal*>(reinterpret_cast<uint8_t*>(cl) + sizeof(ZT_CertificateList));
|
||||
new (clint) p_certificateListInternal;
|
||||
|
||||
clint->entries = m_ctx.ts->all(false);
|
||||
clint->c.reserve(clint->entries.size());
|
||||
clint->t.reserve(clint->entries.size());
|
||||
for (Vector< SharedPtr< TrustStore::Entry > >::const_iterator i(clint->entries.begin()); i != clint->entries.end(); ++i) {
|
||||
for (Vector<SharedPtr<TrustStore::Entry> >::const_iterator i(clint->entries.begin()); i != clint->entries.end();
|
||||
++i) {
|
||||
clint->c.push_back(&((*i)->certificate()));
|
||||
clint->t.push_back((*i)->localTrust());
|
||||
}
|
||||
|
@ -564,10 +606,10 @@ ZT_CertificateList *Node::listCertificates()
|
|||
}
|
||||
|
||||
int Node::sendUserMessage(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
uint64_t dest,
|
||||
uint64_t /*typeId*/,
|
||||
const void */*data*/,
|
||||
const void* /*data*/,
|
||||
unsigned int /*len*/)
|
||||
{
|
||||
try {
|
||||
|
@ -582,22 +624,24 @@ int Node::sendUserMessage(
|
|||
*/
|
||||
return 1;
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Node::setController(void *networkControllerInstance)
|
||||
void Node::setController(void* networkControllerInstance)
|
||||
{
|
||||
m_ctx.localNetworkController = reinterpret_cast<NetworkController *>(networkControllerInstance);
|
||||
m_ctx.localNetworkController = reinterpret_cast<NetworkController*>(networkControllerInstance);
|
||||
if (networkControllerInstance)
|
||||
m_ctx.localNetworkController->init(m_ctx.identity, this);
|
||||
}
|
||||
|
||||
bool Node::filterPotentialPath(void *tPtr, const Identity &id, int64_t localSocket, const InetAddress &remoteAddress)
|
||||
bool Node::filterPotentialPath(void* tPtr, const Identity& id, int64_t localSocket, const InetAddress& remoteAddress)
|
||||
{
|
||||
{
|
||||
Mutex::Lock l(m_allNetworks_l);
|
||||
for (Vector< SharedPtr< Network > >::iterator i(m_allNetworks.begin()); i != m_allNetworks.end(); ++i) {
|
||||
for (Vector<SharedPtr<Network> >::iterator i(m_allNetworks.begin()); i != m_allNetworks.end(); ++i) {
|
||||
for (unsigned int k = 0, j = (*i)->config().staticIpCount; k < j; ++k) {
|
||||
if ((*i)->config().staticIps[k].containsAddress(remoteAddress))
|
||||
return false;
|
||||
|
@ -606,62 +650,74 @@ bool Node::filterPotentialPath(void *tPtr, const Identity &id, int64_t localSock
|
|||
}
|
||||
|
||||
if (m_ctx.cb.pathCheckFunction) {
|
||||
return (m_ctx.cb.pathCheckFunction(
|
||||
reinterpret_cast<ZT_Node *>(this),
|
||||
return (
|
||||
m_ctx.cb.pathCheckFunction(
|
||||
reinterpret_cast<ZT_Node*>(this),
|
||||
m_ctx.uPtr,
|
||||
tPtr,
|
||||
id.address().toInt(),
|
||||
(const ZT_Identity *)&id,
|
||||
(const ZT_Identity*)&id,
|
||||
localSocket,
|
||||
reinterpret_cast<const ZT_InetAddress *>(&remoteAddress)) != 0);
|
||||
reinterpret_cast<const ZT_InetAddress*>(&remoteAddress))
|
||||
!= 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Node::externalPathLookup(void *tPtr, const Identity &id, int family, InetAddress &addr)
|
||||
bool Node::externalPathLookup(void* tPtr, const Identity& id, int family, InetAddress& addr)
|
||||
{
|
||||
if (m_ctx.cb.pathLookupFunction) {
|
||||
return (m_ctx.cb.pathLookupFunction(
|
||||
reinterpret_cast<ZT_Node *>(this),
|
||||
return (
|
||||
m_ctx.cb.pathLookupFunction(
|
||||
reinterpret_cast<ZT_Node*>(this),
|
||||
m_ctx.uPtr,
|
||||
tPtr,
|
||||
id.address().toInt(),
|
||||
reinterpret_cast<const ZT_Identity *>(&id),
|
||||
reinterpret_cast<const ZT_Identity*>(&id),
|
||||
family,
|
||||
reinterpret_cast<ZT_InetAddress *>(&addr)) == ZT_RESULT_OK);
|
||||
reinterpret_cast<ZT_InetAddress*>(&addr))
|
||||
== ZT_RESULT_OK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implementation of NetworkController::Sender ------------------------------------------------------------------------
|
||||
|
||||
void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig)
|
||||
void Node::ncSendConfig(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
const NetworkConfig& nc,
|
||||
bool sendLegacyFormatConfig)
|
||||
{
|
||||
if (destination == m_ctx.identity.address()) {
|
||||
SharedPtr< Network > n(m_ctx.networks->get(nwid));
|
||||
if (!n)
|
||||
SharedPtr<Network> n(m_ctx.networks->get(nwid));
|
||||
if (! n)
|
||||
return;
|
||||
CallContext cc(clock, ticks, tPtr);
|
||||
n->setConfiguration(cc, nc, true);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Dictionary dconf;
|
||||
if (nc.toDictionary(dconf)) {
|
||||
uint64_t configUpdateId = Utils::random();
|
||||
if (!configUpdateId)
|
||||
if (! configUpdateId)
|
||||
++configUpdateId;
|
||||
|
||||
Vector< uint8_t > ddata;
|
||||
Vector<uint8_t> ddata;
|
||||
dconf.encode(ddata);
|
||||
// TODO
|
||||
/*
|
||||
unsigned int chunkIndex = 0;
|
||||
while (chunkIndex < totalSize) {
|
||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256)));
|
||||
Packet outp(destination,m_ctx.identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG);
|
||||
if (requestPacketId) {
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH
|
||||
- (ZT_PACKET_IDX_PAYLOAD + 256))); Packet outp(destination,m_ctx.identity.address(),(requestPacketId) ?
|
||||
Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG); if (requestPacketId) { outp.append((unsigned
|
||||
char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append(requestPacketId);
|
||||
}
|
||||
|
||||
const unsigned int sigStart = outp.size();
|
||||
|
@ -675,9 +731,8 @@ void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
outp.append((uint32_t)chunkIndex);
|
||||
|
||||
uint8_t sig[256];
|
||||
const unsigned int siglen = m_ctx.identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart,sig,sizeof(sig));
|
||||
outp.append((uint8_t)1);
|
||||
outp.append((uint16_t)siglen);
|
||||
const unsigned int siglen = m_ctx.identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) +
|
||||
sigStart,outp.size() - sigStart,sig,sizeof(sig)); outp.append((uint8_t)1); outp.append((uint16_t)siglen);
|
||||
outp.append(sig,siglen);
|
||||
|
||||
outp.compress();
|
||||
|
@ -689,15 +744,21 @@ void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
}
|
||||
}
|
||||
|
||||
void Node::ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev)
|
||||
void Node::ncSendRevocation(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
const Address& destination,
|
||||
const RevocationCredential& rev)
|
||||
{
|
||||
if (destination == m_ctx.identity.address()) {
|
||||
SharedPtr< Network > n(m_ctx.networks->get(rev.networkId()));
|
||||
if (!n)
|
||||
SharedPtr<Network> n(m_ctx.networks->get(rev.networkId()));
|
||||
if (! n)
|
||||
return;
|
||||
CallContext cc(clock, ticks, tPtr);
|
||||
n->addCredential(cc, m_ctx.identity, rev);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
/*
|
||||
Packet outp(destination,m_ctx.identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||
|
@ -712,11 +773,18 @@ void Node::ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Addr
|
|||
}
|
||||
}
|
||||
|
||||
void Node::ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode)
|
||||
void Node::ncSendError(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
NetworkController::ErrorCode errorCode)
|
||||
{
|
||||
if (destination == m_ctx.identity.address()) {
|
||||
SharedPtr< Network > n(m_ctx.networks->get(nwid));
|
||||
if (!n)
|
||||
SharedPtr<Network> n(m_ctx.networks->get(nwid));
|
||||
if (! n)
|
||||
return;
|
||||
switch (errorCode) {
|
||||
case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
|
||||
|
@ -730,7 +798,8 @@ void Node::ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (requestPacketId) {
|
||||
}
|
||||
else if (requestPacketId) {
|
||||
// TODO
|
||||
/*
|
||||
Packet outp(destination,m_ctx.identity.address(),Packet::VERB_ERROR);
|
||||
|
|
159
core/Node.hpp
159
core/Node.hpp
|
@ -14,19 +14,19 @@
|
|||
#ifndef ZT_NODE_HPP
|
||||
#define ZT_NODE_HPP
|
||||
|
||||
#include "Buf.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Store.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -35,89 +35,64 @@ namespace ZeroTier {
|
|||
*
|
||||
* The pointer returned by ZT_Node_new() is an instance of this class.
|
||||
*/
|
||||
class Node : public NetworkController::Sender
|
||||
{
|
||||
public:
|
||||
class Node : public NetworkController::Sender {
|
||||
public:
|
||||
// Get rid of alignment warnings on 32-bit Windows
|
||||
#ifdef __WINDOWS__
|
||||
void * operator new(size_t i) { return _mm_malloc(i,16); }
|
||||
void operator delete(void* p) { _mm_free(p); }
|
||||
void* operator new(size_t i)
|
||||
{
|
||||
return _mm_malloc(i, 16);
|
||||
}
|
||||
void operator delete(void* p)
|
||||
{
|
||||
_mm_free(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
Node(void *uPtr, const struct ZT_Node_Callbacks *callbacks, const CallContext &cc);
|
||||
Node(void* uPtr, const struct ZT_Node_Callbacks* callbacks, const CallContext& cc);
|
||||
|
||||
virtual ~Node();
|
||||
|
||||
void shutdown(const CallContext &cc);
|
||||
void shutdown(const CallContext& cc);
|
||||
|
||||
ZT_ResultCode processBackgroundTasks(
|
||||
const CallContext &cc,
|
||||
volatile int64_t *nextBackgroundTaskDeadline);
|
||||
ZT_ResultCode processBackgroundTasks(const CallContext& cc, volatile int64_t* nextBackgroundTaskDeadline);
|
||||
|
||||
ZT_ResultCode join(
|
||||
uint64_t nwid,
|
||||
const ZT_Fingerprint *controllerFingerprint,
|
||||
void *uptr,
|
||||
const CallContext &cc);
|
||||
ZT_ResultCode join(uint64_t nwid, const ZT_Fingerprint* controllerFingerprint, void* uptr, const CallContext& cc);
|
||||
|
||||
ZT_ResultCode leave(
|
||||
uint64_t nwid,
|
||||
void **uptr,
|
||||
const CallContext &cc);
|
||||
ZT_ResultCode leave(uint64_t nwid, void** uptr, const CallContext& cc);
|
||||
|
||||
ZT_ResultCode multicastSubscribe(
|
||||
const CallContext &cc,
|
||||
uint64_t nwid,
|
||||
uint64_t multicastGroup,
|
||||
unsigned long multicastAdi);
|
||||
ZT_ResultCode
|
||||
multicastSubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi);
|
||||
|
||||
ZT_ResultCode multicastUnsubscribe(
|
||||
const CallContext &cc,
|
||||
uint64_t nwid,
|
||||
uint64_t multicastGroup,
|
||||
unsigned long multicastAdi);
|
||||
ZT_ResultCode
|
||||
multicastUnsubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi);
|
||||
|
||||
void status(
|
||||
ZT_NodeStatus *status) const;
|
||||
void status(ZT_NodeStatus* status) const;
|
||||
|
||||
ZT_PeerList *peers(
|
||||
const CallContext &cc) const;
|
||||
ZT_PeerList* peers(const CallContext& cc) const;
|
||||
|
||||
ZT_VirtualNetworkConfig *networkConfig(
|
||||
uint64_t nwid) const;
|
||||
ZT_VirtualNetworkConfig* networkConfig(uint64_t nwid) const;
|
||||
|
||||
ZT_VirtualNetworkList *networks() const;
|
||||
ZT_VirtualNetworkList* networks() const;
|
||||
|
||||
void setNetworkUserPtr(
|
||||
uint64_t nwid,
|
||||
void *ptr);
|
||||
void setNetworkUserPtr(uint64_t nwid, void* ptr);
|
||||
|
||||
void setInterfaceAddresses(
|
||||
const ZT_InterfaceAddress *addrs,
|
||||
unsigned int addrCount);
|
||||
void setInterfaceAddresses(const ZT_InterfaceAddress* addrs, unsigned int addrCount);
|
||||
|
||||
ZT_CertificateError addCertificate(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
unsigned int localTrust,
|
||||
const ZT_Certificate *cert,
|
||||
const void *certData,
|
||||
const ZT_Certificate* cert,
|
||||
const void* certData,
|
||||
unsigned int certSize);
|
||||
|
||||
ZT_ResultCode deleteCertificate(
|
||||
const CallContext &cc,
|
||||
const void *serialNo);
|
||||
ZT_ResultCode deleteCertificate(const CallContext& cc, const void* serialNo);
|
||||
|
||||
ZT_CertificateList *listCertificates();
|
||||
ZT_CertificateList* listCertificates();
|
||||
|
||||
int sendUserMessage(
|
||||
const CallContext &cc,
|
||||
uint64_t dest,
|
||||
uint64_t typeId,
|
||||
const void *data,
|
||||
unsigned int len);
|
||||
int sendUserMessage(const CallContext& cc, uint64_t dest, uint64_t typeId, const void* data, unsigned int len);
|
||||
|
||||
void setController(
|
||||
void *networkControllerInstance);
|
||||
void setController(void* networkControllerInstance);
|
||||
|
||||
/**
|
||||
* Post an event via external callback
|
||||
|
@ -127,8 +102,12 @@ public:
|
|||
* @param md Event data or NULL if none
|
||||
* @param mdSize Size of event data
|
||||
*/
|
||||
ZT_INLINE void postEvent(void *const tPtr, const ZT_Event ev, const void *const md = nullptr, const unsigned int mdSize = 0) noexcept
|
||||
{ m_ctx.cb.eventCallback(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, tPtr, ev, md, mdSize); }
|
||||
ZT_INLINE void
|
||||
postEvent(void* const tPtr, const ZT_Event ev, const void* const md = nullptr, const unsigned int mdSize = 0)
|
||||
noexcept
|
||||
{
|
||||
m_ctx.cb.eventCallback(reinterpret_cast<ZT_Node*>(this), m_ctx.uPtr, tPtr, ev, md, mdSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a path should be used for ZeroTier traffic
|
||||
|
@ -141,7 +120,7 @@ public:
|
|||
* @param remoteAddress Remote address
|
||||
* @return True if path should be used
|
||||
*/
|
||||
bool filterPotentialPath(void *tPtr, const Identity &id, int64_t localSocket, const InetAddress &remoteAddress);
|
||||
bool filterPotentialPath(void* tPtr, const Identity& id, int64_t localSocket, const InetAddress& remoteAddress);
|
||||
|
||||
/**
|
||||
* Query callback for a physical address for a peer
|
||||
|
@ -152,35 +131,59 @@ public:
|
|||
* @param addr Buffer to store address (result paramter)
|
||||
* @return True if addr was filled with something
|
||||
*/
|
||||
bool externalPathLookup(void *tPtr, const Identity &id, int family, InetAddress &addr);
|
||||
bool externalPathLookup(void* tPtr, const Identity& id, int family, InetAddress& addr);
|
||||
|
||||
ZT_INLINE const Identity &identity() const noexcept
|
||||
{ return m_ctx.identity; }
|
||||
ZT_INLINE const Identity& identity() const noexcept
|
||||
{
|
||||
return m_ctx.identity;
|
||||
}
|
||||
|
||||
ZT_INLINE const Context &context() const noexcept
|
||||
{ return m_ctx; }
|
||||
ZT_INLINE const Context& context() const noexcept
|
||||
{
|
||||
return m_ctx;
|
||||
}
|
||||
|
||||
// Implementation of NetworkController::Sender interface
|
||||
virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig);
|
||||
virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev);
|
||||
virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode);
|
||||
virtual void ncSendConfig(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
const NetworkConfig& nc,
|
||||
bool sendLegacyFormatConfig);
|
||||
virtual void ncSendRevocation(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
const Address& destination,
|
||||
const RevocationCredential& rev);
|
||||
virtual void ncSendError(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
NetworkController::ErrorCode errorCode);
|
||||
|
||||
private:
|
||||
private:
|
||||
Context m_ctx;
|
||||
|
||||
// Data store wrapper
|
||||
Store m_store;
|
||||
|
||||
// Pointer to a struct defined in Node that holds instances of core objects.
|
||||
void *m_objects;
|
||||
void* m_objects;
|
||||
|
||||
// This stores networks for rapid iteration, while RR->networks is the primary lookup.
|
||||
Vector< SharedPtr< Network > > m_allNetworks;
|
||||
Vector<SharedPtr<Network> > m_allNetworks;
|
||||
Mutex m_allNetworks_l;
|
||||
|
||||
// These are local interface addresses that have been configured via the API
|
||||
// and can be pushed to other nodes.
|
||||
Vector< ZT_InterfaceAddress > m_localInterfaceAddresses;
|
||||
Vector<ZT_InterfaceAddress> m_localInterfaceAddresses;
|
||||
Mutex m_localInterfaceAddresses_m;
|
||||
|
||||
// This is locked while running processBackgroundTasks().
|
||||
|
@ -193,7 +196,7 @@ private:
|
|||
int64_t m_lastTrustStoreUpdate;
|
||||
|
||||
// True if at least one root appears reachable.
|
||||
std::atomic< bool > m_online;
|
||||
std::atomic<bool> m_online;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
41
core/OS.hpp
41
core/OS.hpp
|
@ -17,7 +17,9 @@
|
|||
/* Uncomment this to force a whole lot of debug output. */
|
||||
#define ZT_DEBUG_SPEW
|
||||
|
||||
#if !defined(__GNUC__) && (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__INTEL_COMPILER) || defined(__clang__))
|
||||
#if ! defined(__GNUC__) \
|
||||
&& (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
|
||||
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__INTEL_COMPILER) || defined(__clang__))
|
||||
#define __GNUC__ 3
|
||||
#endif
|
||||
|
||||
|
@ -48,46 +50,50 @@
|
|||
#undef __BSD__
|
||||
#endif
|
||||
|
||||
#include <Shlobj.h>
|
||||
#include <WinSock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <Windows.h>
|
||||
#include <memoryapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <Shlobj.h>
|
||||
#include <sys/param.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#endif /* Microsoft Windows */
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#endif /* NOT Microsoft Windows */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||
#if ( \
|
||||
defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) \
|
||||
|| defined(__AMD64__) || defined(_M_X64))
|
||||
#define ZT_ARCH_X64 1
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <immintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#if defined(ZT_ARCH_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386)
|
||||
#if defined(ZT_ARCH_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) \
|
||||
|| defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) \
|
||||
|| defined(__I86__) || defined(__INTEL__) || defined(__386)
|
||||
#define ZT_ARCH_X86 1
|
||||
#endif
|
||||
|
||||
#if !defined(ZT_ARCH_X86)
|
||||
#if ! defined(ZT_ARCH_X86)
|
||||
#ifndef ZT_NO_UNALIGNED_ACCESS
|
||||
#define ZT_NO_UNALIGNED_ACCESS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(ZT_ARCH_ARM_HAS_NEON)
|
||||
#if (defined(__APPLE__) && !defined(__LP64__)) || (defined(__ANDROID__) && defined(__arm__))
|
||||
#if (defined(__APPLE__) && ! defined(__LP64__)) || (defined(__ANDROID__) && defined(__arm__))
|
||||
#ifdef ZT_ARCH_ARM_HAS_NEON
|
||||
#undef ZT_ARCH_ARM_HAS_NEON
|
||||
#endif
|
||||
|
@ -225,7 +231,7 @@
|
|||
|
||||
#ifndef likely
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define likely(x) __builtin_expect((x),1)
|
||||
#define likely(x) __builtin_expect((x), 1)
|
||||
#else
|
||||
#define likely(x) x
|
||||
#endif
|
||||
|
@ -233,7 +239,7 @@
|
|||
|
||||
#ifndef unlikely
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define unlikely(x) __builtin_expect((x),0)
|
||||
#define unlikely(x) __builtin_expect((x), 0)
|
||||
#else
|
||||
#define unlikely(x) x
|
||||
#endif
|
||||
|
@ -249,17 +255,17 @@ typedef unsigned uint128_t __attribute__((mode(TI)));
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(__BYTE_ORDER) && defined(__BYTE_ORDER__)
|
||||
#if ! defined(__BYTE_ORDER) && defined(__BYTE_ORDER__)
|
||||
#define __BYTE_ORDER __BYTE_ORDER__
|
||||
#define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
|
||||
#define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||
#endif
|
||||
#if !defined(__BYTE_ORDER) && defined(BYTE_ORDER)
|
||||
#if ! defined(__BYTE_ORDER) && defined(BYTE_ORDER)
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#define __BIG_ENDIAN BIG_ENDIAN
|
||||
#endif
|
||||
#if !defined(__BYTE_ORDER) && defined(_BYTE_ORDER)
|
||||
#if ! defined(__BYTE_ORDER) && defined(_BYTE_ORDER)
|
||||
#define __BYTE_ORDER _BYTE_ORDER
|
||||
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
|
||||
#define __BIG_ENDIAN _BIG_ENDIAN
|
||||
|
@ -268,9 +274,10 @@ typedef unsigned uint128_t __attribute__((mode(TI)));
|
|||
#define ZT_VA_ARGS(...) , ##__VA_ARGS__
|
||||
|
||||
#ifdef ZT_DEBUG_SPEW
|
||||
#define ZT_SPEW(f,...) fprintf(stderr,"%s:%d(%s): " f ZT_EOL_S,__FILE__,__LINE__,__FUNCTION__ ZT_VA_ARGS(__VA_ARGS__))
|
||||
#define ZT_SPEW(f, ...) \
|
||||
fprintf(stderr, "%s:%d(%s): " f ZT_EOL_S, __FILE__, __LINE__, __FUNCTION__ ZT_VA_ARGS(__VA_ARGS__))
|
||||
#else
|
||||
#define ZT_SPEW(f,...)
|
||||
#define ZT_SPEW(f, ...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,22 +15,27 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
void OwnershipCredential::addThing(const InetAddress &ip)
|
||||
void OwnershipCredential::addThing(const InetAddress& ip)
|
||||
{
|
||||
if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS)
|
||||
return;
|
||||
if (ip.as.sa.sa_family == AF_INET) {
|
||||
m_thingTypes[m_thingCount] = THING_IPV4_ADDRESS;
|
||||
Utils::copy<4>(m_thingValues[m_thingCount], &(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr));
|
||||
Utils::copy<4>(
|
||||
m_thingValues[m_thingCount],
|
||||
&(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr));
|
||||
++m_thingCount;
|
||||
} else if (ip.as.sa.sa_family == AF_INET6) {
|
||||
}
|
||||
else if (ip.as.sa.sa_family == AF_INET6) {
|
||||
m_thingTypes[m_thingCount] = THING_IPV6_ADDRESS;
|
||||
Utils::copy<16>(m_thingValues[m_thingCount], reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr);
|
||||
Utils::copy<16>(
|
||||
m_thingValues[m_thingCount],
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr);
|
||||
++m_thingCount;
|
||||
}
|
||||
}
|
||||
|
||||
void OwnershipCredential::addThing(const MAC &mac)
|
||||
void OwnershipCredential::addThing(const MAC& mac)
|
||||
{
|
||||
if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS)
|
||||
return;
|
||||
|
@ -39,12 +44,12 @@ void OwnershipCredential::addThing(const MAC &mac)
|
|||
++m_thingCount;
|
||||
}
|
||||
|
||||
bool OwnershipCredential::sign(const Identity &signer)
|
||||
bool OwnershipCredential::sign(const Identity& signer)
|
||||
{
|
||||
uint8_t buf[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX + 16];
|
||||
if (signer.hasPrivate()) {
|
||||
m_signedBy = signer.address();
|
||||
m_signatureLength = signer.sign(buf, (unsigned int) marshal(buf, true), m_signature, sizeof(m_signature));
|
||||
m_signatureLength = signer.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -54,16 +59,16 @@ int OwnershipCredential::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_
|
|||
{
|
||||
int p = 0;
|
||||
if (forSign) {
|
||||
for (int k = 0;k < 16;++k)
|
||||
for (int k = 0; k < 16; ++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
Utils::storeBigEndian<uint64_t>(data + p, m_networkId);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, (uint64_t) m_ts);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, (uint64_t)m_ts);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 16, m_flags);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 24, m_id);
|
||||
Utils::storeBigEndian<uint16_t>(data + p + 28, (uint16_t) m_thingCount);
|
||||
Utils::storeBigEndian<uint16_t>(data + p + 28, (uint16_t)m_thingCount);
|
||||
p += 30;
|
||||
for (unsigned int i = 0, j = m_thingCount;i < j;++i) {
|
||||
for (unsigned int i = 0, j = m_thingCount; i < j; ++i) {
|
||||
data[p++] = m_thingTypes[i];
|
||||
Utils::copy<ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE>(data + p, m_thingValues[i]);
|
||||
p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE;
|
||||
|
@ -72,29 +77,29 @@ int OwnershipCredential::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_
|
|||
p += ZT_ADDRESS_LENGTH;
|
||||
m_signedBy.copyTo(data + p);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
if (!forSign) {
|
||||
if (! forSign) {
|
||||
data[p++] = 1;
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_signatureLength);
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_signatureLength);
|
||||
p += 2;
|
||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||
p += (int) m_signatureLength;
|
||||
p += (int)m_signatureLength;
|
||||
}
|
||||
data[p++] = 0;
|
||||
data[p++] = 0;
|
||||
if (forSign) {
|
||||
for (int k = 0;k < 16;++k)
|
||||
for (int k = 0; k < 16; ++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int OwnershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
||||
int OwnershipCredential::unmarshal(const uint8_t* data, int len) noexcept
|
||||
{
|
||||
if (len < 30)
|
||||
return -1;
|
||||
|
||||
m_networkId = Utils::loadBigEndian<uint64_t>(data);
|
||||
m_ts = (int64_t) Utils::loadBigEndian<uint64_t>(data + 8);
|
||||
m_ts = (int64_t)Utils::loadBigEndian<uint64_t>(data + 8);
|
||||
m_flags = Utils::loadBigEndian<uint64_t>(data + 16);
|
||||
m_id = Utils::loadBigEndian<uint32_t>(data + 24);
|
||||
m_thingCount = Utils::loadBigEndian<uint16_t>(data + 28);
|
||||
|
@ -102,7 +107,7 @@ int OwnershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
return -1;
|
||||
int p = 30;
|
||||
|
||||
for (unsigned int i = 0, j = m_thingCount;i < j;++i) {
|
||||
for (unsigned int i = 0, j = m_thingCount; i < j; ++i) {
|
||||
if ((p + 1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) > len)
|
||||
return -1;
|
||||
m_thingTypes[i] = data[p++];
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
#ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MAC.hpp"
|
||||
|
@ -28,7 +28,9 @@
|
|||
// Maximum size of a thing's value field in bytes
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE 16
|
||||
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX (8 + 8 + 8 + 4 + 2 + ((1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) * ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) + 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX \
|
||||
(8 + 8 + 8 + 4 + 2 + ((1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) * ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) \
|
||||
+ 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -40,26 +42,24 @@ class Context;
|
|||
* These are used in conjunction with the rules engine to make IP addresses and
|
||||
* other identifiers un-spoofable.
|
||||
*/
|
||||
class OwnershipCredential : public Credential
|
||||
{
|
||||
class OwnershipCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_COO; }
|
||||
|
||||
enum Thing
|
||||
{
|
||||
THING_NULL = 0,
|
||||
THING_MAC_ADDRESS = 1,
|
||||
THING_IPV4_ADDRESS = 2,
|
||||
THING_IPV6_ADDRESS = 3
|
||||
};
|
||||
return ZT_CREDENTIAL_TYPE_COO;
|
||||
}
|
||||
|
||||
enum Thing { THING_NULL = 0, THING_MAC_ADDRESS = 1, THING_IPV4_ADDRESS = 2, THING_IPV6_ADDRESS = 3 };
|
||||
|
||||
ZT_INLINE OwnershipCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id) noexcept
|
||||
ZT_INLINE
|
||||
OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address& issuedTo, const uint32_t id) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
m_networkId = nwid;
|
||||
|
@ -69,48 +69,77 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_ts; }
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_ts; }
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
|
||||
ZT_INLINE const Address &issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
|
||||
ZT_INLINE const Address &signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
|
||||
ZT_INLINE const uint8_t *signature() const noexcept
|
||||
{ return m_signature; }
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
|
||||
ZT_INLINE unsigned int thingCount() const noexcept
|
||||
{ return (unsigned int)m_thingCount; }
|
||||
|
||||
ZT_INLINE Thing thingType(const unsigned int i) const noexcept
|
||||
{ return (Thing)m_thingTypes[i]; }
|
||||
|
||||
ZT_INLINE const uint8_t *thingValue(const unsigned int i) const noexcept
|
||||
{ return m_thingValues[i]; }
|
||||
|
||||
ZT_INLINE bool owns(const InetAddress &ip) const noexcept
|
||||
{
|
||||
if (ip.as.sa.sa_family == AF_INET)
|
||||
return this->_owns(THING_IPV4_ADDRESS, &(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr), 4);
|
||||
else if (ip.as.sa.sa_family == AF_INET6)
|
||||
return this->_owns(THING_IPV6_ADDRESS, reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr, 16);
|
||||
else return false;
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
ZT_INLINE bool owns(const MAC &mac) const noexcept
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& issuedTo() const noexcept
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int thingCount() const noexcept
|
||||
{
|
||||
return (unsigned int)m_thingCount;
|
||||
}
|
||||
|
||||
ZT_INLINE Thing thingType(const unsigned int i) const noexcept
|
||||
{
|
||||
return (Thing)m_thingTypes[i];
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t* thingValue(const unsigned int i) const noexcept
|
||||
{
|
||||
return m_thingValues[i];
|
||||
}
|
||||
|
||||
ZT_INLINE bool owns(const InetAddress& ip) const noexcept
|
||||
{
|
||||
if (ip.as.sa.sa_family == AF_INET)
|
||||
return this->_owns(
|
||||
THING_IPV4_ADDRESS,
|
||||
&(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr),
|
||||
4);
|
||||
else if (ip.as.sa.sa_family == AF_INET6)
|
||||
return this->_owns(
|
||||
THING_IPV6_ADDRESS,
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr,
|
||||
16);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE bool owns(const MAC& mac) const noexcept
|
||||
{
|
||||
uint8_t tmp[6];
|
||||
mac.copyTo(tmp);
|
||||
|
@ -122,7 +151,7 @@ public:
|
|||
*
|
||||
* @param ip IPv4 or IPv6 address
|
||||
*/
|
||||
void addThing(const InetAddress &ip);
|
||||
void addThing(const InetAddress& ip);
|
||||
|
||||
/**
|
||||
* Add an Ethernet MAC address
|
||||
|
@ -133,7 +162,7 @@ public:
|
|||
*
|
||||
* @param mac 48-bit MAC address
|
||||
*/
|
||||
void addThing(const MAC &mac);
|
||||
void addThing(const MAC& mac);
|
||||
|
||||
/**
|
||||
* Sign this certificate
|
||||
|
@ -141,40 +170,50 @@ public:
|
|||
* @param signer Signing identity, must have private key
|
||||
* @return True if signature was successful
|
||||
*/
|
||||
bool sign(const Identity &signer);
|
||||
bool sign(const Identity& signer);
|
||||
|
||||
/**
|
||||
* Verify certificate signature
|
||||
*
|
||||
* @return Credential verification result: OK, bad signature, or identity needed
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context &ctx, const CallContext &cc) const
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_INLINE bool operator<(const OwnershipCredential &coo) const noexcept
|
||||
{ return (m_id < coo.m_id); }
|
||||
ZT_INLINE bool operator<(const OwnershipCredential& coo) const noexcept
|
||||
{
|
||||
return (m_id < coo.m_id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const OwnershipCredential &coo) const noexcept
|
||||
{ return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0); }
|
||||
ZT_INLINE bool operator==(const OwnershipCredential& coo) const noexcept
|
||||
{
|
||||
return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const OwnershipCredential &coo) const noexcept
|
||||
{ return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); }
|
||||
ZT_INLINE bool operator!=(const OwnershipCredential& coo) const noexcept
|
||||
{
|
||||
return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE bool _owns(const Thing &t, const void *v, unsigned int l) const noexcept
|
||||
private:
|
||||
ZT_INLINE bool _owns(const Thing& t, const void* v, unsigned int l) const noexcept
|
||||
{
|
||||
for (unsigned int i = 0, j = m_thingCount; i < j; ++i) {
|
||||
if (m_thingTypes[i] == (uint8_t)t) {
|
||||
unsigned int k = 0;
|
||||
while (k < l) {
|
||||
if (reinterpret_cast<const uint8_t *>(v)[k] != m_thingValues[i][k])
|
||||
if (reinterpret_cast<const uint8_t*>(v)[k] != m_thingValues[i][k])
|
||||
break;
|
||||
++k;
|
||||
}
|
||||
|
|
|
@ -12,14 +12,25 @@
|
|||
/****/
|
||||
|
||||
#include "Path.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool Path::send(const Context &ctx, const CallContext &cc, const void *const data, const unsigned int len) noexcept
|
||||
bool Path::send(const Context& ctx, const CallContext& cc, const void* const data, const unsigned int len) noexcept
|
||||
{
|
||||
if (likely(ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, m_localSocket, reinterpret_cast<const ZT_InetAddress *>(&m_addr), data, len, 0) == 0)) {
|
||||
if (likely(
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
m_localSocket,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&m_addr),
|
||||
data,
|
||||
len,
|
||||
0)
|
||||
== 0)) {
|
||||
m_lastOut = cc.ticks;
|
||||
m_outMeter.log(cc.ticks, len);
|
||||
return true;
|
||||
|
|
152
core/Path.hpp
152
core/Path.hpp
|
@ -14,61 +14,63 @@
|
|||
#ifndef ZT_PATH_HPP
|
||||
#define ZT_PATH_HPP
|
||||
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Meter.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Meter.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class Context;
|
||||
|
||||
template< unsigned int MF, unsigned int MFP, unsigned int GCT, unsigned int GCS, typename P >
|
||||
class Defragmenter;
|
||||
template <unsigned int MF, unsigned int MFP, unsigned int GCT, unsigned int GCS, typename P> class Defragmenter;
|
||||
|
||||
/**
|
||||
* A path across the physical network
|
||||
*/
|
||||
class Path
|
||||
{
|
||||
friend class SharedPtr< Path >;
|
||||
class Path {
|
||||
friend class SharedPtr<Path>;
|
||||
|
||||
// Allow defragmenter to access fragment-in-flight info stored in Path for performance reasons.
|
||||
template< unsigned int MF, unsigned int MFP, unsigned int GCT, unsigned int GCS, typename P >
|
||||
friend
|
||||
class Defragmenter;
|
||||
template <unsigned int MF, unsigned int MFP, unsigned int GCT, unsigned int GCS, typename P>
|
||||
friend class Defragmenter;
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Map key for paths designed for very fast lookup
|
||||
*/
|
||||
class Key
|
||||
{
|
||||
class Key {
|
||||
public:
|
||||
ZT_INLINE Key() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Key(const InetAddress &ip) noexcept
|
||||
ZT_INLINE Key(const InetAddress& ip) noexcept
|
||||
{
|
||||
const unsigned int family = ip.as.sa.sa_family;
|
||||
if (family == AF_INET) {
|
||||
const uint16_t p = (uint16_t)ip.as.sa_in.sin_port;
|
||||
m_hashCode = Utils::hash64((((uint64_t)ip.as.sa_in.sin_addr.s_addr) << 16U) ^ ((uint64_t)p) ^ Utils::s_mapNonce);
|
||||
m_hashCode =
|
||||
Utils::hash64((((uint64_t)ip.as.sa_in.sin_addr.s_addr) << 16U) ^ ((uint64_t)p) ^ Utils::s_mapNonce);
|
||||
m_ipv6Net64 = 0; // 0 for IPv4, never 0 for IPv6
|
||||
m_port = p;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (likely(family == AF_INET6)) {
|
||||
const uint64_t a = Utils::loadMachineEndian< uint64_t >(reinterpret_cast<const uint8_t *>(ip.as.sa_in6.sin6_addr.s6_addr));
|
||||
const uint64_t b = Utils::loadMachineEndian< uint64_t >(reinterpret_cast<const uint8_t *>(ip.as.sa_in6.sin6_addr.s6_addr) + 8);
|
||||
const uint64_t a = Utils::loadMachineEndian<uint64_t>(
|
||||
reinterpret_cast<const uint8_t*>(ip.as.sa_in6.sin6_addr.s6_addr));
|
||||
const uint64_t b = Utils::loadMachineEndian<uint64_t>(
|
||||
reinterpret_cast<const uint8_t*>(ip.as.sa_in6.sin6_addr.s6_addr) + 8);
|
||||
const uint16_t p = ip.as.sa_in6.sin6_port;
|
||||
m_hashCode = Utils::hash64(a ^ b ^ ((uint64_t)p) ^ Utils::s_mapNonce);
|
||||
m_ipv6Net64 = a; // IPv6 /64
|
||||
m_port = p;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// This is not reachable since InetAddress can only be AF_INET or AF_INET6, but implement something.
|
||||
m_hashCode = Utils::fnv1a32(&ip, sizeof(InetAddress));
|
||||
m_ipv6Net64 = 0;
|
||||
|
@ -78,36 +80,50 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)m_hashCode; }
|
||||
{
|
||||
return (unsigned long)m_hashCode;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Key &k) const noexcept
|
||||
{ return (m_hashCode == k.m_hashCode) && (m_ipv6Net64 == k.m_ipv6Net64) && (m_port == k.m_port); }
|
||||
ZT_INLINE bool operator==(const Key& k) const noexcept
|
||||
{
|
||||
return (m_hashCode == k.m_hashCode) && (m_ipv6Net64 == k.m_ipv6Net64) && (m_port == k.m_port);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Key &k) const noexcept
|
||||
{ return (!(*this == k)); }
|
||||
ZT_INLINE bool operator!=(const Key& k) const noexcept
|
||||
{
|
||||
return (! (*this == k));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Key &k) const noexcept
|
||||
ZT_INLINE bool operator<(const Key& k) const noexcept
|
||||
{
|
||||
if (m_hashCode < k.m_hashCode) {
|
||||
return true;
|
||||
} else if (m_hashCode == k.m_hashCode) {
|
||||
}
|
||||
else if (m_hashCode == k.m_hashCode) {
|
||||
if (m_ipv6Net64 < k.m_ipv6Net64) {
|
||||
return true;
|
||||
} else if (m_ipv6Net64 == k.m_ipv6Net64) {
|
||||
}
|
||||
else if (m_ipv6Net64 == k.m_ipv6Net64) {
|
||||
return (m_port < k.m_port);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Key &k) const noexcept
|
||||
{ return (k < *this); }
|
||||
ZT_INLINE bool operator>(const Key& k) const noexcept
|
||||
{
|
||||
return (k < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Key &k) const noexcept
|
||||
{ return !(k < *this); }
|
||||
ZT_INLINE bool operator<=(const Key& k) const noexcept
|
||||
{
|
||||
return ! (k < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Key &k) const noexcept
|
||||
{ return !(*this < k); }
|
||||
ZT_INLINE bool operator>=(const Key& k) const noexcept
|
||||
{
|
||||
return ! (*this < k);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_hashCode;
|
||||
|
@ -115,13 +131,14 @@ public:
|
|||
uint16_t m_port;
|
||||
};
|
||||
|
||||
ZT_INLINE Path(const int64_t l, const InetAddress &r) noexcept:
|
||||
m_localSocket(l),
|
||||
m_lastIn(0),
|
||||
m_lastOut(0),
|
||||
m_latency(-1),
|
||||
m_addr(r)
|
||||
{}
|
||||
ZT_INLINE Path(const int64_t l, const InetAddress& r) noexcept
|
||||
: m_localSocket(l)
|
||||
, m_lastIn(0)
|
||||
, m_lastOut(0)
|
||||
, m_latency(-1)
|
||||
, m_addr(r)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet via this path (last out time is also updated)
|
||||
|
@ -130,7 +147,7 @@ public:
|
|||
* @param len Packet length
|
||||
* @return True if transport reported success
|
||||
*/
|
||||
bool send(const Context &ctx, const CallContext &cc, const void *data, unsigned int len) noexcept;
|
||||
bool send(const Context& ctx, const CallContext& cc, const void* data, unsigned int len) noexcept;
|
||||
|
||||
/**
|
||||
* Explicitly update last sent time
|
||||
|
@ -138,7 +155,7 @@ public:
|
|||
* @param now Time of send
|
||||
* @param bytes Bytes sent
|
||||
*/
|
||||
ZT_INLINE void sent(const CallContext &cc, const unsigned int bytes) noexcept
|
||||
ZT_INLINE void sent(const CallContext& cc, const unsigned int bytes) noexcept
|
||||
{
|
||||
m_lastOut.store(cc.ticks, std::memory_order_relaxed);
|
||||
m_outMeter.log(cc.ticks, bytes);
|
||||
|
@ -150,7 +167,7 @@ public:
|
|||
* @param now Time of receive
|
||||
* @param bytes Bytes received
|
||||
*/
|
||||
ZT_INLINE void received(const CallContext &cc, const unsigned int bytes) noexcept
|
||||
ZT_INLINE void received(const CallContext& cc, const unsigned int bytes) noexcept
|
||||
{
|
||||
m_lastIn.store(cc.ticks, std::memory_order_relaxed);
|
||||
m_inMeter.log(cc.ticks, bytes);
|
||||
|
@ -166,7 +183,8 @@ public:
|
|||
const int lat = m_latency.load(std::memory_order_relaxed);
|
||||
if (likely(lat > 0)) {
|
||||
m_latency.store((lat + (int)newMeasurement) >> 1U, std::memory_order_relaxed);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_latency.store((int)newMeasurement, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
@ -175,45 +193,57 @@ public:
|
|||
* @return Latency in milliseconds or -1 if unknown
|
||||
*/
|
||||
ZT_INLINE int latency() const noexcept
|
||||
{ return m_latency.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_latency.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check path aliveness
|
||||
*
|
||||
* @param now Current time
|
||||
*/
|
||||
ZT_INLINE bool alive(const CallContext &cc) const noexcept
|
||||
{ return ((cc.ticks - m_lastIn.load(std::memory_order_relaxed)) < ZT_PATH_ALIVE_TIMEOUT); }
|
||||
ZT_INLINE bool alive(const CallContext& cc) const noexcept
|
||||
{
|
||||
return ((cc.ticks - m_lastIn.load(std::memory_order_relaxed)) < ZT_PATH_ALIVE_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Physical address
|
||||
*/
|
||||
ZT_INLINE const InetAddress &address() const noexcept
|
||||
{ return m_addr; }
|
||||
ZT_INLINE const InetAddress& address() const noexcept
|
||||
{
|
||||
return m_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Local socket as specified by external code
|
||||
*/
|
||||
ZT_INLINE int64_t localSocket() const noexcept
|
||||
{ return m_localSocket; }
|
||||
{
|
||||
return m_localSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last time we received anything
|
||||
*/
|
||||
ZT_INLINE int64_t lastIn() const noexcept
|
||||
{ return m_lastIn.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_lastIn.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last time we sent something
|
||||
*/
|
||||
ZT_INLINE int64_t lastOut() const noexcept
|
||||
{ return m_lastOut.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_lastOut.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
const int64_t m_localSocket;
|
||||
std::atomic< int64_t > m_lastIn;
|
||||
std::atomic< int64_t > m_lastOut;
|
||||
std::atomic< int > m_latency;
|
||||
std::atomic<int64_t> m_lastIn;
|
||||
std::atomic<int64_t> m_lastOut;
|
||||
std::atomic<int> m_latency;
|
||||
const InetAddress m_addr;
|
||||
Meter<> m_inMeter;
|
||||
Meter<> m_outMeter;
|
||||
|
@ -221,10 +251,10 @@ private:
|
|||
// These fields belong to Defragmenter but are kept in Path for performance
|
||||
// as it's much faster this way than having Defragmenter maintain another
|
||||
// mapping from paths to inbound message IDs.
|
||||
Set< uint64_t > m_inboundFragmentedMessages;
|
||||
Set<uint64_t> m_inboundFragmentedMessages;
|
||||
Mutex m_inboundFragmentedMessages_l;
|
||||
|
||||
std::atomic< int > __refCount;
|
||||
std::atomic<int> __refCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
340
core/Peer.cpp
340
core/Peer.cpp
|
@ -11,50 +11,54 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Peer.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Expect.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
// An arbitrary byte to send in single byte probes, incremented on each probe.
|
||||
static uint8_t s_arbitraryByte = (uint8_t)Utils::random();
|
||||
|
||||
Peer::Peer() :
|
||||
m_key((uintptr_t)&m_identityKey),
|
||||
m_keyRenegotiationNeeded(false),
|
||||
m_lastReceive(0),
|
||||
m_lastSend(0),
|
||||
m_lastSentHello(0),
|
||||
m_lastWhoisRequestReceived(0),
|
||||
m_lastEchoRequestReceived(0),
|
||||
m_lastProbeReceived(0),
|
||||
m_alivePathCount(0),
|
||||
m_bestPath(0),
|
||||
m_vProto(0),
|
||||
m_vMajor(0),
|
||||
m_vMinor(0),
|
||||
m_vRevision(0)
|
||||
{}
|
||||
Peer::Peer()
|
||||
: m_key((uintptr_t)&m_identityKey)
|
||||
, m_keyRenegotiationNeeded(false)
|
||||
, m_lastReceive(0)
|
||||
, m_lastSend(0)
|
||||
, m_lastSentHello(0)
|
||||
, m_lastWhoisRequestReceived(0)
|
||||
, m_lastEchoRequestReceived(0)
|
||||
, m_lastProbeReceived(0)
|
||||
, m_alivePathCount(0)
|
||||
, m_bestPath(0)
|
||||
, m_vProto(0)
|
||||
, m_vMajor(0)
|
||||
, m_vMinor(0)
|
||||
, m_vRevision(0)
|
||||
{
|
||||
}
|
||||
|
||||
Peer::~Peer()
|
||||
{ Utils::burn(m_helloMacKey, sizeof(m_helloMacKey)); }
|
||||
{
|
||||
Utils::burn(m_helloMacKey, sizeof(m_helloMacKey));
|
||||
}
|
||||
|
||||
bool Peer::init(const Context &ctx, const CallContext &cc, const Identity &peerIdentity)
|
||||
bool Peer::init(const Context& ctx, const CallContext& cc, const Identity& peerIdentity)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
|
||||
m_id = peerIdentity;
|
||||
|
||||
uint8_t k[ZT_SYMMETRIC_KEY_SIZE];
|
||||
if (unlikely(!ctx.identity.agree(peerIdentity, k)))
|
||||
if (unlikely(! ctx.identity.agree(peerIdentity, k)))
|
||||
return false;
|
||||
m_identityKey.init(cc.ticks, k);
|
||||
Utils::burn(k, sizeof(k));
|
||||
|
@ -65,9 +69,9 @@ bool Peer::init(const Context &ctx, const CallContext &cc, const Identity &peerI
|
|||
}
|
||||
|
||||
void Peer::received(
|
||||
const Context &ctx,
|
||||
const CallContext &cc,
|
||||
const SharedPtr< Path > &path,
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const SharedPtr<Path>& path,
|
||||
const unsigned int hops,
|
||||
const uint64_t packetId,
|
||||
const unsigned int payloadLength,
|
||||
|
@ -103,44 +107,62 @@ void Peer::received(
|
|||
m_prioritizePaths(cc);
|
||||
if (m_alivePathCount == ZT_MAX_PEER_NETWORK_PATHS) {
|
||||
newPathIdx = ZT_MAX_PEER_NETWORK_PATHS - 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
newPathIdx = m_alivePathCount++;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
newPathIdx = m_alivePathCount++;
|
||||
}
|
||||
|
||||
// Save a reference to the current path in case we replace it. This
|
||||
// should technically never happen, but this ensures safety if it does.
|
||||
const SharedPtr< Path > currentBest(reinterpret_cast<Path *>(m_bestPath.load(std::memory_order_acquire)));
|
||||
const SharedPtr<Path> currentBest(reinterpret_cast<Path*>(m_bestPath.load(std::memory_order_acquire)));
|
||||
|
||||
SharedPtr< Path > old;
|
||||
SharedPtr<Path> old;
|
||||
old.move(m_paths[newPathIdx]);
|
||||
m_paths[newPathIdx] = path;
|
||||
|
||||
m_prioritizePaths(cc);
|
||||
|
||||
ctx.t->learnedNewPath(cc, 0x582fabdd, packetId, m_id, path->address(), (old) ? old->address() : InetAddress());
|
||||
} else {
|
||||
int64_t < = m_lastTried[Endpoint(path->address())];
|
||||
ctx.t->learnedNewPath(
|
||||
cc,
|
||||
0x582fabdd,
|
||||
packetId,
|
||||
m_id,
|
||||
path->address(),
|
||||
(old) ? old->address() : InetAddress());
|
||||
}
|
||||
else {
|
||||
int64_t& lt = m_lastTried[Endpoint(path->address())];
|
||||
if ((cc.ticks - lt) < ZT_PATH_MIN_TRY_INTERVAL) {
|
||||
lt = cc.ticks;
|
||||
path->sent(cc, m_hello(ctx, cc, path->localSocket(), path->address(), false));
|
||||
ctx.t->tryingNewPath(cc, 0xb7747ddd, m_id, path->address(), path->address(), packetId, (uint8_t)verb, m_id);
|
||||
ctx.t->tryingNewPath(
|
||||
cc,
|
||||
0xb7747ddd,
|
||||
m_id,
|
||||
path->address(),
|
||||
path->address(),
|
||||
packetId,
|
||||
(uint8_t)verb,
|
||||
m_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::send(const Context &ctx, const CallContext &cc, const void *data, unsigned int len) noexcept
|
||||
void Peer::send(const Context& ctx, const CallContext& cc, const void* data, unsigned int len) noexcept
|
||||
{
|
||||
SharedPtr< Path > via(reinterpret_cast<Path *>(m_bestPath.load(std::memory_order_acquire)));
|
||||
SharedPtr<Path> via(reinterpret_cast<Path*>(m_bestPath.load(std::memory_order_acquire)));
|
||||
if (likely(via)) {
|
||||
if (likely(via->send(ctx, cc, data, len)))
|
||||
this->sent(cc, len);
|
||||
} else {
|
||||
const SharedPtr< Peer > root(ctx.topology->root());
|
||||
}
|
||||
else {
|
||||
const SharedPtr<Peer> root(ctx.topology->root());
|
||||
if (likely((root) && (root.ptr() != this))) {
|
||||
via = root->path(cc);
|
||||
if (likely(via)) {
|
||||
|
@ -153,17 +175,22 @@ void Peer::send(const Context &ctx, const CallContext &cc, const void *data, uns
|
|||
}
|
||||
}
|
||||
|
||||
void Peer::pulse(const Context &ctx, const CallContext &cc)
|
||||
void Peer::pulse(const Context& ctx, const CallContext& cc)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
|
||||
// Grab current key (this is never NULL).
|
||||
SymmetricKey *const key = reinterpret_cast<SymmetricKey *>(m_key.load(std::memory_order_relaxed));
|
||||
SymmetricKey* const key = reinterpret_cast<SymmetricKey*>(m_key.load(std::memory_order_relaxed));
|
||||
|
||||
// Determine if we need a new ephemeral key pair and if a new HELLO needs
|
||||
// to be sent. The latter happens every ZT_PEER_HELLO_INTERVAL or if a new
|
||||
// ephemeral key pair is generated.
|
||||
bool needHello = (((m_vProto >= 20) && (m_keyRenegotiationNeeded || (key == &m_identityKey) || ((cc.ticks - key->timestamp()) >= (ZT_SYMMETRIC_KEY_TTL / 2)) || (key->odometer() > (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2)))) || ((cc.ticks - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL));
|
||||
bool needHello =
|
||||
(((m_vProto >= 20)
|
||||
&& (m_keyRenegotiationNeeded || (key == &m_identityKey)
|
||||
|| ((cc.ticks - key->timestamp()) >= (ZT_SYMMETRIC_KEY_TTL / 2))
|
||||
|| (key->odometer() > (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2))))
|
||||
|| ((cc.ticks - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL));
|
||||
|
||||
// Prioritize paths and more importantly for here forget dead ones.
|
||||
m_prioritizePaths(cc);
|
||||
|
@ -175,13 +202,24 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
// callback (if one was supplied).
|
||||
|
||||
if (m_locator) {
|
||||
for (Vector< std::pair< Endpoint, SharedPtr< const Locator::EndpointAttributes > > >::const_iterator ep(m_locator->endpoints().begin()); ep != m_locator->endpoints().end(); ++ep) {
|
||||
for (Vector<std::pair<Endpoint, SharedPtr<const Locator::EndpointAttributes> > >::const_iterator ep(
|
||||
m_locator->endpoints().begin());
|
||||
ep != m_locator->endpoints().end();
|
||||
++ep) {
|
||||
if (ep->first.type == ZT_ENDPOINT_TYPE_IP_UDP) {
|
||||
if (ctx.node->filterPotentialPath(cc.tPtr, m_id, -1, ep->first.ip())) {
|
||||
int64_t < = m_lastTried[ep->first];
|
||||
int64_t& lt = m_lastTried[ep->first];
|
||||
if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) {
|
||||
lt = cc.ticks;
|
||||
ctx.t->tryingNewPath(cc, 0x84b22322, m_id, ep->first.ip(), InetAddress::NIL, 0, 0, Identity::NIL);
|
||||
ctx.t->tryingNewPath(
|
||||
cc,
|
||||
0x84b22322,
|
||||
m_id,
|
||||
ep->first.ip(),
|
||||
InetAddress::NIL,
|
||||
0,
|
||||
0,
|
||||
Identity::NIL);
|
||||
sent(cc, m_sendProbe(ctx, cc, -1, ep->first.ip(), nullptr, 0));
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +230,7 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
InetAddress addr;
|
||||
if (ctx.node->externalPathLookup(cc.tPtr, m_id, -1, addr)) {
|
||||
if ((addr) && ctx.node->filterPotentialPath(cc.tPtr, m_id, -1, addr)) {
|
||||
int64_t < = m_lastTried[Endpoint(addr)];
|
||||
int64_t& lt = m_lastTried[Endpoint(addr)];
|
||||
if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) {
|
||||
lt = cc.ticks;
|
||||
ctx.t->tryingNewPath(cc, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL);
|
||||
|
@ -201,10 +239,11 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
unsigned int attempts = 0;
|
||||
for (;;) {
|
||||
p_TryQueueItem &qi = m_tryQueue.front();
|
||||
p_TryQueueItem& qi = m_tryQueue.front();
|
||||
|
||||
if (qi.target.isInetAddr()) {
|
||||
// Skip entry if it overlaps with any currently active IP.
|
||||
|
@ -219,21 +258,19 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
|
||||
++attempts;
|
||||
if (qi.iteration < 0) {
|
||||
|
||||
// If iteration is less than zero, try to contact the original address.
|
||||
// It may be set to a larger negative value to try multiple times such
|
||||
// as e.g. -3 to try 3 times.
|
||||
sent(cc, m_sendProbe(ctx, cc, -1, qi.target.ip(), nullptr, 0));
|
||||
++qi.iteration;
|
||||
goto requeue_item;
|
||||
|
||||
} else if (qi.target.ip().isV4() && (m_alivePathCount == 0)) {
|
||||
}
|
||||
else if (qi.target.ip().isV4() && (m_alivePathCount == 0)) {
|
||||
// When iteration reaches zero the queue item is dropped unless it's
|
||||
// IPv4 and we have no direct paths. In that case some heavier NAT-t
|
||||
// strategies are attempted.
|
||||
|
||||
if (qi.target.ip().port() < 1024) {
|
||||
|
||||
// If the source port is privileged, we actually scan every possible
|
||||
// privileged port in random order slowly over multiple iterations
|
||||
// of pulse(). This is done in batches of ZT_NAT_T_PORT_SCAN_MAX.
|
||||
|
@ -248,9 +285,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
sent(cc, m_sendProbe(ctx, cc, -1, qi.target.ip(), ports, pn));
|
||||
if (qi.iteration < 1023)
|
||||
goto requeue_item;
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
else {
|
||||
// For un-privileged ports we'll try ZT_NAT_T_PORT_SCAN_MAX ports
|
||||
// beyond the one we were sent to catch some sequentially assigning
|
||||
// symmetric NATs.
|
||||
|
@ -262,7 +298,6 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
sent(cc, m_sendProbe(ctx, cc, -1, tmp, nullptr, 0));
|
||||
if (qi.iteration < ZT_NAT_T_PORT_SCAN_MAX)
|
||||
goto requeue_item;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +307,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
m_tryQueue.pop_front();
|
||||
if (attempts >= std::min((unsigned int)m_tryQueue.size(), (unsigned int)ZT_NAT_T_PORT_SCAN_MAX))
|
||||
break;
|
||||
else continue;
|
||||
else
|
||||
continue;
|
||||
|
||||
// If the code skips here the front item is instead moved to the back.
|
||||
requeue_item:
|
||||
|
@ -280,7 +316,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
m_tryQueue.splice(m_tryQueue.end(), m_tryQueue, m_tryQueue.begin());
|
||||
if (attempts >= std::min((unsigned int)m_tryQueue.size(), (unsigned int)ZT_NAT_T_PORT_SCAN_MAX))
|
||||
break;
|
||||
else continue;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,14 +326,16 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
for (unsigned int i = 0; i < m_alivePathCount; ++i) {
|
||||
if (needHello) {
|
||||
needHello = false;
|
||||
const unsigned int bytes = m_hello(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), m_keyRenegotiationNeeded);
|
||||
const unsigned int bytes =
|
||||
m_hello(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), m_keyRenegotiationNeeded);
|
||||
if (bytes) {
|
||||
m_paths[i]->sent(cc, bytes);
|
||||
sent(cc, bytes);
|
||||
m_lastSentHello = cc.ticks;
|
||||
m_keyRenegotiationNeeded = false;
|
||||
}
|
||||
} else if ((cc.ticks - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) {
|
||||
}
|
||||
else if ((cc.ticks - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) {
|
||||
m_paths[i]->send(ctx, cc, &s_arbitraryByte, 1);
|
||||
++s_arbitraryByte;
|
||||
sent(cc, 1);
|
||||
|
@ -305,11 +344,12 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
|
||||
// Send a HELLO indirectly if we were not able to send one via any direct path.
|
||||
if (needHello) {
|
||||
const SharedPtr< Peer > root(ctx.topology->root());
|
||||
const SharedPtr<Peer> root(ctx.topology->root());
|
||||
if (root) {
|
||||
const SharedPtr< Path > via(root->path(cc));
|
||||
const SharedPtr<Path> via(root->path(cc));
|
||||
if (via) {
|
||||
const unsigned int bytes = m_hello(ctx, cc, via->localSocket(), via->address(), m_keyRenegotiationNeeded);
|
||||
const unsigned int bytes =
|
||||
m_hello(ctx, cc, via->localSocket(), via->address(), m_keyRenegotiationNeeded);
|
||||
if (bytes) {
|
||||
via->sent(cc, bytes);
|
||||
root->relayed(cc, bytes);
|
||||
|
@ -322,14 +362,15 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
}
|
||||
|
||||
// Clean m_lastTried
|
||||
for (Map< Endpoint, int64_t >::iterator i(m_lastTried.begin()); i != m_lastTried.end();) {
|
||||
for (Map<Endpoint, int64_t>::iterator i(m_lastTried.begin()); i != m_lastTried.end();) {
|
||||
if ((cc.ticks - i->second) > (ZT_PATH_MIN_TRY_INTERVAL * 3))
|
||||
m_lastTried.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::contact(const Context &ctx, const CallContext &cc, const Endpoint &ep, int tries)
|
||||
void Peer::contact(const Context& ctx, const CallContext& cc, const Endpoint& ep, int tries)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
|
||||
|
@ -342,7 +383,7 @@ void Peer::contact(const Context &ctx, const CallContext &cc, const Endpoint &ep
|
|||
}
|
||||
|
||||
// Check underlying path attempt rate limit.
|
||||
int64_t < = m_lastTried[ep];
|
||||
int64_t& lt = m_lastTried[ep];
|
||||
if ((cc.ticks - lt) < ZT_PATH_MIN_TRY_INTERVAL)
|
||||
return;
|
||||
lt = cc.ticks;
|
||||
|
@ -350,12 +391,20 @@ void Peer::contact(const Context &ctx, const CallContext &cc, const Endpoint &ep
|
|||
// For IPv4 addresses we send a tiny packet with a low TTL, which helps to
|
||||
// traverse some NAT types. It has no effect otherwise.
|
||||
if (ep.isInetAddr() && ep.ip().isV4()) {
|
||||
ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&ep.ip()), &s_arbitraryByte, 1, 2);
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
-1,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&ep.ip()),
|
||||
&s_arbitraryByte,
|
||||
1,
|
||||
2);
|
||||
++s_arbitraryByte;
|
||||
}
|
||||
|
||||
// Make sure address is not already in the try queue. If so just update it.
|
||||
for (List< p_TryQueueItem >::iterator i(m_tryQueue.begin()); i != m_tryQueue.end(); ++i) {
|
||||
for (List<p_TryQueueItem>::iterator i(m_tryQueue.begin()); i != m_tryQueue.end(); ++i) {
|
||||
if (i->target.isSameAddress(ep)) {
|
||||
i->target = ep;
|
||||
i->iteration = -tries;
|
||||
|
@ -366,16 +415,24 @@ void Peer::contact(const Context &ctx, const CallContext &cc, const Endpoint &ep
|
|||
m_tryQueue.push_back(p_TryQueueItem(ep, -tries));
|
||||
}
|
||||
|
||||
void Peer::resetWithinScope(const Context &ctx, const CallContext &cc, InetAddress::IpScope scope, int inetAddressFamily)
|
||||
void Peer::resetWithinScope(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
InetAddress::IpScope scope,
|
||||
int inetAddressFamily)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
unsigned int pc = 0;
|
||||
for (unsigned int i = 0; i < m_alivePathCount; ++i) {
|
||||
if ((m_paths[i]) && (((int)m_paths[i]->address().as.sa.sa_family == inetAddressFamily) && (m_paths[i]->address().ipScope() == scope))) {
|
||||
const unsigned int bytes = m_sendProbe(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0);
|
||||
if ((m_paths[i])
|
||||
&& (((int)m_paths[i]->address().as.sa.sa_family == inetAddressFamily)
|
||||
&& (m_paths[i]->address().ipScope() == scope))) {
|
||||
const unsigned int bytes =
|
||||
m_sendProbe(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0);
|
||||
m_paths[i]->sent(cc, bytes);
|
||||
sent(cc, bytes);
|
||||
} else if (pc != i) {
|
||||
}
|
||||
else if (pc != i) {
|
||||
m_paths[pc++] = m_paths[i];
|
||||
}
|
||||
}
|
||||
|
@ -384,12 +441,12 @@ void Peer::resetWithinScope(const Context &ctx, const CallContext &cc, InetAddre
|
|||
m_paths[pc++].zero();
|
||||
}
|
||||
|
||||
void Peer::save(const Context &ctx, const CallContext &cc) const
|
||||
void Peer::save(const Context& ctx, const CallContext& cc) const
|
||||
{
|
||||
uint8_t buf[8 + ZT_PEER_MARSHAL_SIZE_MAX];
|
||||
|
||||
// Prefix each saved peer with the current timestamp.
|
||||
Utils::storeBigEndian< uint64_t >(buf, (uint64_t)cc.clock);
|
||||
Utils::storeBigEndian<uint64_t>(buf, (uint64_t)cc.clock);
|
||||
|
||||
const int len = marshal(ctx, buf + 8);
|
||||
if (len > 0) {
|
||||
|
@ -400,7 +457,7 @@ void Peer::save(const Context &ctx, const CallContext &cc) const
|
|||
}
|
||||
}
|
||||
|
||||
int Peer::marshal(const Context &ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept
|
||||
int Peer::marshal(const Context& ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
|
||||
|
@ -430,7 +487,8 @@ int Peer::marshal(const Context &ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) co
|
|||
if (s <= 0)
|
||||
return s;
|
||||
p += s;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data[p++] = 0;
|
||||
}
|
||||
|
||||
|
@ -449,7 +507,7 @@ int Peer::marshal(const Context &ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) co
|
|||
return p;
|
||||
}
|
||||
|
||||
int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *restrict data, const int len) noexcept
|
||||
int Peer::unmarshal(const Context& ctx, const int64_t ticks, const uint8_t* restrict data, const int len) noexcept
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
|
||||
|
@ -465,7 +523,9 @@ int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *rest
|
|||
bool identityKeyRestored = false;
|
||||
if (Address(data + 1) == ctx.identity.address()) {
|
||||
uint8_t k[ZT_SYMMETRIC_KEY_SIZE];
|
||||
static_assert(ZT_SYMMETRIC_KEY_SIZE == 48, "marshal() and unmarshal() must be revisited if ZT_SYMMETRIC_KEY_SIZE is changed");
|
||||
static_assert(
|
||||
ZT_SYMMETRIC_KEY_SIZE == 48,
|
||||
"marshal() and unmarshal() must be revisited if ZT_SYMMETRIC_KEY_SIZE is changed");
|
||||
ctx.localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH, k);
|
||||
ctx.localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 16, k + 16);
|
||||
ctx.localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 32, k + 32);
|
||||
|
@ -481,9 +541,9 @@ int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *rest
|
|||
return s;
|
||||
p += s;
|
||||
|
||||
if (!identityKeyRestored) {
|
||||
if (! identityKeyRestored) {
|
||||
uint8_t k[ZT_SYMMETRIC_KEY_SIZE];
|
||||
if (!ctx.identity.agree(m_id, k))
|
||||
if (! ctx.identity.agree(m_id, k))
|
||||
return -1;
|
||||
m_identityKey.init(ticks, k);
|
||||
Utils::burn(k, sizeof(k));
|
||||
|
@ -494,55 +554,58 @@ int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *rest
|
|||
if (data[p] == 0) {
|
||||
++p;
|
||||
m_locator.zero();
|
||||
} else if (data[p] == 1) {
|
||||
}
|
||||
else if (data[p] == 1) {
|
||||
++p;
|
||||
Locator *const loc = new Locator();
|
||||
Locator* const loc = new Locator();
|
||||
s = loc->unmarshal(data + p, len - p);
|
||||
m_locator.set(loc);
|
||||
if (s < 0)
|
||||
return s;
|
||||
p += s;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((p + 10) > len)
|
||||
return -1;
|
||||
m_vProto = Utils::loadBigEndian< uint16_t >(data + p);
|
||||
m_vProto = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
m_vMajor = Utils::loadBigEndian< uint16_t >(data + p);
|
||||
m_vMajor = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
m_vMinor = Utils::loadBigEndian< uint16_t >(data + p);
|
||||
m_vMinor = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
m_vRevision = Utils::loadBigEndian< uint16_t >(data + p);
|
||||
m_vRevision = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
p += 2 + (int)Utils::loadBigEndian< uint16_t >(data + p);
|
||||
p += 2 + (int)Utils::loadBigEndian<uint16_t>(data + p);
|
||||
|
||||
m_deriveSecondaryIdentityKeys();
|
||||
|
||||
return (p > len) ? -1 : p;
|
||||
}
|
||||
|
||||
struct _PathPriorityComparisonOperator
|
||||
{
|
||||
ZT_INLINE bool operator()(const SharedPtr< Path > &a, const SharedPtr< Path > &b) const noexcept
|
||||
struct _PathPriorityComparisonOperator {
|
||||
ZT_INLINE bool operator()(const SharedPtr<Path>& a, const SharedPtr<Path>& b) const noexcept
|
||||
{
|
||||
if (a) {
|
||||
if (b)
|
||||
return (a->lastIn() > b->lastIn());
|
||||
else return true;
|
||||
} else {
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Peer::m_prioritizePaths(const CallContext &cc)
|
||||
void Peer::m_prioritizePaths(const CallContext& cc)
|
||||
{
|
||||
// assumes m_lock is locked
|
||||
|
||||
// Need to hold the current best just in case we drop it before changing the atomic.
|
||||
const SharedPtr< Path > oldBest(reinterpret_cast<Path *>(m_bestPath.load(std::memory_order_acquire)));
|
||||
const SharedPtr<Path> oldBest(reinterpret_cast<Path*>(m_bestPath.load(std::memory_order_acquire)));
|
||||
|
||||
// Clean and reprioritize paths.
|
||||
if (m_alivePathCount != 0) {
|
||||
|
@ -565,7 +628,13 @@ void Peer::m_prioritizePaths(const CallContext &cc)
|
|||
m_bestPath.store((m_alivePathCount != 0) ? (uintptr_t)m_paths[0].ptr() : (uintptr_t)0, std::memory_order_release);
|
||||
}
|
||||
|
||||
unsigned int Peer::m_sendProbe(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, const unsigned int numPorts)
|
||||
unsigned int Peer::m_sendProbe(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
const uint16_t* ports,
|
||||
const unsigned int numPorts)
|
||||
{
|
||||
// Assumes m_lock is locked
|
||||
|
||||
|
@ -574,7 +643,9 @@ unsigned int Peer::m_sendProbe(const Context &ctx, const CallContext &cc, int64_
|
|||
// some future attacker compromises it.
|
||||
|
||||
uint8_t p[ZT_PROTO_MIN_PACKET_LENGTH];
|
||||
Utils::storeMachineEndian< uint64_t >(p + ZT_PROTO_PACKET_ID_INDEX, m_identityKey.nextMessage(ctx.identity.address(), m_id.address()));
|
||||
Utils::storeMachineEndian<uint64_t>(
|
||||
p + ZT_PROTO_PACKET_ID_INDEX,
|
||||
m_identityKey.nextMessage(ctx.identity.address(), m_id.address()));
|
||||
m_id.address().copyTo(p + ZT_PROTO_PACKET_DESTINATION_INDEX);
|
||||
ctx.identity.address().copyTo(p + ZT_PROTO_PACKET_SOURCE_INDEX);
|
||||
p[ZT_PROTO_PACKET_FLAGS_INDEX] = 0;
|
||||
|
@ -586,11 +657,28 @@ unsigned int Peer::m_sendProbe(const Context &ctx, const CallContext &cc, int64_
|
|||
InetAddress tmp(atAddress);
|
||||
for (unsigned int i = 0; i < numPorts; ++i) {
|
||||
tmp.setPort(ports[i]);
|
||||
ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&tmp), p, ZT_PROTO_MIN_PACKET_LENGTH, 0);
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
-1,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&tmp),
|
||||
p,
|
||||
ZT_PROTO_MIN_PACKET_LENGTH,
|
||||
0);
|
||||
}
|
||||
return ZT_PROTO_MIN_PACKET_LENGTH * numPorts;
|
||||
} else {
|
||||
ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&atAddress), p, ZT_PROTO_MIN_PACKET_LENGTH, 0);
|
||||
}
|
||||
else {
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
-1,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&atAddress),
|
||||
p,
|
||||
ZT_PROTO_MIN_PACKET_LENGTH,
|
||||
0);
|
||||
return ZT_PROTO_MIN_PACKET_LENGTH;
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +697,12 @@ void Peer::m_deriveSecondaryIdentityKeys() noexcept
|
|||
KBKDFHMACSHA384(m_identityKey.key(), ZT_KBKDF_LABEL_PACKET_HMAC, 0, 0, m_helloMacKey);
|
||||
}
|
||||
|
||||
unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const bool forceNewKey)
|
||||
unsigned int Peer::m_hello(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
const bool forceNewKey)
|
||||
{
|
||||
// assumes m_lock is at least locked for reading
|
||||
|
||||
|
@ -624,10 +717,10 @@ unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t lo
|
|||
* here is also needed to satisfy some FIPS/NIST type requirements. */
|
||||
|
||||
// Pick or generate an ephemeral key to send with this HELLO.
|
||||
p_EphemeralPrivate *ephemeral;
|
||||
p_EphemeralPrivate* ephemeral;
|
||||
{
|
||||
p_EphemeralPrivate *earliest = m_ephemeralKeysSent;
|
||||
p_EphemeralPrivate *latest = nullptr;
|
||||
p_EphemeralPrivate* earliest = m_ephemeralKeysSent;
|
||||
p_EphemeralPrivate* latest = nullptr;
|
||||
int64_t earliestEphemeralPrivate = 9223372036854775807LL;
|
||||
int64_t latestEphemeralPrivate = 0;
|
||||
for (unsigned int k = 0; k < ZT_PEER_EPHEMERAL_KEY_BUFFER_SIZE; ++k) {
|
||||
|
@ -635,15 +728,18 @@ unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t lo
|
|||
if (ct <= earliestEphemeralPrivate) {
|
||||
earliestEphemeralPrivate = ct;
|
||||
earliest = m_ephemeralKeysSent + k;
|
||||
} else if (ct >= latestEphemeralPrivate) { // creationTime will be -1 if not initialized
|
||||
}
|
||||
else if (ct >= latestEphemeralPrivate) { // creationTime will be -1 if not initialized
|
||||
latestEphemeralPrivate = ct;
|
||||
latest = m_ephemeralKeysSent + k;
|
||||
}
|
||||
}
|
||||
|
||||
if ((latest != nullptr) && (!forceNewKey) && ((cc.ticks - latest->creationTime) < (ZT_SYMMETRIC_KEY_TTL / 2))) {
|
||||
if ((latest != nullptr) && (! forceNewKey)
|
||||
&& ((cc.ticks - latest->creationTime) < (ZT_SYMMETRIC_KEY_TTL / 2))) {
|
||||
ephemeral = latest;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
earliest->creationTime = cc.ticks;
|
||||
earliest->pub.type = ZT_PROTO_EPHEMERAL_KEY_TYPE_C25519_P384;
|
||||
C25519::generateC25519(earliest->pub.c25519Public, earliest->c25519Private);
|
||||
|
@ -672,14 +768,14 @@ unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t lo
|
|||
// LEGACY: the six reserved bytes after the IV exist for legacy compatibility with v1.x nodes.
|
||||
// Once those are dead they'll become just reserved bytes for future use as flags etc.
|
||||
outp.wI32(ii, 0); // reserved bytes
|
||||
void *const legacyMoonCountStart = outp.unsafeData + ii;
|
||||
void* const legacyMoonCountStart = outp.unsafeData + ii;
|
||||
outp.wI16(ii, 0);
|
||||
const uint64_t legacySalsaIv = packetId & ZT_CONST_TO_BE_UINT64(0xfffffffffffffff8ULL);
|
||||
Salsa20(m_identityKey.key(), &legacySalsaIv).crypt12(legacyMoonCountStart, legacyMoonCountStart, 2);
|
||||
|
||||
// Append dictionary containinig meta-data and ephemeral key info.
|
||||
const int cryptSectionStart = ii;
|
||||
FCV< uint8_t, 2048 > md;
|
||||
FCV<uint8_t, 2048> md;
|
||||
Dictionary::append(md, ZT_PROTO_HELLO_NODE_META_INSTANCE_ID, ctx.instanceId);
|
||||
// TODO: add other fields and ephemeral key info
|
||||
outp.wI16(ii, (uint16_t)md.size());
|
||||
|
@ -694,7 +790,7 @@ unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t lo
|
|||
// particular this means that the public keys exchanged for ephemeral keying
|
||||
// are concealed from any observer.
|
||||
AES::CTR ctr(m_helloCipher);
|
||||
void *const cryptSection = outp.unsafeData + ii;
|
||||
void* const cryptSection = outp.unsafeData + ii;
|
||||
ctr.init(outp.unsafeData + ivStart, 0, cryptSection);
|
||||
ctr.crypt(cryptSection, ii - cryptSectionStart);
|
||||
ctr.finish();
|
||||
|
@ -708,12 +804,26 @@ unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t lo
|
|||
Protocol::salsa2012DeriveKey(m_identityKey.key(), perPacketKey, outp, ii);
|
||||
Salsa20(perPacketKey, &packetId).crypt12(Utils::ZERO256, polyKey, sizeof(polyKey));
|
||||
Poly1305 p1305(polyKey);
|
||||
p1305.update(outp.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, ii - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START);
|
||||
p1305.update(
|
||||
outp.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,
|
||||
ii - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START);
|
||||
uint64_t polyMac[2];
|
||||
p1305.finish(polyMac);
|
||||
Utils::storeMachineEndian< uint64_t >(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]);
|
||||
Utils::storeMachineEndian<uint64_t>(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]);
|
||||
|
||||
return (likely(ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, localSocket, reinterpret_cast<const ZT_InetAddress *>(&atAddress), outp.unsafeData, ii, 0) == 0)) ? (unsigned int)ii : 0U;
|
||||
return (likely(
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
localSocket,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&atAddress),
|
||||
outp.unsafeData,
|
||||
ii,
|
||||
0)
|
||||
== 0))
|
||||
? (unsigned int)ii
|
||||
: 0U;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
247
core/Peer.hpp
247
core/Peer.hpp
|
@ -14,31 +14,26 @@
|
|||
#ifndef ZT_PEER_HPP
|
||||
#define ZT_PEER_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "SymmetricKey.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_PEER_MARSHAL_SIZE_MAX ( \
|
||||
1 + \
|
||||
ZT_ADDRESS_LENGTH + \
|
||||
ZT_SYMMETRIC_KEY_SIZE + \
|
||||
ZT_IDENTITY_MARSHAL_SIZE_MAX + \
|
||||
1 + ZT_LOCATOR_MARSHAL_SIZE_MAX + \
|
||||
(2 * 4) + \
|
||||
2 )
|
||||
#define ZT_PEER_MARSHAL_SIZE_MAX \
|
||||
(1 + ZT_ADDRESS_LENGTH + ZT_SYMMETRIC_KEY_SIZE + ZT_IDENTITY_MARSHAL_SIZE_MAX + 1 + ZT_LOCATOR_MARSHAL_SIZE_MAX \
|
||||
+ (2 * 4) + 2)
|
||||
|
||||
#define ZT_PEER_DEDUP_BUFFER_SIZE 1024
|
||||
#define ZT_PEER_DEDUP_BUFFER_MASK 1023U
|
||||
|
@ -52,12 +47,11 @@ class Topology;
|
|||
/**
|
||||
* Peer on P2P Network (virtual layer 1)
|
||||
*/
|
||||
class Peer
|
||||
{
|
||||
friend class SharedPtr< Peer >;
|
||||
class Peer {
|
||||
friend class SharedPtr<Peer>;
|
||||
friend class Topology;
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Create an uninitialized peer
|
||||
*
|
||||
|
@ -74,24 +68,28 @@ public:
|
|||
* @param peerIdentity The peer's identity
|
||||
* @return True if initialization was succcesful
|
||||
*/
|
||||
bool init(const Context &ctx, const CallContext &cc, const Identity &peerIdentity);
|
||||
bool init(const Context& ctx, const CallContext& cc, const Identity& peerIdentity);
|
||||
|
||||
/**
|
||||
* @return This peer's ZT address (short for identity().address())
|
||||
*/
|
||||
ZT_INLINE Address address() const noexcept
|
||||
{ return m_id.address(); }
|
||||
{
|
||||
return m_id.address();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This peer's identity
|
||||
*/
|
||||
ZT_INLINE const Identity &identity() const noexcept
|
||||
{ return m_id; }
|
||||
ZT_INLINE const Identity& identity() const noexcept
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current locator or NULL if no locator is known
|
||||
*/
|
||||
ZT_INLINE const SharedPtr< const Locator > locator() const noexcept
|
||||
ZT_INLINE const SharedPtr<const Locator> locator() const noexcept
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
return m_locator;
|
||||
|
@ -107,11 +105,11 @@ public:
|
|||
* @param verify If true, verify locator's signature and structure
|
||||
* @return New locator or previous if it was not replaced.
|
||||
*/
|
||||
ZT_INLINE SharedPtr< const Locator > setLocator(const SharedPtr< const Locator > &loc, const bool verify) noexcept
|
||||
ZT_INLINE SharedPtr<const Locator> setLocator(const SharedPtr<const Locator>& loc, const bool verify) noexcept
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
if ((loc) && ((!m_locator) || (m_locator->revision() < loc->revision()))) {
|
||||
if ((!verify) || loc->verify(m_id))
|
||||
if ((loc) && ((! m_locator) || (m_locator->revision() < loc->revision()))) {
|
||||
if ((! verify) || loc->verify(m_id))
|
||||
m_locator = loc;
|
||||
}
|
||||
return m_locator;
|
||||
|
@ -130,9 +128,9 @@ public:
|
|||
* @param inReVerb In-reply verb for OK or ERROR verbs
|
||||
*/
|
||||
void received(
|
||||
const Context &ctx,
|
||||
const CallContext &cc,
|
||||
const SharedPtr< Path > &path,
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const SharedPtr<Path>& path,
|
||||
unsigned int hops,
|
||||
uint64_t packetId,
|
||||
unsigned int payloadLength,
|
||||
|
@ -144,7 +142,7 @@ public:
|
|||
*
|
||||
* @param bytes Number of bytes written
|
||||
*/
|
||||
ZT_INLINE void sent(const CallContext &cc, const unsigned int bytes) noexcept
|
||||
ZT_INLINE void sent(const CallContext& cc, const unsigned int bytes) noexcept
|
||||
{
|
||||
m_lastSend.store(cc.ticks, std::memory_order_relaxed);
|
||||
m_outMeter.log(cc.ticks, bytes);
|
||||
|
@ -155,16 +153,20 @@ public:
|
|||
*
|
||||
* @param bytes Number of bytes relayed
|
||||
*/
|
||||
ZT_INLINE void relayed(const CallContext &cc, const unsigned int bytes) noexcept
|
||||
{ m_relayedMeter.log(cc.ticks, bytes); }
|
||||
ZT_INLINE void relayed(const CallContext& cc, const unsigned int bytes) noexcept
|
||||
{
|
||||
m_relayedMeter.log(cc.ticks, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current best direct path or NULL if none
|
||||
*
|
||||
* @return Current best path or NULL if there is no direct path
|
||||
*/
|
||||
ZT_INLINE SharedPtr< Path > path(const CallContext &cc) noexcept
|
||||
{ return SharedPtr< Path >(reinterpret_cast<Path *>(m_bestPath.load(std::memory_order_acquire))); }
|
||||
ZT_INLINE SharedPtr<Path> path(const CallContext& cc) noexcept
|
||||
{
|
||||
return SharedPtr<Path>(reinterpret_cast<Path*>(m_bestPath.load(std::memory_order_acquire)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to this peer over a specific path only
|
||||
|
@ -173,7 +175,9 @@ public:
|
|||
* @param len Length in bytes
|
||||
* @param via Path over which to send data (may or may not be an already-learned path for this peer)
|
||||
*/
|
||||
ZT_INLINE void send(const Context &ctx, const CallContext &cc, const void *data, unsigned int len, const SharedPtr< Path > &via) noexcept
|
||||
ZT_INLINE void
|
||||
send(const Context& ctx, const CallContext& cc, const void* data, unsigned int len, const SharedPtr<Path>& via)
|
||||
noexcept
|
||||
{
|
||||
via->send(ctx, cc, data, len);
|
||||
sent(cc, len);
|
||||
|
@ -188,12 +192,12 @@ public:
|
|||
* @param data Data to send
|
||||
* @param len Length in bytes
|
||||
*/
|
||||
void send(const Context &ctx, const CallContext &cc, const void *data, unsigned int len) noexcept;
|
||||
void send(const Context& ctx, const CallContext& cc, const void* data, unsigned int len) noexcept;
|
||||
|
||||
/**
|
||||
* Do ping, probes, re-keying, and keepalive with this peer, as needed.
|
||||
*/
|
||||
void pulse(const Context &ctx, const CallContext &cc);
|
||||
void pulse(const Context& ctx, const CallContext& cc);
|
||||
|
||||
/**
|
||||
* Attempt to contact this peer at a given endpoint.
|
||||
|
@ -204,7 +208,7 @@ public:
|
|||
* @param ep Endpoint to attempt to contact
|
||||
* @param tries Number of times to try (default: 1)
|
||||
*/
|
||||
void contact(const Context &ctx, const CallContext &cc, const Endpoint &ep, int tries = 1);
|
||||
void contact(const Context& ctx, const CallContext& cc, const Endpoint& ep, int tries = 1);
|
||||
|
||||
/**
|
||||
* Reset paths within a given IP scope and address family
|
||||
|
@ -217,13 +221,15 @@ public:
|
|||
* @param scope IP scope
|
||||
* @param inetAddressFamily Family e.g. AF_INET
|
||||
*/
|
||||
void resetWithinScope(const Context &ctx, const CallContext &cc, InetAddress::IpScope scope, int inetAddressFamily);
|
||||
void resetWithinScope(const Context& ctx, const CallContext& cc, InetAddress::IpScope scope, int inetAddressFamily);
|
||||
|
||||
/**
|
||||
* @return Time of last receive of anything, whether direct or relayed
|
||||
*/
|
||||
ZT_INLINE int64_t lastReceive() const noexcept
|
||||
{ return m_lastReceive.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_lastReceive.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Average latency of all direct paths or -1 if no direct paths or unknown
|
||||
|
@ -248,7 +254,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE uint8_t cipher() const noexcept
|
||||
{
|
||||
//if (m_vProto >= 11)
|
||||
// if (m_vProto >= 11)
|
||||
// return ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV;
|
||||
return ZT_PROTO_CIPHER_POLY1305_SALSA2012;
|
||||
}
|
||||
|
@ -256,32 +262,42 @@ public:
|
|||
/**
|
||||
* @return The permanent shared key for this peer computed by simple identity agreement
|
||||
*/
|
||||
ZT_INLINE SymmetricKey &identityKey() noexcept
|
||||
{ return m_identityKey; }
|
||||
ZT_INLINE SymmetricKey& identityKey() noexcept
|
||||
{
|
||||
return m_identityKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AES instance for HELLO dictionary / encrypted section encryption/decryption
|
||||
*/
|
||||
ZT_INLINE const AES &identityHelloDictionaryEncryptionCipher() const noexcept
|
||||
{ return m_helloCipher; }
|
||||
ZT_INLINE const AES& identityHelloDictionaryEncryptionCipher() const noexcept
|
||||
{
|
||||
return m_helloCipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Key for HMAC on HELLOs
|
||||
*/
|
||||
ZT_INLINE const uint8_t *identityHelloHmacKey() const noexcept
|
||||
{ return m_helloMacKey; }
|
||||
ZT_INLINE const uint8_t* identityHelloHmacKey() const noexcept
|
||||
{
|
||||
return m_helloMacKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw identity key bytes
|
||||
*/
|
||||
ZT_INLINE const uint8_t *rawIdentityKey() const noexcept
|
||||
{ return m_identityKey.key(); }
|
||||
ZT_INLINE const uint8_t* rawIdentityKey() const noexcept
|
||||
{
|
||||
return m_identityKey.key();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current best key: either the latest ephemeral or the identity key
|
||||
*/
|
||||
ZT_INLINE SymmetricKey &key() noexcept
|
||||
{ return *reinterpret_cast<SymmetricKey *>(m_key.load(std::memory_order_relaxed)); }
|
||||
ZT_INLINE SymmetricKey& key() noexcept
|
||||
{
|
||||
return *reinterpret_cast<SymmetricKey*>(m_key.load(std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get keys other than a key we have already tried.
|
||||
|
@ -294,14 +310,16 @@ public:
|
|||
* @param notYetTried All keys known (long lived or session) other than alreadyTried
|
||||
* @return Number of pointers written to notYetTried[]
|
||||
*/
|
||||
ZT_INLINE int getOtherKeys(const SymmetricKey *const alreadyTried, SymmetricKey *notYetTried[ZT_PEER_EPHEMERAL_KEY_COUNT_MAX]) noexcept
|
||||
ZT_INLINE int getOtherKeys(
|
||||
const SymmetricKey* const alreadyTried,
|
||||
SymmetricKey* notYetTried[ZT_PEER_EPHEMERAL_KEY_COUNT_MAX]) noexcept
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
int cnt = 0;
|
||||
if (alreadyTried != &m_identityKey)
|
||||
notYetTried[cnt++] = &m_identityKey;
|
||||
for (unsigned int k=0;k<ZT_PEER_EPHEMERAL_KEY_BUFFER_SIZE;++k) {
|
||||
SymmetricKey *const kk = &m_ephemeralSessions[k].key;
|
||||
for (unsigned int k = 0; k < ZT_PEER_EPHEMERAL_KEY_BUFFER_SIZE; ++k) {
|
||||
SymmetricKey* const kk = &m_ephemeralSessions[k].key;
|
||||
if (m_ephemeralSessions[k].established && (alreadyTried != kk))
|
||||
notYetTried[cnt++] = kk;
|
||||
}
|
||||
|
@ -330,7 +348,8 @@ public:
|
|||
* @param vmin Minor version
|
||||
* @param vrev Revision
|
||||
*/
|
||||
ZT_INLINE void setRemoteVersion(unsigned int vproto, unsigned int vmaj, unsigned int vmin, unsigned int vrev) noexcept
|
||||
ZT_INLINE void
|
||||
setRemoteVersion(unsigned int vproto, unsigned int vmaj, unsigned int vmin, unsigned int vrev) noexcept
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
m_vProto = (uint16_t)vproto;
|
||||
|
@ -351,10 +370,10 @@ public:
|
|||
* @param vRevision Set to revision
|
||||
* @return True if remote version is known
|
||||
*/
|
||||
ZT_INLINE bool remoteVersion(uint16_t &vProto, uint16_t &vMajor, uint16_t &vMinor, uint16_t &vRevision)
|
||||
ZT_INLINE bool remoteVersion(uint16_t& vProto, uint16_t& vMajor, uint16_t& vMinor, uint16_t& vRevision)
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
return (((vProto = m_vProto)|(vMajor = m_vMajor)|(vMinor = m_vMinor)|(vRevision = m_vRevision)) != 0);
|
||||
return (((vProto = m_vProto) | (vMajor = m_vMajor) | (vMinor = m_vMinor) | (vRevision = m_vRevision)) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -371,7 +390,7 @@ public:
|
|||
*
|
||||
* @param paths Vector of paths with the first path being the current preferred path
|
||||
*/
|
||||
ZT_INLINE void getAllPaths(Vector< SharedPtr< Path > > &paths) const
|
||||
ZT_INLINE void getAllPaths(Vector<SharedPtr<Path> >& paths) const
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
paths.assign(m_paths, m_paths + m_alivePathCount);
|
||||
|
@ -380,18 +399,20 @@ public:
|
|||
/**
|
||||
* Save the latest version of this peer to the data store
|
||||
*/
|
||||
void save(const Context &ctx, const CallContext &cc) const;
|
||||
void save(const Context& ctx, const CallContext& cc) const;
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_PEER_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_PEER_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(const Context &ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept;
|
||||
int unmarshal(const Context &ctx, int64_t ticks, const uint8_t *restrict data, int len) noexcept;
|
||||
int marshal(const Context& ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept;
|
||||
int unmarshal(const Context& ctx, int64_t ticks, const uint8_t* restrict data, int len) noexcept;
|
||||
|
||||
/**
|
||||
* Rate limit gate for inbound WHOIS requests
|
||||
*/
|
||||
ZT_INLINE bool rateGateInboundWhoisRequest(CallContext &cc) noexcept
|
||||
ZT_INLINE bool rateGateInboundWhoisRequest(CallContext& cc) noexcept
|
||||
{
|
||||
if ((cc.ticks - m_lastWhoisRequestReceived.load(std::memory_order_relaxed)) >= ZT_PEER_WHOIS_RATE_LIMIT) {
|
||||
m_lastWhoisRequestReceived.store(cc.ticks, std::memory_order_relaxed);
|
||||
|
@ -403,7 +424,7 @@ public:
|
|||
/**
|
||||
* Rate limit gate for inbound ECHO requests
|
||||
*/
|
||||
ZT_INLINE bool rateGateEchoRequest(CallContext &cc) noexcept
|
||||
ZT_INLINE bool rateGateEchoRequest(CallContext& cc) noexcept
|
||||
{
|
||||
if ((cc.ticks - m_lastEchoRequestReceived.load(std::memory_order_relaxed)) >= ZT_PEER_GENERAL_RATE_LIMIT) {
|
||||
m_lastEchoRequestReceived.store(cc.ticks, std::memory_order_relaxed);
|
||||
|
@ -415,7 +436,7 @@ public:
|
|||
/**
|
||||
* Rate limit gate for inbound probes
|
||||
*/
|
||||
ZT_INLINE bool rateGateProbeRequest(CallContext &cc) noexcept
|
||||
ZT_INLINE bool rateGateProbeRequest(CallContext& cc) noexcept
|
||||
{
|
||||
if ((cc.ticks - m_lastProbeReceived.load(std::memory_order_relaxed)) > ZT_PEER_PROBE_RESPONSE_RATE_LIMIT) {
|
||||
m_lastProbeReceived.store(cc.ticks, std::memory_order_relaxed);
|
||||
|
@ -434,25 +455,33 @@ public:
|
|||
* @return True if this is a duplicate
|
||||
*/
|
||||
ZT_INLINE bool deduplicateIncomingPacket(const uint64_t packetId) noexcept
|
||||
{ return m_dedup[Utils::hash32((uint32_t)packetId) & ZT_PEER_DEDUP_BUFFER_MASK].exchange(packetId, std::memory_order_relaxed) == packetId; }
|
||||
|
||||
private:
|
||||
struct p_EphemeralPublic
|
||||
{
|
||||
return m_dedup[Utils::hash32((uint32_t)packetId) & ZT_PEER_DEDUP_BUFFER_MASK].exchange(
|
||||
packetId,
|
||||
std::memory_order_relaxed)
|
||||
== packetId;
|
||||
}
|
||||
|
||||
private:
|
||||
struct p_EphemeralPublic {
|
||||
uint8_t type;
|
||||
uint8_t c25519Public[ZT_C25519_ECDH_PUBLIC_KEY_SIZE];
|
||||
uint8_t p384Public[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
};
|
||||
|
||||
static_assert(sizeof(p_EphemeralPublic) == (1 + ZT_C25519_ECDH_PUBLIC_KEY_SIZE + ZT_ECC384_PUBLIC_KEY_SIZE), "p_EphemeralPublic has extra padding");
|
||||
static_assert(
|
||||
sizeof(p_EphemeralPublic) == (1 + ZT_C25519_ECDH_PUBLIC_KEY_SIZE + ZT_ECC384_PUBLIC_KEY_SIZE),
|
||||
"p_EphemeralPublic has extra padding");
|
||||
|
||||
struct p_EphemeralPrivate
|
||||
struct p_EphemeralPrivate {
|
||||
ZT_INLINE p_EphemeralPrivate() noexcept : creationTime(-1)
|
||||
{
|
||||
ZT_INLINE p_EphemeralPrivate() noexcept: creationTime(-1)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE ~p_EphemeralPrivate()
|
||||
{ Utils::burn(this, sizeof(p_EphemeralPublic)); }
|
||||
{
|
||||
Utils::burn(this, sizeof(p_EphemeralPublic));
|
||||
}
|
||||
|
||||
int64_t creationTime;
|
||||
uint64_t sha384OfPublic[6];
|
||||
|
@ -461,20 +490,31 @@ private:
|
|||
uint8_t p384Private[ZT_ECC384_PRIVATE_KEY_SIZE];
|
||||
};
|
||||
|
||||
struct p_EphemeralSession
|
||||
struct p_EphemeralSession {
|
||||
ZT_INLINE p_EphemeralSession() noexcept : established(false)
|
||||
{
|
||||
ZT_INLINE p_EphemeralSession() noexcept: established(false)
|
||||
{}
|
||||
}
|
||||
|
||||
uint64_t sha384OfPeerPublic[6];
|
||||
SymmetricKey key;
|
||||
bool established;
|
||||
};
|
||||
|
||||
void m_prioritizePaths(const CallContext &cc);
|
||||
unsigned int m_sendProbe(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, unsigned int numPorts);
|
||||
void m_prioritizePaths(const CallContext& cc);
|
||||
unsigned int m_sendProbe(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
const uint16_t* ports,
|
||||
unsigned int numPorts);
|
||||
void m_deriveSecondaryIdentityKeys() noexcept;
|
||||
unsigned int m_hello(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, bool forceNewKey);
|
||||
unsigned int m_hello(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
bool forceNewKey);
|
||||
|
||||
// Guards all fields except those otherwise indicated (and atomics of course).
|
||||
RWMutex m_lock;
|
||||
|
@ -495,7 +535,7 @@ private:
|
|||
p_EphemeralSession m_ephemeralSessions[ZT_PEER_EPHEMERAL_KEY_BUFFER_SIZE];
|
||||
|
||||
// Pointer to active key (SymmetricKey).
|
||||
std::atomic< uintptr_t > m_key;
|
||||
std::atomic<uintptr_t> m_key;
|
||||
|
||||
// Flag indicating that we should rekey at next pulse().
|
||||
bool m_keyRenegotiationNeeded;
|
||||
|
@ -504,26 +544,26 @@ private:
|
|||
Identity m_id;
|
||||
|
||||
// This peer's most recent (by revision) locator, or NULL if none on file.
|
||||
SharedPtr< const Locator > m_locator;
|
||||
SharedPtr<const Locator> m_locator;
|
||||
|
||||
// The last time something was received or sent.
|
||||
std::atomic< int64_t > m_lastReceive;
|
||||
std::atomic< int64_t > m_lastSend;
|
||||
std::atomic<int64_t> m_lastReceive;
|
||||
std::atomic<int64_t> m_lastSend;
|
||||
|
||||
// The last time we sent a full HELLO to this peer.
|
||||
int64_t m_lastSentHello; // only checked while locked
|
||||
|
||||
// The last time a WHOIS request was received from this peer (anti-DOS / anti-flood).
|
||||
std::atomic< int64_t > m_lastWhoisRequestReceived;
|
||||
std::atomic<int64_t> m_lastWhoisRequestReceived;
|
||||
|
||||
// The last time an ECHO request was received from this peer (anti-DOS / anti-flood).
|
||||
std::atomic< int64_t > m_lastEchoRequestReceived;
|
||||
std::atomic<int64_t> m_lastEchoRequestReceived;
|
||||
|
||||
// The last time we got a probe from this peer.
|
||||
std::atomic< int64_t > m_lastProbeReceived;
|
||||
std::atomic<int64_t> m_lastProbeReceived;
|
||||
|
||||
// Deduplication buffer.
|
||||
std::atomic< uint64_t > m_dedup[ZT_PEER_DEDUP_BUFFER_SIZE];
|
||||
std::atomic<uint64_t> m_dedup[ZT_PEER_DEDUP_BUFFER_SIZE];
|
||||
|
||||
// Meters measuring actual bandwidth in, out, and relayed via this peer (mostly if this is a root).
|
||||
Meter<> m_inMeter;
|
||||
|
@ -531,7 +571,7 @@ private:
|
|||
Meter<> m_relayedMeter;
|
||||
|
||||
// Direct paths sorted in descending order of preference.
|
||||
SharedPtr< Path > m_paths[ZT_MAX_PEER_NETWORK_PATHS];
|
||||
SharedPtr<Path> m_paths[ZT_MAX_PEER_NETWORK_PATHS];
|
||||
|
||||
// Size of m_paths[] in non-NULL paths (max: MAX_PEER_NETWORK_PATHS).
|
||||
unsigned int m_alivePathCount;
|
||||
|
@ -540,29 +580,26 @@ private:
|
|||
std::atomic<uintptr_t> m_bestPath;
|
||||
|
||||
// For SharedPtr<>
|
||||
std::atomic< int > __refCount;
|
||||
std::atomic<int> __refCount;
|
||||
|
||||
struct p_TryQueueItem
|
||||
struct p_TryQueueItem {
|
||||
ZT_INLINE p_TryQueueItem() : target(), iteration(0)
|
||||
{
|
||||
ZT_INLINE p_TryQueueItem() :
|
||||
target(),
|
||||
iteration(0)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE p_TryQueueItem(const Endpoint &t, int iter) :
|
||||
target(t),
|
||||
iteration(iter)
|
||||
{}
|
||||
ZT_INLINE p_TryQueueItem(const Endpoint& t, int iter) : target(t), iteration(iter)
|
||||
{
|
||||
}
|
||||
|
||||
Endpoint target;
|
||||
int iteration;
|
||||
};
|
||||
|
||||
// Queue of endpoints to try.
|
||||
List< p_TryQueueItem > m_tryQueue;
|
||||
List<p_TryQueueItem> m_tryQueue;
|
||||
|
||||
// Time each endpoint was last tried, for rate limiting.
|
||||
Map< Endpoint, int64_t > m_lastTried;
|
||||
Map<Endpoint, int64_t> m_lastTried;
|
||||
|
||||
// Version of remote peer, if known.
|
||||
uint16_t m_vProto;
|
||||
|
|
|
@ -6,20 +6,21 @@ Public domain.
|
|||
|
||||
// Small modifications have been made for ZeroTier, but this code remains in the public domain.
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Poly1305.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#pragma warning(disable: 4146)
|
||||
#pragma warning(disable : 4146)
|
||||
#endif
|
||||
|
||||
#define U8TO64(p) Utils::loadLittleEndian<uint64_t>(p)
|
||||
#define U64TO8(p,v) Utils::storeLittleEndian<uint64_t>(p,v)
|
||||
#define U64TO8(p, v) Utils::storeLittleEndian<uint64_t>(p, v)
|
||||
#define U8TO32(p) Utils::loadLittleEndian<uint32_t>(p)
|
||||
#define U32TO8(p,v) Utils::storeLittleEndian<uint32_t>(p,v)
|
||||
#define U32TO8(p, v) Utils::storeLittleEndian<uint32_t>(p, v)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -49,18 +50,18 @@ typedef struct poly1305_state_internal_t {
|
|||
unsigned char final;
|
||||
} poly1305_state_internal_t;
|
||||
|
||||
ZT_INLINE void poly1305_init(poly1305_context *ctx,const unsigned char key[32])
|
||||
ZT_INLINE void poly1305_init(poly1305_context* ctx, const unsigned char key[32])
|
||||
{
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
unsigned long long t0,t1;
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
unsigned long long t0, t1;
|
||||
|
||||
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||
t0 = U8TO64(&key[0]);
|
||||
t1 = U8TO64(&key[8]);
|
||||
|
||||
st->r[0] = ( t0 ) & 0xffc0fffffff;
|
||||
st->r[0] = (t0)&0xffc0fffffff;
|
||||
st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
|
||||
st->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f;
|
||||
st->r[2] = ((t1 >> 24)) & 0x00ffffffc0f;
|
||||
|
||||
/* h = 0 */
|
||||
st->h[0] = 0;
|
||||
|
@ -75,13 +76,13 @@ ZT_INLINE void poly1305_init(poly1305_context *ctx,const unsigned char key[32])
|
|||
st->final = 0;
|
||||
}
|
||||
|
||||
void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes)
|
||||
void poly1305_blocks(poly1305_state_internal_t* st, const unsigned char* m, size_t bytes)
|
||||
{
|
||||
const unsigned long long hibit = (st->final) ? 0 : ((unsigned long long)1 << 40); /* 1 << 128 */
|
||||
unsigned long long r0,r1,r2;
|
||||
unsigned long long s1,s2;
|
||||
unsigned long long h0,h1,h2;
|
||||
uint128_t d0,d1,d2,d;
|
||||
unsigned long long r0, r1, r2;
|
||||
unsigned long long s1, s2;
|
||||
unsigned long long h0, h1, h2;
|
||||
uint128_t d0, d1, d2, d;
|
||||
|
||||
r0 = st->r[0];
|
||||
r1 = st->r[1];
|
||||
|
@ -95,26 +96,45 @@ void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size
|
|||
s2 = r2 * (5 << 2);
|
||||
|
||||
while (bytes >= poly1305_block_size) {
|
||||
unsigned long long t0,t1;
|
||||
unsigned long long t0, t1;
|
||||
|
||||
/* h += m[i] */
|
||||
t0 = U8TO64(&m[0]);
|
||||
t1 = U8TO64(&m[8]);
|
||||
|
||||
h0 += (( t0 ) & 0xfffffffffff);
|
||||
h0 += ((t0)&0xfffffffffff);
|
||||
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
|
||||
h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit;
|
||||
h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
|
||||
MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
|
||||
MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
|
||||
MUL(d0, h0, r0);
|
||||
MUL(d, h1, s2);
|
||||
ADD(d0, d);
|
||||
MUL(d, h2, s1);
|
||||
ADD(d0, d);
|
||||
MUL(d1, h0, r1);
|
||||
MUL(d, h1, r0);
|
||||
ADD(d1, d);
|
||||
MUL(d, h2, s2);
|
||||
ADD(d1, d);
|
||||
MUL(d2, h0, r2);
|
||||
MUL(d, h1, r1);
|
||||
ADD(d2, d);
|
||||
MUL(d, h2, r0);
|
||||
ADD(d2, d);
|
||||
|
||||
/* (partial) h %= p */
|
||||
unsigned long long c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
|
||||
ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
|
||||
ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff;
|
||||
unsigned long long c = SHR(d0, 44);
|
||||
h0 = LO(d0) & 0xfffffffffff;
|
||||
ADDLO(d1, c);
|
||||
c = SHR(d1, 44);
|
||||
h1 = LO(d1) & 0xfffffffffff;
|
||||
ADDLO(d2, c);
|
||||
c = SHR(d2, 42);
|
||||
h2 = LO(d2) & 0x3ffffffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 44);
|
||||
h0 = h0 & 0xfffffffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
|
@ -126,12 +146,12 @@ void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size
|
|||
st->h[2] = h2;
|
||||
}
|
||||
|
||||
ZT_INLINE void poly1305_finish(poly1305_context *ctx,unsigned char mac[16])
|
||||
ZT_INLINE void poly1305_finish(poly1305_context* ctx, unsigned char mac[16])
|
||||
{
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
unsigned long long h0,h1,h2,c;
|
||||
unsigned long long g0,g1,g2;
|
||||
unsigned long long t0,t1;
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
unsigned long long h0, h1, h2, c;
|
||||
unsigned long long g0, g1, g2;
|
||||
unsigned long long t0, t1;
|
||||
|
||||
/* process the remaining block */
|
||||
if (st->leftover) {
|
||||
|
@ -148,17 +168,32 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx,unsigned char mac[16])
|
|||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
|
||||
c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
c = (h1 >> 44);
|
||||
h1 &= 0xfffffffffff;
|
||||
h2 += c;
|
||||
c = (h2 >> 42);
|
||||
h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 44);
|
||||
h0 &= 0xfffffffffff;
|
||||
h1 += c;
|
||||
c = (h1 >> 44);
|
||||
h1 &= 0xfffffffffff;
|
||||
h2 += c;
|
||||
c = (h2 >> 42);
|
||||
h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 44);
|
||||
h0 &= 0xfffffffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
|
||||
g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
|
||||
g0 = h0 + 5;
|
||||
c = (g0 >> 44);
|
||||
g0 &= 0xfffffffffff;
|
||||
g1 = h1 + c;
|
||||
c = (g1 >> 44);
|
||||
g1 &= 0xfffffffffff;
|
||||
g2 = h2 + c - ((unsigned long long)1 << 42);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
|
@ -175,12 +210,17 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx,unsigned char mac[16])
|
|||
t0 = st->pad[0];
|
||||
t1 = st->pad[1];
|
||||
|
||||
h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff;
|
||||
h0 += ((t0)&0xfffffffffff);
|
||||
c = (h0 >> 44);
|
||||
h0 &= 0xfffffffffff;
|
||||
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
|
||||
c = (h1 >> 44);
|
||||
h1 &= 0xfffffffffff;
|
||||
h2 += (((t1 >> 24)) & 0x3ffffffffff) + c;
|
||||
h2 &= 0x3ffffffffff;
|
||||
|
||||
/* mac = h % (2^128) */
|
||||
h0 = ((h0 ) | (h1 << 44));
|
||||
h0 = ((h0) | (h1 << 44));
|
||||
h1 = ((h1 >> 20) | (h2 << 24));
|
||||
|
||||
U64TO8(&mac[0], h0);
|
||||
|
@ -210,15 +250,15 @@ typedef struct poly1305_state_internal_t {
|
|||
unsigned char final;
|
||||
} poly1305_state_internal_t;
|
||||
|
||||
ZT_INLINE void poly1305_init(poly1305_context *ctx, const unsigned char key[32])
|
||||
ZT_INLINE void poly1305_init(poly1305_context* ctx, const unsigned char key[32])
|
||||
{
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
|
||||
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||
st->r[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff;
|
||||
st->r[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03;
|
||||
st->r[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff;
|
||||
st->r[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff;
|
||||
st->r[0] = (U8TO32(&key[0])) & 0x3ffffff;
|
||||
st->r[1] = (U8TO32(&key[3]) >> 2) & 0x3ffff03;
|
||||
st->r[2] = (U8TO32(&key[6]) >> 4) & 0x3ffc0ff;
|
||||
st->r[3] = (U8TO32(&key[9]) >> 6) & 0x3f03fff;
|
||||
st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
|
||||
|
||||
/* h = 0 */
|
||||
|
@ -238,12 +278,12 @@ ZT_INLINE void poly1305_init(poly1305_context *ctx, const unsigned char key[32])
|
|||
st->final = 0;
|
||||
}
|
||||
|
||||
void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes)
|
||||
void poly1305_blocks(poly1305_state_internal_t* st, const unsigned char* m, size_t bytes)
|
||||
{
|
||||
const unsigned long hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */
|
||||
unsigned long r0,r1,r2,r3,r4;
|
||||
unsigned long s1,s2,s3,s4;
|
||||
unsigned long h0,h1,h2,h3,h4;
|
||||
unsigned long r0, r1, r2, r3, r4;
|
||||
unsigned long s1, s2, s3, s4;
|
||||
unsigned long h0, h1, h2, h3, h4;
|
||||
|
||||
r0 = st->r[0];
|
||||
r1 = st->r[1];
|
||||
|
@ -264,26 +304,47 @@ void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size
|
|||
|
||||
while (bytes >= poly1305_block_size) {
|
||||
/* h += m[i] */
|
||||
h0 += (U8TO32(m+ 0) ) & 0x3ffffff;
|
||||
h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
|
||||
h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
|
||||
h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
|
||||
h4 += (U8TO32(m+12) >> 8) | hibit;
|
||||
h0 += (U8TO32(m + 0)) & 0x3ffffff;
|
||||
h1 += (U8TO32(m + 3) >> 2) & 0x3ffffff;
|
||||
h2 += (U8TO32(m + 6) >> 4) & 0x3ffffff;
|
||||
h3 += (U8TO32(m + 9) >> 6) & 0x3ffffff;
|
||||
h4 += (U8TO32(m + 12) >> 8) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
unsigned long long d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
|
||||
unsigned long long d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
|
||||
unsigned long long d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
|
||||
unsigned long long d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
|
||||
unsigned long long d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
|
||||
unsigned long long d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4)
|
||||
+ ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2)
|
||||
+ ((unsigned long long)h4 * s1);
|
||||
unsigned long long d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0)
|
||||
+ ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3)
|
||||
+ ((unsigned long long)h4 * s2);
|
||||
unsigned long long d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1)
|
||||
+ ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4)
|
||||
+ ((unsigned long long)h4 * s3);
|
||||
unsigned long long d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2)
|
||||
+ ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0)
|
||||
+ ((unsigned long long)h4 * s4);
|
||||
unsigned long long d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3)
|
||||
+ ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1)
|
||||
+ ((unsigned long long)h4 * r0);
|
||||
|
||||
/* (partial) h %= p */
|
||||
unsigned long c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;
|
||||
d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;
|
||||
d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;
|
||||
d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;
|
||||
d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;
|
||||
h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
|
||||
unsigned long c = (unsigned long)(d0 >> 26);
|
||||
h0 = (unsigned long)d0 & 0x3ffffff;
|
||||
d1 += c;
|
||||
c = (unsigned long)(d1 >> 26);
|
||||
h1 = (unsigned long)d1 & 0x3ffffff;
|
||||
d2 += c;
|
||||
c = (unsigned long)(d2 >> 26);
|
||||
h2 = (unsigned long)d2 & 0x3ffffff;
|
||||
d3 += c;
|
||||
c = (unsigned long)(d3 >> 26);
|
||||
h3 = (unsigned long)d3 & 0x3ffffff;
|
||||
d4 += c;
|
||||
c = (unsigned long)(d4 >> 26);
|
||||
h4 = (unsigned long)d4 & 0x3ffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 26);
|
||||
h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
|
@ -297,11 +358,11 @@ void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size
|
|||
st->h[4] = h4;
|
||||
}
|
||||
|
||||
ZT_INLINE void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
|
||||
ZT_INLINE void poly1305_finish(poly1305_context* ctx, unsigned char mac[16])
|
||||
{
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
unsigned long h0,h1,h2,h3,h4,c;
|
||||
unsigned long g0,g1,g2,g3,g4;
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
unsigned long h0, h1, h2, h3, h4, c;
|
||||
unsigned long g0, g1, g2, g3, g4;
|
||||
unsigned long long f;
|
||||
unsigned long mask;
|
||||
|
||||
|
@ -322,18 +383,35 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
|
|||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
c = h1 >> 26; h1 = h1 & 0x3ffffff;
|
||||
h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
|
||||
h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
|
||||
h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
c = h1 >> 26;
|
||||
h1 = h1 & 0x3ffffff;
|
||||
h2 += c;
|
||||
c = h2 >> 26;
|
||||
h2 = h2 & 0x3ffffff;
|
||||
h3 += c;
|
||||
c = h3 >> 26;
|
||||
h3 = h3 & 0x3ffffff;
|
||||
h4 += c;
|
||||
c = h4 >> 26;
|
||||
h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5;
|
||||
c = h0 >> 26;
|
||||
h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
|
||||
g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
|
||||
g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
|
||||
g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
|
||||
g0 = h0 + 5;
|
||||
c = g0 >> 26;
|
||||
g0 &= 0x3ffffff;
|
||||
g1 = h1 + c;
|
||||
c = g1 >> 26;
|
||||
g1 &= 0x3ffffff;
|
||||
g2 = h2 + c;
|
||||
c = g2 >> 26;
|
||||
g2 &= 0x3ffffff;
|
||||
g3 = h3 + c;
|
||||
c = g3 >> 26;
|
||||
g3 &= 0x3ffffff;
|
||||
g4 = h4 + c - (1 << 26);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
|
@ -351,16 +429,20 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
|
|||
h4 = (h4 & mask) | g4;
|
||||
|
||||
/* h = h % (2^128) */
|
||||
h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
|
||||
h0 = ((h0) | (h1 << 26)) & 0xffffffff;
|
||||
h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
|
||||
h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
|
||||
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
|
||||
|
||||
/* mac = (h + pad) % (2^128) */
|
||||
f = (unsigned long long)h0 + st->pad[0] ; h0 = (unsigned long)f;
|
||||
f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f;
|
||||
f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f;
|
||||
f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f;
|
||||
f = (unsigned long long)h0 + st->pad[0];
|
||||
h0 = (unsigned long)f;
|
||||
f = (unsigned long long)h1 + st->pad[1] + (f >> 32);
|
||||
h1 = (unsigned long)f;
|
||||
f = (unsigned long long)h2 + st->pad[2] + (f >> 32);
|
||||
h2 = (unsigned long)f;
|
||||
f = (unsigned long long)h3 + st->pad[3] + (f >> 32);
|
||||
h3 = (unsigned long)f;
|
||||
|
||||
U32TO8(mac + 0, h0);
|
||||
U32TO8(mac + 4, h1);
|
||||
|
@ -386,9 +468,9 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
|
|||
|
||||
#endif // uint128_t or portable version?
|
||||
|
||||
ZT_INLINE void poly1305_update(poly1305_context *ctx,const unsigned char *m,size_t bytes) noexcept
|
||||
ZT_INLINE void poly1305_update(poly1305_context* ctx, const unsigned char* m, size_t bytes) noexcept
|
||||
{
|
||||
poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
size_t i;
|
||||
|
||||
/* handle leftover */
|
||||
|
@ -425,20 +507,23 @@ ZT_INLINE void poly1305_update(poly1305_context *ctx,const unsigned char *m,size
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
void Poly1305::init(const void *key) noexcept
|
||||
void Poly1305::init(const void* key) noexcept
|
||||
{
|
||||
static_assert(sizeof(ctx) >= sizeof(poly1305_context),"buffer in class smaller than required structure size");
|
||||
poly1305_init(reinterpret_cast<poly1305_context *>(&ctx),reinterpret_cast<const unsigned char *>(key));
|
||||
static_assert(sizeof(ctx) >= sizeof(poly1305_context), "buffer in class smaller than required structure size");
|
||||
poly1305_init(reinterpret_cast<poly1305_context*>(&ctx), reinterpret_cast<const unsigned char*>(key));
|
||||
}
|
||||
|
||||
void Poly1305::update(const void *data,unsigned int len) noexcept
|
||||
void Poly1305::update(const void* data, unsigned int len) noexcept
|
||||
{
|
||||
poly1305_update(reinterpret_cast<poly1305_context *>(&ctx),reinterpret_cast<const unsigned char *>(data),(size_t)len);
|
||||
poly1305_update(
|
||||
reinterpret_cast<poly1305_context*>(&ctx),
|
||||
reinterpret_cast<const unsigned char*>(data),
|
||||
(size_t)len);
|
||||
}
|
||||
|
||||
void Poly1305::finish(void *auth) noexcept
|
||||
void Poly1305::finish(void* auth) noexcept
|
||||
{
|
||||
poly1305_finish(reinterpret_cast<poly1305_context *>(&ctx),reinterpret_cast<unsigned char *>(auth));
|
||||
poly1305_finish(reinterpret_cast<poly1305_context*>(&ctx), reinterpret_cast<unsigned char*>(auth));
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -22,29 +22,31 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Poly1305 one-time MAC calculator
|
||||
*/
|
||||
class Poly1305
|
||||
{
|
||||
public:
|
||||
class Poly1305 {
|
||||
public:
|
||||
ZT_INLINE Poly1305()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Poly1305(const void *key)
|
||||
{ this->init(key); }
|
||||
ZT_INLINE Poly1305(const void* key)
|
||||
{
|
||||
this->init(key);
|
||||
}
|
||||
|
||||
void init(const void *key) noexcept;
|
||||
void update(const void *data, unsigned int len) noexcept;
|
||||
void finish(void *auth) noexcept;
|
||||
void init(const void* key) noexcept;
|
||||
void update(const void* data, unsigned int len) noexcept;
|
||||
void finish(void* auth) noexcept;
|
||||
|
||||
static ZT_INLINE void compute(void *const auth, const void *const data, const unsigned int len, const void *const key) noexcept
|
||||
static ZT_INLINE void
|
||||
compute(void* const auth, const void* const data, const unsigned int len, const void* const key) noexcept
|
||||
{
|
||||
Poly1305 p(key);
|
||||
p.update(data, len);
|
||||
p.finish(auth);
|
||||
}
|
||||
|
||||
private:
|
||||
struct
|
||||
{
|
||||
private:
|
||||
struct {
|
||||
size_t aligner;
|
||||
unsigned char opaque[136];
|
||||
} ctx;
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
#ifndef ZT_PROTOCOL_HPP
|
||||
#define ZT_PROTOCOL_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "Poly1305.hpp"
|
||||
#include "LZ4.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "LZ4.hpp"
|
||||
#include "Poly1305.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "SymmetricKey.hpp"
|
||||
|
||||
/*
|
||||
|
@ -253,7 +253,9 @@
|
|||
#define ZT_PROTO_HELLO_NODE_META_EPHEMERAL_ACK "E"
|
||||
|
||||
static_assert(ZT_PROTO_MAX_PACKET_LENGTH < ZT_BUF_MEM_SIZE, "maximum packet length won't fit in Buf");
|
||||
static_assert(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START == (ZT_PROTO_MIN_PACKET_LENGTH - 1), "encrypted packet section must start right before protocol verb at one less than minimum packet size");
|
||||
static_assert(
|
||||
ZT_PROTO_PACKET_ENCRYPTED_SECTION_START == (ZT_PROTO_MIN_PACKET_LENGTH - 1),
|
||||
"encrypted packet section must start right before protocol verb at one less than minimum packet size");
|
||||
|
||||
namespace ZeroTier {
|
||||
namespace Protocol {
|
||||
|
@ -261,8 +263,7 @@ namespace Protocol {
|
|||
/**
|
||||
* Packet verb (message type)
|
||||
*/
|
||||
enum Verb
|
||||
{
|
||||
enum Verb {
|
||||
/**
|
||||
* No operation
|
||||
*
|
||||
|
@ -685,7 +686,7 @@ enum Verb
|
|||
|
||||
#ifdef ZT_DEBUG_SPEW
|
||||
|
||||
static ZT_INLINE const char *verbName(const Verb v) noexcept
|
||||
static ZT_INLINE const char* verbName(const Verb v) noexcept
|
||||
{
|
||||
switch (v) {
|
||||
case VERB_NOP:
|
||||
|
@ -736,8 +737,7 @@ static ZT_INLINE const char *verbName(const Verb v) noexcept
|
|||
/**
|
||||
* Error codes used in ERROR packets.
|
||||
*/
|
||||
enum ErrorCode
|
||||
{
|
||||
enum ErrorCode {
|
||||
/* Invalid request */
|
||||
ERROR_INVALID_REQUEST = 0x01,
|
||||
|
||||
|
@ -766,8 +766,7 @@ enum ErrorCode
|
|||
* This allows the node to know whether this is a normal frame or one generated
|
||||
* by a special tee or redirect type flow rule.
|
||||
*/
|
||||
enum ExtFrameSubtype
|
||||
{
|
||||
enum ExtFrameSubtype {
|
||||
EXT_FRAME_SUBTYPE_NORMAL = 0x0,
|
||||
EXT_FRAME_SUBTYPE_TEE_OUTBOUND = 0x1,
|
||||
EXT_FRAME_SUBTYPE_REDIRECT_OUTBOUND = 0x2,
|
||||
|
@ -780,8 +779,7 @@ enum ExtFrameSubtype
|
|||
/**
|
||||
* EXT_FRAME flags
|
||||
*/
|
||||
enum ExtFrameFlag
|
||||
{
|
||||
enum ExtFrameFlag {
|
||||
/**
|
||||
* A certifiate of membership was included (no longer used but still accepted)
|
||||
*/
|
||||
|
@ -798,8 +796,7 @@ enum ExtFrameFlag
|
|||
/**
|
||||
* NETWORK_CONFIG (or OK(NETWORK_CONFIG_REQUEST)) flags
|
||||
*/
|
||||
enum NetworkConfigFlag
|
||||
{
|
||||
enum NetworkConfigFlag {
|
||||
/**
|
||||
* Indicates that this network config chunk should be fast propagated via rumor mill flooding.
|
||||
*/
|
||||
|
@ -816,17 +813,22 @@ enum NetworkConfigFlag
|
|||
* @param in Input key (32 bytes)
|
||||
* @param out Output buffer (32 bytes)
|
||||
*/
|
||||
static ZT_INLINE void salsa2012DeriveKey(const uint8_t *const in, uint8_t *const out, const Buf &packet, const unsigned int packetSize) noexcept
|
||||
static ZT_INLINE void
|
||||
salsa2012DeriveKey(const uint8_t* const in, uint8_t* const out, const Buf& packet, const unsigned int packetSize)
|
||||
noexcept
|
||||
{
|
||||
// IV and source/destination addresses. Using the addresses divides the
|
||||
// key space into two halves-- A->B and B->A (since order will change).
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
for(int i=0;i<18;++i)
|
||||
for (int i = 0; i < 18; ++i)
|
||||
out[i] = in[i] ^ packet.unsafeData[i];
|
||||
#else
|
||||
*reinterpret_cast<uint64_t *>(out) = *reinterpret_cast<const uint64_t *>(in) ^ *reinterpret_cast<const uint64_t *>(packet.unsafeData);
|
||||
*reinterpret_cast<uint64_t *>(out + 8) = *reinterpret_cast<const uint64_t *>(in + 8) ^ *reinterpret_cast<const uint64_t *>(packet.unsafeData + 8);
|
||||
*reinterpret_cast<uint16_t *>(out + 16) = *reinterpret_cast<const uint16_t *>(in + 16) ^ *reinterpret_cast<const uint16_t *>(packet.unsafeData + 16);
|
||||
*reinterpret_cast<uint64_t*>(out) =
|
||||
*reinterpret_cast<const uint64_t*>(in) ^ *reinterpret_cast<const uint64_t*>(packet.unsafeData);
|
||||
*reinterpret_cast<uint64_t*>(out + 8) =
|
||||
*reinterpret_cast<const uint64_t*>(in + 8) ^ *reinterpret_cast<const uint64_t*>(packet.unsafeData + 8);
|
||||
*reinterpret_cast<uint16_t*>(out + 16) =
|
||||
*reinterpret_cast<const uint16_t*>(in + 16) ^ *reinterpret_cast<const uint16_t*>(packet.unsafeData + 16);
|
||||
#endif
|
||||
|
||||
// Flags, but with hop count masked off. Hop count is altered by forwarding
|
||||
|
@ -839,13 +841,13 @@ static ZT_INLINE void salsa2012DeriveKey(const uint8_t *const in, uint8_t *const
|
|||
|
||||
// Rest of raw key is used unchanged
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
for(int i=21;i<32;++i)
|
||||
for (int i = 21; i < 32; ++i)
|
||||
out[i] = in[i];
|
||||
#else
|
||||
out[21] = in[21];
|
||||
out[22] = in[22];
|
||||
out[23] = in[23];
|
||||
*reinterpret_cast<uint64_t *>(out + 24) = *reinterpret_cast<const uint64_t *>(in + 24);
|
||||
*reinterpret_cast<uint64_t*>(out + 24) = *reinterpret_cast<const uint64_t*>(in + 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -859,19 +861,24 @@ static ZT_INLINE void salsa2012DeriveKey(const uint8_t *const in, uint8_t *const
|
|||
* @param verb Protocol verb
|
||||
* @return Index of packet start
|
||||
*/
|
||||
static ZT_INLINE int newPacket(uint8_t pkt[28], const uint64_t packetId, const Address destination, const Address source, const Verb verb) noexcept
|
||||
static ZT_INLINE int
|
||||
newPacket(uint8_t pkt[28], const uint64_t packetId, const Address destination, const Address source, const Verb verb)
|
||||
noexcept
|
||||
{
|
||||
Utils::storeMachineEndian< uint64_t >(pkt + ZT_PROTO_PACKET_ID_INDEX, packetId);
|
||||
Utils::storeMachineEndian<uint64_t>(pkt + ZT_PROTO_PACKET_ID_INDEX, packetId);
|
||||
destination.copyTo(pkt + ZT_PROTO_PACKET_DESTINATION_INDEX);
|
||||
source.copyTo(pkt + ZT_PROTO_PACKET_SOURCE_INDEX);
|
||||
pkt[ZT_PROTO_PACKET_FLAGS_INDEX] = 0;
|
||||
Utils::storeMachineEndian< uint64_t >(pkt + ZT_PROTO_PACKET_MAC_INDEX, 0);
|
||||
Utils::storeMachineEndian<uint64_t>(pkt + ZT_PROTO_PACKET_MAC_INDEX, 0);
|
||||
pkt[ZT_PROTO_PACKET_VERB_INDEX] = (uint8_t)verb;
|
||||
return ZT_PROTO_PACKET_VERB_INDEX + 1;
|
||||
}
|
||||
|
||||
static ZT_INLINE int newPacket(Buf &pkt, const uint64_t packetId, const Address destination, const Address source, const Verb verb) noexcept
|
||||
{ return newPacket(pkt.unsafeData, packetId, destination, source, verb); }
|
||||
static ZT_INLINE int
|
||||
newPacket(Buf& pkt, const uint64_t packetId, const Address destination, const Address source, const Verb verb) noexcept
|
||||
{
|
||||
return newPacket(pkt.unsafeData, packetId, destination, source, verb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt and compute packet MAC
|
||||
|
@ -882,7 +889,8 @@ static ZT_INLINE int newPacket(Buf &pkt, const uint64_t packetId, const Address
|
|||
* @param cipherSuite Cipher suite to use for AEAD encryption or just MAC
|
||||
* @return Packet ID of packet (which may change!)
|
||||
*/
|
||||
static ZT_INLINE uint64_t armor(uint8_t *const pkt, const int packetSize, const SymmetricKey &key, const uint8_t cipherSuite) noexcept
|
||||
static ZT_INLINE uint64_t
|
||||
armor(uint8_t* const pkt, const int packetSize, const SymmetricKey& key, const uint8_t cipherSuite) noexcept
|
||||
{
|
||||
// TODO
|
||||
#if 0
|
||||
|
@ -940,7 +948,7 @@ static ZT_INLINE uint64_t armor(uint8_t *const pkt, const int packetSize, const
|
|||
* @param packetSize Total size of packet in bytes (including headers)
|
||||
* @return New size of packet after compression or original size of compression wasn't helpful
|
||||
*/
|
||||
static ZT_INLINE int compress(Buf &pkt, int packetSize) noexcept
|
||||
static ZT_INLINE int compress(Buf& pkt, int packetSize) noexcept
|
||||
{
|
||||
// TODO
|
||||
return packetSize;
|
||||
|
|
|
@ -7,7 +7,7 @@ Give it wire packets and it gives you Ethernet packets, and vice versa. The core
|
|||
|
||||
Code in here follows these guidelines:
|
||||
|
||||
- Keep it minimal, especially in terms of code footprint and memory use.
|
||||
- There should be no OS-dependent code here unless absolutely necessary (e.g. getSecureRandom).
|
||||
- If it's not part of the core virtual Ethernet switch it does not belong here.
|
||||
- Minimize the use of complex C++ features since at some point we might end up "minus-minus'ing" this code if doing so proves necessary to port to tiny embedded systems.
|
||||
- Keep it minimal, especially in terms of code footprint and memory use.
|
||||
- There should be no OS-dependent code here unless absolutely necessary (e.g. getSecureRandom).
|
||||
- If it's not part of the core virtual Ethernet switch it does not belong here.
|
||||
- Minimize the use of complex C++ features since at some point we might end up "minus-minus'ing" this code if doing so proves necessary to port to tiny embedded systems.
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool RevocationCredential::sign(const Identity &signer) noexcept
|
||||
bool RevocationCredential::sign(const Identity& signer) noexcept
|
||||
{
|
||||
uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX + 32];
|
||||
if (signer.hasPrivate()) {
|
||||
|
@ -33,22 +33,22 @@ int RevocationCredential::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX],
|
|||
for (int k = 0; k < 8; ++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
Utils::storeBigEndian< uint32_t >(data + p, 0);
|
||||
Utils::storeBigEndian< uint32_t >(data + p + 4, m_id);
|
||||
Utils::storeBigEndian< uint64_t >(data + p + 8, m_networkId);
|
||||
Utils::storeBigEndian< uint32_t >(data + p + 16, 0);
|
||||
Utils::storeBigEndian< uint32_t >(data + p + 20, m_credentialId);
|
||||
Utils::storeBigEndian< uint64_t >(data + p + 24, (uint64_t)m_threshold);
|
||||
Utils::storeBigEndian< uint64_t >(data + p + 32, m_flags);
|
||||
Utils::storeBigEndian<uint32_t>(data + p, 0);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 4, m_id);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, m_networkId);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 16, 0);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 20, m_credentialId);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 24, (uint64_t)m_threshold);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 32, m_flags);
|
||||
p += 40;
|
||||
m_target.copyTo(data + p);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
m_signedBy.copyTo(data + p);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
data[p++] = (uint8_t)m_type;
|
||||
if (!forSign) {
|
||||
if (! forSign) {
|
||||
data[p++] = 1;
|
||||
Utils::storeBigEndian< uint16_t >(data + p, (uint16_t)m_signatureLength);
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_signatureLength);
|
||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||
p += (int)m_signatureLength;
|
||||
}
|
||||
|
@ -61,29 +61,29 @@ int RevocationCredential::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX],
|
|||
return p;
|
||||
}
|
||||
|
||||
int RevocationCredential::unmarshal(const uint8_t *restrict data, const int len) noexcept
|
||||
int RevocationCredential::unmarshal(const uint8_t* restrict data, const int len) noexcept
|
||||
{
|
||||
if (len < 54)
|
||||
return -1;
|
||||
// 4 bytes reserved
|
||||
m_id = Utils::loadBigEndian< uint32_t >(data + 4);
|
||||
m_networkId = Utils::loadBigEndian< uint64_t >(data + 8);
|
||||
m_id = Utils::loadBigEndian<uint32_t>(data + 4);
|
||||
m_networkId = Utils::loadBigEndian<uint64_t>(data + 8);
|
||||
// 4 bytes reserved
|
||||
m_credentialId = Utils::loadBigEndian< uint32_t >(data + 20);
|
||||
m_threshold = (int64_t)Utils::loadBigEndian< uint64_t >(data + 24);
|
||||
m_flags = Utils::loadBigEndian< uint64_t >(data + 32);
|
||||
m_credentialId = Utils::loadBigEndian<uint32_t>(data + 20);
|
||||
m_threshold = (int64_t)Utils::loadBigEndian<uint64_t>(data + 24);
|
||||
m_flags = Utils::loadBigEndian<uint64_t>(data + 32);
|
||||
m_target.setTo(data + 40);
|
||||
m_signedBy.setTo(data + 45);
|
||||
m_type = (ZT_CredentialType)data[50];
|
||||
// 1 byte reserved
|
||||
m_signatureLength = Utils::loadBigEndian< uint16_t >(data + 52);
|
||||
m_signatureLength = Utils::loadBigEndian<uint16_t>(data + 52);
|
||||
int p = 54 + (int)m_signatureLength;
|
||||
if ((m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE) || (p > len))
|
||||
return -1;
|
||||
Utils::copy(m_signature, data + 54, m_signatureLength);
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
p += 2 + Utils::loadBigEndian< uint16_t >(data + p);
|
||||
p += 2 + Utils::loadBigEndian<uint16_t>(data + p);
|
||||
if (p > len)
|
||||
return -1;
|
||||
return p;
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
#ifndef ZT_REVOCATION_HPP
|
||||
#define ZT_REVOCATION_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
/**
|
||||
* Flag: fast propagation via rumor mill algorithm
|
||||
|
@ -35,16 +35,19 @@ class Context;
|
|||
/**
|
||||
* Revocation certificate to instantaneously revoke a COM, capability, or tag
|
||||
*/
|
||||
class RevocationCredential : public Credential
|
||||
{
|
||||
class RevocationCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_REVOCATION; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_REVOCATION;
|
||||
}
|
||||
|
||||
ZT_INLINE RevocationCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i ID (arbitrary for revocations, currently random)
|
||||
|
@ -55,53 +58,82 @@ public:
|
|||
* @param tgt Target node whose credential(s) are being revoked
|
||||
* @param ct Credential type being revoked
|
||||
*/
|
||||
ZT_INLINE RevocationCredential(const uint32_t i, const uint64_t nwid, const uint32_t cid, const uint64_t thr, const uint64_t fl, const Address &tgt, const ZT_CredentialType ct) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_id(i),
|
||||
m_credentialId(cid),
|
||||
m_networkId(nwid),
|
||||
m_threshold(thr),
|
||||
m_flags(fl),
|
||||
m_target(tgt),
|
||||
m_signedBy(),
|
||||
m_type(ct),
|
||||
m_signatureLength(0)
|
||||
{}
|
||||
ZT_INLINE RevocationCredential(
|
||||
const uint32_t i,
|
||||
const uint64_t nwid,
|
||||
const uint32_t cid,
|
||||
const uint64_t thr,
|
||||
const uint64_t fl,
|
||||
const Address& tgt,
|
||||
const ZT_CredentialType ct) noexcept
|
||||
: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_id(i)
|
||||
, m_credentialId(cid)
|
||||
, m_networkId(nwid)
|
||||
, m_threshold(thr)
|
||||
, m_flags(fl)
|
||||
, m_target(tgt)
|
||||
, m_signedBy()
|
||||
, m_type(ct)
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t credentialId() const noexcept
|
||||
{ return m_credentialId; }
|
||||
{
|
||||
return m_credentialId;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
{
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t threshold() const noexcept
|
||||
{ return m_threshold; }
|
||||
{
|
||||
return m_threshold;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address &target() const noexcept
|
||||
{ return m_target; }
|
||||
ZT_INLINE const Address& target() const noexcept
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address &signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE ZT_CredentialType typeBeingRevoked() const noexcept
|
||||
{ return m_type; }
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t *signature() const noexcept
|
||||
{ return m_signature; }
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
ZT_INLINE bool fastPropagate() const noexcept
|
||||
{ return ((m_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); }
|
||||
{
|
||||
return ((m_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signer Signing identity, must have private key
|
||||
* @return True if signature was successful
|
||||
*/
|
||||
bool sign(const Identity &signer) noexcept;
|
||||
bool sign(const Identity& signer) noexcept;
|
||||
|
||||
/**
|
||||
* Verify this revocation's signature
|
||||
|
@ -109,16 +141,20 @@ public:
|
|||
* @param RR Runtime environment to provide for peer lookup, etc.
|
||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context &ctx, const CallContext &cc) const noexcept
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const noexcept
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_REVOCATION_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_REVOCATION_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
int unmarshal(const uint8_t *restrict data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* restrict data, int len) noexcept;
|
||||
|
||||
private:
|
||||
private:
|
||||
uint32_t m_id;
|
||||
uint32_t m_credentialId;
|
||||
uint64_t m_networkId;
|
||||
|
|
153
core/SHA512.cpp
153
core/SHA512.cpp
|
@ -1,6 +1,7 @@
|
|||
// This code is public domain, taken from a PD crypto source file on GitHub.
|
||||
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -10,48 +11,44 @@ namespace ZeroTier {
|
|||
namespace {
|
||||
|
||||
struct sha512_state {
|
||||
uint64_t length,state[8];
|
||||
uint64_t length, state[8];
|
||||
unsigned long curlen;
|
||||
uint8_t buf[128];
|
||||
};
|
||||
|
||||
static const uint64_t K[80] = {
|
||||
0x428a2f98d728ae22ULL,0x7137449123ef65cdULL,0xb5c0fbcfec4d3b2fULL,0xe9b5dba58189dbbcULL,
|
||||
0x3956c25bf348b538ULL,0x59f111f1b605d019ULL,0x923f82a4af194f9bULL,0xab1c5ed5da6d8118ULL,
|
||||
0xd807aa98a3030242ULL,0x12835b0145706fbeULL,0x243185be4ee4b28cULL,0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL,0x80deb1fe3b1696b1ULL,0x9bdc06a725c71235ULL,0xc19bf174cf692694ULL,
|
||||
0xe49b69c19ef14ad2ULL,0xefbe4786384f25e3ULL,0x0fc19dc68b8cd5b5ULL,0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL,0x4a7484aa6ea6e483ULL,0x5cb0a9dcbd41fbd4ULL,0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL,0xa831c66d2db43210ULL,0xb00327c898fb213fULL,0xbf597fc7beef0ee4ULL,
|
||||
0xc6e00bf33da88fc2ULL,0xd5a79147930aa725ULL,0x06ca6351e003826fULL,0x142929670a0e6e70ULL,
|
||||
0x27b70a8546d22ffcULL,0x2e1b21385c26c926ULL,0x4d2c6dfc5ac42aedULL,0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL,0x766a0abb3c77b2a8ULL,0x81c2c92e47edaee6ULL,0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL,0xa81a664bbc423001ULL,0xc24b8b70d0f89791ULL,0xc76c51a30654be30ULL,
|
||||
0xd192e819d6ef5218ULL,0xd69906245565a910ULL,0xf40e35855771202aULL,0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL,0x1e376c085141ab53ULL,0x2748774cdf8eeb99ULL,0x34b0bcb5e19b48a8ULL,
|
||||
0x391c0cb3c5c95a63ULL,0x4ed8aa4ae3418acbULL,0x5b9cca4f7763e373ULL,0x682e6ff3d6b2b8a3ULL,
|
||||
0x748f82ee5defb2fcULL,0x78a5636f43172f60ULL,0x84c87814a1f0ab72ULL,0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL,0xa4506cebde82bde9ULL,0xbef9a3f7b2c67915ULL,0xc67178f2e372532bULL,
|
||||
0xca273eceea26619cULL,0xd186b8c721c0c207ULL,0xeada7dd6cde0eb1eULL,0xf57d4f7fee6ed178ULL,
|
||||
0x06f067aa72176fbaULL,0x0a637dc5a2c898a6ULL,0x113f9804bef90daeULL,0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL,0x32caab7b40c72493ULL,0x3c9ebe0a15c9bebcULL,0x431d67c49c100d4cULL,
|
||||
0x4cc5d4becb3e42b6ULL,0x597f299cfc657e2aULL,0x5fcb6fab3ad6faecULL,0x6c44198c4a475817ULL
|
||||
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL,
|
||||
0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
|
||||
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL,
|
||||
0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL,
|
||||
0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
|
||||
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL,
|
||||
0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL,
|
||||
0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
|
||||
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
|
||||
};
|
||||
|
||||
#define STORE64H(x, y) Utils::storeBigEndian<uint64_t>(y,x)
|
||||
#define STORE64H(x, y) Utils::storeBigEndian<uint64_t>(y, x)
|
||||
#define LOAD64H(x, y) x = Utils::loadBigEndian<uint64_t>(y)
|
||||
#define ROL64c(x,y) (((x)<<(y)) | ((x)>>(64-(y))))
|
||||
#define ROR64c(x,y) (((x)>>(y)) | ((x)<<(64-(y))))
|
||||
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x,y,z) (((x | y) & z) | (x & y))
|
||||
#define ROL64c(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
|
||||
#define ROR64c(x, y) (((x) >> (y)) | ((x) << (64 - (y))))
|
||||
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x, y, z) (((x | y) & z) | (x & y))
|
||||
#define S(x, n) ROR64c(x, n)
|
||||
#define R(x, n) ((x)>>(n))
|
||||
#define R(x, n) ((x) >> (n))
|
||||
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
|
||||
#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
|
||||
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
|
||||
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
|
||||
|
||||
static ZT_INLINE void sha512_compress(sha512_state *const md,uint8_t *const buf)
|
||||
static ZT_INLINE void sha512_compress(sha512_state* const md, uint8_t* const buf)
|
||||
{
|
||||
uint64_t S[8], W[80], t0, t1;
|
||||
int i;
|
||||
|
@ -59,32 +56,32 @@ static ZT_INLINE void sha512_compress(sha512_state *const md,uint8_t *const buf)
|
|||
for (i = 0; i < 8; i++)
|
||||
S[i] = md->state[i];
|
||||
for (i = 0; i < 16; i++)
|
||||
LOAD64H(W[i], buf + (8*i));
|
||||
LOAD64H(W[i], buf + (8 * i));
|
||||
for (i = 16; i < 80; i++)
|
||||
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
|
||||
|
||||
#define RND(a,b,c,d,e,f,g,h,i) \
|
||||
#define RND(a, b, c, d, e, f, g, h, i) \
|
||||
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
|
||||
t1 = Sigma0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
for (i = 0; i < 80; i += 8) {
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i + 0);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], i + 1);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], i + 2);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], i + 3);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], i + 4);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], i + 5);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], i + 6);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], i + 7);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
md->state[i] = md->state[i] + S[i];
|
||||
}
|
||||
|
||||
static ZT_INLINE void sha384_init(sha512_state *const md)
|
||||
static ZT_INLINE void sha384_init(sha512_state* const md)
|
||||
{
|
||||
md->curlen = 0;
|
||||
md->length = 0;
|
||||
|
@ -98,7 +95,7 @@ static ZT_INLINE void sha384_init(sha512_state *const md)
|
|||
md->state[7] = 0x47b5481dbefa4fa4ULL;
|
||||
}
|
||||
|
||||
static ZT_INLINE void sha512_init(sha512_state *const md)
|
||||
static ZT_INLINE void sha512_init(sha512_state* const md)
|
||||
{
|
||||
md->curlen = 0;
|
||||
md->length = 0;
|
||||
|
@ -112,30 +109,31 @@ static ZT_INLINE void sha512_init(sha512_state *const md)
|
|||
md->state[7] = 0x5be0cd19137e2179ULL;
|
||||
}
|
||||
|
||||
static void sha512_process(sha512_state *const md,const uint8_t *in,unsigned long inlen)
|
||||
static void sha512_process(sha512_state* const md, const uint8_t* in, unsigned long inlen)
|
||||
{
|
||||
while (inlen > 0) {
|
||||
if (md->curlen == 0 && inlen >= 128) {
|
||||
sha512_compress(md,(uint8_t *)in);
|
||||
sha512_compress(md, (uint8_t*)in);
|
||||
md->length += 128 * 8;
|
||||
in += 128;
|
||||
inlen -= 128;
|
||||
} else {
|
||||
unsigned long n = std::min(inlen,(128 - md->curlen));
|
||||
Utils::copy(md->buf + md->curlen,in,n);
|
||||
}
|
||||
else {
|
||||
unsigned long n = std::min(inlen, (128 - md->curlen));
|
||||
Utils::copy(md->buf + md->curlen, in, n);
|
||||
md->curlen += n;
|
||||
in += n;
|
||||
inlen -= n;
|
||||
if (md->curlen == 128) {
|
||||
sha512_compress(md,md->buf);
|
||||
md->length += 8*128;
|
||||
sha512_compress(md, md->buf);
|
||||
md->length += 8 * 128;
|
||||
md->curlen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_INLINE void sha512_done(sha512_state *const md,uint8_t *out)
|
||||
static ZT_INLINE void sha512_done(sha512_state* const md, uint8_t* out)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -154,58 +152,58 @@ static ZT_INLINE void sha512_done(sha512_state *const md,uint8_t *out)
|
|||
md->buf[md->curlen++] = (uint8_t)0;
|
||||
}
|
||||
|
||||
STORE64H(md->length, md->buf+120);
|
||||
STORE64H(md->length, md->buf + 120);
|
||||
sha512_compress(md, md->buf);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
STORE64H(md->state[i], out+(8*i));
|
||||
STORE64H(md->state[i], out + (8 * i));
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void SHA512(void *digest,const void *data,unsigned int len)
|
||||
void SHA512(void* digest, const void* data, unsigned int len)
|
||||
{
|
||||
sha512_state state;
|
||||
sha512_init(&state);
|
||||
sha512_process(&state,(uint8_t *)data,(unsigned long)len);
|
||||
sha512_done(&state,(uint8_t *)digest);
|
||||
sha512_process(&state, (uint8_t*)data, (unsigned long)len);
|
||||
sha512_done(&state, (uint8_t*)digest);
|
||||
}
|
||||
|
||||
void SHA384(void *digest,const void *data,unsigned int len)
|
||||
void SHA384(void* digest, const void* data, unsigned int len)
|
||||
{
|
||||
uint8_t tmp[64];
|
||||
sha512_state state;
|
||||
sha384_init(&state);
|
||||
sha512_process(&state,(uint8_t *)data,(unsigned long)len);
|
||||
sha512_done(&state,tmp);
|
||||
Utils::copy<48>(digest,tmp);
|
||||
sha512_process(&state, (uint8_t*)data, (unsigned long)len);
|
||||
sha512_done(&state, tmp);
|
||||
Utils::copy<48>(digest, tmp);
|
||||
}
|
||||
|
||||
void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
|
||||
void SHA384(void* digest, const void* data0, unsigned int len0, const void* data1, unsigned int len1)
|
||||
{
|
||||
uint8_t tmp[64];
|
||||
sha512_state state;
|
||||
sha384_init(&state);
|
||||
sha512_process(&state,(uint8_t *)data0,(unsigned long)len0);
|
||||
sha512_process(&state,(uint8_t *)data1,(unsigned long)len1);
|
||||
sha512_done(&state,tmp);
|
||||
Utils::copy<48>(digest,tmp);
|
||||
sha512_process(&state, (uint8_t*)data0, (unsigned long)len0);
|
||||
sha512_process(&state, (uint8_t*)data1, (unsigned long)len1);
|
||||
sha512_done(&state, tmp);
|
||||
Utils::copy<48>(digest, tmp);
|
||||
}
|
||||
|
||||
#endif // !ZT_HAVE_NATIVE_SHA512
|
||||
|
||||
void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,const unsigned int msglen,uint8_t mac[48])
|
||||
void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE], const void* msg, const unsigned int msglen, uint8_t mac[48])
|
||||
{
|
||||
uint64_t kInPadded[16]; // input padded key
|
||||
uint64_t outer[22]; // output padded key | H(input padded key | msg)
|
||||
|
||||
const uint64_t k0 = Utils::loadMachineEndian< uint64_t >(key);
|
||||
const uint64_t k1 = Utils::loadMachineEndian< uint64_t >(key + 8);
|
||||
const uint64_t k2 = Utils::loadMachineEndian< uint64_t >(key + 16);
|
||||
const uint64_t k3 = Utils::loadMachineEndian< uint64_t >(key + 24);
|
||||
const uint64_t k4 = Utils::loadMachineEndian< uint64_t >(key + 32);
|
||||
const uint64_t k5 = Utils::loadMachineEndian< uint64_t >(key + 40);
|
||||
const uint64_t k0 = Utils::loadMachineEndian<uint64_t>(key);
|
||||
const uint64_t k1 = Utils::loadMachineEndian<uint64_t>(key + 8);
|
||||
const uint64_t k2 = Utils::loadMachineEndian<uint64_t>(key + 16);
|
||||
const uint64_t k3 = Utils::loadMachineEndian<uint64_t>(key + 24);
|
||||
const uint64_t k4 = Utils::loadMachineEndian<uint64_t>(key + 32);
|
||||
const uint64_t k5 = Utils::loadMachineEndian<uint64_t>(key + 40);
|
||||
|
||||
const uint64_t ipad = 0x3636363636363636ULL;
|
||||
kInPadded[0] = k0 ^ ipad;
|
||||
|
@ -244,15 +242,20 @@ void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,const u
|
|||
outer[15] = opad;
|
||||
|
||||
// H(output padded key | H(input padded key | msg))
|
||||
SHA384(reinterpret_cast<uint8_t *>(outer) + 128,kInPadded,128,msg,msglen);
|
||||
SHA384(mac,outer,176);
|
||||
SHA384(reinterpret_cast<uint8_t*>(outer) + 128, kInPadded, 128, msg, msglen);
|
||||
SHA384(mac, outer, 176);
|
||||
}
|
||||
|
||||
void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const char label,const char context,const uint32_t iter,uint8_t out[ZT_SYMMETRIC_KEY_SIZE])
|
||||
void KBKDFHMACSHA384(
|
||||
const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],
|
||||
const char label,
|
||||
const char context,
|
||||
const uint32_t iter,
|
||||
uint8_t out[ZT_SYMMETRIC_KEY_SIZE])
|
||||
{
|
||||
uint8_t kbkdfMsg[13];
|
||||
|
||||
Utils::storeBigEndian<uint32_t>(kbkdfMsg,(uint32_t)iter);
|
||||
Utils::storeBigEndian<uint32_t>(kbkdfMsg, (uint32_t)iter);
|
||||
|
||||
kbkdfMsg[4] = (uint8_t)'Z';
|
||||
kbkdfMsg[5] = (uint8_t)'T'; // preface our labels with something ZT-specific
|
||||
|
@ -267,8 +270,8 @@ void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const char label,c
|
|||
kbkdfMsg[11] = 0x01;
|
||||
kbkdfMsg[12] = 0x80;
|
||||
|
||||
static_assert(ZT_SYMMETRIC_KEY_SIZE == ZT_SHA384_DIGEST_SIZE,"sizeof(out) != ZT_SHA384_DIGEST_SIZE");
|
||||
HMACSHA384(key,&kbkdfMsg,sizeof(kbkdfMsg),out);
|
||||
static_assert(ZT_SYMMETRIC_KEY_SIZE == ZT_SHA384_DIGEST_SIZE, "sizeof(out) != ZT_SHA384_DIGEST_SIZE");
|
||||
HMACSHA384(key, &kbkdfMsg, sizeof(kbkdfMsg), out);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -32,34 +32,34 @@ namespace ZeroTier {
|
|||
// SHA384 and SHA512 are actually in the standard libraries on MacOS and iOS
|
||||
#ifdef __APPLE__
|
||||
#define ZT_HAVE_NATIVE_SHA512 1
|
||||
static ZT_INLINE void SHA512(void *digest,const void *data,unsigned int len)
|
||||
static ZT_INLINE void SHA512(void* digest, const void* data, unsigned int len)
|
||||
{
|
||||
CC_SHA512_CTX ctx;
|
||||
CC_SHA512_Init(&ctx);
|
||||
CC_SHA512_Update(&ctx,data,len);
|
||||
CC_SHA512_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
|
||||
CC_SHA512_Update(&ctx, data, len);
|
||||
CC_SHA512_Final(reinterpret_cast<unsigned char*>(digest), &ctx);
|
||||
}
|
||||
static ZT_INLINE void SHA384(void *digest,const void *data,unsigned int len)
|
||||
static ZT_INLINE void SHA384(void* digest, const void* data, unsigned int len)
|
||||
{
|
||||
CC_SHA512_CTX ctx;
|
||||
CC_SHA384_Init(&ctx);
|
||||
CC_SHA384_Update(&ctx,data,len);
|
||||
CC_SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
|
||||
CC_SHA384_Update(&ctx, data, len);
|
||||
CC_SHA384_Final(reinterpret_cast<unsigned char*>(digest), &ctx);
|
||||
}
|
||||
static ZT_INLINE void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
|
||||
static ZT_INLINE void SHA384(void* digest, const void* data0, unsigned int len0, const void* data1, unsigned int len1)
|
||||
{
|
||||
CC_SHA512_CTX ctx;
|
||||
CC_SHA384_Init(&ctx);
|
||||
CC_SHA384_Update(&ctx,data0,len0);
|
||||
CC_SHA384_Update(&ctx,data1,len1);
|
||||
CC_SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
|
||||
CC_SHA384_Update(&ctx, data0, len0);
|
||||
CC_SHA384_Update(&ctx, data1, len1);
|
||||
CC_SHA384_Final(reinterpret_cast<unsigned char*>(digest), &ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ZT_HAVE_NATIVE_SHA512
|
||||
void SHA512(void *digest,const void *data,unsigned int len);
|
||||
void SHA384(void *digest,const void *data,unsigned int len);
|
||||
void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1);
|
||||
void SHA512(void* digest, const void* data, unsigned int len);
|
||||
void SHA384(void* digest, const void* data, unsigned int len);
|
||||
void SHA384(void* digest, const void* data0, unsigned int len0, const void* data1, unsigned int len1);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -70,7 +70,7 @@ void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,u
|
|||
* @param msglen Length of message
|
||||
* @param mac Buffer to fill with result
|
||||
*/
|
||||
void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,unsigned int msglen,uint8_t mac[48]);
|
||||
void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE], const void* msg, unsigned int msglen, uint8_t mac[48]);
|
||||
|
||||
/**
|
||||
* Compute KBKDF (key-based key derivation function) using HMAC-SHA-384 as a PRF
|
||||
|
@ -81,7 +81,12 @@ void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,unsigne
|
|||
* @param iter Key iteration for generation of multiple keys for the same label/context
|
||||
* @param out Output to receive derived key
|
||||
*/
|
||||
void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],char label,char context,uint32_t iter,uint8_t out[ZT_SYMMETRIC_KEY_SIZE]);
|
||||
void KBKDFHMACSHA384(
|
||||
const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],
|
||||
char label,
|
||||
char context,
|
||||
uint32_t iter,
|
||||
uint8_t out[ZT_SYMMETRIC_KEY_SIZE]);
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
228
core/Salsa20.cpp
228
core/Salsa20.cpp
|
@ -7,9 +7,10 @@
|
|||
* Since the original was public domain, this is too.
|
||||
*/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#define ROTATE(v, c) (((v) << (c)) | ((v) >> (32 - (c))))
|
||||
#define XOR(v, w) ((v) ^ (w))
|
||||
#define PLUS(v, w) ((uint32_t)((v) + (w)))
|
||||
|
@ -18,30 +19,43 @@
|
|||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
// Slower version that does not use type punning
|
||||
#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) )
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); }
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24))
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t* const c, const uint32_t v)
|
||||
{
|
||||
c[0] = (uint8_t)v;
|
||||
c[1] = (uint8_t)(v >> 8);
|
||||
c[2] = (uint8_t)(v >> 16);
|
||||
c[3] = (uint8_t)(v >> 24);
|
||||
}
|
||||
#else
|
||||
// Fast version that just does 32-bit load/store
|
||||
#define U8TO32_LITTLE(p) (*((const uint32_t *)((const void *)(p))))
|
||||
#define U32TO8_LITTLE(c,v) *((uint32_t *)((void *)(c))) = (v)
|
||||
#define U8TO32_LITTLE(p) (*((const uint32_t*)((const void*)(p))))
|
||||
#define U32TO8_LITTLE(c, v) *((uint32_t*)((void*)(c))) = (v)
|
||||
#endif // ZT_NO_UNALIGNED_ACCESS
|
||||
#else // __BYTE_ORDER == __BIG_ENDIAN (we don't support anything else... does MIDDLE_ENDIAN even still exist?)
|
||||
#ifdef __GNUC__
|
||||
// Use GNUC builtin bswap macros on big-endian machines if available
|
||||
#define U8TO32_LITTLE(p) __builtin_bswap32(*((const uint32_t *)((const void *)(p))))
|
||||
#define U32TO8_LITTLE(c,v) *((uint32_t *)((void *)(c))) = __builtin_bswap32((v))
|
||||
#define U8TO32_LITTLE(p) __builtin_bswap32(*((const uint32_t*)((const void*)(p))))
|
||||
#define U32TO8_LITTLE(c, v) *((uint32_t*)((void*)(c))) = __builtin_bswap32((v))
|
||||
#else // no __GNUC__
|
||||
// Otherwise do it the slow, manual way on BE machines
|
||||
#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) )
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); }
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24))
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t* const c, const uint32_t v)
|
||||
{
|
||||
c[0] = (uint8_t)v;
|
||||
c[1] = (uint8_t)(v >> 8);
|
||||
c[2] = (uint8_t)(v >> 16);
|
||||
c[3] = (uint8_t)(v >> 24);
|
||||
}
|
||||
#endif // __GNUC__ or not
|
||||
#endif // __BYTE_ORDER little or big?
|
||||
#endif // !ZT_SALSA20_SSE
|
||||
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
class _s20sseconsts
|
||||
{
|
||||
public:
|
||||
class _s20sseconsts {
|
||||
public:
|
||||
_s20sseconsts() noexcept
|
||||
{
|
||||
maskLo32 = _mm_shuffle_epi32(_mm_cvtsi32_si128(-1), _MM_SHUFFLE(1, 0, 1, 0));
|
||||
|
@ -54,10 +68,10 @@ static const _s20sseconsts s_S20SSECONSTANTS;
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
void Salsa20::init(const void *key, const void *iv) noexcept
|
||||
void Salsa20::init(const void* key, const void* iv) noexcept
|
||||
{
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
const uint32_t *const k = (const uint32_t *)key;
|
||||
const uint32_t* const k = (const uint32_t*)key;
|
||||
_state.i[0] = 0x61707865;
|
||||
_state.i[1] = 0x3320646e;
|
||||
_state.i[2] = 0x79622d32;
|
||||
|
@ -69,22 +83,22 @@ void Salsa20::init(const void *key, const void *iv) noexcept
|
|||
_state.i[8] = 0;
|
||||
_state.i[9] = k[6];
|
||||
_state.i[10] = k[1];
|
||||
_state.i[11] = ((const uint32_t *)iv)[1];
|
||||
_state.i[11] = ((const uint32_t*)iv)[1];
|
||||
_state.i[12] = k[5];
|
||||
_state.i[13] = k[0];
|
||||
_state.i[14] = ((const uint32_t *)iv)[0];
|
||||
_state.i[14] = ((const uint32_t*)iv)[0];
|
||||
_state.i[15] = k[4];
|
||||
#else
|
||||
const char *const constants = "expand 32-byte k";
|
||||
const uint8_t *const k = (const uint8_t *)key;
|
||||
const char* const constants = "expand 32-byte k";
|
||||
const uint8_t* const k = (const uint8_t*)key;
|
||||
_state.i[0] = U8TO32_LITTLE(constants + 0);
|
||||
_state.i[1] = U8TO32_LITTLE(k + 0);
|
||||
_state.i[2] = U8TO32_LITTLE(k + 4);
|
||||
_state.i[3] = U8TO32_LITTLE(k + 8);
|
||||
_state.i[4] = U8TO32_LITTLE(k + 12);
|
||||
_state.i[5] = U8TO32_LITTLE(constants + 4);
|
||||
_state.i[6] = U8TO32_LITTLE(((const uint8_t *)iv) + 0);
|
||||
_state.i[7] = U8TO32_LITTLE(((const uint8_t *)iv) + 4);
|
||||
_state.i[6] = U8TO32_LITTLE(((const uint8_t*)iv) + 0);
|
||||
_state.i[7] = U8TO32_LITTLE(((const uint8_t*)iv) + 4);
|
||||
_state.i[8] = 0;
|
||||
_state.i[9] = 0;
|
||||
_state.i[10] = U8TO32_LITTLE(constants + 8);
|
||||
|
@ -96,22 +110,21 @@ void Salsa20::init(const void *key, const void *iv) noexcept
|
|||
#endif
|
||||
}
|
||||
|
||||
union p_SalsaState
|
||||
{
|
||||
union p_SalsaState {
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
__m128i v[4];
|
||||
#endif // ZT_SALSA20_SSE
|
||||
uint32_t i[16];
|
||||
};
|
||||
|
||||
template< unsigned int R >
|
||||
static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m, uint8_t *c, unsigned int bytes) noexcept
|
||||
template <unsigned int R>
|
||||
static ZT_INLINE void p_salsaCrypt(p_SalsaState* const state, const uint8_t* m, uint8_t* c, unsigned int bytes) noexcept
|
||||
{
|
||||
if (unlikely(bytes == 0))
|
||||
return;
|
||||
|
||||
uint8_t tmp[64];
|
||||
uint8_t *ctarget = c;
|
||||
uint8_t* ctarget = c;
|
||||
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
__m128i X0 = state->v[0];
|
||||
|
@ -195,10 +208,18 @@ static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m,
|
|||
k02 = _mm_shuffle_epi32(k02, _MM_SHUFFLE(0, 1, 2, 3));
|
||||
k13 = _mm_shuffle_epi32(k13, _MM_SHUFFLE(0, 1, 2, 3));
|
||||
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c), _mm_xor_si128(_mm_unpackhi_epi64(k02, k20), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m))));
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c) + 1, _mm_xor_si128(_mm_unpackhi_epi64(k13, k31), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m) + 1)));
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c) + 2, _mm_xor_si128(_mm_unpacklo_epi64(k20, k02), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m) + 2)));
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c) + 3, _mm_xor_si128(_mm_unpacklo_epi64(k31, k13), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m) + 3)));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c),
|
||||
_mm_xor_si128(_mm_unpackhi_epi64(k02, k20), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m))));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c) + 1,
|
||||
_mm_xor_si128(_mm_unpackhi_epi64(k13, k31), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m) + 1)));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c) + 2,
|
||||
_mm_xor_si128(_mm_unpacklo_epi64(k20, k02), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m) + 2)));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c) + 3,
|
||||
_mm_xor_si128(_mm_unpacklo_epi64(k31, k13), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m) + 3)));
|
||||
|
||||
X0 = X0s;
|
||||
X1 = X1s;
|
||||
|
@ -224,74 +245,74 @@ static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m,
|
|||
x14 = j14;
|
||||
x15 = j15;
|
||||
|
||||
for(unsigned int rr=0;rr<(R/2);++rr) {
|
||||
x4 = XOR( x4,ROTATE(PLUS( x0,x12), 7));
|
||||
x8 = XOR( x8,ROTATE(PLUS( x4, x0), 9));
|
||||
x12 = XOR(x12,ROTATE(PLUS( x8, x4),13));
|
||||
x0 = XOR( x0,ROTATE(PLUS(x12, x8),18));
|
||||
x9 = XOR( x9,ROTATE(PLUS( x5, x1), 7));
|
||||
x13 = XOR(x13,ROTATE(PLUS( x9, x5), 9));
|
||||
x1 = XOR( x1,ROTATE(PLUS(x13, x9),13));
|
||||
x5 = XOR( x5,ROTATE(PLUS( x1,x13),18));
|
||||
x14 = XOR(x14,ROTATE(PLUS(x10, x6), 7));
|
||||
x2 = XOR( x2,ROTATE(PLUS(x14,x10), 9));
|
||||
x6 = XOR( x6,ROTATE(PLUS( x2,x14),13));
|
||||
x10 = XOR(x10,ROTATE(PLUS( x6, x2),18));
|
||||
x3 = XOR( x3,ROTATE(PLUS(x15,x11), 7));
|
||||
x7 = XOR( x7,ROTATE(PLUS( x3,x15), 9));
|
||||
x11 = XOR(x11,ROTATE(PLUS( x7, x3),13));
|
||||
x15 = XOR(x15,ROTATE(PLUS(x11, x7),18));
|
||||
x1 = XOR( x1,ROTATE(PLUS( x0, x3), 7));
|
||||
x2 = XOR( x2,ROTATE(PLUS( x1, x0), 9));
|
||||
x3 = XOR( x3,ROTATE(PLUS( x2, x1),13));
|
||||
x0 = XOR( x0,ROTATE(PLUS( x3, x2),18));
|
||||
x6 = XOR( x6,ROTATE(PLUS( x5, x4), 7));
|
||||
x7 = XOR( x7,ROTATE(PLUS( x6, x5), 9));
|
||||
x4 = XOR( x4,ROTATE(PLUS( x7, x6),13));
|
||||
x5 = XOR( x5,ROTATE(PLUS( x4, x7),18));
|
||||
x11 = XOR(x11,ROTATE(PLUS(x10, x9), 7));
|
||||
x8 = XOR( x8,ROTATE(PLUS(x11,x10), 9));
|
||||
x9 = XOR( x9,ROTATE(PLUS( x8,x11),13));
|
||||
x10 = XOR(x10,ROTATE(PLUS( x9, x8),18));
|
||||
x12 = XOR(x12,ROTATE(PLUS(x15,x14), 7));
|
||||
x13 = XOR(x13,ROTATE(PLUS(x12,x15), 9));
|
||||
x14 = XOR(x14,ROTATE(PLUS(x13,x12),13));
|
||||
x15 = XOR(x15,ROTATE(PLUS(x14,x13),18));
|
||||
for (unsigned int rr = 0; rr < (R / 2); ++rr) {
|
||||
x4 = XOR(x4, ROTATE(PLUS(x0, x12), 7));
|
||||
x8 = XOR(x8, ROTATE(PLUS(x4, x0), 9));
|
||||
x12 = XOR(x12, ROTATE(PLUS(x8, x4), 13));
|
||||
x0 = XOR(x0, ROTATE(PLUS(x12, x8), 18));
|
||||
x9 = XOR(x9, ROTATE(PLUS(x5, x1), 7));
|
||||
x13 = XOR(x13, ROTATE(PLUS(x9, x5), 9));
|
||||
x1 = XOR(x1, ROTATE(PLUS(x13, x9), 13));
|
||||
x5 = XOR(x5, ROTATE(PLUS(x1, x13), 18));
|
||||
x14 = XOR(x14, ROTATE(PLUS(x10, x6), 7));
|
||||
x2 = XOR(x2, ROTATE(PLUS(x14, x10), 9));
|
||||
x6 = XOR(x6, ROTATE(PLUS(x2, x14), 13));
|
||||
x10 = XOR(x10, ROTATE(PLUS(x6, x2), 18));
|
||||
x3 = XOR(x3, ROTATE(PLUS(x15, x11), 7));
|
||||
x7 = XOR(x7, ROTATE(PLUS(x3, x15), 9));
|
||||
x11 = XOR(x11, ROTATE(PLUS(x7, x3), 13));
|
||||
x15 = XOR(x15, ROTATE(PLUS(x11, x7), 18));
|
||||
x1 = XOR(x1, ROTATE(PLUS(x0, x3), 7));
|
||||
x2 = XOR(x2, ROTATE(PLUS(x1, x0), 9));
|
||||
x3 = XOR(x3, ROTATE(PLUS(x2, x1), 13));
|
||||
x0 = XOR(x0, ROTATE(PLUS(x3, x2), 18));
|
||||
x6 = XOR(x6, ROTATE(PLUS(x5, x4), 7));
|
||||
x7 = XOR(x7, ROTATE(PLUS(x6, x5), 9));
|
||||
x4 = XOR(x4, ROTATE(PLUS(x7, x6), 13));
|
||||
x5 = XOR(x5, ROTATE(PLUS(x4, x7), 18));
|
||||
x11 = XOR(x11, ROTATE(PLUS(x10, x9), 7));
|
||||
x8 = XOR(x8, ROTATE(PLUS(x11, x10), 9));
|
||||
x9 = XOR(x9, ROTATE(PLUS(x8, x11), 13));
|
||||
x10 = XOR(x10, ROTATE(PLUS(x9, x8), 18));
|
||||
x12 = XOR(x12, ROTATE(PLUS(x15, x14), 7));
|
||||
x13 = XOR(x13, ROTATE(PLUS(x12, x15), 9));
|
||||
x14 = XOR(x14, ROTATE(PLUS(x13, x12), 13));
|
||||
x15 = XOR(x15, ROTATE(PLUS(x14, x13), 18));
|
||||
}
|
||||
|
||||
x0 = PLUS(x0,j0);
|
||||
x1 = PLUS(x1,j1);
|
||||
x2 = PLUS(x2,j2);
|
||||
x3 = PLUS(x3,j3);
|
||||
x4 = PLUS(x4,j4);
|
||||
x5 = PLUS(x5,j5);
|
||||
x6 = PLUS(x6,j6);
|
||||
x7 = PLUS(x7,j7);
|
||||
x8 = PLUS(x8,j8);
|
||||
x9 = PLUS(x9,j9);
|
||||
x10 = PLUS(x10,j10);
|
||||
x11 = PLUS(x11,j11);
|
||||
x12 = PLUS(x12,j12);
|
||||
x13 = PLUS(x13,j13);
|
||||
x14 = PLUS(x14,j14);
|
||||
x15 = PLUS(x15,j15);
|
||||
x0 = PLUS(x0, j0);
|
||||
x1 = PLUS(x1, j1);
|
||||
x2 = PLUS(x2, j2);
|
||||
x3 = PLUS(x3, j3);
|
||||
x4 = PLUS(x4, j4);
|
||||
x5 = PLUS(x5, j5);
|
||||
x6 = PLUS(x6, j6);
|
||||
x7 = PLUS(x7, j7);
|
||||
x8 = PLUS(x8, j8);
|
||||
x9 = PLUS(x9, j9);
|
||||
x10 = PLUS(x10, j10);
|
||||
x11 = PLUS(x11, j11);
|
||||
x12 = PLUS(x12, j12);
|
||||
x13 = PLUS(x13, j13);
|
||||
x14 = PLUS(x14, j14);
|
||||
x15 = PLUS(x15, j15);
|
||||
|
||||
U32TO8_LITTLE(c + 0,XOR(x0,U8TO32_LITTLE(m + 0)));
|
||||
U32TO8_LITTLE(c + 4,XOR(x1,U8TO32_LITTLE(m + 4)));
|
||||
U32TO8_LITTLE(c + 8,XOR(x2,U8TO32_LITTLE(m + 8)));
|
||||
U32TO8_LITTLE(c + 12,XOR(x3,U8TO32_LITTLE(m + 12)));
|
||||
U32TO8_LITTLE(c + 16,XOR(x4,U8TO32_LITTLE(m + 16)));
|
||||
U32TO8_LITTLE(c + 20,XOR(x5,U8TO32_LITTLE(m + 20)));
|
||||
U32TO8_LITTLE(c + 24,XOR(x6,U8TO32_LITTLE(m + 24)));
|
||||
U32TO8_LITTLE(c + 28,XOR(x7,U8TO32_LITTLE(m + 28)));
|
||||
U32TO8_LITTLE(c + 32,XOR(x8,U8TO32_LITTLE(m + 32)));
|
||||
U32TO8_LITTLE(c + 36,XOR(x9,U8TO32_LITTLE(m + 36)));
|
||||
U32TO8_LITTLE(c + 40,XOR(x10,U8TO32_LITTLE(m + 40)));
|
||||
U32TO8_LITTLE(c + 44,XOR(x11,U8TO32_LITTLE(m + 44)));
|
||||
U32TO8_LITTLE(c + 48,XOR(x12,U8TO32_LITTLE(m + 48)));
|
||||
U32TO8_LITTLE(c + 52,XOR(x13,U8TO32_LITTLE(m + 52)));
|
||||
U32TO8_LITTLE(c + 56,XOR(x14,U8TO32_LITTLE(m + 56)));
|
||||
U32TO8_LITTLE(c + 60,XOR(x15,U8TO32_LITTLE(m + 60)));
|
||||
U32TO8_LITTLE(c + 0, XOR(x0, U8TO32_LITTLE(m + 0)));
|
||||
U32TO8_LITTLE(c + 4, XOR(x1, U8TO32_LITTLE(m + 4)));
|
||||
U32TO8_LITTLE(c + 8, XOR(x2, U8TO32_LITTLE(m + 8)));
|
||||
U32TO8_LITTLE(c + 12, XOR(x3, U8TO32_LITTLE(m + 12)));
|
||||
U32TO8_LITTLE(c + 16, XOR(x4, U8TO32_LITTLE(m + 16)));
|
||||
U32TO8_LITTLE(c + 20, XOR(x5, U8TO32_LITTLE(m + 20)));
|
||||
U32TO8_LITTLE(c + 24, XOR(x6, U8TO32_LITTLE(m + 24)));
|
||||
U32TO8_LITTLE(c + 28, XOR(x7, U8TO32_LITTLE(m + 28)));
|
||||
U32TO8_LITTLE(c + 32, XOR(x8, U8TO32_LITTLE(m + 32)));
|
||||
U32TO8_LITTLE(c + 36, XOR(x9, U8TO32_LITTLE(m + 36)));
|
||||
U32TO8_LITTLE(c + 40, XOR(x10, U8TO32_LITTLE(m + 40)));
|
||||
U32TO8_LITTLE(c + 44, XOR(x11, U8TO32_LITTLE(m + 44)));
|
||||
U32TO8_LITTLE(c + 48, XOR(x12, U8TO32_LITTLE(m + 48)));
|
||||
U32TO8_LITTLE(c + 52, XOR(x13, U8TO32_LITTLE(m + 52)));
|
||||
U32TO8_LITTLE(c + 56, XOR(x14, U8TO32_LITTLE(m + 56)));
|
||||
U32TO8_LITTLE(c + 60, XOR(x15, U8TO32_LITTLE(m + 60)));
|
||||
|
||||
++j8;
|
||||
|
||||
|
@ -301,7 +322,8 @@ static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m,
|
|||
bytes -= 64;
|
||||
c += 64;
|
||||
m += 64;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (bytes < 64) {
|
||||
for (unsigned int i = 0; i < bytes; ++i)
|
||||
ctarget[i] = c[i];
|
||||
|
@ -316,14 +338,22 @@ static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m,
|
|||
}
|
||||
}
|
||||
|
||||
void Salsa20::crypt12(const void *in, void *out, unsigned int bytes) noexcept
|
||||
void Salsa20::crypt12(const void* in, void* out, unsigned int bytes) noexcept
|
||||
{
|
||||
p_salsaCrypt< 12 >(reinterpret_cast<p_SalsaState *>(&_state), reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out), bytes);
|
||||
p_salsaCrypt<12>(
|
||||
reinterpret_cast<p_SalsaState*>(&_state),
|
||||
reinterpret_cast<const uint8_t*>(in),
|
||||
reinterpret_cast<uint8_t*>(out),
|
||||
bytes);
|
||||
}
|
||||
|
||||
void Salsa20::crypt20(const void *in, void *out, unsigned int bytes) noexcept
|
||||
void Salsa20::crypt20(const void* in, void* out, unsigned int bytes) noexcept
|
||||
{
|
||||
p_salsaCrypt< 20 >(reinterpret_cast<p_SalsaState *>(&_state), reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out), bytes);
|
||||
p_salsaCrypt<20>(
|
||||
reinterpret_cast<p_SalsaState*>(&_state),
|
||||
reinterpret_cast<const uint8_t*>(in),
|
||||
reinterpret_cast<uint8_t*>(out),
|
||||
bytes);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
#define ZT_SALSA20_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#ifdef ZT_ARCH_X64
|
||||
#define ZT_SALSA20_SSE 1
|
||||
|
@ -35,30 +35,39 @@ namespace ZeroTier {
|
|||
* a minor optimization done here because ZeroTier messages are
|
||||
* nowhere near this large.
|
||||
*/
|
||||
class Salsa20 : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
class Salsa20 : public TriviallyCopyable {
|
||||
public:
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
|
||||
static constexpr bool accelerated() noexcept
|
||||
{ return true; }
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
static constexpr bool accelerated() noexcept { return false; }
|
||||
static constexpr bool accelerated() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
ZT_INLINE Salsa20() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~Salsa20() noexcept
|
||||
{ Utils::burn(&_state, sizeof(_state)); }
|
||||
{
|
||||
Utils::burn(&_state, sizeof(_state));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key 256-bit (32 byte) key
|
||||
* @param iv 64-bit initialization vector
|
||||
*/
|
||||
ZT_INLINE Salsa20(const void *key, const void *iv) noexcept
|
||||
{ init(key, iv); }
|
||||
ZT_INLINE Salsa20(const void* key, const void* iv) noexcept
|
||||
{
|
||||
init(key, iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize cipher
|
||||
|
@ -66,7 +75,7 @@ public:
|
|||
* @param key Key bits
|
||||
* @param iv 64-bit initialization vector
|
||||
*/
|
||||
void init(const void *key, const void *iv) noexcept;
|
||||
void init(const void* key, const void* iv) noexcept;
|
||||
|
||||
/**
|
||||
* Encrypt/decrypt data using Salsa20/12
|
||||
|
@ -75,7 +84,7 @@ public:
|
|||
* @param out Output buffer
|
||||
* @param bytes Length of data
|
||||
*/
|
||||
void crypt12(const void *in, void *out, unsigned int bytes) noexcept;
|
||||
void crypt12(const void* in, void* out, unsigned int bytes) noexcept;
|
||||
|
||||
/**
|
||||
* Encrypt/decrypt data using Salsa20/20
|
||||
|
@ -84,11 +93,10 @@ public:
|
|||
* @param out Output buffer
|
||||
* @param bytes Length of data
|
||||
*/
|
||||
void crypt20(const void *in, void *out, unsigned int bytes) noexcept;
|
||||
void crypt20(const void* in, void* out, unsigned int bytes) noexcept;
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
private:
|
||||
union {
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
__m128i v[4];
|
||||
#endif // ZT_SALSA20_SSE
|
||||
|
|
|
@ -24,66 +24,88 @@ namespace ZeroTier {
|
|||
*
|
||||
* This is used in the core to avoid requiring C++11 and because auto_ptr is weird.
|
||||
*/
|
||||
template< typename T >
|
||||
class ScopedPtr : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
explicit ZT_INLINE ScopedPtr(T *const p) noexcept: m_ptr(p)
|
||||
{}
|
||||
template <typename T> class ScopedPtr : public TriviallyCopyable {
|
||||
public:
|
||||
explicit ZT_INLINE ScopedPtr(T* const p) noexcept : m_ptr(p)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~ScopedPtr()
|
||||
{ delete m_ptr; }
|
||||
|
||||
ZT_INLINE T *operator->() const noexcept
|
||||
{ return m_ptr; }
|
||||
|
||||
ZT_INLINE T &operator*() const noexcept
|
||||
{ return *m_ptr; }
|
||||
|
||||
ZT_INLINE T *ptr() const noexcept
|
||||
{ return m_ptr; }
|
||||
|
||||
ZT_INLINE void swap(const ScopedPtr &p) noexcept
|
||||
{
|
||||
T *const tmp = m_ptr;
|
||||
delete m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T* operator->() const noexcept
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T& operator*() const noexcept
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T* ptr() const noexcept
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE void swap(const ScopedPtr& p) noexcept
|
||||
{
|
||||
T* const tmp = m_ptr;
|
||||
m_ptr = p.m_ptr;
|
||||
p.m_ptr = tmp;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_ptr != (T *)0); }
|
||||
{
|
||||
return (m_ptr != (T*)0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const ScopedPtr &p) const noexcept
|
||||
{ return (m_ptr == p.m_ptr); }
|
||||
ZT_INLINE bool operator==(const ScopedPtr& p) const noexcept
|
||||
{
|
||||
return (m_ptr == p.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const ScopedPtr &p) const noexcept
|
||||
{ return (m_ptr != p.m_ptr); }
|
||||
ZT_INLINE bool operator!=(const ScopedPtr& p) const noexcept
|
||||
{
|
||||
return (m_ptr != p.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(T *const p) const noexcept
|
||||
{ return (m_ptr == p); }
|
||||
ZT_INLINE bool operator==(T* const p) const noexcept
|
||||
{
|
||||
return (m_ptr == p);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(T *const p) const noexcept
|
||||
{ return (m_ptr != p); }
|
||||
ZT_INLINE bool operator!=(T* const p) const noexcept
|
||||
{
|
||||
return (m_ptr != p);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
ZT_INLINE ScopedPtr() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ScopedPtr(const ScopedPtr &p) noexcept: m_ptr(nullptr)
|
||||
{}
|
||||
ZT_INLINE ScopedPtr(const ScopedPtr& p) noexcept : m_ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ScopedPtr &operator=(const ScopedPtr &p) noexcept
|
||||
{ return *this; }
|
||||
ZT_INLINE ScopedPtr& operator=(const ScopedPtr& p) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
T *const m_ptr;
|
||||
T* const m_ptr;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
namespace std {
|
||||
template< typename T >
|
||||
ZT_INLINE void swap(ZeroTier::ScopedPtr< T > &a, ZeroTier::ScopedPtr< T > &b) noexcept
|
||||
{ a.swap(b); }
|
||||
template <typename T> ZT_INLINE void swap(ZeroTier::ScopedPtr<T>& a, ZeroTier::ScopedPtr<T>& b) noexcept
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,34 +11,44 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
// Entry timeout -- make it fairly long since this is just to prevent stale buildup
|
||||
#define ZT_SELFAWARENESS_ENTRY_TIMEOUT 300000
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
SelfAwareness::SelfAwareness(const Context &ctx) :
|
||||
m_ctx(ctx)
|
||||
{}
|
||||
SelfAwareness::SelfAwareness(const Context& ctx) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void SelfAwareness::iam(const CallContext &cc, const Identity &reporter, const int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted)
|
||||
void SelfAwareness::iam(
|
||||
const CallContext& cc,
|
||||
const Identity& reporter,
|
||||
const int64_t receivedOnLocalSocket,
|
||||
const InetAddress& reporterPhysicalAddress,
|
||||
const InetAddress& myPhysicalAddress,
|
||||
bool trusted)
|
||||
{
|
||||
const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
|
||||
|
||||
if ((scope != reporterPhysicalAddress.ipScope()) || (scope == ZT_IP_SCOPE_NONE) || (scope == ZT_IP_SCOPE_LOOPBACK) || (scope == ZT_IP_SCOPE_MULTICAST))
|
||||
if ((scope != reporterPhysicalAddress.ipScope()) || (scope == ZT_IP_SCOPE_NONE) || (scope == ZT_IP_SCOPE_LOOPBACK)
|
||||
|| (scope == ZT_IP_SCOPE_MULTICAST))
|
||||
return;
|
||||
|
||||
Mutex::Lock l(m_phy_l);
|
||||
p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)];
|
||||
p_PhySurfaceEntry& entry =
|
||||
m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)];
|
||||
|
||||
if ((trusted) && ((cc.ticks - entry.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress))) {
|
||||
if ((trusted) && ((cc.ticks - entry.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
&& (! entry.mySurface.ipsEqual(myPhysicalAddress))) {
|
||||
// Changes to external surface reported by trusted peers causes path reset in this scope
|
||||
entry.mySurface = myPhysicalAddress;
|
||||
entry.timestampTicks = cc.ticks;
|
||||
|
@ -47,20 +57,29 @@ void SelfAwareness::iam(const CallContext &cc, const Identity &reporter, const i
|
|||
// Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing'
|
||||
// due to multiple reports of endpoint change.
|
||||
// Don't use 'entry' after this since hash table gets modified.
|
||||
for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::iterator i(m_phy.begin()); i != m_phy.end();) {
|
||||
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::iterator i(m_phy.begin()); i != m_phy.end();) {
|
||||
if ((i->first.scope == scope) && (i->first.reporterPhysicalAddress != reporterPhysicalAddress))
|
||||
m_phy.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
// Reset all paths within this scope and address family
|
||||
Vector< SharedPtr< Peer > > peers, rootPeers;
|
||||
Vector<SharedPtr<Peer> > peers, rootPeers;
|
||||
m_ctx.topology->allPeers(peers, rootPeers);
|
||||
for(Vector< SharedPtr< Peer > >::const_iterator p(peers.begin());p!=peers.end();++p)
|
||||
for (Vector<SharedPtr<Peer> >::const_iterator p(peers.begin()); p != peers.end(); ++p)
|
||||
(*p)->resetWithinScope(m_ctx, cc, (InetAddress::IpScope)scope, myPhysicalAddress.as.sa.sa_family);
|
||||
|
||||
m_ctx.t->resettingPathsInScope(cc, 0x9afff100, reporter, reporterPhysicalAddress, entry.mySurface, myPhysicalAddress, scope);
|
||||
} else {
|
||||
m_ctx.t->resettingPathsInScope(
|
||||
cc,
|
||||
0x9afff100,
|
||||
reporter,
|
||||
reporterPhysicalAddress,
|
||||
entry.mySurface,
|
||||
myPhysicalAddress,
|
||||
scope);
|
||||
}
|
||||
else {
|
||||
// Otherwise just update DB to use to determine external surface info
|
||||
entry.mySurface = myPhysicalAddress;
|
||||
entry.timestampTicks = cc.ticks;
|
||||
|
@ -68,33 +87,34 @@ void SelfAwareness::iam(const CallContext &cc, const Identity &reporter, const i
|
|||
}
|
||||
}
|
||||
|
||||
void SelfAwareness::clean(const CallContext &cc)
|
||||
void SelfAwareness::clean(const CallContext& cc)
|
||||
{
|
||||
Mutex::Lock l(m_phy_l);
|
||||
for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::iterator i(m_phy.begin()); i != m_phy.end();) {
|
||||
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::iterator i(m_phy.begin()); i != m_phy.end();) {
|
||||
if ((cc.ticks - i->second.timestampTicks) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
m_phy.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
MultiMap< unsigned int, InetAddress > SelfAwareness::externalAddresses(CallContext &cc) const
|
||||
MultiMap<unsigned int, InetAddress> SelfAwareness::externalAddresses(CallContext& cc) const
|
||||
{
|
||||
MultiMap< unsigned int, InetAddress > r;
|
||||
MultiMap<unsigned int, InetAddress> r;
|
||||
|
||||
// Count endpoints reporting each IP/port combo
|
||||
Map< InetAddress, unsigned long > counts;
|
||||
Map<InetAddress, unsigned long> counts;
|
||||
{
|
||||
Mutex::Lock l(m_phy_l);
|
||||
for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::const_iterator i(m_phy.begin()); i != m_phy.end(); ++i) {
|
||||
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::const_iterator i(m_phy.begin()); i != m_phy.end(); ++i) {
|
||||
if ((cc.ticks - i->second.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
++counts[i->second.mySurface];
|
||||
}
|
||||
}
|
||||
|
||||
// Invert to create a map from count to address
|
||||
for (Map< InetAddress, unsigned long >::iterator i(counts.begin()); i != counts.end(); ++i)
|
||||
r.insert(std::pair< unsigned long, InetAddress >(i->second, i->first));
|
||||
for (Map<InetAddress, unsigned long>::iterator i(counts.begin()); i != counts.end(); ++i)
|
||||
r.insert(std::pair<unsigned long, InetAddress>(i->second, i->first));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
#ifndef ZT_SELFAWARENESS_HPP
|
||||
#define ZT_SELFAWARENESS_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -31,10 +31,9 @@ class Context;
|
|||
*
|
||||
* Name aside, it shouldn't be capable of achieving sentience.
|
||||
*/
|
||||
class SelfAwareness
|
||||
{
|
||||
public:
|
||||
explicit SelfAwareness(const Context &ctx);
|
||||
class SelfAwareness {
|
||||
public:
|
||||
explicit SelfAwareness(const Context& ctx);
|
||||
|
||||
/**
|
||||
* Called when a remote peer informs us of our external network address
|
||||
|
@ -45,54 +44,77 @@ public:
|
|||
* @param myPhysicalAddress Physical address that peer says we have
|
||||
* @param trusted True if this peer is trusted as an authority to inform us of external address changes
|
||||
*/
|
||||
void iam(const CallContext &cc, const Identity &reporter, int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted);
|
||||
void
|
||||
iam(const CallContext& cc,
|
||||
const Identity& reporter,
|
||||
int64_t receivedOnLocalSocket,
|
||||
const InetAddress& reporterPhysicalAddress,
|
||||
const InetAddress& myPhysicalAddress,
|
||||
bool trusted);
|
||||
|
||||
/**
|
||||
* Clean up database periodically
|
||||
*/
|
||||
void clean(const CallContext &cc);
|
||||
void clean(const CallContext& cc);
|
||||
|
||||
/**
|
||||
* Get external address consensus, which is the statistical "mode" of external addresses.
|
||||
*
|
||||
* @return Map of count to IP/port representing how many endpoints reported each address
|
||||
*/
|
||||
MultiMap< unsigned int, InetAddress > externalAddresses(CallContext &cc) const;
|
||||
MultiMap<unsigned int, InetAddress> externalAddresses(CallContext& cc) const;
|
||||
|
||||
private:
|
||||
struct p_PhySurfaceKey
|
||||
{
|
||||
private:
|
||||
struct p_PhySurfaceKey {
|
||||
Address reporter;
|
||||
int64_t receivedOnLocalSocket;
|
||||
InetAddress reporterPhysicalAddress;
|
||||
InetAddress::IpScope scope;
|
||||
|
||||
ZT_INLINE p_PhySurfaceKey() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE p_PhySurfaceKey(const Address &r, const int64_t rol, const InetAddress &ra, InetAddress::IpScope s) noexcept: reporter(r), receivedOnLocalSocket(rol), reporterPhysicalAddress(ra), scope(s)
|
||||
{}
|
||||
ZT_INLINE
|
||||
p_PhySurfaceKey(const Address& r, const int64_t rol, const InetAddress& ra, InetAddress::IpScope s) noexcept
|
||||
: reporter(r)
|
||||
, receivedOnLocalSocket(rol)
|
||||
, reporterPhysicalAddress(ra)
|
||||
, scope(s)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return ((unsigned long)reporter.toInt() + (unsigned long)receivedOnLocalSocket + (unsigned long)scope); }
|
||||
{
|
||||
return ((unsigned long)reporter.toInt() + (unsigned long)receivedOnLocalSocket + (unsigned long)scope);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const p_PhySurfaceKey &k) const noexcept
|
||||
{ return ((reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket) && (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope)); }
|
||||
ZT_INLINE bool operator==(const p_PhySurfaceKey& k) const noexcept
|
||||
{
|
||||
return (
|
||||
(reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket)
|
||||
&& (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const p_PhySurfaceKey &k) const noexcept
|
||||
{ return (!(*this == k)); }
|
||||
ZT_INLINE bool operator!=(const p_PhySurfaceKey& k) const noexcept
|
||||
{
|
||||
return (! (*this == k));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const p_PhySurfaceKey &k) const noexcept
|
||||
ZT_INLINE bool operator<(const p_PhySurfaceKey& k) const noexcept
|
||||
{
|
||||
if (reporter < k.reporter) {
|
||||
return true;
|
||||
} else if (reporter == k.reporter) {
|
||||
}
|
||||
else if (reporter == k.reporter) {
|
||||
if (receivedOnLocalSocket < k.receivedOnLocalSocket) {
|
||||
return true;
|
||||
} else if (receivedOnLocalSocket == k.receivedOnLocalSocket) {
|
||||
}
|
||||
else if (receivedOnLocalSocket == k.receivedOnLocalSocket) {
|
||||
if (reporterPhysicalAddress < k.reporterPhysicalAddress) {
|
||||
return true;
|
||||
} else if (reporterPhysicalAddress == k.reporterPhysicalAddress) {
|
||||
}
|
||||
else if (reporterPhysicalAddress == k.reporterPhysicalAddress) {
|
||||
return scope < k.scope;
|
||||
}
|
||||
}
|
||||
|
@ -101,21 +123,28 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
struct p_PhySurfaceEntry
|
||||
{
|
||||
struct p_PhySurfaceEntry {
|
||||
InetAddress mySurface;
|
||||
int64_t timestampTicks;
|
||||
bool trusted;
|
||||
|
||||
ZT_INLINE p_PhySurfaceEntry() noexcept: mySurface(), timestampTicks(0), trusted(false)
|
||||
{}
|
||||
ZT_INLINE p_PhySurfaceEntry() noexcept
|
||||
: mySurface()
|
||||
, timestampTicks(0)
|
||||
, trusted(false)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE p_PhySurfaceEntry(const InetAddress &a, const int64_t t) noexcept: mySurface(a), timestampTicks(t), trusted(false)
|
||||
{}
|
||||
ZT_INLINE p_PhySurfaceEntry(const InetAddress& a, const int64_t t) noexcept
|
||||
: mySurface(a)
|
||||
, timestampTicks(t)
|
||||
, trusted(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
const Context &m_ctx;
|
||||
Map< p_PhySurfaceKey, p_PhySurfaceEntry > m_phy;
|
||||
const Context& m_ctx;
|
||||
Map<p_PhySurfaceKey, p_PhySurfaceEntry> m_phy;
|
||||
Mutex m_phy_l;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,37 +25,42 @@ namespace ZeroTier {
|
|||
* Classes must have an atomic<int> field called __refCount and set this class
|
||||
* as a friend to be used with this.
|
||||
*/
|
||||
template< typename T >
|
||||
class SharedPtr : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
ZT_INLINE SharedPtr() noexcept: m_ptr(nullptr)
|
||||
{}
|
||||
template <typename T> class SharedPtr : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE SharedPtr() noexcept : m_ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ZT_INLINE SharedPtr(T *obj) noexcept: m_ptr(obj)
|
||||
{ if (likely(obj != nullptr)) const_cast<std::atomic< int > *>(&(obj->__refCount))->fetch_add(1, std::memory_order_acquire); }
|
||||
explicit ZT_INLINE SharedPtr(T* obj) noexcept : m_ptr(obj)
|
||||
{
|
||||
if (likely(obj != nullptr))
|
||||
const_cast<std::atomic<int>*>(&(obj->__refCount))->fetch_add(1, std::memory_order_acquire);
|
||||
}
|
||||
|
||||
ZT_INLINE SharedPtr(const SharedPtr &sp) noexcept: m_ptr(sp.m_acquire())
|
||||
{}
|
||||
ZT_INLINE SharedPtr(const SharedPtr& sp) noexcept : m_ptr(sp.m_acquire())
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~SharedPtr()
|
||||
{ m_release(); }
|
||||
{
|
||||
m_release();
|
||||
}
|
||||
|
||||
ZT_INLINE SharedPtr &operator=(const SharedPtr &sp)
|
||||
ZT_INLINE SharedPtr& operator=(const SharedPtr& sp)
|
||||
{
|
||||
if (likely(m_ptr != sp.m_ptr)) {
|
||||
T *const p = sp.m_acquire();
|
||||
T* const p = sp.m_acquire();
|
||||
m_release();
|
||||
m_ptr = p;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE void set(T *ptr) noexcept
|
||||
ZT_INLINE void set(T* ptr) noexcept
|
||||
{
|
||||
m_release();
|
||||
m_ptr = ptr;
|
||||
const_cast<std::atomic< int > *>(&(ptr->__refCount))->fetch_add(1, std::memory_order_acquire);
|
||||
const_cast<std::atomic<int>*>(&(ptr->__refCount))->fetch_add(1, std::memory_order_acquire);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,9 +71,9 @@ public:
|
|||
*
|
||||
* @param with Pointer to swap with
|
||||
*/
|
||||
ZT_INLINE void swap(SharedPtr &with) noexcept
|
||||
ZT_INLINE void swap(SharedPtr& with) noexcept
|
||||
{
|
||||
T *const tmp = m_ptr;
|
||||
T* const tmp = m_ptr;
|
||||
m_ptr = with.m_ptr;
|
||||
with.m_ptr = tmp;
|
||||
}
|
||||
|
@ -82,7 +87,7 @@ public:
|
|||
*
|
||||
* @param from Source pointer; will be changed to NULL
|
||||
*/
|
||||
ZT_INLINE void move(SharedPtr &from)
|
||||
ZT_INLINE void move(SharedPtr& from)
|
||||
{
|
||||
m_release();
|
||||
m_ptr = from.m_ptr;
|
||||
|
@ -90,19 +95,27 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_ptr != nullptr); }
|
||||
{
|
||||
return (m_ptr != nullptr);
|
||||
}
|
||||
|
||||
ZT_INLINE T &operator*() const noexcept
|
||||
{ return *m_ptr; }
|
||||
ZT_INLINE T& operator*() const noexcept
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T *operator->() const noexcept
|
||||
{ return m_ptr; }
|
||||
ZT_INLINE T* operator->() const noexcept
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw pointer to held object
|
||||
*/
|
||||
ZT_INLINE T *ptr() const noexcept
|
||||
{ return m_ptr; }
|
||||
ZT_INLINE T* ptr() const noexcept
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this pointer to NULL
|
||||
|
@ -123,60 +136,77 @@ public:
|
|||
*
|
||||
* @return Pointer or NULL if more than one reference
|
||||
*/
|
||||
ZT_INLINE T *weakGC()
|
||||
ZT_INLINE T* weakGC()
|
||||
{
|
||||
if (likely(m_ptr != nullptr)) {
|
||||
int one = 1;
|
||||
if (const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->compare_exchange_strong(one, (int)0)) {
|
||||
T *const ptr = m_ptr;
|
||||
if (const_cast<std::atomic<int>*>(&(m_ptr->__refCount))->compare_exchange_strong(one, (int)0)) {
|
||||
T* const ptr = m_ptr;
|
||||
m_ptr = nullptr;
|
||||
return ptr;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)((uintptr_t)m_ptr + (uintptr_t)Utils::hash32((uint32_t)m_ptr)); }
|
||||
{
|
||||
return (unsigned long)((uintptr_t)m_ptr + (uintptr_t)Utils::hash32((uint32_t)m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const SharedPtr &sp) const noexcept
|
||||
{ return (m_ptr == sp.m_ptr); }
|
||||
ZT_INLINE bool operator==(const SharedPtr& sp) const noexcept
|
||||
{
|
||||
return (m_ptr == sp.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const SharedPtr &sp) const noexcept
|
||||
{ return (m_ptr != sp.m_ptr); }
|
||||
ZT_INLINE bool operator!=(const SharedPtr& sp) const noexcept
|
||||
{
|
||||
return (m_ptr != sp.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const SharedPtr &sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) > reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
ZT_INLINE bool operator>(const SharedPtr& sp) const noexcept
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) > reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const SharedPtr &sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) < reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
ZT_INLINE bool operator<(const SharedPtr& sp) const noexcept
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) < reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const SharedPtr &sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) >= reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
ZT_INLINE bool operator>=(const SharedPtr& sp) const noexcept
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) >= reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const SharedPtr &sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) <= reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
ZT_INLINE bool operator<=(const SharedPtr& sp) const noexcept
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) <= reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE T *m_acquire() const noexcept
|
||||
private:
|
||||
ZT_INLINE T* m_acquire() const noexcept
|
||||
{
|
||||
if (likely(m_ptr != nullptr))
|
||||
const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->fetch_add(1, std::memory_order_acquire);
|
||||
const_cast<std::atomic<int>*>(&(m_ptr->__refCount))->fetch_add(1, std::memory_order_acquire);
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE void m_release() const noexcept
|
||||
{
|
||||
if (likely(m_ptr != nullptr)) {
|
||||
if (unlikely(const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_release) <= 1))
|
||||
if (unlikely(
|
||||
const_cast<std::atomic<int>*>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_release) <= 1))
|
||||
delete m_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
T *m_ptr;
|
||||
T* m_ptr;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
@ -184,13 +214,15 @@ private:
|
|||
// Augment std::swap to speed up some operations with SharedPtr.
|
||||
namespace std {
|
||||
|
||||
template< typename T >
|
||||
ZT_MAYBE_UNUSED ZT_INLINE void swap(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept
|
||||
{ a.swap(b); }
|
||||
template <typename T> ZT_MAYBE_UNUSED ZT_INLINE void swap(ZeroTier::SharedPtr<T>& a, ZeroTier::SharedPtr<T>& b) noexcept
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
ZT_MAYBE_UNUSED ZT_INLINE void move(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept
|
||||
{ a.move(b); }
|
||||
template <typename T> ZT_MAYBE_UNUSED ZT_INLINE void move(ZeroTier::SharedPtr<T>& a, ZeroTier::SharedPtr<T>& b) noexcept
|
||||
{
|
||||
a.move(b);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
|
|
@ -29,9 +29,8 @@
|
|||
* This can be used in place of Mutex to lock things that are extremely fast
|
||||
* to access. It should be used very sparingly.
|
||||
*/
|
||||
class Spinlock
|
||||
{
|
||||
public:
|
||||
class Spinlock {
|
||||
public:
|
||||
/**
|
||||
* Pause current thread using whatever methods might be available
|
||||
*
|
||||
|
@ -50,8 +49,9 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
ZT_INLINE Spinlock() noexcept: m_locked(false)
|
||||
{}
|
||||
ZT_INLINE Spinlock() noexcept : m_locked(false)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE void lock() noexcept
|
||||
{
|
||||
|
@ -63,11 +63,18 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE void unlock() noexcept
|
||||
{ m_locked.clear(std::memory_order_release); }
|
||||
{
|
||||
m_locked.clear(std::memory_order_release);
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE Spinlock(const Spinlock &) noexcept {}
|
||||
ZT_INLINE const Spinlock &operator=(const Spinlock &) noexcept { return *this; }
|
||||
private:
|
||||
ZT_INLINE Spinlock(const Spinlock&) noexcept
|
||||
{
|
||||
}
|
||||
ZT_INLINE const Spinlock& operator=(const Spinlock&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::atomic_flag m_locked;
|
||||
};
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
#ifndef ZT_STORE_HPP
|
||||
#define ZT_STORE_HPP
|
||||
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Wrapper around API callbacks for data store
|
||||
*/
|
||||
class Store
|
||||
{
|
||||
public:
|
||||
ZT_INLINE Store(const Context &ctx): m_ctx(ctx)
|
||||
{}
|
||||
class Store {
|
||||
public:
|
||||
ZT_INLINE Store(const Context& ctx) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a state object
|
||||
|
@ -38,14 +38,23 @@ public:
|
|||
* @param idSize Size of object ID in qwords
|
||||
* @return Data or empty vector if not found
|
||||
*/
|
||||
ZT_INLINE Vector< uint8_t > get(const CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, unsigned int idSize) const
|
||||
ZT_INLINE Vector<uint8_t>
|
||||
get(const CallContext& cc, ZT_StateObjectType type, const uint64_t* const id, unsigned int idSize) const
|
||||
{
|
||||
Vector< uint8_t > dv;
|
||||
void *data = nullptr;
|
||||
void (*freeFunc)(void *) = nullptr;
|
||||
const int r = m_ctx.cb.stateGetFunction(reinterpret_cast<ZT_Node *>(m_ctx.node), m_ctx.uPtr, cc.tPtr, type, id, idSize, &data, &freeFunc);
|
||||
Vector<uint8_t> dv;
|
||||
void* data = nullptr;
|
||||
void (*freeFunc)(void*) = nullptr;
|
||||
const int r = m_ctx.cb.stateGetFunction(
|
||||
reinterpret_cast<ZT_Node*>(m_ctx.node),
|
||||
m_ctx.uPtr,
|
||||
cc.tPtr,
|
||||
type,
|
||||
id,
|
||||
idSize,
|
||||
&data,
|
||||
&freeFunc);
|
||||
if (r > 0)
|
||||
dv.assign(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data) + r);
|
||||
dv.assign(reinterpret_cast<const uint8_t*>(data), reinterpret_cast<const uint8_t*>(data) + r);
|
||||
if ((data) && (freeFunc))
|
||||
freeFunc(data);
|
||||
return dv;
|
||||
|
@ -60,8 +69,17 @@ public:
|
|||
* @param data Data to store
|
||||
* @param len Length of data
|
||||
*/
|
||||
ZT_INLINE void put(const CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize, const void *const data, const unsigned int len) noexcept
|
||||
{ m_ctx.cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, data, (int)len); }
|
||||
ZT_INLINE void
|
||||
put(const CallContext& cc,
|
||||
ZT_StateObjectType type,
|
||||
const uint64_t* const id,
|
||||
const unsigned int idSize,
|
||||
const void* const data,
|
||||
const unsigned int len) noexcept
|
||||
{
|
||||
m_ctx.cb
|
||||
.statePutFunction(reinterpret_cast<ZT_Node*>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, data, (int)len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase a state object from the object store
|
||||
|
@ -70,11 +88,14 @@ public:
|
|||
* @param id Object ID
|
||||
* @param idSize Size of object ID in qwords
|
||||
*/
|
||||
ZT_INLINE void erase(const CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize) noexcept
|
||||
{ m_ctx.cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, nullptr, -1); }
|
||||
ZT_INLINE void
|
||||
erase(const CallContext& cc, ZT_StateObjectType type, const uint64_t* const id, const unsigned int idSize) noexcept
|
||||
{
|
||||
m_ctx.cb.statePutFunction(reinterpret_cast<ZT_Node*>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, nullptr, -1);
|
||||
}
|
||||
|
||||
private:
|
||||
const Context &m_ctx;
|
||||
private:
|
||||
const Context& m_ctx;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,29 +14,24 @@
|
|||
#ifndef ZT_SYMMETRICKEY_HPP
|
||||
#define ZT_SYMMETRICKEY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Container for symmetric keys and ciphers initialized with them.
|
||||
*/
|
||||
class SymmetricKey
|
||||
{
|
||||
public:
|
||||
class SymmetricKey {
|
||||
public:
|
||||
/**
|
||||
* Construct an uninitialized key (init() must be called)
|
||||
*/
|
||||
ZT_INLINE SymmetricKey():
|
||||
m_secret(),
|
||||
m_ts(-1),
|
||||
m_initialNonce(0),
|
||||
m_cipher(),
|
||||
m_nonce(0)
|
||||
{}
|
||||
ZT_INLINE SymmetricKey() : m_secret(), m_ts(-1), m_initialNonce(0), m_cipher(), m_nonce(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new symmetric key
|
||||
|
@ -47,26 +42,30 @@ public:
|
|||
* @param ts Key timestamp
|
||||
* @param key Key (must be 48 bytes / 384 bits)
|
||||
*/
|
||||
ZT_INLINE SymmetricKey(const int64_t ts, const void *const key) noexcept:
|
||||
m_secret(key),
|
||||
m_ts(ts),
|
||||
m_initialNonce(Utils::getSecureRandomU64() >> 1U),
|
||||
m_cipher(key),
|
||||
m_nonce(m_initialNonce)
|
||||
{}
|
||||
ZT_INLINE SymmetricKey(const int64_t ts, const void* const key) noexcept
|
||||
: m_secret(key)
|
||||
, m_ts(ts)
|
||||
, m_initialNonce(Utils::getSecureRandomU64() >> 1U)
|
||||
, m_cipher(key)
|
||||
, m_nonce(m_initialNonce)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE SymmetricKey(const SymmetricKey &k) noexcept:
|
||||
m_secret(k.m_secret),
|
||||
m_ts(k.m_ts),
|
||||
m_initialNonce(k.m_initialNonce),
|
||||
m_cipher(k.m_secret.data),
|
||||
m_nonce(k.m_nonce.load(std::memory_order_relaxed))
|
||||
{}
|
||||
ZT_INLINE SymmetricKey(const SymmetricKey& k) noexcept
|
||||
: m_secret(k.m_secret)
|
||||
, m_ts(k.m_ts)
|
||||
, m_initialNonce(k.m_initialNonce)
|
||||
, m_cipher(k.m_secret.data)
|
||||
, m_nonce(k.m_nonce.load(std::memory_order_relaxed))
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~SymmetricKey() noexcept
|
||||
{ Utils::burn(m_secret.data, ZT_SYMMETRIC_KEY_SIZE); }
|
||||
{
|
||||
Utils::burn(m_secret.data, ZT_SYMMETRIC_KEY_SIZE);
|
||||
}
|
||||
|
||||
ZT_INLINE SymmetricKey &operator=(const SymmetricKey &k) noexcept
|
||||
ZT_INLINE SymmetricKey& operator=(const SymmetricKey& k) noexcept
|
||||
{
|
||||
m_secret = k.m_secret;
|
||||
m_ts = k.m_ts;
|
||||
|
@ -82,9 +81,9 @@ public:
|
|||
* @param ts Key timestamp
|
||||
* @param key Key (must be 48 bytes / 384 bits)
|
||||
*/
|
||||
ZT_INLINE void init(const int64_t ts, const void *const key) noexcept
|
||||
ZT_INLINE void init(const int64_t ts, const void* const key) noexcept
|
||||
{
|
||||
Utils::copy< ZT_SYMMETRIC_KEY_SIZE >(m_secret.data, key);
|
||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(m_secret.data, key);
|
||||
m_ts = ts;
|
||||
m_initialNonce = Utils::getSecureRandomU64() >> 1U;
|
||||
m_cipher.init(key);
|
||||
|
@ -99,7 +98,9 @@ public:
|
|||
* @return Next unique IV for next message
|
||||
*/
|
||||
ZT_INLINE uint64_t nextMessage(const Address sender, const Address receiver) noexcept
|
||||
{ return m_nonce.fetch_add(1, std::memory_order_relaxed) ^ (((uint64_t)(sender > receiver)) << 63U); }
|
||||
{
|
||||
return m_nonce.fetch_add(1, std::memory_order_relaxed) ^ (((uint64_t)(sender > receiver)) << 63U);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of times this key has been used.
|
||||
|
@ -110,32 +111,40 @@ public:
|
|||
* @return Number of times nextMessage() has been called since object creation
|
||||
*/
|
||||
ZT_INLINE uint64_t odometer() const noexcept
|
||||
{ return m_nonce.load(std::memory_order_relaxed) - m_initialNonce; }
|
||||
{
|
||||
return m_nonce.load(std::memory_order_relaxed) - m_initialNonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Key creation timestamp or -1 if this is a long-lived key
|
||||
*/
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 48-byte / 384-bit secret key
|
||||
*/
|
||||
ZT_INLINE const uint8_t *key() const noexcept
|
||||
{ return m_secret.data; }
|
||||
ZT_INLINE const uint8_t* key() const noexcept
|
||||
{
|
||||
return m_secret.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AES cipher (already initialized with secret key)
|
||||
*/
|
||||
ZT_INLINE const AES &aes() const noexcept
|
||||
{ return m_cipher; }
|
||||
ZT_INLINE const AES& aes() const noexcept
|
||||
{
|
||||
return m_cipher;
|
||||
}
|
||||
|
||||
private:
|
||||
Blob< ZT_SYMMETRIC_KEY_SIZE > m_secret;
|
||||
private:
|
||||
Blob<ZT_SYMMETRIC_KEY_SIZE> m_secret;
|
||||
int64_t m_ts;
|
||||
uint64_t m_initialNonce;
|
||||
AES m_cipher;
|
||||
std::atomic< uint64_t > m_nonce;
|
||||
std::atomic<uint64_t> m_nonce;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool TagCredential::sign(const Identity &signer) noexcept
|
||||
bool TagCredential::sign(const Identity& signer) noexcept
|
||||
{
|
||||
uint8_t buf[ZT_TAG_MARSHAL_SIZE_MAX];
|
||||
if (signer.hasPrivate()) {
|
||||
|
@ -33,18 +33,18 @@ int TagCredential::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign)
|
|||
for (int k = 0; k < 8; ++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
Utils::storeBigEndian< uint64_t >(data + p, m_networkId);
|
||||
Utils::storeBigEndian< uint64_t >(data + p + 8, (uint64_t)m_ts);
|
||||
Utils::storeBigEndian< uint32_t >(data + p + 16, m_id);
|
||||
Utils::storeBigEndian< uint32_t >(data + p + 20, m_value);
|
||||
Utils::storeBigEndian<uint64_t>(data + p, m_networkId);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8, (uint64_t)m_ts);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 16, m_id);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 20, m_value);
|
||||
p += 24;
|
||||
m_issuedTo.copyTo(data + p);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
m_signedBy.copyTo(data + p);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
if (!forSign) {
|
||||
if (! forSign) {
|
||||
data[p++] = 1;
|
||||
Utils::storeBigEndian< uint16_t >(data + p, (uint16_t)m_signatureLength);
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_signatureLength);
|
||||
p += 2;
|
||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||
p += (int)m_signatureLength;
|
||||
|
@ -58,25 +58,25 @@ int TagCredential::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign)
|
|||
return p;
|
||||
}
|
||||
|
||||
int TagCredential::unmarshal(const uint8_t *data, int len) noexcept
|
||||
int TagCredential::unmarshal(const uint8_t* data, int len) noexcept
|
||||
{
|
||||
if (len < 37)
|
||||
return -1;
|
||||
m_networkId = Utils::loadBigEndian< uint64_t >(data);
|
||||
m_ts = (int64_t)Utils::loadBigEndian< uint64_t >(data + 8);
|
||||
m_id = Utils::loadBigEndian< uint32_t >(data + 16);
|
||||
m_value = Utils::loadBigEndian< uint32_t >(data + 20);
|
||||
m_networkId = Utils::loadBigEndian<uint64_t>(data);
|
||||
m_ts = (int64_t)Utils::loadBigEndian<uint64_t>(data + 8);
|
||||
m_id = Utils::loadBigEndian<uint32_t>(data + 16);
|
||||
m_value = Utils::loadBigEndian<uint32_t>(data + 20);
|
||||
m_issuedTo.setTo(data + 24);
|
||||
m_signedBy.setTo(data + 29);
|
||||
// 1 byte reserved
|
||||
m_signatureLength = Utils::loadBigEndian< uint16_t >(data + 35);
|
||||
m_signatureLength = Utils::loadBigEndian<uint16_t>(data + 35);
|
||||
int p = 37 + (int)m_signatureLength;
|
||||
if ((m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE) || (p > len))
|
||||
return -1;
|
||||
Utils::copy(m_signature, data + p, m_signatureLength);
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
p += 2 + Utils::loadBigEndian< uint16_t >(data + p);
|
||||
p += 2 + Utils::loadBigEndian<uint16_t>(data + p);
|
||||
if (p > len)
|
||||
return -1;
|
||||
return p;
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
#ifndef ZT_TAG_HPP
|
||||
#define ZT_TAG_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
|
||||
#define ZT_TAG_MARSHAL_SIZE_MAX (8 + 8 + 4 + 4 + 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
|
||||
|
@ -43,16 +43,19 @@ class Context;
|
|||
* Unlike capabilities tags are signed only by the issuer and are never
|
||||
* transferable.
|
||||
*/
|
||||
class TagCredential : public Credential
|
||||
{
|
||||
class TagCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_TAG; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_TAG;
|
||||
}
|
||||
|
||||
ZT_INLINE TagCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nwid Network ID
|
||||
|
@ -61,42 +64,66 @@ public:
|
|||
* @param id Tag ID
|
||||
* @param value Tag value
|
||||
*/
|
||||
ZT_INLINE TagCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id, const uint32_t value) noexcept:
|
||||
m_id(id),
|
||||
m_value(value),
|
||||
m_networkId(nwid),
|
||||
m_ts(ts),
|
||||
m_issuedTo(issuedTo),
|
||||
m_signedBy(),
|
||||
m_signatureLength(0)
|
||||
{}
|
||||
ZT_INLINE TagCredential(
|
||||
const uint64_t nwid,
|
||||
const int64_t ts,
|
||||
const Address& issuedTo,
|
||||
const uint32_t id,
|
||||
const uint32_t value) noexcept
|
||||
: m_id(id)
|
||||
, m_value(value)
|
||||
, m_networkId(nwid)
|
||||
, m_ts(ts)
|
||||
, m_issuedTo(issuedTo)
|
||||
, m_signedBy()
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint32_t &value() const noexcept
|
||||
{ return m_value; }
|
||||
ZT_INLINE const uint32_t& value() const noexcept
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
{
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address &issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
ZT_INLINE const Address& issuedTo() const noexcept
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address &signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t *signature() const noexcept
|
||||
{ return m_signature; }
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign this tag
|
||||
|
@ -104,7 +131,7 @@ public:
|
|||
* @param signer Signing identity, must have private key
|
||||
* @return True if signature was successful
|
||||
*/
|
||||
bool sign(const Identity &signer) noexcept;
|
||||
bool sign(const Identity& signer) noexcept;
|
||||
|
||||
/**
|
||||
* Check this tag's signature
|
||||
|
@ -112,58 +139,85 @@ public:
|
|||
* @param RR Runtime environment to allow identity lookup for signedBy
|
||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context &ctx, const CallContext &cc) const noexcept
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const noexcept
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_TAG_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_TAG_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
|
||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_INLINE bool operator<(const TagCredential &t) const noexcept
|
||||
{ return (m_id < t.m_id); }
|
||||
ZT_INLINE bool operator<(const TagCredential& t) const noexcept
|
||||
{
|
||||
return (m_id < t.m_id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const TagCredential &t) const noexcept
|
||||
{ return (memcmp(this, &t, sizeof(TagCredential)) == 0); }
|
||||
ZT_INLINE bool operator==(const TagCredential& t) const noexcept
|
||||
{
|
||||
return (memcmp(this, &t, sizeof(TagCredential)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const TagCredential &t) const noexcept
|
||||
{ return (memcmp(this, &t, sizeof(TagCredential)) != 0); }
|
||||
ZT_INLINE bool operator!=(const TagCredential& t) const noexcept
|
||||
{
|
||||
return (memcmp(this, &t, sizeof(TagCredential)) != 0);
|
||||
}
|
||||
|
||||
// For searching sorted arrays or lists of Tags by ID
|
||||
struct IdComparePredicate
|
||||
struct IdComparePredicate {
|
||||
ZT_INLINE bool operator()(const TagCredential& a, const TagCredential& b) const noexcept
|
||||
{
|
||||
ZT_INLINE bool operator()(const TagCredential &a, const TagCredential &b) const noexcept
|
||||
{ return (a.id() < b.id()); }
|
||||
return (a.id() < b.id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint32_t a, const TagCredential &b) const noexcept
|
||||
{ return (a < b.id()); }
|
||||
ZT_INLINE bool operator()(const uint32_t a, const TagCredential& b) const noexcept
|
||||
{
|
||||
return (a < b.id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential &a, const uint32_t b) const noexcept
|
||||
{ return (a.id() < b); }
|
||||
ZT_INLINE bool operator()(const TagCredential& a, const uint32_t b) const noexcept
|
||||
{
|
||||
return (a.id() < b);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential *a, const TagCredential *b) const noexcept
|
||||
{ return (a->id() < b->id()); }
|
||||
ZT_INLINE bool operator()(const TagCredential* a, const TagCredential* b) const noexcept
|
||||
{
|
||||
return (a->id() < b->id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential *a, const TagCredential &b) const noexcept
|
||||
{ return (a->id() < b.id()); }
|
||||
ZT_INLINE bool operator()(const TagCredential* a, const TagCredential& b) const noexcept
|
||||
{
|
||||
return (a->id() < b.id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential &a, const TagCredential *b) const noexcept
|
||||
{ return (a.id() < b->id()); }
|
||||
ZT_INLINE bool operator()(const TagCredential& a, const TagCredential* b) const noexcept
|
||||
{
|
||||
return (a.id() < b->id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint32_t a, const TagCredential *b) const noexcept
|
||||
{ return (a < b->id()); }
|
||||
ZT_INLINE bool operator()(const uint32_t a, const TagCredential* b) const noexcept
|
||||
{
|
||||
return (a < b->id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential *a, const uint32_t b) const noexcept
|
||||
{ return (a->id() < b); }
|
||||
ZT_INLINE bool operator()(const TagCredential* a, const uint32_t b) const noexcept
|
||||
{
|
||||
return (a->id() < b);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint32_t a, const uint32_t b) const noexcept
|
||||
{ return (a < b); }
|
||||
{
|
||||
return (a < b);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
private:
|
||||
uint32_t m_id;
|
||||
uint32_t m_value;
|
||||
uint64_t m_networkId;
|
||||
|
|
1833
core/Tests.cpp
1833
core/Tests.cpp
File diff suppressed because it is too large
Load diff
|
@ -47,7 +47,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#ifndef ZT_T_PRINTF
|
||||
#define ZT_T_PRINTF(fmt,...) printf((fmt),##__VA_ARGS__),fflush(stdout)
|
||||
#define ZT_T_PRINTF(fmt, ...) printf((fmt), ##__VA_ARGS__), fflush(stdout)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -57,7 +57,7 @@ extern "C" {
|
|||
/**
|
||||
* Test platform, compiler behavior, utility functions, and core classes
|
||||
*/
|
||||
const char *ZTT_general();
|
||||
const char* ZTT_general();
|
||||
|
||||
/**
|
||||
* Test crypto using test vectors and simple scenarios
|
||||
|
@ -65,12 +65,12 @@ const char *ZTT_general();
|
|||
* This is not an absolutely exhaustive test, just a sanity check to make sure
|
||||
* crypto routines are basically working.
|
||||
*/
|
||||
const char *ZTT_crypto();
|
||||
const char* ZTT_crypto();
|
||||
|
||||
/**
|
||||
* Run benchmarks of cryptographic routines and common constructions
|
||||
*/
|
||||
const char *ZTT_benchmarkCrypto();
|
||||
const char* ZTT_benchmarkCrypto();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Spinlock.hpp"
|
||||
|
||||
// The number of buckets must be a power of two.
|
||||
|
@ -36,30 +36,32 @@ namespace ZeroTier {
|
|||
* fast lookup, with lookups sometimes requiring only a few instructions. It
|
||||
* uses a "lock free" (actually pointer-as-spinlock) design.
|
||||
*/
|
||||
template< typename V >
|
||||
class TinyMap
|
||||
{
|
||||
private:
|
||||
typedef Vector< std::pair< uint64_t, V > > EV;
|
||||
template <typename V> class TinyMap {
|
||||
private:
|
||||
typedef Vector<std::pair<uint64_t, V> > EV;
|
||||
|
||||
public:
|
||||
public:
|
||||
ZT_INLINE TinyMap()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~TinyMap()
|
||||
{ this->clear(); }
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
ZT_INLINE void clear()
|
||||
{
|
||||
for(unsigned int i=0; i < ZT_TINYMAP_BUCKETS; ++i) {
|
||||
for(;;) {
|
||||
for (unsigned int i = 0; i < ZT_TINYMAP_BUCKETS; ++i) {
|
||||
for (;;) {
|
||||
const uintptr_t vptr = m_buckets[i].exchange(ZT_TINYMAP_LOCKED_POINTER, std::memory_order_acquire);
|
||||
if (likely(vptr != ZT_TINYMAP_LOCKED_POINTER)) {
|
||||
if (vptr != 0)
|
||||
delete reinterpret_cast<EV *>(vptr);
|
||||
delete reinterpret_cast<EV*>(vptr);
|
||||
m_buckets[i].store(0, std::memory_order_release);
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
|
@ -69,12 +71,14 @@ public:
|
|||
ZT_INLINE V get(const uint64_t key) noexcept
|
||||
{
|
||||
V tmp;
|
||||
std::atomic<uintptr_t> &bucket = m_buckets[(key ^ (key >> 32)) & ZT_TINYMAP_BUCKETS_MASK];
|
||||
for(;;) {
|
||||
std::atomic<uintptr_t>& bucket = m_buckets[(key ^ (key >> 32)) & ZT_TINYMAP_BUCKETS_MASK];
|
||||
for (;;) {
|
||||
const uintptr_t vptr = bucket.exchange(ZT_TINYMAP_LOCKED_POINTER, std::memory_order_acquire);
|
||||
if (likely(vptr != ZT_TINYMAP_LOCKED_POINTER)) {
|
||||
if (likely(vptr != 0)) {
|
||||
for(typename EV::const_iterator n(reinterpret_cast<const EV *>(vptr)->begin()); n != reinterpret_cast<const EV *>(vptr)->end(); ++n) {
|
||||
for (typename EV::const_iterator n(reinterpret_cast<const EV*>(vptr)->begin());
|
||||
n != reinterpret_cast<const EV*>(vptr)->end();
|
||||
++n) {
|
||||
if (likely(n->first == key)) {
|
||||
tmp = n->second;
|
||||
break;
|
||||
|
@ -83,22 +87,26 @@ public:
|
|||
}
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
return tmp;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE void set(const uint64_t key, const V &value)
|
||||
ZT_INLINE void set(const uint64_t key, const V& value)
|
||||
{
|
||||
std::atomic<uintptr_t> &bucket = m_buckets[(key ^ (key >> 32)) & ZT_TINYMAP_BUCKETS_MASK];
|
||||
for(;;) {
|
||||
std::atomic<uintptr_t>& bucket = m_buckets[(key ^ (key >> 32)) & ZT_TINYMAP_BUCKETS_MASK];
|
||||
for (;;) {
|
||||
uintptr_t vptr = bucket.exchange(ZT_TINYMAP_LOCKED_POINTER, std::memory_order_acquire);
|
||||
if (likely(vptr != ZT_TINYMAP_LOCKED_POINTER)) {
|
||||
if (vptr == 0) {
|
||||
vptr = reinterpret_cast<uintptr_t>(new EV());
|
||||
} else {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV *>(vptr)->begin()); n != reinterpret_cast<EV *>(vptr)->end(); ++n) {
|
||||
}
|
||||
else {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV*>(vptr)->begin());
|
||||
n != reinterpret_cast<EV*>(vptr)->end();
|
||||
++n) {
|
||||
if (n->first == key) {
|
||||
n->second = value;
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
|
@ -106,10 +114,11 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
reinterpret_cast<EV *>(vptr)->push_back(std::pair< uint64_t, V >(key, value));
|
||||
reinterpret_cast<EV*>(vptr)->push_back(std::pair<uint64_t, V>(key, value));
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
|
@ -117,31 +126,34 @@ public:
|
|||
|
||||
ZT_INLINE void erase(const uint64_t key)
|
||||
{
|
||||
std::atomic<uintptr_t> &bucket = m_buckets[(key ^ (key >> 32)) & ZT_TINYMAP_BUCKETS_MASK];
|
||||
for(;;) {
|
||||
std::atomic<uintptr_t>& bucket = m_buckets[(key ^ (key >> 32)) & ZT_TINYMAP_BUCKETS_MASK];
|
||||
for (;;) {
|
||||
uintptr_t vptr = bucket.exchange(ZT_TINYMAP_LOCKED_POINTER, std::memory_order_acquire);
|
||||
if (likely(vptr != ZT_TINYMAP_LOCKED_POINTER)) {
|
||||
if (likely(vptr != 0)) {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV *>(vptr)->begin()); n != reinterpret_cast<EV *>(vptr)->end(); ++n) {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV*>(vptr)->begin());
|
||||
n != reinterpret_cast<EV*>(vptr)->end();
|
||||
++n) {
|
||||
if (n->first == key) {
|
||||
reinterpret_cast<EV *>(vptr)->erase(n);
|
||||
reinterpret_cast<EV*>(vptr)->erase(n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (reinterpret_cast<EV *>(vptr)->empty()) {
|
||||
delete reinterpret_cast<EV *>(vptr);
|
||||
if (reinterpret_cast<EV*>(vptr)->empty()) {
|
||||
delete reinterpret_cast<EV*>(vptr);
|
||||
vptr = 0;
|
||||
}
|
||||
}
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
std::atomic<uintptr_t> m_buckets[ZT_TINYMAP_BUCKETS];
|
||||
};
|
||||
|
||||
|
|
|
@ -12,20 +12,21 @@
|
|||
/****/
|
||||
|
||||
#include "Topology.hpp"
|
||||
|
||||
#include "Defaults.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Topology::Topology(const Context &ctx, const CallContext &cc) :
|
||||
m_ctx(ctx)
|
||||
{}
|
||||
Topology::Topology(const Context& ctx, const CallContext& cc) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
SharedPtr< Peer > Topology::add(const CallContext &cc, const SharedPtr< Peer > &peer)
|
||||
SharedPtr<Peer> Topology::add(const CallContext& cc, const SharedPtr<Peer>& peer)
|
||||
{
|
||||
RWMutex::Lock _l(m_peers_l);
|
||||
SharedPtr< Peer > &hp = m_peers[peer->address()];
|
||||
SharedPtr<Peer>& hp = m_peers[peer->address()];
|
||||
if (hp)
|
||||
return hp;
|
||||
m_loadCached(cc, peer->address(), hp);
|
||||
|
@ -35,13 +36,13 @@ SharedPtr< Peer > Topology::add(const CallContext &cc, const SharedPtr< Peer > &
|
|||
return peer;
|
||||
}
|
||||
|
||||
void Topology::allPeers(Vector< SharedPtr< Peer > > &allPeers, Vector< SharedPtr< Peer > > &rootPeers) const
|
||||
void Topology::allPeers(Vector<SharedPtr<Peer> >& allPeers, Vector<SharedPtr<Peer> >& rootPeers) const
|
||||
{
|
||||
allPeers.clear();
|
||||
{
|
||||
RWMutex::RLock l(m_peers_l);
|
||||
allPeers.reserve(m_peers.size());
|
||||
for (Map< Address, SharedPtr< Peer > >::const_iterator i(m_peers.begin()); i != m_peers.end(); ++i)
|
||||
for (Map<Address, SharedPtr<Peer> >::const_iterator i(m_peers.begin()); i != m_peers.end(); ++i)
|
||||
allPeers.push_back(i->second);
|
||||
}
|
||||
{
|
||||
|
@ -50,15 +51,15 @@ void Topology::allPeers(Vector< SharedPtr< Peer > > &allPeers, Vector< SharedPtr
|
|||
}
|
||||
}
|
||||
|
||||
void Topology::doPeriodicTasks(const CallContext &cc)
|
||||
void Topology::doPeriodicTasks(const CallContext& cc)
|
||||
{
|
||||
// Get a list of root peer pointer addresses for filtering during peer cleanup.
|
||||
Vector< uintptr_t > rootLookup;
|
||||
Vector<uintptr_t> rootLookup;
|
||||
{
|
||||
Mutex::Lock l(m_roots_l);
|
||||
m_rankRoots();
|
||||
rootLookup.reserve(m_roots.size());
|
||||
for (Vector< SharedPtr< Peer > >::const_iterator r(m_roots.begin()); r != m_roots.end(); ++r)
|
||||
for (Vector<SharedPtr<Peer> >::const_iterator r(m_roots.begin()); r != m_roots.end(); ++r)
|
||||
rootLookup.push_back((uintptr_t)r->ptr());
|
||||
}
|
||||
std::sort(rootLookup.begin(), rootLookup.end());
|
||||
|
@ -67,22 +68,27 @@ void Topology::doPeriodicTasks(const CallContext &cc)
|
|||
// m_peers or m_paths for any significant amount of time. This avoids pauses
|
||||
// on nodes with large numbers of peers or paths.
|
||||
{
|
||||
Vector< Address > toDelete;
|
||||
Vector<Address> toDelete;
|
||||
{
|
||||
RWMutex::RLock l1(m_peers_l);
|
||||
for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) {
|
||||
// TODO: also delete if the peer has not exchanged meaningful communication in a while, such as a network frame or non-trivial control packet.
|
||||
if (((cc.ticks - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (!std::binary_search(rootLookup.begin(), rootLookup.end(), reinterpret_cast<uintptr_t>(i->second.ptr()))))
|
||||
for (Map<Address, SharedPtr<Peer> >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) {
|
||||
// TODO: also delete if the peer has not exchanged meaningful communication in a while, such as a
|
||||
// network frame or non-trivial control packet.
|
||||
if (((cc.ticks - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT)
|
||||
&& (! std::binary_search(
|
||||
rootLookup.begin(),
|
||||
rootLookup.end(),
|
||||
reinterpret_cast<uintptr_t>(i->second.ptr()))))
|
||||
toDelete.push_back(i->first);
|
||||
}
|
||||
}
|
||||
if (!toDelete.empty()) {
|
||||
if (! toDelete.empty()) {
|
||||
ZT_SPEW("garbage collecting %u offline or stale peer objects", (unsigned int)toDelete.size());
|
||||
for (Vector< Address >::iterator i(toDelete.begin()); i != toDelete.end(); ++i) {
|
||||
SharedPtr< Peer > toSave;
|
||||
for (Vector<Address>::iterator i(toDelete.begin()); i != toDelete.end(); ++i) {
|
||||
SharedPtr<Peer> toSave;
|
||||
{
|
||||
RWMutex::Lock l1(m_peers_l);
|
||||
const Map< Address, SharedPtr< Peer > >::iterator p(m_peers.find(*i));
|
||||
const Map<Address, SharedPtr<Peer> >::iterator p(m_peers.find(*i));
|
||||
if (p != m_peers.end()) {
|
||||
p->second.swap(toSave);
|
||||
m_peers.erase(p);
|
||||
|
@ -95,45 +101,48 @@ void Topology::doPeriodicTasks(const CallContext &cc)
|
|||
}
|
||||
|
||||
{
|
||||
Vector< Path * > toDelete;
|
||||
Vector<Path*> toDelete;
|
||||
{
|
||||
RWMutex::Lock l1(m_paths_l);
|
||||
for (Map< Path::Key, SharedPtr< Path > >::iterator i(m_paths.begin()); i != m_paths.end();) {
|
||||
Path *const d = i->second.weakGC();
|
||||
for (Map<Path::Key, SharedPtr<Path> >::iterator i(m_paths.begin()); i != m_paths.end();) {
|
||||
Path* const d = i->second.weakGC();
|
||||
if (likely(d == nullptr)) {
|
||||
++i;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_paths.erase(i++);
|
||||
try {
|
||||
toDelete.push_back(d);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!toDelete.empty()) {
|
||||
for (Vector< Path * >::iterator i(toDelete.begin()); i != toDelete.end(); ++i)
|
||||
if (! toDelete.empty()) {
|
||||
for (Vector<Path*>::iterator i(toDelete.begin()); i != toDelete.end(); ++i)
|
||||
delete *i;
|
||||
ZT_SPEW("garbage collected %u orphaned paths", (unsigned int)toDelete.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Topology::trustStoreChanged(const CallContext &cc)
|
||||
void Topology::trustStoreChanged(const CallContext& cc)
|
||||
{
|
||||
Map< Identity, SharedPtr< const Locator > > roots(m_ctx.ts->roots());
|
||||
Map<Identity, SharedPtr<const Locator> > roots(m_ctx.ts->roots());
|
||||
|
||||
Vector< SharedPtr< Peer > > newRootList;
|
||||
Vector<SharedPtr<Peer> > newRootList;
|
||||
newRootList.reserve(roots.size());
|
||||
|
||||
for (Map< Identity, SharedPtr< const Locator > >::const_iterator r(roots.begin()); r != roots.end(); ++r) {
|
||||
SharedPtr< Peer > root(this->peer(cc, r->first.address(), true));
|
||||
if (!root) {
|
||||
for (Map<Identity, SharedPtr<const Locator> >::const_iterator r(roots.begin()); r != roots.end(); ++r) {
|
||||
SharedPtr<Peer> root(this->peer(cc, r->first.address(), true));
|
||||
if (! root) {
|
||||
root.set(new Peer());
|
||||
if (root->init(m_ctx, cc, r->first)) {
|
||||
root = this->add(cc, root);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
root.zero();
|
||||
}
|
||||
}
|
||||
|
@ -151,16 +160,15 @@ void Topology::trustStoreChanged(const CallContext &cc)
|
|||
}
|
||||
}
|
||||
|
||||
void Topology::saveAll(const CallContext &cc)
|
||||
void Topology::saveAll(const CallContext& cc)
|
||||
{
|
||||
RWMutex::RLock l(m_peers_l);
|
||||
for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i)
|
||||
for (Map<Address, SharedPtr<Peer> >::iterator i(m_peers.begin()); i != m_peers.end(); ++i)
|
||||
i->second->save(m_ctx, cc);
|
||||
}
|
||||
|
||||
struct p_RootRankingComparisonOperator
|
||||
{
|
||||
ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const noexcept
|
||||
struct p_RootRankingComparisonOperator {
|
||||
ZT_INLINE bool operator()(const SharedPtr<Peer>& a, const SharedPtr<Peer>& b) const noexcept
|
||||
{
|
||||
// Sort roots first in order of which root has spoken most recently, but
|
||||
// only at a resolution of ZT_PATH_KEEPALIVE_PERIOD/2 units of time. This
|
||||
|
@ -171,7 +179,8 @@ struct p_RootRankingComparisonOperator
|
|||
const int64_t blr = b->lastReceive() / (ZT_PATH_KEEPALIVE_PERIOD / 2);
|
||||
if (alr < blr) {
|
||||
return true;
|
||||
} else if (blr == alr) {
|
||||
}
|
||||
else if (blr == alr) {
|
||||
const int bb = b->latency();
|
||||
if (bb < 0)
|
||||
return true;
|
||||
|
@ -188,7 +197,8 @@ void Topology::m_rankRoots()
|
|||
l_bestRoot.lock();
|
||||
m_bestRoot.zero();
|
||||
l_bestRoot.unlock();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::sort(m_roots.begin(), m_roots.end(), p_RootRankingComparisonOperator());
|
||||
l_bestRoot.lock();
|
||||
m_bestRoot = m_roots.front();
|
||||
|
@ -196,7 +206,7 @@ void Topology::m_rankRoots()
|
|||
}
|
||||
}
|
||||
|
||||
void Topology::m_loadCached(const CallContext &cc, const Address &zta, SharedPtr< Peer > &peer)
|
||||
void Topology::m_loadCached(const CallContext& cc, const Address& zta, SharedPtr<Peer>& peer)
|
||||
{
|
||||
// does not require any locks to be held
|
||||
|
||||
|
@ -204,13 +214,13 @@ void Topology::m_loadCached(const CallContext &cc, const Address &zta, SharedPtr
|
|||
uint64_t id[2];
|
||||
id[0] = zta.toInt();
|
||||
id[1] = 0;
|
||||
Vector< uint8_t > data(m_ctx.store->get(cc, ZT_STATE_OBJECT_PEER, id, 1));
|
||||
Vector<uint8_t> data(m_ctx.store->get(cc, ZT_STATE_OBJECT_PEER, id, 1));
|
||||
if (data.size() > 8) {
|
||||
const uint8_t *d = data.data();
|
||||
const uint8_t* d = data.data();
|
||||
int dl = (int)data.size();
|
||||
|
||||
const int64_t ts = (int64_t)Utils::loadBigEndian< uint64_t >(d);
|
||||
Peer *const p = new Peer();
|
||||
const int64_t ts = (int64_t)Utils::loadBigEndian<uint64_t>(d);
|
||||
Peer* const p = new Peer();
|
||||
int n = p->unmarshal(m_ctx, cc.ticks, d + 8, dl - 8);
|
||||
if (n < 0) {
|
||||
delete p;
|
||||
|
@ -222,18 +232,19 @@ void Topology::m_loadCached(const CallContext &cc, const Address &zta, SharedPtr
|
|||
return;
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
peer.zero();
|
||||
}
|
||||
}
|
||||
|
||||
SharedPtr< Peer > Topology::m_peerFromCached(const CallContext &cc, const Address &zta)
|
||||
SharedPtr<Peer> Topology::m_peerFromCached(const CallContext& cc, const Address& zta)
|
||||
{
|
||||
SharedPtr< Peer > p;
|
||||
SharedPtr<Peer> p;
|
||||
m_loadCached(cc, zta, p);
|
||||
if (p) {
|
||||
RWMutex::Lock l(m_peers_l);
|
||||
SharedPtr< Peer > &hp = m_peers[zta];
|
||||
SharedPtr<Peer>& hp = m_peers[zta];
|
||||
if (hp)
|
||||
return hp;
|
||||
hp = p;
|
||||
|
@ -241,11 +252,11 @@ SharedPtr< Peer > Topology::m_peerFromCached(const CallContext &cc, const Addres
|
|||
return p;
|
||||
}
|
||||
|
||||
SharedPtr< Path > Topology::m_newPath(const int64_t l, const InetAddress &r, const Path::Key &k)
|
||||
SharedPtr<Path> Topology::m_newPath(const int64_t l, const InetAddress& r, const Path::Key& k)
|
||||
{
|
||||
SharedPtr< Path > p(new Path(l, r));
|
||||
SharedPtr<Path> p(new Path(l, r));
|
||||
RWMutex::Lock lck(m_paths_l);
|
||||
SharedPtr< Path > &p2 = m_paths[k];
|
||||
SharedPtr<Path>& p2 = m_paths[k];
|
||||
if (p2)
|
||||
return p2;
|
||||
p2 = p;
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
#ifndef ZT_TOPOLOGY_HPP
|
||||
#define ZT_TOPOLOGY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Certificate.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Spinlock.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Certificate.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Spinlock.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,10 +37,9 @@ class Context;
|
|||
/**
|
||||
* Database of network topology
|
||||
*/
|
||||
class Topology
|
||||
{
|
||||
public:
|
||||
Topology(const Context &ctx, const CallContext &cc);
|
||||
class Topology {
|
||||
public:
|
||||
Topology(const Context& ctx, const CallContext& cc);
|
||||
|
||||
/**
|
||||
* Add peer to database
|
||||
|
@ -51,7 +50,7 @@ public:
|
|||
* @param peer Peer to add
|
||||
* @return New or existing peer
|
||||
*/
|
||||
SharedPtr< Peer > add(const CallContext &cc, const SharedPtr< Peer > &peer);
|
||||
SharedPtr<Peer> add(const CallContext& cc, const SharedPtr<Peer>& peer);
|
||||
|
||||
/**
|
||||
* Get a peer from its address
|
||||
|
@ -60,17 +59,17 @@ public:
|
|||
* @param loadFromCached If false do not load from cache if not in memory (default: true)
|
||||
* @return Peer or NULL if not found
|
||||
*/
|
||||
ZT_INLINE SharedPtr< Peer > peer(const CallContext &cc, const Address &zta, const bool loadFromCached = true)
|
||||
ZT_INLINE SharedPtr<Peer> peer(const CallContext& cc, const Address& zta, const bool loadFromCached = true)
|
||||
{
|
||||
{
|
||||
RWMutex::RLock l(m_peers_l);
|
||||
Map< Address, SharedPtr< Peer > >::const_iterator ap(m_peers.find(zta));
|
||||
Map<Address, SharedPtr<Peer> >::const_iterator ap(m_peers.find(zta));
|
||||
if (likely(ap != m_peers.end()))
|
||||
return ap->second;
|
||||
}
|
||||
if (loadFromCached)
|
||||
return m_peerFromCached(cc, zta);
|
||||
return SharedPtr< Peer >();
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,12 +79,12 @@ public:
|
|||
* @param r Remote address
|
||||
* @return Pointer to canonicalized Path object or NULL on error
|
||||
*/
|
||||
ZT_INLINE SharedPtr< Path > path(const int64_t l, const InetAddress &r)
|
||||
ZT_INLINE SharedPtr<Path> path(const int64_t l, const InetAddress& r)
|
||||
{
|
||||
const Path::Key k(r);
|
||||
{
|
||||
RWMutex::RLock lck(m_paths_l);
|
||||
Map< Path::Key, SharedPtr< Path > >::const_iterator p(m_paths.find(k));
|
||||
Map<Path::Key, SharedPtr<Path> >::const_iterator p(m_paths.find(k));
|
||||
if (likely(p != m_paths.end()))
|
||||
return p->second;
|
||||
}
|
||||
|
@ -97,10 +96,10 @@ public:
|
|||
*
|
||||
* @return Root peer or nullptr if none
|
||||
*/
|
||||
ZT_INLINE SharedPtr< Peer > root()
|
||||
ZT_INLINE SharedPtr<Peer> root()
|
||||
{
|
||||
l_bestRoot.lock(); // spinlock
|
||||
SharedPtr< Peer > r(m_bestRoot);
|
||||
SharedPtr<Peer> r(m_bestRoot);
|
||||
l_bestRoot.unlock();
|
||||
return r;
|
||||
}
|
||||
|
@ -110,7 +109,7 @@ public:
|
|||
*
|
||||
* @param root Set to best root or nullptr if none
|
||||
*/
|
||||
ZT_INLINE void root(SharedPtr< Peer > &root)
|
||||
ZT_INLINE void root(SharedPtr<Peer>& root)
|
||||
{
|
||||
l_bestRoot.lock(); // spinlock
|
||||
root = m_bestRoot;
|
||||
|
@ -121,17 +120,17 @@ public:
|
|||
* @param allPeers Vector to fill with all current peers
|
||||
* @param rootPeers Vector to fill with peers that are roots
|
||||
*/
|
||||
void allPeers(Vector< SharedPtr< Peer > > &allPeers, Vector< SharedPtr< Peer > > &rootPeers) const;
|
||||
void allPeers(Vector<SharedPtr<Peer> >& allPeers, Vector<SharedPtr<Peer> >& rootPeers) const;
|
||||
|
||||
/**
|
||||
* Do periodic tasks such as database cleanup, cert cleanup, root ranking, etc.
|
||||
*/
|
||||
void doPeriodicTasks(const CallContext &cc);
|
||||
void doPeriodicTasks(const CallContext& cc);
|
||||
|
||||
/**
|
||||
* Rank root servers in descending order of quality
|
||||
*/
|
||||
ZT_INLINE void rankRoots(const CallContext &cc)
|
||||
ZT_INLINE void rankRoots(const CallContext& cc)
|
||||
{
|
||||
Mutex::Lock l(m_roots_l);
|
||||
m_rankRoots();
|
||||
|
@ -140,30 +139,30 @@ public:
|
|||
/**
|
||||
* Perform internal updates based on changes in the trust store
|
||||
*/
|
||||
void trustStoreChanged(const CallContext &cc);
|
||||
void trustStoreChanged(const CallContext& cc);
|
||||
|
||||
/**
|
||||
* Save all currently known peers to data store
|
||||
*/
|
||||
void saveAll(const CallContext &cc);
|
||||
void saveAll(const CallContext& cc);
|
||||
|
||||
private:
|
||||
private:
|
||||
void m_rankRoots();
|
||||
void m_loadCached(const CallContext &cc, const Address &zta, SharedPtr< Peer > &peer);
|
||||
SharedPtr< Peer > m_peerFromCached(const CallContext &cc, const Address &zta);
|
||||
SharedPtr< Path > m_newPath(int64_t l, const InetAddress &r, const Path::Key &k);
|
||||
void m_loadCached(const CallContext& cc, const Address& zta, SharedPtr<Peer>& peer);
|
||||
SharedPtr<Peer> m_peerFromCached(const CallContext& cc, const Address& zta);
|
||||
SharedPtr<Path> m_newPath(int64_t l, const InetAddress& r, const Path::Key& k);
|
||||
|
||||
const Context &m_ctx;
|
||||
const Context& m_ctx;
|
||||
|
||||
Vector< SharedPtr< Peer > > m_roots;
|
||||
Map< Address, SharedPtr< Peer > > m_peers;
|
||||
Map< Path::Key, SharedPtr< Path > > m_paths;
|
||||
Vector<SharedPtr<Peer> > m_roots;
|
||||
Map<Address, SharedPtr<Peer> > m_peers;
|
||||
Map<Path::Key, SharedPtr<Path> > m_paths;
|
||||
|
||||
RWMutex m_peers_l; // m_peers
|
||||
RWMutex m_paths_l; // m_paths
|
||||
Mutex m_roots_l; // m_roots
|
||||
|
||||
SharedPtr< Peer > m_bestRoot;
|
||||
SharedPtr<Peer> m_bestRoot;
|
||||
Spinlock l_bestRoot;
|
||||
};
|
||||
|
||||
|
|
143
core/Trace.cpp
143
core/Trace.cpp
|
@ -12,28 +12,24 @@
|
|||
/****/
|
||||
|
||||
#include "Trace.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "FCV.hpp"
|
||||
|
||||
// NOTE: packet IDs are always handled in network byte order, so no need to convert them.
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Trace::Trace(const Context &ctx) :
|
||||
m_ctx(ctx),
|
||||
m_traceFlags(0)
|
||||
{}
|
||||
|
||||
void Trace::unexpectedError(
|
||||
const CallContext &cc,
|
||||
uint32_t codeLocation,
|
||||
const char *message,
|
||||
...)
|
||||
Trace::Trace(const Context& ctx) : m_ctx(ctx), m_traceFlags(0)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
}
|
||||
|
||||
void Trace::unexpectedError(const CallContext& cc, uint32_t codeLocation, const char* message, ...)
|
||||
{
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_UNEXPECTED_ERROR);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_MESSAGE, message);
|
||||
|
@ -42,15 +38,15 @@ void Trace::unexpectedError(
|
|||
}
|
||||
|
||||
void Trace::m_resettingPathsInScope(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
const Identity &reporter,
|
||||
const InetAddress &from,
|
||||
const InetAddress &oldExternal,
|
||||
const InetAddress &newExternal,
|
||||
const Identity& reporter,
|
||||
const InetAddress& from,
|
||||
const InetAddress& oldExternal,
|
||||
const InetAddress& newExternal,
|
||||
ZT_InetAddress_IpScope scope)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
if (reporter)
|
||||
|
@ -67,17 +63,17 @@ void Trace::m_resettingPathsInScope(
|
|||
}
|
||||
|
||||
void Trace::m_tryingNewPath(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
const Identity &trying,
|
||||
const InetAddress &physicalAddress,
|
||||
const InetAddress &triggerAddress,
|
||||
const Identity& trying,
|
||||
const InetAddress& physicalAddress,
|
||||
const InetAddress& triggerAddress,
|
||||
uint64_t triggeringPacketId,
|
||||
uint8_t triggeringPacketVerb,
|
||||
const Identity &triggeringPeer)
|
||||
const Identity& triggeringPeer)
|
||||
{
|
||||
if ((trying)&&(physicalAddress)) {
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
if ((trying) && (physicalAddress)) {
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_TRYING_NEW_PATH);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::appendObject(buf, ZT_TRACE_FIELD_IDENTITY_FINGERPRINT, trying.fingerprint());
|
||||
|
@ -94,15 +90,15 @@ void Trace::m_tryingNewPath(
|
|||
}
|
||||
|
||||
void Trace::m_learnedNewPath(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t packetId,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const InetAddress &replaced)
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
const InetAddress& replaced)
|
||||
{
|
||||
if (peerIdentity) {
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_LEARNED_NEW_PATH);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::appendPacketId(buf, ZT_TRACE_FIELD_PACKET_ID, packetId);
|
||||
|
@ -117,17 +113,17 @@ void Trace::m_learnedNewPath(
|
|||
}
|
||||
|
||||
void Trace::m_incomingPacketDropped(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t packetId,
|
||||
uint64_t networkId,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
uint8_t hops,
|
||||
uint8_t verb,
|
||||
ZT_TracePacketDropReason reason)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::appendPacketId(buf, ZT_TRACE_FIELD_PACKET_ID, packetId);
|
||||
|
@ -144,17 +140,17 @@ void Trace::m_incomingPacketDropped(
|
|||
}
|
||||
|
||||
void Trace::m_outgoingNetworkFrameDropped(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
uint16_t etherType,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
ZT_TraceFrameDropReason reason)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_NETWORK_ID, networkId);
|
||||
|
@ -163,29 +159,33 @@ void Trace::m_outgoingNetworkFrameDropped(
|
|||
Dictionary::append(buf, ZT_TRACE_FIELD_ETHERTYPE, etherType);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_LENGTH, frameLength);
|
||||
if (frameData)
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_DATA, frameData, std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(
|
||||
buf,
|
||||
ZT_TRACE_FIELD_FRAME_DATA,
|
||||
frameData,
|
||||
std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_REASON, reason);
|
||||
buf.push_back(0);
|
||||
m_ctx.node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
|
||||
}
|
||||
|
||||
void Trace::m_incomingNetworkFrameDropped(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
const uint16_t etherType,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
uint8_t hops,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
uint8_t verb,
|
||||
bool credentialRequestSent,
|
||||
ZT_TraceFrameDropReason reason)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_INCOMING_FRAME_DROPPED);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_NETWORK_ID, networkId);
|
||||
|
@ -199,19 +199,20 @@ void Trace::m_incomingNetworkFrameDropped(
|
|||
Dictionary::append(buf, ZT_TRACE_FIELD_PACKET_VERB, verb);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_LENGTH, frameLength);
|
||||
if (frameData)
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_DATA, frameData, std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(
|
||||
buf,
|
||||
ZT_TRACE_FIELD_FRAME_DATA,
|
||||
frameData,
|
||||
std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FLAG_CREDENTIAL_REQUEST_SENT, credentialRequestSent);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_REASON, reason);
|
||||
buf.push_back(0);
|
||||
m_ctx.node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
|
||||
}
|
||||
|
||||
void Trace::m_networkConfigRequestSent(
|
||||
void *tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId)
|
||||
void Trace::m_networkConfigRequestSent(void* tPtr, uint32_t codeLocation, uint64_t networkId)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_NETWORK_ID, networkId);
|
||||
|
@ -220,32 +221,32 @@ void Trace::m_networkConfigRequestSent(
|
|||
}
|
||||
|
||||
void Trace::m_networkFilter(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const uint8_t *primaryRuleSetLog,
|
||||
const uint8_t *matchingCapabilityRuleSetLog,
|
||||
const uint8_t* primaryRuleSetLog,
|
||||
const uint8_t* matchingCapabilityRuleSetLog,
|
||||
uint32_t matchingCapabilityId,
|
||||
int64_t matchingCapabilityTimestamp,
|
||||
const Address &source,
|
||||
const Address &dest,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
uint16_t etherType,
|
||||
uint16_t vlanId,
|
||||
bool noTee,
|
||||
bool inbound,
|
||||
int accept)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_FILTER);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_NETWORK_ID, networkId);
|
||||
if ((primaryRuleSetLog) && (!Utils::allZero(primaryRuleSetLog, 512)))
|
||||
if ((primaryRuleSetLog) && (! Utils::allZero(primaryRuleSetLog, 512)))
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_PRIMARY_RULE_SET_LOG, primaryRuleSetLog, 512);
|
||||
if ((matchingCapabilityRuleSetLog) && (!Utils::allZero(matchingCapabilityRuleSetLog, 512)))
|
||||
if ((matchingCapabilityRuleSetLog) && (! Utils::allZero(matchingCapabilityRuleSetLog, 512)))
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_MATCHING_CAPABILITY_RULE_SET_LOG, matchingCapabilityRuleSetLog, 512);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_MATCHING_CAPABILITY_ID, matchingCapabilityId);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_MATCHING_CAPABILITY_TIMESTAMP, matchingCapabilityTimestamp);
|
||||
|
@ -255,7 +256,11 @@ void Trace::m_networkFilter(
|
|||
Dictionary::append(buf, ZT_TRACE_FIELD_DEST_MAC, destMac.toInt());
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_LENGTH, frameLength);
|
||||
if (frameData)
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_DATA, frameData, std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(
|
||||
buf,
|
||||
ZT_TRACE_FIELD_FRAME_DATA,
|
||||
frameData,
|
||||
std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_ETHERTYPE, etherType);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_VLAN_ID, vlanId);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_RULE_FLAG_NOTEE, noTee);
|
||||
|
@ -266,16 +271,16 @@ void Trace::m_networkFilter(
|
|||
}
|
||||
|
||||
void Trace::m_credentialRejected(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const Identity &identity,
|
||||
const Identity& identity,
|
||||
uint32_t credentialId,
|
||||
int64_t credentialTimestamp,
|
||||
uint8_t credentialType,
|
||||
ZT_TraceCredentialRejectionReason reason)
|
||||
{
|
||||
FCV< uint8_t, 4096 > buf;
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CREDENTIAL_REJECTED);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_NETWORK_ID, networkId);
|
||||
|
|
258
core/Trace.hpp
258
core/Trace.hpp
|
@ -14,15 +14,15 @@
|
|||
#ifndef ZT_TRACE_HPP
|
||||
#define ZT_TRACE_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_TRACE_F_VL1 0x01U
|
||||
#define ZT_TRACE_F_VL2 0x02U
|
||||
|
@ -56,38 +56,38 @@ struct NetworkConfig;
|
|||
* turned into constants that are semi-official and stored in a database to
|
||||
* provide extra debug context.
|
||||
*/
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
struct RuleResultLog : public TriviallyCopyable
|
||||
{
|
||||
class Trace {
|
||||
public:
|
||||
struct RuleResultLog : public TriviallyCopyable {
|
||||
uint8_t l[ZT_MAX_NETWORK_RULES / 2]; // ZT_MAX_NETWORK_RULES 4-bit fields
|
||||
|
||||
ZT_INLINE void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches) noexcept
|
||||
{ l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U); }
|
||||
{
|
||||
l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U);
|
||||
}
|
||||
|
||||
ZT_INLINE void logSkipped(const unsigned int rn, const uint8_t thisSetMatches) noexcept
|
||||
{ l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U); }
|
||||
{
|
||||
l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U);
|
||||
}
|
||||
|
||||
ZT_INLINE void clear() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
};
|
||||
|
||||
explicit Trace(const Context &ctx);
|
||||
explicit Trace(const Context& ctx);
|
||||
|
||||
void unexpectedError(
|
||||
const CallContext &cc,
|
||||
uint32_t codeLocation,
|
||||
const char *message,
|
||||
...);
|
||||
void unexpectedError(const CallContext& cc, uint32_t codeLocation, const char* message, ...);
|
||||
|
||||
ZT_INLINE void resettingPathsInScope(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
const Identity &reporter,
|
||||
const InetAddress &from,
|
||||
const InetAddress &oldExternal,
|
||||
const InetAddress &newExternal,
|
||||
const Identity& reporter,
|
||||
const InetAddress& from,
|
||||
const InetAddress& oldExternal,
|
||||
const InetAddress& newExternal,
|
||||
const InetAddress::IpScope scope)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
|
||||
|
@ -95,104 +95,141 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE void tryingNewPath(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
const Identity &trying,
|
||||
const InetAddress &physicalAddress,
|
||||
const InetAddress &triggerAddress,
|
||||
const Identity& trying,
|
||||
const InetAddress& physicalAddress,
|
||||
const InetAddress& triggerAddress,
|
||||
uint64_t triggeringPacketId,
|
||||
uint8_t triggeringPacketVerb,
|
||||
const Identity &triggeringPeer)
|
||||
const Identity& triggeringPeer)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
|
||||
m_tryingNewPath(cc.tPtr, codeLocation, trying, physicalAddress, triggerAddress, triggeringPacketId, triggeringPacketVerb, triggeringPeer);
|
||||
m_tryingNewPath(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
trying,
|
||||
physicalAddress,
|
||||
triggerAddress,
|
||||
triggeringPacketId,
|
||||
triggeringPacketVerb,
|
||||
triggeringPeer);
|
||||
}
|
||||
|
||||
ZT_INLINE void learnedNewPath(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t packetId,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const InetAddress &replaced)
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
const InetAddress& replaced)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
|
||||
m_learnedNewPath(cc.tPtr, codeLocation, packetId, peerIdentity, physicalAddress, replaced);
|
||||
}
|
||||
|
||||
ZT_INLINE void incomingPacketDropped(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t packetId,
|
||||
uint64_t networkId,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
uint8_t hops,
|
||||
uint8_t verb,
|
||||
const ZT_TracePacketDropReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
|
||||
m_incomingPacketDropped(cc.tPtr, codeLocation, packetId, networkId, peerIdentity, physicalAddress, hops, verb, reason);
|
||||
m_incomingPacketDropped(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
packetId,
|
||||
networkId,
|
||||
peerIdentity,
|
||||
physicalAddress,
|
||||
hops,
|
||||
verb,
|
||||
reason);
|
||||
}
|
||||
|
||||
ZT_INLINE void outgoingNetworkFrameDropped(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
uint16_t etherType,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
ZT_TraceFrameDropReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_outgoingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, frameLength, frameData, reason);
|
||||
m_outgoingNetworkFrameDropped(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
networkId,
|
||||
sourceMac,
|
||||
destMac,
|
||||
etherType,
|
||||
frameLength,
|
||||
frameData,
|
||||
reason);
|
||||
}
|
||||
|
||||
ZT_INLINE void incomingNetworkFrameDropped(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
const uint16_t etherType,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
uint8_t hops,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
uint8_t verb,
|
||||
bool credentialRequestSent,
|
||||
ZT_TraceFrameDropReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_incomingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, peerIdentity, physicalAddress, hops, frameLength, frameData, verb, credentialRequestSent, reason);
|
||||
m_incomingNetworkFrameDropped(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
networkId,
|
||||
sourceMac,
|
||||
destMac,
|
||||
etherType,
|
||||
peerIdentity,
|
||||
physicalAddress,
|
||||
hops,
|
||||
frameLength,
|
||||
frameData,
|
||||
verb,
|
||||
credentialRequestSent,
|
||||
reason);
|
||||
}
|
||||
|
||||
ZT_INLINE void networkConfigRequestSent(
|
||||
const CallContext &cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t networkId)
|
||||
ZT_INLINE void networkConfigRequestSent(const CallContext& cc, const uint32_t codeLocation, uint64_t networkId)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_networkConfigRequestSent(cc.tPtr, codeLocation, networkId);
|
||||
}
|
||||
|
||||
ZT_INLINE void networkFilter(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const uint8_t primaryRuleSetLog[512],
|
||||
const uint8_t matchingCapabilityRuleSetLog[512],
|
||||
uint32_t matchingCapabilityId,
|
||||
int64_t matchingCapabilityTimestamp,
|
||||
const Address &source,
|
||||
const Address &dest,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
uint16_t etherType,
|
||||
uint16_t vlanId,
|
||||
bool noTee,
|
||||
|
@ -223,104 +260,109 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE void credentialRejected(
|
||||
const CallContext &cc,
|
||||
const CallContext& cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const Identity &identity,
|
||||
const Identity& identity,
|
||||
uint32_t credentialId,
|
||||
int64_t credentialTimestamp,
|
||||
uint8_t credentialType,
|
||||
ZT_TraceCredentialRejectionReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_credentialRejected(cc.tPtr, codeLocation, networkId, identity, credentialId, credentialTimestamp, credentialType, reason);
|
||||
m_credentialRejected(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
networkId,
|
||||
identity,
|
||||
credentialId,
|
||||
credentialTimestamp,
|
||||
credentialType,
|
||||
reason);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
void m_resettingPathsInScope(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
const Identity &reporter,
|
||||
const InetAddress &from,
|
||||
const InetAddress &oldExternal,
|
||||
const InetAddress &newExternal,
|
||||
const Identity& reporter,
|
||||
const InetAddress& from,
|
||||
const InetAddress& oldExternal,
|
||||
const InetAddress& newExternal,
|
||||
InetAddress::IpScope scope);
|
||||
|
||||
void m_tryingNewPath(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
const Identity &trying,
|
||||
const InetAddress &physicalAddress,
|
||||
const InetAddress &triggerAddress,
|
||||
const Identity& trying,
|
||||
const InetAddress& physicalAddress,
|
||||
const InetAddress& triggerAddress,
|
||||
uint64_t triggeringPacketId,
|
||||
uint8_t triggeringPacketVerb,
|
||||
const Identity &triggeringPeer);
|
||||
const Identity& triggeringPeer);
|
||||
|
||||
void m_learnedNewPath(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t packetId,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const InetAddress &replaced);
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
const InetAddress& replaced);
|
||||
|
||||
void m_incomingPacketDropped(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t packetId,
|
||||
uint64_t networkId,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
uint8_t hops,
|
||||
uint8_t verb,
|
||||
ZT_TracePacketDropReason reason);
|
||||
|
||||
void m_outgoingNetworkFrameDropped(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
uint16_t etherType,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
ZT_TraceFrameDropReason reason);
|
||||
|
||||
void m_incomingNetworkFrameDropped(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
const uint16_t etherType,
|
||||
const Identity &peerIdentity,
|
||||
const InetAddress &physicalAddress,
|
||||
const Identity& peerIdentity,
|
||||
const InetAddress& physicalAddress,
|
||||
uint8_t hops,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
uint8_t verb,
|
||||
bool credentialRequestSent,
|
||||
ZT_TraceFrameDropReason reason);
|
||||
|
||||
void m_networkConfigRequestSent(
|
||||
void *tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId);
|
||||
void m_networkConfigRequestSent(void* tPtr, uint32_t codeLocation, uint64_t networkId);
|
||||
|
||||
void m_networkFilter(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const uint8_t *primaryRuleSetLog,
|
||||
const uint8_t *matchingCapabilityRuleSetLog,
|
||||
const uint8_t* primaryRuleSetLog,
|
||||
const uint8_t* matchingCapabilityRuleSetLog,
|
||||
uint32_t matchingCapabilityId,
|
||||
int64_t matchingCapabilityTimestamp,
|
||||
const Address &source,
|
||||
const Address &dest,
|
||||
const MAC &sourceMac,
|
||||
const MAC &destMac,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
const MAC& sourceMac,
|
||||
const MAC& destMac,
|
||||
uint16_t frameLength,
|
||||
const uint8_t *frameData,
|
||||
const uint8_t* frameData,
|
||||
uint16_t etherType,
|
||||
uint16_t vlanId,
|
||||
bool noTee,
|
||||
|
@ -328,16 +370,16 @@ private:
|
|||
int accept);
|
||||
|
||||
void m_credentialRejected(
|
||||
void *tPtr,
|
||||
void* tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId,
|
||||
const Identity &identity,
|
||||
const Identity& identity,
|
||||
uint32_t credentialId,
|
||||
int64_t credentialTimestamp,
|
||||
uint8_t credentialType,
|
||||
ZT_TraceCredentialRejectionReason reason);
|
||||
|
||||
const Context &m_ctx;
|
||||
const Context& m_ctx;
|
||||
volatile unsigned int m_traceFlags; // faster than atomic, but may not "instantly" change... should be okay
|
||||
};
|
||||
|
||||
|
|
|
@ -24,17 +24,15 @@ namespace ZeroTier {
|
|||
*
|
||||
* It also includes some static methods to do this conveniently.
|
||||
*/
|
||||
struct TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
struct TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Zero a TriviallyCopyable object
|
||||
*
|
||||
* @tparam T Automatically inferred type of object
|
||||
* @param obj Any TriviallyCopyable object
|
||||
*/
|
||||
template<typename T>
|
||||
static ZT_INLINE void memoryZero(T *obj) noexcept
|
||||
template <typename T> static ZT_INLINE void memoryZero(T* obj) noexcept
|
||||
{
|
||||
mustBeTriviallyCopyable(obj);
|
||||
Utils::zero<sizeof(T)>(obj);
|
||||
|
@ -46,16 +44,19 @@ public:
|
|||
* @tparam T Automatically inferred type of object
|
||||
* @param obj Any TriviallyCopyable object
|
||||
*/
|
||||
template<typename T>
|
||||
static ZT_INLINE void memoryZero(T &obj) noexcept
|
||||
template <typename T> static ZT_INLINE void memoryZero(T& obj) noexcept
|
||||
{
|
||||
mustBeTriviallyCopyable(obj);
|
||||
Utils::zero<sizeof(T)>(&obj);
|
||||
}
|
||||
|
||||
private:
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable &) noexcept {}
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable *) noexcept {}
|
||||
private:
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable&) noexcept
|
||||
{
|
||||
}
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable*) noexcept
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -12,93 +12,98 @@
|
|||
/****/
|
||||
|
||||
#include "TrustStore.hpp"
|
||||
|
||||
#include "LZ4.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
TrustStore::TrustStore()
|
||||
{}
|
||||
|
||||
TrustStore::~TrustStore()
|
||||
{}
|
||||
|
||||
SharedPtr< TrustStore::Entry > TrustStore::get(const H384 &serial) const
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.find(serial));
|
||||
return (c != m_bySerial.end()) ? c->second : SharedPtr< TrustStore::Entry >();
|
||||
}
|
||||
|
||||
Map< Identity, SharedPtr< const Locator > > TrustStore::roots()
|
||||
TrustStore::~TrustStore()
|
||||
{
|
||||
}
|
||||
|
||||
SharedPtr<TrustStore::Entry> TrustStore::get(const H384& serial) const
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
Map< Identity, SharedPtr< const Locator > > r;
|
||||
Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.find(serial));
|
||||
return (c != m_bySerial.end()) ? c->second : SharedPtr<TrustStore::Entry>();
|
||||
}
|
||||
|
||||
Map<Identity, SharedPtr<const Locator> > TrustStore::roots()
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
Map<Identity, SharedPtr<const Locator> > r;
|
||||
|
||||
// Iterate using m_bySubjectIdentity to only scan certificates with subject identities.
|
||||
// This map also does not contian error or deprecated certificates.
|
||||
for (Map< Fingerprint, Vector< SharedPtr< Entry > > >::const_iterator cv(m_bySubjectIdentity.begin()); cv != m_bySubjectIdentity.end(); ++cv) {
|
||||
for (Vector< SharedPtr< Entry > >::const_iterator c(cv->second.begin()); c != cv->second.end(); ++c) {
|
||||
|
||||
for (Map<Fingerprint, Vector<SharedPtr<Entry> > >::const_iterator cv(m_bySubjectIdentity.begin());
|
||||
cv != m_bySubjectIdentity.end();
|
||||
++cv) {
|
||||
for (Vector<SharedPtr<Entry> >::const_iterator c(cv->second.begin()); c != cv->second.end(); ++c) {
|
||||
// A root set cert must be marked for this use and authorized to influence this node's config.
|
||||
if ((((*c)->m_certificate.usageFlags & ZT_CERTIFICATE_USAGE_ZEROTIER_ROOT_SET) != 0) && (((*c)->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_CONFIG) != 0)) {
|
||||
|
||||
// Add all identities to the root set, and for each entry in the set make sure we have the latest locator if there's more than one cert with one.
|
||||
if ((((*c)->m_certificate.usageFlags & ZT_CERTIFICATE_USAGE_ZEROTIER_ROOT_SET) != 0)
|
||||
&& (((*c)->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_CONFIG) != 0)) {
|
||||
// Add all identities to the root set, and for each entry in the set make sure we have the latest
|
||||
// locator if there's more than one cert with one.
|
||||
for (unsigned int j = 0; j < (*c)->certificate().subject.identityCount; ++j) {
|
||||
const Identity *const id = reinterpret_cast<const Identity *>((*c)->certificate().subject.identities[j].identity);
|
||||
const Identity* const id =
|
||||
reinterpret_cast<const Identity*>((*c)->certificate().subject.identities[j].identity);
|
||||
if ((id) && (*id)) { // sanity check
|
||||
SharedPtr< const Locator > &existingLoc = r[*id];
|
||||
const Locator *const loc = reinterpret_cast<const Locator *>((*c)->certificate().subject.identities[j].locator);
|
||||
SharedPtr<const Locator>& existingLoc = r[*id];
|
||||
const Locator* const loc =
|
||||
reinterpret_cast<const Locator*>((*c)->certificate().subject.identities[j].locator);
|
||||
if (loc) {
|
||||
if ((!existingLoc) || (existingLoc->revision() < loc->revision()))
|
||||
if ((! existingLoc) || (existingLoc->revision() < loc->revision()))
|
||||
existingLoc.set(new Locator(*loc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector< SharedPtr< TrustStore::Entry > > TrustStore::all(const bool includeRejectedCertificates) const
|
||||
Vector<SharedPtr<TrustStore::Entry> > TrustStore::all(const bool includeRejectedCertificates) const
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
Vector< SharedPtr< Entry > > r;
|
||||
Vector<SharedPtr<Entry> > r;
|
||||
r.reserve(m_bySerial.size());
|
||||
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if ((includeRejectedCertificates) || (c->second->error() == ZT_CERTIFICATE_ERROR_NONE))
|
||||
r.push_back(c->second);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void TrustStore::add(const Certificate &cert, const unsigned int localTrust)
|
||||
void TrustStore::add(const Certificate& cert, const unsigned int localTrust)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
m_addQueue.push_front(SharedPtr< Entry >(new Entry(this->m_lock, cert, localTrust)));
|
||||
m_addQueue.push_front(SharedPtr<Entry>(new Entry(this->m_lock, cert, localTrust)));
|
||||
}
|
||||
|
||||
void TrustStore::erase(const H384 &serial)
|
||||
void TrustStore::erase(const H384& serial)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
m_deleteQueue.push_front(serial);
|
||||
}
|
||||
|
||||
bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const purge)
|
||||
bool TrustStore::update(const int64_t clock, Vector<SharedPtr<Entry> >* const purge)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
|
||||
// Check for certificate time validity status changes. If any of these occur then
|
||||
// full re-validation is required.
|
||||
bool errorStateModified = false;
|
||||
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
const bool timeValid = c->second->m_certificate.verifyTimeWindow(clock);
|
||||
switch (c->second->m_error) {
|
||||
case ZT_CERTIFICATE_ERROR_NONE:
|
||||
case ZT_CERTIFICATE_ERROR_INVALID_CHAIN:
|
||||
if (!timeValid) {
|
||||
if (! timeValid) {
|
||||
c->second->m_error = ZT_CERTIFICATE_ERROR_OUT_OF_VALID_TIME_WINDOW;
|
||||
errorStateModified = true;
|
||||
}
|
||||
|
@ -116,28 +121,28 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
|
||||
// If there were not any such changes and if the add and delete queues are empty,
|
||||
// there is nothing more to be done.
|
||||
if ((!errorStateModified) && (m_addQueue.empty()) && (m_deleteQueue.empty()))
|
||||
if ((! errorStateModified) && (m_addQueue.empty()) && (m_deleteQueue.empty()))
|
||||
return false;
|
||||
|
||||
// Add new certificates to m_bySerial, which is the master certificate set. They still
|
||||
// have yet to have their full certificate chains validated. Full signature checking is
|
||||
// performed here.
|
||||
while (!m_addQueue.empty()) {
|
||||
SharedPtr< Entry > &qi = m_addQueue.front();
|
||||
while (! m_addQueue.empty()) {
|
||||
SharedPtr<Entry>& qi = m_addQueue.front();
|
||||
qi->m_error = qi->m_certificate.verify(clock, true);
|
||||
m_bySerial[H384(qi->m_certificate.serialNo)].move(qi);
|
||||
m_addQueue.pop_front();
|
||||
}
|
||||
|
||||
// Delete any certificates enqueued to be deleted.
|
||||
while (!m_deleteQueue.empty()) {
|
||||
while (! m_deleteQueue.empty()) {
|
||||
m_bySerial.erase(m_deleteQueue.front());
|
||||
m_deleteQueue.pop_front();
|
||||
}
|
||||
|
||||
// Reset flags for deprecation and a cert being on a trust path, which are
|
||||
// recomputed when chain and subjects are checked below.
|
||||
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if (c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) {
|
||||
c->second->m_subjectDeprecated = false;
|
||||
c->second->m_onTrustPath = false;
|
||||
|
@ -146,44 +151,51 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
|
||||
// Validate certificate trust paths.
|
||||
{
|
||||
Vector< Entry * > visited;
|
||||
Vector<Entry*> visited;
|
||||
visited.reserve(8);
|
||||
for (Map< H384, SharedPtr< Entry > >::iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if ((c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) && (!c->second->m_onTrustPath) && ((c->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0)) {
|
||||
for (Map<H384, SharedPtr<Entry> >::iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if ((c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) && (! c->second->m_onTrustPath)
|
||||
&& ((c->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0)) {
|
||||
// Trace the path of each certificate all the way back to a trusted CA.
|
||||
unsigned int pathLength = 0;
|
||||
Map< H384, SharedPtr< Entry > >::const_iterator current(c);
|
||||
Map<H384, SharedPtr<Entry> >::const_iterator current(c);
|
||||
visited.clear();
|
||||
for (;;) {
|
||||
if (pathLength <= current->second->m_certificate.maxPathLength) {
|
||||
|
||||
// Check if this cert isn't a CA or already part of a valid trust path. If so then step upward toward CA.
|
||||
if (((current->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0) && (!current->second->m_onTrustPath)) {
|
||||
// If the issuer (parent) certificiate is (1) valid, (2) not already visited (to prevent loops),
|
||||
// and (3) has a public key that matches this cert's issuer public key (sanity check), proceed
|
||||
// up the certificate graph toward a potential CA.
|
||||
// Check if this cert isn't a CA or already part of a valid trust path. If so then step upward
|
||||
// toward CA.
|
||||
if (((current->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0)
|
||||
&& (! current->second->m_onTrustPath)) {
|
||||
// If the issuer (parent) certificiate is (1) valid, (2) not already visited (to prevent
|
||||
// loops), and (3) has a public key that matches this cert's issuer public key (sanity
|
||||
// check), proceed up the certificate graph toward a potential CA.
|
||||
visited.push_back(current->second.ptr());
|
||||
const Map< H384, SharedPtr< Entry > >::const_iterator prevChild(current);
|
||||
const Map<H384, SharedPtr<Entry> >::const_iterator prevChild(current);
|
||||
current = m_bySerial.find(H384(current->second->m_certificate.issuer));
|
||||
if ((current != m_bySerial.end()) &&
|
||||
(std::find(visited.begin(), visited.end(), current->second.ptr()) == visited.end()) &&
|
||||
(current->second->m_error == ZT_CERTIFICATE_ERROR_NONE) &&
|
||||
(current->second->m_certificate.publicKeySize == prevChild->second->m_certificate.issuerPublicKeySize) &&
|
||||
(memcmp(current->second->m_certificate.publicKey, prevChild->second->m_certificate.issuerPublicKey, current->second->m_certificate.publicKeySize) == 0)) {
|
||||
if ((current != m_bySerial.end())
|
||||
&& (std::find(visited.begin(), visited.end(), current->second.ptr()) == visited.end())
|
||||
&& (current->second->m_error == ZT_CERTIFICATE_ERROR_NONE)
|
||||
&& (current->second->m_certificate.publicKeySize
|
||||
== prevChild->second->m_certificate.issuerPublicKeySize)
|
||||
&& (memcmp(
|
||||
current->second->m_certificate.publicKey,
|
||||
prevChild->second->m_certificate.issuerPublicKey,
|
||||
current->second->m_certificate.publicKeySize)
|
||||
== 0)) {
|
||||
++pathLength;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// If we've traced this to a root CA, flag its parents as also being on a trust path. Then
|
||||
// break the loop without setting an error. We don't flag the current cert as being on a
|
||||
// trust path since no other certificates depend on it.
|
||||
for (Vector< Entry * >::const_iterator v(visited.begin()); v != visited.end(); ++v) {
|
||||
for (Vector<Entry*>::const_iterator v(visited.begin()); v != visited.end(); ++v) {
|
||||
if (*v != c->second.ptr())
|
||||
(*v)->m_onTrustPath = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we made it here without breaking or continuing, no path to a
|
||||
|
@ -199,60 +211,67 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
// certificates for the same subject as deprecated. A deprecated certificate is not invalid
|
||||
// but will be purged if it is also not part of a trust path. Error certificates are ignored.
|
||||
m_bySubjectUniqueId.clear();
|
||||
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) {
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) {
|
||||
if (c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) {
|
||||
|
||||
const unsigned int uniqueIdSize = c->second->m_certificate.subject.uniqueIdSize;
|
||||
if ((uniqueIdSize > 0) && (uniqueIdSize <= ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE)) {
|
||||
SharedPtr< Entry > &entry = m_bySubjectUniqueId[Blob< ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE >(c->second->m_certificate.subject.uniqueId, uniqueIdSize)];
|
||||
SharedPtr<Entry>& entry = m_bySubjectUniqueId[Blob<ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE>(
|
||||
c->second->m_certificate.subject.uniqueId,
|
||||
uniqueIdSize)];
|
||||
if (entry) {
|
||||
|
||||
// If there's already an entry, see if there's a newer certificate for this subject.
|
||||
if (c->second->m_certificate.subject.timestamp > entry->m_certificate.subject.timestamp) {
|
||||
entry->m_subjectDeprecated = true;
|
||||
entry = c->second;
|
||||
} else if (c->second->m_certificate.subject.timestamp < entry->m_certificate.subject.timestamp) {
|
||||
}
|
||||
else if (c->second->m_certificate.subject.timestamp < entry->m_certificate.subject.timestamp) {
|
||||
c->second->m_subjectDeprecated = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// Equal timestamps should never happen, but handle it anyway by comparing serials.
|
||||
if (memcmp(c->second->m_certificate.serialNo, entry->m_certificate.serialNo, ZT_CERTIFICATE_HASH_SIZE) > 0) {
|
||||
if (memcmp(
|
||||
c->second->m_certificate.serialNo,
|
||||
entry->m_certificate.serialNo,
|
||||
ZT_CERTIFICATE_HASH_SIZE)
|
||||
> 0) {
|
||||
entry->m_subjectDeprecated = true;
|
||||
entry = c->second;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
c->second->m_subjectDeprecated = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
entry = c->second;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Populate mapping of identities to certificates whose subjects reference them, ignoring
|
||||
// error or deprecated certificates.
|
||||
m_bySubjectIdentity.clear();
|
||||
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if ((c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) && (!c->second->m_subjectDeprecated)) {
|
||||
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if ((c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) && (! c->second->m_subjectDeprecated)) {
|
||||
for (unsigned int i = 0; i < c->second->m_certificate.subject.identityCount; ++i) {
|
||||
const Identity *const id = reinterpret_cast<const Identity *>(c->second->m_certificate.subject.identities[i].identity);
|
||||
const Identity* const id =
|
||||
reinterpret_cast<const Identity*>(c->second->m_certificate.subject.identities[i].identity);
|
||||
if ((id) && (*id)) // sanity check
|
||||
m_bySubjectIdentity[id->fingerprint()].push_back(c->second);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If purge is set, erase and return error and deprecated certs (that are not on a trust path).
|
||||
if (purge) {
|
||||
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) {
|
||||
if ( (c->second->error() != ZT_CERTIFICATE_ERROR_NONE) || ((c->second->m_subjectDeprecated) && (!c->second->m_onTrustPath)) ) {
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) {
|
||||
if ((c->second->error() != ZT_CERTIFICATE_ERROR_NONE)
|
||||
|| ((c->second->m_subjectDeprecated) && (! c->second->m_onTrustPath))) {
|
||||
purge->push_back(c->second);
|
||||
m_bySerial.erase(c++);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
@ -261,23 +280,23 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
return true;
|
||||
}
|
||||
|
||||
Vector< uint8_t > TrustStore::save() const
|
||||
Vector<uint8_t> TrustStore::save() const
|
||||
{
|
||||
Vector< uint8_t > comp;
|
||||
Vector<uint8_t> comp;
|
||||
|
||||
int compSize;
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
|
||||
Vector< uint8_t > b;
|
||||
Vector<uint8_t> b;
|
||||
b.reserve(4096);
|
||||
|
||||
// A version byte.
|
||||
b.push_back(0);
|
||||
|
||||
// <size[2]> <certificate[...]> <trust[2]> tuples terminated by a 0 size.
|
||||
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
const Vector< uint8_t > cdata(c->second->certificate().encode());
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
const Vector<uint8_t> cdata(c->second->certificate().encode());
|
||||
const unsigned long size = (uint32_t)cdata.size();
|
||||
if ((size > 0) && (size <= 0xffff)) {
|
||||
b.push_back((uint8_t)(size >> 8U));
|
||||
|
@ -292,9 +311,13 @@ Vector< uint8_t > TrustStore::save() const
|
|||
b.push_back(0);
|
||||
|
||||
comp.resize((unsigned long)LZ4_COMPRESSBOUND(b.size()) + 8);
|
||||
compSize = LZ4_compress_fast(reinterpret_cast<const char *>(b.data()), reinterpret_cast<char *>(comp.data() + 8), (int)b.size(), (int)(comp.size() - 8));
|
||||
compSize = LZ4_compress_fast(
|
||||
reinterpret_cast<const char*>(b.data()),
|
||||
reinterpret_cast<char*>(comp.data() + 8),
|
||||
(int)b.size(),
|
||||
(int)(comp.size() - 8));
|
||||
if (unlikely(compSize <= 0)) // shouldn't be possible
|
||||
return Vector< uint8_t >();
|
||||
return Vector<uint8_t>();
|
||||
|
||||
const uint32_t uncompSize = (uint32_t)b.size();
|
||||
Utils::storeBigEndian(comp.data(), uncompSize);
|
||||
|
@ -308,24 +331,29 @@ Vector< uint8_t > TrustStore::save() const
|
|||
return comp;
|
||||
}
|
||||
|
||||
int TrustStore::load(const Vector< uint8_t > &data)
|
||||
int TrustStore::load(const Vector<uint8_t>& data)
|
||||
{
|
||||
if (data.size() < 8)
|
||||
return -1;
|
||||
|
||||
const unsigned int uncompSize = Utils::loadBigEndian< uint32_t >(data.data());
|
||||
const unsigned int uncompSize = Utils::loadBigEndian<uint32_t>(data.data());
|
||||
if ((uncompSize == 0) || (uncompSize > (unsigned int)(data.size() * 128)))
|
||||
return -1;
|
||||
|
||||
Vector< uint8_t > uncomp;
|
||||
Vector<uint8_t> uncomp;
|
||||
uncomp.resize(uncompSize);
|
||||
|
||||
if (LZ4_decompress_safe(reinterpret_cast<const char *>(data.data() + 8), reinterpret_cast<char *>(uncomp.data()), (int)(data.size() - 8), (int)uncompSize) != (int)uncompSize)
|
||||
if (LZ4_decompress_safe(
|
||||
reinterpret_cast<const char*>(data.data() + 8),
|
||||
reinterpret_cast<char*>(uncomp.data()),
|
||||
(int)(data.size() - 8),
|
||||
(int)uncompSize)
|
||||
!= (int)uncompSize)
|
||||
return -1;
|
||||
const uint8_t *b = uncomp.data();
|
||||
if (Utils::fnv1a32(b, (unsigned int)uncompSize) != Utils::loadBigEndian< uint32_t >(data.data() + 4))
|
||||
const uint8_t* b = uncomp.data();
|
||||
if (Utils::fnv1a32(b, (unsigned int)uncompSize) != Utils::loadBigEndian<uint32_t>(data.data() + 4))
|
||||
return -1;
|
||||
const uint8_t *const eof = b + uncompSize;
|
||||
const uint8_t* const eof = b + uncompSize;
|
||||
|
||||
if (*(b++) != 0) // unrecognized version
|
||||
return -1;
|
||||
|
@ -335,7 +363,7 @@ int TrustStore::load(const Vector< uint8_t > &data)
|
|||
for (;;) {
|
||||
if ((b + 2) > eof)
|
||||
break;
|
||||
const uint32_t certDataSize = Utils::loadBigEndian< uint16_t >(b);
|
||||
const uint32_t certDataSize = Utils::loadBigEndian<uint16_t>(b);
|
||||
b += 2;
|
||||
|
||||
if (certDataSize == 0)
|
||||
|
@ -346,7 +374,7 @@ int TrustStore::load(const Vector< uint8_t > &data)
|
|||
Certificate c;
|
||||
if (c.decode(b, (unsigned int)certDataSize)) {
|
||||
b += certDataSize;
|
||||
this->add(c, Utils::loadBigEndian< uint16_t >(b));
|
||||
this->add(c, Utils::loadBigEndian<uint16_t>(b));
|
||||
b += 2;
|
||||
|
||||
++readCount;
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
#ifndef ZT_TRUSTSTORE_HPP
|
||||
#define ZT_TRUSTSTORE_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Certificate.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -43,24 +43,24 @@ namespace ZeroTier {
|
|||
* hence there are no methods for doing that. There's only one instance in a
|
||||
* node anyway.
|
||||
*/
|
||||
class TrustStore
|
||||
{
|
||||
public:
|
||||
class TrustStore {
|
||||
public:
|
||||
/**
|
||||
* An entry in the node certificate trust store
|
||||
*/
|
||||
class Entry
|
||||
{
|
||||
friend class SharedPtr< TrustStore::Entry >;
|
||||
friend class SharedPtr< const TrustStore::Entry >;
|
||||
class Entry {
|
||||
friend class SharedPtr<TrustStore::Entry>;
|
||||
friend class SharedPtr<const TrustStore::Entry>;
|
||||
friend class TrustStore;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @return Reference to held certificate
|
||||
*/
|
||||
ZT_INLINE const Certificate &certificate() const noexcept
|
||||
{ return m_certificate; }
|
||||
ZT_INLINE const Certificate& certificate() const noexcept
|
||||
{
|
||||
return m_certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local trust for this certificate
|
||||
|
@ -98,21 +98,25 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
Entry &operator=(const Entry &) { return *this; }
|
||||
Entry& operator=(const Entry&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE Entry(RWMutex &l, const Certificate &cert, const unsigned int lt) noexcept:
|
||||
__refCount(0),
|
||||
m_lock(l),
|
||||
m_certificate(cert),
|
||||
m_localTrust(lt),
|
||||
m_error(ZT_CERTIFICATE_ERROR_NONE),
|
||||
m_subjectDeprecated(false),
|
||||
m_onTrustPath(false)
|
||||
{}
|
||||
ZT_INLINE Entry(RWMutex& l, const Certificate& cert, const unsigned int lt) noexcept
|
||||
: __refCount(0)
|
||||
, m_lock(l)
|
||||
, m_certificate(cert)
|
||||
, m_localTrust(lt)
|
||||
, m_error(ZT_CERTIFICATE_ERROR_NONE)
|
||||
, m_subjectDeprecated(false)
|
||||
, m_onTrustPath(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::atomic< int > __refCount;
|
||||
std::atomic<int> __refCount;
|
||||
|
||||
RWMutex &m_lock;
|
||||
RWMutex& m_lock;
|
||||
const Certificate m_certificate;
|
||||
unsigned int m_localTrust;
|
||||
ZT_CertificateError m_error;
|
||||
|
@ -133,7 +137,7 @@ public:
|
|||
* @param serial SHA384 hash of certificate
|
||||
* @return Entry or empty/nil if not found
|
||||
*/
|
||||
SharedPtr< Entry > get(const H384 &serial) const;
|
||||
SharedPtr<Entry> get(const H384& serial) const;
|
||||
|
||||
/**
|
||||
* Get roots specified by root set certificates in the local store.
|
||||
|
@ -144,13 +148,13 @@ public:
|
|||
*
|
||||
* @return Roots and the latest locator specified for each (if any)
|
||||
*/
|
||||
Map< Identity, SharedPtr< const Locator > > roots();
|
||||
Map<Identity, SharedPtr<const Locator> > roots();
|
||||
|
||||
/**
|
||||
* @param includeRejectedCertificates If true, also include certificates with error codes
|
||||
* @return All certificates in asecending sort order by serial
|
||||
*/
|
||||
Vector< SharedPtr< Entry > > all(bool includeRejectedCertificates) const;
|
||||
Vector<SharedPtr<Entry> > all(bool includeRejectedCertificates) const;
|
||||
|
||||
/**
|
||||
* Add a certificate
|
||||
|
@ -164,7 +168,7 @@ public:
|
|||
*
|
||||
* @param cert Certificate to add
|
||||
*/
|
||||
void add(const Certificate &cert, unsigned int localTrust);
|
||||
void add(const Certificate& cert, unsigned int localTrust);
|
||||
|
||||
/**
|
||||
* Queue a certificate to be deleted
|
||||
|
@ -173,7 +177,7 @@ public:
|
|||
*
|
||||
* @param serial Serial of certificate to delete
|
||||
*/
|
||||
void erase(const H384 &serial);
|
||||
void erase(const H384& serial);
|
||||
|
||||
/**
|
||||
* Validate all certificates and their certificate chains
|
||||
|
@ -184,14 +188,14 @@ public:
|
|||
* @param purge If non-NULL, purge rejected certificates and return them in this vector (vector should be empty)
|
||||
* @return True if there were changes
|
||||
*/
|
||||
bool update(int64_t clock, Vector< SharedPtr< Entry > > *purge);
|
||||
bool update(int64_t clock, Vector<SharedPtr<Entry> >* purge);
|
||||
|
||||
/**
|
||||
* Create a compressed binary version of certificates and their local trust
|
||||
*
|
||||
* @return Binary compressed certificates and local trust info
|
||||
*/
|
||||
Vector< uint8_t > save() const;
|
||||
Vector<uint8_t> save() const;
|
||||
|
||||
/**
|
||||
* Decode a saved trust store
|
||||
|
@ -202,14 +206,15 @@ public:
|
|||
* @param data Data to decode
|
||||
* @return Number of certificates or -1 if input is invalid
|
||||
*/
|
||||
int load(const Vector< uint8_t > &data);
|
||||
int load(const Vector<uint8_t>& data);
|
||||
|
||||
private:
|
||||
Map< H384, SharedPtr< Entry > > m_bySerial; // all certificates
|
||||
Map< Blob< ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE >, SharedPtr< Entry > > m_bySubjectUniqueId; // non-rejected certificates only
|
||||
Map< Fingerprint, Vector< SharedPtr< Entry > > > m_bySubjectIdentity; // non-rejected certificates only
|
||||
ForwardList< SharedPtr< Entry > > m_addQueue;
|
||||
ForwardList< H384 > m_deleteQueue;
|
||||
private:
|
||||
Map<H384, SharedPtr<Entry> > m_bySerial; // all certificates
|
||||
Map<Blob<ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE>, SharedPtr<Entry> >
|
||||
m_bySubjectUniqueId; // non-rejected certificates only
|
||||
Map<Fingerprint, Vector<SharedPtr<Entry> > > m_bySubjectIdentity; // non-rejected certificates only
|
||||
ForwardList<SharedPtr<Entry> > m_addQueue;
|
||||
ForwardList<H384> m_deleteQueue;
|
||||
RWMutex m_lock;
|
||||
};
|
||||
|
||||
|
|
142
core/Utils.cpp
142
core/Utils.cpp
|
@ -12,16 +12,17 @@
|
|||
/****/
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
#include "AES.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
@ -32,8 +33,8 @@
|
|||
#ifdef ZT_ARCH_ARM_HAS_NEON
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
|
@ -73,7 +74,6 @@ namespace Utils {
|
|||
#ifdef ZT_ARCH_ARM_HAS_NEON
|
||||
ARMCapabilities::ARMCapabilities() noexcept
|
||||
{
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
this->aes = true;
|
||||
|
@ -86,14 +86,15 @@ ARMCapabilities::ARMCapabilities() noexcept
|
|||
|
||||
#ifdef __LINUX__
|
||||
#ifdef HWCAP2_AES
|
||||
if (sizeof(void *) == 4) {
|
||||
if (sizeof(void*) == 4) {
|
||||
const long hwcaps2 = getauxval(AT_HWCAP2);
|
||||
this->aes = (hwcaps2 & HWCAP2_AES) != 0;
|
||||
this->crc32 = (hwcaps2 & HWCAP2_CRC32) != 0;
|
||||
this->pmull = (hwcaps2 & HWCAP2_PMULL) != 0;
|
||||
this->sha1 = (hwcaps2 & HWCAP2_SHA1) != 0;
|
||||
this->sha2 = (hwcaps2 & HWCAP2_SHA2) != 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
const long hwcaps = getauxval(AT_HWCAP);
|
||||
this->aes = (hwcaps & HWCAP_AES) != 0;
|
||||
|
@ -107,7 +108,6 @@ ARMCapabilities::ARMCapabilities() noexcept
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
const ARMCapabilities ARMCAP;
|
||||
|
@ -120,17 +120,13 @@ CPUIDRegisters::CPUIDRegisters() noexcept
|
|||
|
||||
#ifdef __WINDOWS__
|
||||
int regs[4];
|
||||
__cpuid(regs,1);
|
||||
__cpuid(regs, 1);
|
||||
eax = (uint32_t)regs[0];
|
||||
ebx = (uint32_t)regs[1];
|
||||
ecx = (uint32_t)regs[2];
|
||||
edx = (uint32_t)regs[3];
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(1), "c"(0)
|
||||
);
|
||||
__asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1), "c"(0));
|
||||
#endif
|
||||
|
||||
rdrand = ((ecx & (1U << 30U)) != 0);
|
||||
|
@ -138,17 +134,13 @@ CPUIDRegisters::CPUIDRegisters() noexcept
|
|||
avx = ((ecx & (1U << 25U)) != 0);
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
__cpuid(regs,7);
|
||||
__cpuid(regs, 7);
|
||||
eax = (uint32_t)regs[0];
|
||||
ebx = (uint32_t)regs[1];
|
||||
ecx = (uint32_t)regs[2];
|
||||
edx = (uint32_t)regs[3];
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(7), "c"(0)
|
||||
);
|
||||
__asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(7), "c"(0));
|
||||
#endif
|
||||
|
||||
vaes = aes && avx && ((ecx & (1U << 9U)) != 0);
|
||||
|
@ -164,28 +156,28 @@ const CPUIDRegisters CPUID;
|
|||
|
||||
const std::bad_alloc BadAllocException;
|
||||
const std::out_of_range OutOfRangeException("access out of range");
|
||||
const uint64_t ZERO256[4] = {0, 0, 0, 0};
|
||||
const char HEXCHARS[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
const uint64_t ZERO256[4] = { 0, 0, 0, 0 };
|
||||
const char HEXCHARS[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
const uint64_t s_mapNonce = getSecureRandomU64();
|
||||
|
||||
bool secureEq(const void *const a, const void *const b, const unsigned int len) noexcept
|
||||
bool secureEq(const void* const a, const void* const b, const unsigned int len) noexcept
|
||||
{
|
||||
uint8_t diff = 0;
|
||||
for (unsigned int i = 0; i < len; ++i)
|
||||
diff |= ((reinterpret_cast<const uint8_t *>(a))[i] ^ (reinterpret_cast<const uint8_t *>(b))[i]);
|
||||
diff |= ((reinterpret_cast<const uint8_t*>(a))[i] ^ (reinterpret_cast<const uint8_t*>(b))[i]);
|
||||
return (diff == 0);
|
||||
}
|
||||
|
||||
void burn(volatile void *const ptr, const unsigned int len)
|
||||
void burn(volatile void* const ptr, const unsigned int len)
|
||||
{
|
||||
static volatile uintptr_t foo = 0;
|
||||
Utils::zero((void *)ptr, len);
|
||||
Utils::zero((void*)ptr, len);
|
||||
// Force compiler not to optimize this function out by taking a volatile
|
||||
// parameter and also updating a volatile variable.
|
||||
foo += (uintptr_t)len ^ (uintptr_t)reinterpret_cast<volatile uint8_t *>(ptr)[0];
|
||||
foo += (uintptr_t)len ^ (uintptr_t) reinterpret_cast<volatile uint8_t*>(ptr)[0];
|
||||
}
|
||||
|
||||
static unsigned long s_decimalRecursive(unsigned long n, char *s)
|
||||
static unsigned long s_decimalRecursive(unsigned long n, char* s)
|
||||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
@ -196,7 +188,7 @@ static unsigned long s_decimalRecursive(unsigned long n, char *s)
|
|||
return pos + 1;
|
||||
}
|
||||
|
||||
char *decimal(unsigned long n, char s[24]) noexcept
|
||||
char* decimal(unsigned long n, char s[24]) noexcept
|
||||
{
|
||||
if (n == 0) {
|
||||
s[0] = '0';
|
||||
|
@ -207,36 +199,39 @@ char *decimal(unsigned long n, char s[24]) noexcept
|
|||
return s;
|
||||
}
|
||||
|
||||
char *hex(uint64_t i, char buf[17]) noexcept
|
||||
char* hex(uint64_t i, char buf[17]) noexcept
|
||||
{
|
||||
if (i != 0) {
|
||||
char *p = nullptr;
|
||||
char* p = nullptr;
|
||||
for (int b = 60; b >= 0; b -= 4) {
|
||||
const unsigned int nyb = (unsigned int)(i >> (unsigned int)b) & 0xfU;
|
||||
if (p) {
|
||||
*(p++) = HEXCHARS[nyb];
|
||||
} else if (nyb != 0) {
|
||||
}
|
||||
else if (nyb != 0) {
|
||||
p = buf;
|
||||
*(p++) = HEXCHARS[nyb];
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
return buf;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
buf[0] = '0';
|
||||
buf[1] = 0;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t unhex(const char *s) noexcept
|
||||
uint64_t unhex(const char* s) noexcept
|
||||
{
|
||||
uint64_t n = 0;
|
||||
if (s) {
|
||||
int k = 0;
|
||||
while (k < 16) {
|
||||
char hc = *(s++);
|
||||
if (!hc) break;
|
||||
if (! hc)
|
||||
break;
|
||||
|
||||
uint8_t c = 0;
|
||||
if ((hc >= 48) && (hc <= 57))
|
||||
|
@ -254,11 +249,11 @@ uint64_t unhex(const char *s) noexcept
|
|||
return n;
|
||||
}
|
||||
|
||||
char *hex(const void *d, unsigned int l, char *s) noexcept
|
||||
char* hex(const void* d, unsigned int l, char* s) noexcept
|
||||
{
|
||||
char *const save = s;
|
||||
char* const save = s;
|
||||
for (unsigned int i = 0; i < l; ++i) {
|
||||
const unsigned int b = reinterpret_cast<const uint8_t *>(d)[i];
|
||||
const unsigned int b = reinterpret_cast<const uint8_t*>(d)[i];
|
||||
*(s++) = HEXCHARS[b >> 4U];
|
||||
*(s++) = HEXCHARS[b & 0xfU];
|
||||
}
|
||||
|
@ -266,14 +261,16 @@ char *hex(const void *d, unsigned int l, char *s) noexcept
|
|||
return save;
|
||||
}
|
||||
|
||||
unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buflen) noexcept
|
||||
unsigned int unhex(const char* h, unsigned int hlen, void* buf, unsigned int buflen) noexcept
|
||||
{
|
||||
unsigned int l = 0;
|
||||
const char *hend = h + hlen;
|
||||
const char* hend = h + hlen;
|
||||
while (l < buflen) {
|
||||
if (h == hend) break;
|
||||
uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
|
||||
if (!hc) break;
|
||||
if (h == hend)
|
||||
break;
|
||||
uint8_t hc = *(reinterpret_cast<const uint8_t*>(h++));
|
||||
if (! hc)
|
||||
break;
|
||||
|
||||
uint8_t c = 0;
|
||||
if ((hc >= 48) && (hc <= 57))
|
||||
|
@ -283,9 +280,11 @@ unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buf
|
|||
else if ((hc >= 65) && (hc <= 70))
|
||||
c = hc - 55;
|
||||
|
||||
if (h == hend) break;
|
||||
hc = *(reinterpret_cast<const uint8_t *>(h++));
|
||||
if (!hc) break;
|
||||
if (h == hend)
|
||||
break;
|
||||
hc = *(reinterpret_cast<const uint8_t*>(h++));
|
||||
if (! hc)
|
||||
break;
|
||||
|
||||
c <<= 4U;
|
||||
if ((hc >= 48) && (hc <= 57))
|
||||
|
@ -295,7 +294,7 @@ unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buf
|
|||
else if ((hc >= 65) && (hc <= 70))
|
||||
c |= hc - 55;
|
||||
|
||||
reinterpret_cast<uint8_t *>(buf)[l++] = c;
|
||||
reinterpret_cast<uint8_t*>(buf)[l++] = c;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
@ -303,7 +302,7 @@ unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buf
|
|||
#define ZT_GETSECURERANDOM_STATE_SIZE 64
|
||||
#define ZT_GETSECURERANDOM_ITERATIONS_PER_GENERATOR 1048576
|
||||
|
||||
void getSecureRandom(void *const buf, unsigned int bytes) noexcept
|
||||
void getSecureRandom(void* const buf, unsigned int bytes) noexcept
|
||||
{
|
||||
static Mutex globalLock;
|
||||
static bool initialized = false;
|
||||
|
@ -321,20 +320,20 @@ void getSecureRandom(void *const buf, unsigned int bytes) noexcept
|
|||
if (unlikely(randomByteCounter >= ZT_GETSECURERANDOM_ITERATIONS_PER_GENERATOR)) {
|
||||
randomByteCounter = 0;
|
||||
|
||||
if (unlikely(!initialized)) {
|
||||
if (unlikely(! initialized)) {
|
||||
initialized = true;
|
||||
Utils::zero< sizeof(randomState) >(randomState);
|
||||
Utils::zero<sizeof(randomState)>(randomState);
|
||||
#ifdef __WINDOWS__
|
||||
HCRYPTPROV cryptProvider = NULL;
|
||||
if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) {
|
||||
fprintf(stderr,"FATAL: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n");
|
||||
if (! CryptAcquireContextA(&cryptProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
fprintf(stderr, "FATAL: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!CryptGenRandom(cryptProvider,(DWORD)sizeof(randomState),(BYTE *)randomState)) {
|
||||
fprintf(stderr,"FATAL: Utils::getSecureRandom() CryptGenRandom failed!\r\n");
|
||||
if (! CryptGenRandom(cryptProvider, (DWORD)sizeof(randomState), (BYTE*)randomState)) {
|
||||
fprintf(stderr, "FATAL: Utils::getSecureRandom() CryptGenRandom failed!\r\n");
|
||||
exit(1);
|
||||
}
|
||||
CryptReleaseContext(cryptProvider,0);
|
||||
CryptReleaseContext(cryptProvider, 0);
|
||||
#else
|
||||
int devURandomFd = ::open("/dev/urandom", O_RDONLY);
|
||||
if (devURandomFd < 0) {
|
||||
|
@ -356,7 +355,7 @@ void getSecureRandom(void *const buf, unsigned int bytes) noexcept
|
|||
if (CPUID.rdrand) {
|
||||
uint64_t tmp = 0;
|
||||
for (unsigned long i = 0; i < ZT_GETSECURERANDOM_STATE_SIZE; ++i) {
|
||||
_rdrand64_step((unsigned long long *)&tmp);
|
||||
_rdrand64_step((unsigned long long*)&tmp);
|
||||
randomState[i] ^= tmp;
|
||||
}
|
||||
}
|
||||
|
@ -374,8 +373,8 @@ void getSecureRandom(void *const buf, unsigned int bytes) noexcept
|
|||
// Generate random bytes using AES and bytes 32-48 of randomState as an in-place
|
||||
// AES-CTR counter. Counter can be machine endian; we don't care about portability
|
||||
// for a random generator.
|
||||
uint64_t *const ctr = randomState + 4;
|
||||
uint8_t *out = reinterpret_cast<uint8_t *>(buf);
|
||||
uint64_t* const ctr = randomState + 4;
|
||||
uint8_t* out = reinterpret_cast<uint8_t*>(buf);
|
||||
|
||||
while (bytes >= 16) {
|
||||
++*ctr;
|
||||
|
@ -401,7 +400,7 @@ uint64_t getSecureRandomU64() noexcept
|
|||
return tmp;
|
||||
}
|
||||
|
||||
int b32e(const uint8_t *data, int length, char *result, int bufSize) noexcept
|
||||
int b32e(const uint8_t* data, int length, char* result, int bufSize) noexcept
|
||||
{
|
||||
if (length < 0 || length > (1 << 28U)) {
|
||||
result[0] = (char)0;
|
||||
|
@ -418,7 +417,8 @@ int b32e(const uint8_t *data, int length, char *result, int bufSize) noexcept
|
|||
buffer <<= 8U;
|
||||
buffer |= data[next++] & 0xffU;
|
||||
bitsLeft += 8;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int pad = 5 - bitsLeft;
|
||||
buffer <<= pad;
|
||||
bitsLeft += pad;
|
||||
|
@ -437,12 +437,12 @@ int b32e(const uint8_t *data, int length, char *result, int bufSize) noexcept
|
|||
return -1;
|
||||
}
|
||||
|
||||
int b32d(const char *encoded, uint8_t *result, int bufSize) noexcept
|
||||
int b32d(const char* encoded, uint8_t* result, int bufSize) noexcept
|
||||
{
|
||||
int buffer = 0;
|
||||
int bitsLeft = 0;
|
||||
int count = 0;
|
||||
for (const uint8_t *ptr = (const uint8_t *)encoded; count < bufSize && *ptr; ++ptr) {
|
||||
for (const uint8_t* ptr = (const uint8_t*)encoded; count < bufSize && *ptr; ++ptr) {
|
||||
uint8_t ch = *ptr;
|
||||
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-' || ch == '.') {
|
||||
continue;
|
||||
|
@ -451,17 +451,21 @@ int b32d(const char *encoded, uint8_t *result, int bufSize) noexcept
|
|||
|
||||
if (ch == '0') {
|
||||
ch = 'O';
|
||||
} else if (ch == '1') {
|
||||
}
|
||||
else if (ch == '1') {
|
||||
ch = 'L';
|
||||
} else if (ch == '8') {
|
||||
}
|
||||
else if (ch == '8') {
|
||||
ch = 'B';
|
||||
}
|
||||
|
||||
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
|
||||
ch = (ch & 0x1f) - 1;
|
||||
} else if (ch >= '2' && ch <= '7') {
|
||||
}
|
||||
else if (ch >= '2' && ch <= '7') {
|
||||
ch -= '2' - 26;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -506,9 +510,9 @@ uint64_t random() noexcept
|
|||
return result;
|
||||
}
|
||||
|
||||
bool scopy(char *const dest, const unsigned int len, const char *const src) noexcept
|
||||
bool scopy(char* const dest, const unsigned int len, const char* const src) noexcept
|
||||
{
|
||||
if (unlikely((len == 0)||(dest == nullptr))) {
|
||||
if (unlikely((len == 0) || (dest == nullptr))) {
|
||||
return false;
|
||||
}
|
||||
if (unlikely(src == nullptr)) {
|
||||
|
@ -528,12 +532,12 @@ bool scopy(char *const dest, const unsigned int len, const char *const src) noex
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t fnv1a32(const void *const restrict data, const unsigned int len) noexcept
|
||||
uint32_t fnv1a32(const void* const restrict data, const unsigned int len) noexcept
|
||||
{
|
||||
uint32_t h = 0x811c9dc5;
|
||||
const uint32_t p = 0x01000193;
|
||||
for (unsigned int i = 0; i < len; ++i)
|
||||
h = (h ^ (uint32_t)reinterpret_cast<const uint8_t *>(data)[i]) * p;
|
||||
h = (h ^ (uint32_t) reinterpret_cast<const uint8_t*>(data)[i]) * p;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
|
331
core/Utils.hpp
331
core/Utils.hpp
|
@ -16,13 +16,12 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,15 +36,11 @@ namespace Utils {
|
|||
// Macros to convert endian-ness at compile time for constants.
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)((uint16_t)((uint16_t)(x) << 8U) | (uint16_t)((uint16_t)(x) >> 8U)))
|
||||
#define ZT_CONST_TO_BE_UINT64(x) ( \
|
||||
(((uint64_t)(x) & 0x00000000000000ffULL) << 56U) | \
|
||||
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40U) | \
|
||||
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24U) | \
|
||||
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8U) | \
|
||||
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8U) | \
|
||||
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24U) | \
|
||||
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40U) | \
|
||||
(((uint64_t)(x) & 0xff00000000000000ULL) >> 56U))
|
||||
#define ZT_CONST_TO_BE_UINT64(x) \
|
||||
((((uint64_t)(x)&0x00000000000000ffULL) << 56U) | (((uint64_t)(x)&0x000000000000ff00ULL) << 40U) \
|
||||
| (((uint64_t)(x)&0x0000000000ff0000ULL) << 24U) | (((uint64_t)(x)&0x00000000ff000000ULL) << 8U) \
|
||||
| (((uint64_t)(x)&0x000000ff00000000ULL) >> 8U) | (((uint64_t)(x)&0x0000ff0000000000ULL) >> 24U) \
|
||||
| (((uint64_t)(x)&0x00ff000000000000ULL) >> 40U) | (((uint64_t)(x)&0xff00000000000000ULL) >> 56U))
|
||||
#else
|
||||
#define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)(x))
|
||||
#define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x))
|
||||
|
@ -57,8 +52,7 @@ namespace Utils {
|
|||
#define ZT_ROL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||
|
||||
#ifdef ZT_ARCH_ARM_HAS_NEON
|
||||
struct ARMCapabilities
|
||||
{
|
||||
struct ARMCapabilities {
|
||||
ARMCapabilities() noexcept;
|
||||
bool aes, crc32, pmull, sha1, sha2;
|
||||
};
|
||||
|
@ -66,8 +60,7 @@ extern const ARMCapabilities ARMCAP;
|
|||
#endif
|
||||
|
||||
#ifdef ZT_ARCH_X64
|
||||
struct CPUIDRegisters
|
||||
{
|
||||
struct CPUIDRegisters {
|
||||
CPUIDRegisters() noexcept;
|
||||
bool rdrand, aes, avx, vaes, vpclmulqdq, avx2, avx512f, sha, fsrm;
|
||||
};
|
||||
|
@ -100,7 +93,7 @@ extern const uint64_t s_mapNonce;
|
|||
* @param len Length of strings
|
||||
* @return True if strings are equal
|
||||
*/
|
||||
bool secureEq(const void *a, const void *b, unsigned int len) noexcept;
|
||||
bool secureEq(const void* a, const void* b, unsigned int len) noexcept;
|
||||
|
||||
/**
|
||||
* Be absolutely sure to zero memory
|
||||
|
@ -111,14 +104,14 @@ bool secureEq(const void *a, const void *b, unsigned int len) noexcept;
|
|||
* @param ptr Memory to zero
|
||||
* @param len Length of memory in bytes
|
||||
*/
|
||||
void burn(volatile void *ptr, unsigned int len);
|
||||
void burn(volatile void* ptr, unsigned int len);
|
||||
|
||||
/**
|
||||
* @param n Number to convert
|
||||
* @param s Buffer, at least 24 bytes in size
|
||||
* @return String containing 'n' in base 10 form
|
||||
*/
|
||||
char *decimal(unsigned long n, char s[24]) noexcept;
|
||||
char* decimal(unsigned long n, char s[24]) noexcept;
|
||||
|
||||
/**
|
||||
* Convert an unsigned integer into hex
|
||||
|
@ -127,7 +120,7 @@ char *decimal(unsigned long n, char s[24]) noexcept;
|
|||
* @param s Buffer to receive hex, must be at least (2*sizeof(i))+1 in size or overflow will occur.
|
||||
* @return Pointer to s containing hex string with trailing zero byte
|
||||
*/
|
||||
char *hex(uint64_t i, char buf[17]) noexcept;
|
||||
char* hex(uint64_t i, char buf[17]) noexcept;
|
||||
|
||||
/**
|
||||
* Decode an unsigned integer in hex format
|
||||
|
@ -135,7 +128,7 @@ char *hex(uint64_t i, char buf[17]) noexcept;
|
|||
* @param s String to decode, non-hex chars are ignored
|
||||
* @return Unsigned integer
|
||||
*/
|
||||
uint64_t unhex(const char *s) noexcept;
|
||||
uint64_t unhex(const char* s) noexcept;
|
||||
|
||||
/**
|
||||
* Convert a byte array into hex
|
||||
|
@ -145,7 +138,7 @@ uint64_t unhex(const char *s) noexcept;
|
|||
* @param s String buffer, must be at least (l*2)+1 in size or overflow will occur
|
||||
* @return Pointer to filled string buffer
|
||||
*/
|
||||
char *hex(const void *d, unsigned int l, char *s) noexcept;
|
||||
char* hex(const void* d, unsigned int l, char* s) noexcept;
|
||||
|
||||
/**
|
||||
* Decode a hex string
|
||||
|
@ -156,7 +149,7 @@ char *hex(const void *d, unsigned int l, char *s) noexcept;
|
|||
* @param buflen Length of output buffer
|
||||
* @return Number of written bytes
|
||||
*/
|
||||
unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buflen) noexcept;
|
||||
unsigned int unhex(const char* h, unsigned int hlen, void* buf, unsigned int buflen) noexcept;
|
||||
|
||||
/**
|
||||
* Generate secure random bytes
|
||||
|
@ -167,7 +160,7 @@ unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buf
|
|||
* @param buf Buffer to fill
|
||||
* @param bytes Number of random bytes to generate
|
||||
*/
|
||||
void getSecureRandom(void *buf, unsigned int bytes) noexcept;
|
||||
void getSecureRandom(void* buf, unsigned int bytes) noexcept;
|
||||
|
||||
/**
|
||||
* @return Secure random 64-bit integer
|
||||
|
@ -183,7 +176,7 @@ uint64_t getSecureRandomU64() noexcept;
|
|||
* @param bufSize Size of result buffer
|
||||
* @return Number of bytes written
|
||||
*/
|
||||
int b32e(const uint8_t *data, int length, char *result, int bufSize) noexcept;
|
||||
int b32e(const uint8_t* data, int length, char* result, int bufSize) noexcept;
|
||||
|
||||
/**
|
||||
* Decode base32 string
|
||||
|
@ -193,7 +186,7 @@ int b32e(const uint8_t *data, int length, char *result, int bufSize) noexcept;
|
|||
* @param bufSize Size of result buffer
|
||||
* @return Number of bytes written or -1 on error
|
||||
*/
|
||||
int b32d(const char *encoded, uint8_t *result, int bufSize) noexcept;
|
||||
int b32d(const char* encoded, uint8_t* result, int bufSize) noexcept;
|
||||
|
||||
/**
|
||||
* Get a non-cryptographic random integer.
|
||||
|
@ -215,15 +208,15 @@ uint64_t random() noexcept;
|
|||
* @param src Source string (if NULL, dest will receive a zero-length string and true is returned)
|
||||
* @return True on success, false on overflow (buffer will still be 0-terminated)
|
||||
*/
|
||||
bool scopy(char *dest, unsigned int len, const char *src) noexcept;
|
||||
bool scopy(char* dest, unsigned int len, const char* src) noexcept;
|
||||
|
||||
/**
|
||||
* Check if a buffer's contents are all zero
|
||||
*/
|
||||
static ZT_INLINE bool allZero(const void *const b, const unsigned int l) noexcept
|
||||
static ZT_INLINE bool allZero(const void* const b, const unsigned int l) noexcept
|
||||
{
|
||||
for (unsigned int i=0;i<l;++i) {
|
||||
if (reinterpret_cast<const uint8_t *>(b)[i] != 0)
|
||||
for (unsigned int i = 0; i < l; ++i) {
|
||||
if (reinterpret_cast<const uint8_t*>(b)[i] != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -237,7 +230,7 @@ static ZT_INLINE bool allZero(const void *const b, const unsigned int l) noexcep
|
|||
* @param saveptr Pointer to pointer where function can save state
|
||||
* @return Next token or NULL if none
|
||||
*/
|
||||
static ZT_INLINE char *stok(char *str, const char *delim, char **saveptr) noexcept
|
||||
static ZT_INLINE char* stok(char* str, const char* delim, char** saveptr) noexcept
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
return strtok_s(str, delim, saveptr);
|
||||
|
@ -246,13 +239,15 @@ static ZT_INLINE char *stok(char *str, const char *delim, char **saveptr) noexce
|
|||
#endif
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned int strToUInt(const char *s) noexcept
|
||||
{ return (unsigned int)strtoul(s, nullptr, 10); }
|
||||
static ZT_INLINE unsigned int strToUInt(const char* s) noexcept
|
||||
{
|
||||
return (unsigned int)strtoul(s, nullptr, 10);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned long long hexStrToU64(const char *s) noexcept
|
||||
static ZT_INLINE unsigned long long hexStrToU64(const char* s) noexcept
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
return (unsigned long long)_strtoui64(s,nullptr,16);
|
||||
return (unsigned long long)_strtoui64(s, nullptr, 16);
|
||||
#else
|
||||
return strtoull(s, nullptr, 16);
|
||||
#endif
|
||||
|
@ -261,26 +256,33 @@ static ZT_INLINE unsigned long long hexStrToU64(const char *s) noexcept
|
|||
#ifdef __GNUC__
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint8_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcount((unsigned int)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcount((unsigned int)v);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint16_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcount((unsigned int)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcount((unsigned int)v);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint32_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcountl((unsigned long)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcountl((unsigned long)v);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint64_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcountll((unsigned long long)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcountll((unsigned long long)v);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename T>
|
||||
static ZT_INLINE unsigned int countBits(T v) noexcept
|
||||
template <typename T> static ZT_INLINE unsigned int countBits(T v) noexcept
|
||||
{
|
||||
v = v - ((v >> 1) & (T)~(T)0/3);
|
||||
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);
|
||||
v = (v + (v >> 4)) & (T)~(T)0/255*15;
|
||||
return (unsigned int)((v * ((~((T)0))/((T)255))) >> ((sizeof(T) - 1) * 8));
|
||||
v = v - ((v >> 1) & (T) ~(T)0 / 3);
|
||||
v = (v & (T) ~(T)0 / 15 * 3) + ((v >> 2) & (T) ~(T)0 / 15 * 3);
|
||||
v = (v + (v >> 4)) & (T) ~(T)0 / 255 * 15;
|
||||
return (unsigned int)((v * ((~((T)0)) / ((T)255))) >> ((sizeof(T) - 1) * 8));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -300,15 +302,9 @@ static ZT_INLINE uint64_t swapBytes(const uint64_t n) noexcept
|
|||
return (uint64_t)_byteswap_uint64((unsigned __int64)n);
|
||||
#else
|
||||
return (
|
||||
((n & 0x00000000000000ffULL) << 56) |
|
||||
((n & 0x000000000000ff00ULL) << 40) |
|
||||
((n & 0x0000000000ff0000ULL) << 24) |
|
||||
((n & 0x00000000ff000000ULL) << 8) |
|
||||
((n & 0x000000ff00000000ULL) >> 8) |
|
||||
((n & 0x0000ff0000000000ULL) >> 24) |
|
||||
((n & 0x00ff000000000000ULL) >> 40) |
|
||||
((n & 0xff00000000000000ULL) >> 56)
|
||||
);
|
||||
((n & 0x00000000000000ffULL) << 56) | ((n & 0x000000000000ff00ULL) << 40) | ((n & 0x0000000000ff0000ULL) << 24)
|
||||
| ((n & 0x00000000ff000000ULL) << 8) | ((n & 0x000000ff00000000ULL) >> 8) | ((n & 0x0000ff0000000000ULL) >> 24)
|
||||
| ((n & 0x00ff000000000000ULL) >> 40) | ((n & 0xff00000000000000ULL) >> 56));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -353,109 +349,108 @@ static ZT_INLINE uint16_t swapBytes(const uint16_t n) noexcept
|
|||
|
||||
// These are helper adapters to load and swap integer types special cased by size
|
||||
// to work with all typedef'd variants, signed/unsigned, etc.
|
||||
template< typename I, unsigned int S >
|
||||
class _swap_bytes_bysize;
|
||||
template <typename I, unsigned int S> class _swap_bytes_bysize;
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 1 >
|
||||
{
|
||||
public:
|
||||
template <typename I> class _swap_bytes_bysize<I, 1> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return n; }
|
||||
{
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 2 >
|
||||
{
|
||||
public:
|
||||
template <typename I> class _swap_bytes_bysize<I, 2> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return (I)swapBytes((uint16_t)n); }
|
||||
{
|
||||
return (I)swapBytes((uint16_t)n);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 4 >
|
||||
{
|
||||
public:
|
||||
template <typename I> class _swap_bytes_bysize<I, 4> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return (I)swapBytes((uint32_t)n); }
|
||||
{
|
||||
return (I)swapBytes((uint32_t)n);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 8 >
|
||||
{
|
||||
public:
|
||||
template <typename I> class _swap_bytes_bysize<I, 8> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return (I)swapBytes((uint64_t)n); }
|
||||
{
|
||||
return (I)swapBytes((uint64_t)n);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I, unsigned int S >
|
||||
class _load_be_bysize;
|
||||
template <typename I, unsigned int S> class _load_be_bysize;
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 1 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return p[0]; }
|
||||
template <typename I> class _load_be_bysize<I, 1> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return p[0];
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 2 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]); }
|
||||
template <typename I> class _load_be_bysize<I, 2> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 4 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]); }
|
||||
template <typename I> class _load_be_bysize<I, 4> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 8 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return (I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]); }
|
||||
template <typename I> class _load_be_bysize<I, 8> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return (
|
||||
I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I, unsigned int S >
|
||||
class _load_le_bysize;
|
||||
template <typename I, unsigned int S> class _load_le_bysize;
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 1 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return p[0]; }
|
||||
template <typename I> class _load_le_bysize<I, 1> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return p[0];
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 2 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U)); }
|
||||
template <typename I> class _load_le_bysize<I, 2> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U));
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 4 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U)); }
|
||||
template <typename I> class _load_le_bysize<I, 4> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U));
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 8 >
|
||||
{
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t *const p) noexcept
|
||||
{ return (I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U); }
|
||||
template <typename I> class _load_le_bysize<I, 8> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{
|
||||
return (
|
||||
I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -465,11 +460,10 @@ public:
|
|||
* @param n Value to convert
|
||||
* @return Value in big-endian order
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I hton(const I n) noexcept
|
||||
template <typename I> static ZT_INLINE I hton(const I n) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return _swap_bytes_bysize< I, sizeof(I) >::s(n);
|
||||
return _swap_bytes_bysize<I, sizeof(I)>::s(n);
|
||||
#else
|
||||
return n;
|
||||
#endif
|
||||
|
@ -482,11 +476,10 @@ static ZT_INLINE I hton(const I n) noexcept
|
|||
* @param n Value to convert
|
||||
* @return Value in host byte order
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I ntoh(const I n) noexcept
|
||||
template <typename I> static ZT_INLINE I ntoh(const I n) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return _swap_bytes_bysize< I, sizeof(I) >::s(n);
|
||||
return _swap_bytes_bysize<I, sizeof(I)>::s(n);
|
||||
#else
|
||||
return n;
|
||||
#endif
|
||||
|
@ -499,16 +492,15 @@ static ZT_INLINE I ntoh(const I n) noexcept
|
|||
* @param p Byte stream, must be at least sizeof(I) in size
|
||||
* @return Loaded raw integer
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I loadMachineEndian(const void *const restrict p) noexcept
|
||||
template <typename I> static ZT_INLINE I loadMachineEndian(const void* const restrict p) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
I tmp;
|
||||
for(int i=0;i<(int)sizeof(I);++i)
|
||||
reinterpret_cast<uint8_t *>(&tmp)[i] = reinterpret_cast<const uint8_t *>(p)[i];
|
||||
for (int i = 0; i < (int)sizeof(I); ++i)
|
||||
reinterpret_cast<uint8_t*>(&tmp)[i] = reinterpret_cast<const uint8_t*>(p)[i];
|
||||
return tmp;
|
||||
#else
|
||||
return *reinterpret_cast<const I *>(p);
|
||||
return *reinterpret_cast<const I*>(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -519,14 +511,13 @@ static ZT_INLINE I loadMachineEndian(const void *const restrict p) noexcept
|
|||
* @param p Byte array (must be at least sizeof(I))
|
||||
* @param i Integer to store
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE void storeMachineEndian(void *const restrict p, const I i) noexcept
|
||||
template <typename I> static ZT_INLINE void storeMachineEndian(void* const restrict p, const I i) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
for(unsigned int k=0;k<sizeof(I);++k)
|
||||
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
|
||||
for (unsigned int k = 0; k < sizeof(I); ++k)
|
||||
reinterpret_cast<uint8_t*>(p)[k] = reinterpret_cast<const uint8_t*>(&i)[k];
|
||||
#else
|
||||
*reinterpret_cast<I *>(p) = i;
|
||||
*reinterpret_cast<I*>(p) = i;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -537,13 +528,12 @@ static ZT_INLINE void storeMachineEndian(void *const restrict p, const I i) noex
|
|||
* @param p Byte stream, must be at least sizeof(I) in size
|
||||
* @return Decoded integer
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I loadBigEndian(const void *const restrict p) noexcept
|
||||
template <typename I> static ZT_INLINE I loadBigEndian(const void* const restrict p) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return _load_be_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p));
|
||||
return _load_be_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
|
||||
#else
|
||||
return ntoh(*reinterpret_cast<const I *>(p));
|
||||
return ntoh(*reinterpret_cast<const I*>(p));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -554,13 +544,12 @@ static ZT_INLINE I loadBigEndian(const void *const restrict p) noexcept
|
|||
* @param p Byte stream to write (must be at least sizeof(I))
|
||||
* #param i Integer to write
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE void storeBigEndian(void *const restrict p, I i) noexcept
|
||||
template <typename I> static ZT_INLINE void storeBigEndian(void* const restrict p, I i) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
storeMachineEndian(p,hton(i));
|
||||
storeMachineEndian(p, hton(i));
|
||||
#else
|
||||
*reinterpret_cast<I *>(p) = hton(i);
|
||||
*reinterpret_cast<I*>(p) = hton(i);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -571,13 +560,12 @@ static ZT_INLINE void storeBigEndian(void *const restrict p, I i) noexcept
|
|||
* @param p Byte stream, must be at least sizeof(I) in size
|
||||
* @return Decoded integer
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I loadLittleEndian(const void *const restrict p) noexcept
|
||||
template <typename I> static ZT_INLINE I loadLittleEndian(const void* const restrict p) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
|
||||
return _load_le_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p));
|
||||
return _load_le_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
|
||||
#else
|
||||
return *reinterpret_cast<const I *>(p);
|
||||
return *reinterpret_cast<const I*>(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -588,16 +576,15 @@ static ZT_INLINE I loadLittleEndian(const void *const restrict p) noexcept
|
|||
* @param p Byte stream to write (must be at least sizeof(I))
|
||||
* #param i Integer to write
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE void storeLittleEndian(void *const restrict p, const I i) noexcept
|
||||
template <typename I> static ZT_INLINE void storeLittleEndian(void* const restrict p, const I i) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
storeMachineEndian(p,_swap_bytes_bysize<I,sizeof(I)>::s(i));
|
||||
storeMachineEndian(p, _swap_bytes_bysize<I, sizeof(I)>::s(i));
|
||||
#else
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
storeMachineEndian(p,i);
|
||||
storeMachineEndian(p, i);
|
||||
#else
|
||||
*reinterpret_cast<I *>(p) = i;
|
||||
*reinterpret_cast<I*>(p) = i;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -609,12 +596,11 @@ static ZT_INLINE void storeLittleEndian(void *const restrict p, const I i) noexc
|
|||
* @param dest Destination memory
|
||||
* @param src Source memory
|
||||
*/
|
||||
template< unsigned long L >
|
||||
static ZT_INLINE void copy(void *dest, const void *src) noexcept
|
||||
template <unsigned long L> static ZT_INLINE void copy(void* dest, const void* src) noexcept
|
||||
{
|
||||
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||
uintptr_t l = L;
|
||||
__asm__ __volatile__ ("cld ; rep movsb" : "+c"(l), "+S"(src), "+D"(dest) :: "memory");
|
||||
__asm__ __volatile__("cld ; rep movsb" : "+c"(l), "+S"(src), "+D"(dest)::"memory");
|
||||
#else
|
||||
memcpy(dest, src, L);
|
||||
#endif
|
||||
|
@ -627,10 +613,10 @@ static ZT_INLINE void copy(void *dest, const void *src) noexcept
|
|||
* @param src Source memory
|
||||
* @param len Bytes to copy
|
||||
*/
|
||||
static ZT_INLINE void copy(void *dest, const void *src, unsigned long len) noexcept
|
||||
static ZT_INLINE void copy(void* dest, const void* src, unsigned long len) noexcept
|
||||
{
|
||||
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||
__asm__ __volatile__ ("cld ; rep movsb" : "+c"(len), "+S"(src), "+D"(dest) :: "memory");
|
||||
__asm__ __volatile__("cld ; rep movsb" : "+c"(len), "+S"(src), "+D"(dest)::"memory");
|
||||
#else
|
||||
memcpy(dest, src, len);
|
||||
#endif
|
||||
|
@ -642,12 +628,11 @@ static ZT_INLINE void copy(void *dest, const void *src, unsigned long len) noexc
|
|||
* @tparam L Size in bytes
|
||||
* @param dest Memory to zero
|
||||
*/
|
||||
template< unsigned long L >
|
||||
static ZT_INLINE void zero(void *dest) noexcept
|
||||
template <unsigned long L> static ZT_INLINE void zero(void* dest) noexcept
|
||||
{
|
||||
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||
uintptr_t l = L;
|
||||
__asm__ __volatile__ ("cld ; rep stosb" :"+c" (l), "+D" (dest) : "a" (0) : "memory");
|
||||
__asm__ __volatile__("cld ; rep stosb" : "+c"(l), "+D"(dest) : "a"(0) : "memory");
|
||||
#else
|
||||
memset(dest, 0, L);
|
||||
#endif
|
||||
|
@ -659,10 +644,10 @@ static ZT_INLINE void zero(void *dest) noexcept
|
|||
* @param dest Memory to zero
|
||||
* @param len Size in bytes
|
||||
*/
|
||||
static ZT_INLINE void zero(void *dest, unsigned long len) noexcept
|
||||
static ZT_INLINE void zero(void* dest, unsigned long len) noexcept
|
||||
{
|
||||
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||
__asm__ __volatile__ ("cld ; rep stosb" :"+c" (len), "+D" (dest) : "a" (0) : "memory");
|
||||
__asm__ __volatile__("cld ; rep stosb" : "+c"(len), "+D"(dest) : "a"(0) : "memory");
|
||||
#else
|
||||
memset(dest, 0, len);
|
||||
#endif
|
||||
|
@ -677,7 +662,7 @@ static ZT_INLINE void zero(void *dest, unsigned long len) noexcept
|
|||
* @param len Length of data
|
||||
* @return FNV1a checksum
|
||||
*/
|
||||
uint32_t fnv1a32(const void *restrict data, unsigned int len) noexcept;
|
||||
uint32_t fnv1a32(const void* restrict data, unsigned int len) noexcept;
|
||||
|
||||
/**
|
||||
* Mix bits in a 64-bit integer (non-cryptographic, for hash tables)
|
||||
|
|
663
core/VL1.cpp
663
core/VL1.cpp
File diff suppressed because it is too large
Load diff
124
core/VL1.hpp
124
core/VL1.hpp
|
@ -14,15 +14,15 @@
|
|||
#ifndef ZT_VL1_HPP
|
||||
#define ZT_VL1_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Defragmenter.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Defragmenter.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Protocol.hpp"
|
||||
|
||||
#define ZT_VL1_MAX_WHOIS_WAITING_PACKETS 32
|
||||
|
||||
|
@ -43,10 +43,9 @@ class VL2;
|
|||
*
|
||||
* This class is thread safe.
|
||||
*/
|
||||
class VL1
|
||||
{
|
||||
public:
|
||||
explicit VL1(const Context &ctx);
|
||||
class VL1 {
|
||||
public:
|
||||
explicit VL1(const Context& ctx);
|
||||
|
||||
/**
|
||||
* Called when a packet is received from the real network
|
||||
|
@ -62,40 +61,103 @@ public:
|
|||
* @param data Packet data
|
||||
* @param len Packet length
|
||||
*/
|
||||
void onRemotePacket(CallContext &cc, int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, unsigned int len) noexcept;
|
||||
void onRemotePacket(
|
||||
CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& fromAddr,
|
||||
SharedPtr<Buf>& data,
|
||||
unsigned int len) noexcept;
|
||||
|
||||
private:
|
||||
void m_relay(CallContext &cc, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize);
|
||||
void m_sendPendingWhois(CallContext &cc);
|
||||
SharedPtr< Peer > m_HELLO(CallContext &cc, const SharedPtr< Path > &path, Buf &pkt, int packetSize);
|
||||
bool m_ERROR(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb);
|
||||
bool m_OK(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb);
|
||||
bool m_WHOIS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_RENDEZVOUS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_ECHO(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_PUSH_DIRECT_PATHS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_USER_MESSAGE(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_ENCAP(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
private:
|
||||
void m_relay(CallContext& cc, const SharedPtr<Path>& path, Address destination, SharedPtr<Buf>& pkt, int pktSize);
|
||||
void m_sendPendingWhois(CallContext& cc);
|
||||
SharedPtr<Peer> m_HELLO(CallContext& cc, const SharedPtr<Path>& path, Buf& pkt, int packetSize);
|
||||
bool m_ERROR(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize,
|
||||
Protocol::Verb& inReVerb);
|
||||
bool m_OK(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize,
|
||||
Protocol::Verb& inReVerb);
|
||||
bool m_WHOIS(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_RENDEZVOUS(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_ECHO(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_PUSH_DIRECT_PATHS(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_USER_MESSAGE(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_ENCAP(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
|
||||
const Context &m_ctx;
|
||||
const Context& m_ctx;
|
||||
|
||||
// Defragmentation engine for handling inbound packets with more than one fragment.
|
||||
Defragmenter< ZT_MAX_PACKET_FRAGMENTS > m_inputPacketAssembler;
|
||||
Defragmenter<ZT_MAX_PACKET_FRAGMENTS> m_inputPacketAssembler;
|
||||
|
||||
// Queue of outbound WHOIS reqeusts and packets waiting on them.
|
||||
struct p_WhoisQueueItem
|
||||
{
|
||||
struct p_WhoisQueueItem {
|
||||
ZT_INLINE p_WhoisQueueItem() : lastRetry(0), retries(0), waitingPacketCount(0)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
int64_t lastRetry;
|
||||
unsigned int retries;
|
||||
unsigned int waitingPacketCount;
|
||||
unsigned int waitingPacketSize[ZT_VL1_MAX_WHOIS_WAITING_PACKETS];
|
||||
SharedPtr< Buf > waitingPacket[ZT_VL1_MAX_WHOIS_WAITING_PACKETS];
|
||||
SharedPtr<Buf> waitingPacket[ZT_VL1_MAX_WHOIS_WAITING_PACKETS];
|
||||
};
|
||||
|
||||
Map< Address, p_WhoisQueueItem > m_whoisQueue;
|
||||
Map<Address, p_WhoisQueueItem> m_whoisQueue;
|
||||
Mutex m_whoisQueue_l;
|
||||
};
|
||||
|
||||
|
|
105
core/VL2.cpp
105
core/VL2.cpp
|
@ -12,58 +12,129 @@
|
|||
/****/
|
||||
|
||||
#include "VL2.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "VL1.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "VL1.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
VL2::VL2(const Context &ctx):
|
||||
m_ctx(ctx)
|
||||
VL2::VL2(const Context& ctx) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void VL2::onLocalEthernet(CallContext &cc, const SharedPtr< Network > &network, const MAC &from, const MAC &to, const unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len)
|
||||
void VL2::onLocalEthernet(
|
||||
CallContext& cc,
|
||||
const SharedPtr<Network>& network,
|
||||
const MAC& from,
|
||||
const MAC& to,
|
||||
const unsigned int etherType,
|
||||
unsigned int vlanId,
|
||||
SharedPtr<Buf>& data,
|
||||
unsigned int len)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_FRAME(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_EXT_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_EXT_FRAME(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST_LIKE(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST_LIKE(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_NETWORK_CREDENTIALS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_NETWORK_CREDENTIALS(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_NETWORK_CONFIG_REQUEST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_NETWORK_CONFIG_REQUEST(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_NETWORK_CONFIG(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_NETWORK_CONFIG(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST_GATHER(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST_GATHER(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST_FRAME_deprecated(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST_FRAME_deprecated(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue