mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
A bunch of compile fixes, and an edge case fix in Dictionary.
This commit is contained in:
parent
53b85a2bbb
commit
3f4809457f
10 changed files with 293 additions and 303 deletions
29
core/AES.cpp
29
core/AES.cpp
|
@ -512,7 +512,9 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
|
|||
|
||||
#ifdef ZT_AES_AESNI
|
||||
|
||||
#if !defined(__WINDOWS__)
|
||||
// Disable VAES stuff on compilers too old to compile these intrinsics,
|
||||
// and MinGW64 also seems not to support them so disable on Windows.
|
||||
#if !defined(__WINDOWS__) && ((__GNUC__ >= 8) || (__clang_major__ >= 7))
|
||||
|
||||
#define ZT_AES_VAES512
|
||||
static
|
||||
|
@ -793,19 +795,34 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
_len = totalLen + len;
|
||||
|
||||
if (likely(len >= 64)) {
|
||||
|
||||
// Compiler supports both AVX256 VAES and AVX512 VAES
|
||||
#if defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
|
||||
if (Utils::CPUID.vaes) {
|
||||
if ((!Utils::CPUID.avx512f) || ((len < 1024))) {
|
||||
if ((!Utils::CPUID.avx512f) || (len < 512)) {
|
||||
p_aesCtrInnerVAES256(len, c0, c1, in, out, k);
|
||||
} else {
|
||||
p_aesCtrInnerVAES512(len, c0, c1, in, out, k);
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
p_aesCtrInner128(len, c0, c1, in, out, k);
|
||||
#if defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compiler only supports AVX256 VAES
|
||||
#if !defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
|
||||
if (Utils::CPUID.vaes) {
|
||||
p_aesCtrInnerVAES256(len, c0, c1, in, out, k);
|
||||
} else {
|
||||
p_aesCtrInner128(len, c0, c1, in, out, k);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compiler only support conventional AES-NI
|
||||
#if !defined(ZT_AES_VAES512) && !defined(ZT_AES_VAES256)
|
||||
p_aesCtrInner128(len, c0, c1, in, out, k);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
|
@ -1194,7 +1211,7 @@ void AES::_decryptSW(const uint8_t in[16], uint8_t out[16]) const noexcept
|
|||
|
||||
#ifdef ZT_AES_AESNI
|
||||
|
||||
static ZT_INLINE __m128i _init256_1_aesni(__m128i a, __m128i b) noexcept
|
||||
static __m128i _init256_1_aesni(__m128i a, __m128i b) noexcept
|
||||
{
|
||||
__m128i x, y;
|
||||
b = _mm_shuffle_epi32(b, 0xff);
|
||||
|
@ -1208,7 +1225,7 @@ static ZT_INLINE __m128i _init256_1_aesni(__m128i a, __m128i b) noexcept
|
|||
return x;
|
||||
}
|
||||
|
||||
static ZT_INLINE __m128i _init256_2_aesni(__m128i a, __m128i b) noexcept
|
||||
static __m128i _init256_2_aesni(__m128i a, __m128i b) noexcept
|
||||
{
|
||||
__m128i x, y, z;
|
||||
y = _mm_aeskeygenassist_si128(a, 0x00);
|
||||
|
|
|
@ -17,35 +17,30 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
void Certificate::clear()
|
||||
Certificate::Certificate() noexcept
|
||||
{
|
||||
Utils::zero< sizeof(ZT_Certificate) >((ZT_Certificate *)this);
|
||||
|
||||
m_identities.clear();
|
||||
m_locators.clear();
|
||||
m_strings.clear();
|
||||
m_serials.clear();
|
||||
|
||||
m_subjectIdentities.clear();
|
||||
m_subjectNetworks.clear();
|
||||
m_updateUrls.clear();
|
||||
m_subjectCertificates.clear();
|
||||
m_extendedAttributes.clear();
|
||||
m_subjectUniqueId.clear();
|
||||
m_subjectUniqueIdProofSignature.clear();
|
||||
m_signature.clear();
|
||||
ZT_Certificate *const sup = this;
|
||||
Utils::zero< sizeof(ZT_Certificate) >(sup);
|
||||
}
|
||||
|
||||
Certificate &Certificate::operator=(const ZT_Certificate &apiCert)
|
||||
Certificate::Certificate(const ZT_Certificate &apiCert)
|
||||
{
|
||||
clear();
|
||||
Utils::copy< sizeof(ZT_Certificate) >((ZT_Certificate *)this, &apiCert);
|
||||
return *this;
|
||||
ZT_Certificate *const sup = this;
|
||||
Utils::copy< sizeof(ZT_Certificate) >(sup, &apiCert);
|
||||
}
|
||||
|
||||
Certificate &Certificate::operator=(const Certificate &cert)
|
||||
Certificate::Certificate(const Certificate &cert)
|
||||
{ *this = cert; }
|
||||
|
||||
Certificate::~Certificate()
|
||||
{}
|
||||
|
||||
Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
||||
{
|
||||
*this = *((const ZT_Certificate *)(&cert));
|
||||
m_clear();
|
||||
|
||||
ZT_Certificate *const sup = this;
|
||||
Utils::copy< sizeof(ZT_Certificate) >(sup, &cert);
|
||||
|
||||
// Zero these since we must explicitly attach all the objects from
|
||||
// the other certificate to copy them into our containers.
|
||||
|
@ -57,9 +52,15 @@ Certificate &Certificate::operator=(const Certificate &cert)
|
|||
this->subject.certificateCount = 0;
|
||||
this->subject.updateUrls = nullptr;
|
||||
this->subject.updateUrlCount = 0;
|
||||
this->subject.uniqueId = nullptr;
|
||||
this->subject.uniqueIdProofSignature = nullptr;
|
||||
this->subject.uniqueIdSize = 0;
|
||||
this->subject.uniqueIdProofSignatureSize = 0;
|
||||
this->extendedAttributes = nullptr;
|
||||
this->extendedAttributesSize = 0;
|
||||
this->issuer = nullptr;
|
||||
this->signature = nullptr;
|
||||
this->signatureSize = 0;
|
||||
|
||||
for (unsigned int i = 0; i < cert.subject.identityCount; ++i) {
|
||||
if (cert.subject.identities[i].identity) {
|
||||
|
@ -86,15 +87,32 @@ Certificate &Certificate::operator=(const Certificate &cert)
|
|||
}
|
||||
}
|
||||
|
||||
if ((cert.subject.uniqueId) && (cert.subject.uniqueIdSize > 0)) {
|
||||
m_subjectUniqueId.assign(cert.subject.uniqueId, cert.subject.uniqueId + cert.subject.uniqueIdSize);
|
||||
this->subject.uniqueId = m_subjectUniqueId.data();
|
||||
this->subject.uniqueIdSize = (unsigned int)m_subjectUniqueId.size();
|
||||
}
|
||||
if ((cert.subject.uniqueIdProofSignature) && (cert.subject.uniqueIdProofSignatureSize > 0)) {
|
||||
m_subjectUniqueIdProofSignature.assign(cert.subject.uniqueIdProofSignature, cert.subject.uniqueIdProofSignature + cert.subject.uniqueIdProofSignatureSize);
|
||||
this->subject.uniqueIdProofSignature = m_subjectUniqueIdProofSignature.data();
|
||||
this->subject.uniqueIdProofSignatureSize = (unsigned int)m_subjectUniqueIdProofSignature.size();
|
||||
}
|
||||
|
||||
if (cert.issuer) {
|
||||
m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
|
||||
this->issuer = &(m_identities.back());
|
||||
}
|
||||
|
||||
if ((cert.extendedAttributes) && (cert.extendedAttributesSize > 0)) {
|
||||
m_extendedAttributes.assign(cert.extendedAttributes, cert.extendedAttributes + cert.extendedAttributesSize);
|
||||
this->extendedAttributes = m_extendedAttributes.data();
|
||||
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||
}
|
||||
|
||||
if (cert.issuer) {
|
||||
m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
|
||||
this->issuer = &(m_identities.back());
|
||||
if ((cert.signature) && (cert.signatureSize > 0)) {
|
||||
m_signature.assign(cert.signature, cert.signature + cert.signatureSize);
|
||||
this->signature = m_signature.data();
|
||||
this->signatureSize = (unsigned int)m_signature.size();
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -215,7 +233,10 @@ Vector< uint8_t > Certificate::encode(const bool omitSignature) const
|
|||
if (this->issuerName.host[0])
|
||||
d.add("iN.h", this->issuerName.host);
|
||||
|
||||
if ((!omitSignature) && (this->signatureSize > 0) && (this->signatureSize <= sizeof(this->signature)))
|
||||
if ((this->extendedAttributes) && (this->extendedAttributesSize > 0))
|
||||
d["x"].assign(this->extendedAttributes, this->extendedAttributes + this->extendedAttributesSize);
|
||||
|
||||
if ((!omitSignature) && (this->signatureSize > 0) && (this->signature))
|
||||
d["si"].assign(this->signature, this->signature + this->signatureSize);
|
||||
|
||||
d.encode(enc);
|
||||
|
@ -226,7 +247,7 @@ bool Certificate::decode(const Vector< uint8_t > &data)
|
|||
{
|
||||
char tmp[256], tmp2[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||
|
||||
clear();
|
||||
m_clear();
|
||||
|
||||
Dictionary d;
|
||||
if (!d.decode(data.data(), (unsigned int)data.size()))
|
||||
|
@ -238,12 +259,6 @@ bool Certificate::decode(const Vector< uint8_t > &data)
|
|||
this->validity[1] = (int64_t)d.getUI("v#1");
|
||||
this->maxPathLength = (unsigned int)d.getUI("mP");
|
||||
|
||||
m_extendedAttributes = d["x"];
|
||||
if (!m_extendedAttributes.empty()) {
|
||||
this->extendedAttributes = m_extendedAttributes.data();
|
||||
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||
}
|
||||
|
||||
this->subject.timestamp = (int64_t)d.getUI("s.t");
|
||||
|
||||
unsigned int cnt = (unsigned int)d.getUI("s.i$");
|
||||
|
@ -343,6 +358,12 @@ bool Certificate::decode(const Vector< uint8_t > &data)
|
|||
else return false;
|
||||
}
|
||||
|
||||
m_extendedAttributes = d["x"];
|
||||
if (!m_extendedAttributes.empty()) {
|
||||
this->extendedAttributes = m_extendedAttributes.data();
|
||||
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||
}
|
||||
|
||||
m_signature = d["si"];
|
||||
if (!m_signature.empty()) {
|
||||
this->signature = m_signature.data();
|
||||
|
@ -453,9 +474,29 @@ bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQU
|
|||
return true;
|
||||
}
|
||||
|
||||
void Certificate::m_clear()
|
||||
{
|
||||
ZT_Certificate *const sup = this;
|
||||
Utils::zero< sizeof(ZT_Certificate) >(sup);
|
||||
|
||||
m_identities.clear();
|
||||
m_locators.clear();
|
||||
m_strings.clear();
|
||||
m_serials.clear();
|
||||
|
||||
m_subjectIdentities.clear();
|
||||
m_subjectNetworks.clear();
|
||||
m_updateUrls.clear();
|
||||
m_subjectCertificates.clear();
|
||||
m_extendedAttributes.clear();
|
||||
m_subjectUniqueId.clear();
|
||||
m_subjectUniqueIdProofSignature.clear();
|
||||
m_signature.clear();
|
||||
}
|
||||
|
||||
void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature)
|
||||
{
|
||||
char tmp[256];
|
||||
char tmp[64];
|
||||
|
||||
d.add("s.t", (uint64_t)s.timestamp);
|
||||
|
||||
|
|
|
@ -48,25 +48,28 @@ namespace ZeroTier {
|
|||
class Certificate : public ZT_Certificate
|
||||
{
|
||||
friend class SharedPtr< Certificate >;
|
||||
|
||||
friend class SharedPtr< const Certificate >;
|
||||
|
||||
public:
|
||||
ZT_INLINE Certificate() noexcept
|
||||
{ this->clear(); }
|
||||
Certificate() noexcept;
|
||||
|
||||
ZT_INLINE Certificate(const ZT_Certificate &apiCert)
|
||||
{ *this = apiCert; }
|
||||
Certificate(const ZT_Certificate &apiCert);
|
||||
|
||||
ZT_INLINE Certificate(const Certificate &cert)
|
||||
{ *this = cert; }
|
||||
Certificate(const Certificate &cert);
|
||||
|
||||
/**
|
||||
* Zero all fields and release all extra memory
|
||||
*/
|
||||
void clear();
|
||||
~Certificate();
|
||||
|
||||
Certificate &operator=(const ZT_Certificate &apiCert);
|
||||
Certificate &operator=(const Certificate &cert);
|
||||
Certificate &operator=(const ZT_Certificate &cert);
|
||||
|
||||
ZT_INLINE Certificate &operator=(const Certificate &cert)
|
||||
{
|
||||
if (likely(&cert != this)) {
|
||||
const ZT_Certificate *const sup = &cert;
|
||||
*this = *sup;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subject node/identity without a locator
|
||||
|
@ -186,18 +189,25 @@ public:
|
|||
|
||||
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:
|
||||
void m_clear();
|
||||
|
||||
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
|
||||
|
@ -218,7 +228,7 @@ private:
|
|||
Vector< uint8_t > m_subjectUniqueIdProofSignature;
|
||||
Vector< uint8_t > m_signature;
|
||||
|
||||
std::atomic<int> __refCount;
|
||||
std::atomic< int > __refCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -19,18 +19,17 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#ifdef __CPP11__
|
||||
#include <atomic>
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
@ -51,7 +50,7 @@ struct intl_MapHasher
|
|||
};
|
||||
|
||||
template< typename K, typename V >
|
||||
class Map : public std::unordered_map< K, V, intl_MapHasher, std::equal_to< K >, Utils::Mallocator < std::pair< const K, V > > >
|
||||
class Map : public std::unordered_map< K, V, intl_MapHasher >
|
||||
{
|
||||
public:
|
||||
ZT_INLINE V *get(const K &key) noexcept
|
||||
|
@ -72,13 +71,13 @@ public:
|
|||
};
|
||||
|
||||
template< typename K, typename V >
|
||||
class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K >, Utils::Mallocator < std::pair< const K, 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,std::less<K>,Utils::Mallocator< std::pair<const K,V> > >
|
||||
class Map : public std::map< K,V,std::less<K> >
|
||||
{
|
||||
public:
|
||||
ZT_INLINE V *get(const K &key) noexcept
|
||||
|
@ -109,55 +108,31 @@ class MultiMap : public std::multimap< K,V,std::less<K>,Utils::Mallocator< std::
|
|||
#endif
|
||||
|
||||
template< typename K, typename V >
|
||||
class SortedMap : public std::map< K, V, std::less< K >, Utils::Mallocator < std::pair< const K, V > > >
|
||||
{
|
||||
public:
|
||||
ZT_INLINE V *get(const K &key) noexcept
|
||||
{
|
||||
typename SortedMap::iterator i(this->find(key));
|
||||
if (i == this->end())
|
||||
return nullptr;
|
||||
return &(i->second);
|
||||
}
|
||||
ZT_INLINE const V *get(const K &key) const noexcept
|
||||
{
|
||||
typename SortedMap::const_iterator i(this->find(key));
|
||||
if (i == this->end())
|
||||
return nullptr;
|
||||
return &(i->second);
|
||||
}
|
||||
ZT_INLINE void set(const K &key, const V &value) { (*this)[key] = value; }
|
||||
};
|
||||
class SortedMap : public std::map< K, V >
|
||||
{};
|
||||
|
||||
template< typename V >
|
||||
class Vector : public std::vector< V, Utils::Mallocator < V > >
|
||||
class Vector : public std::vector< V >
|
||||
{
|
||||
public:
|
||||
ZT_INLINE Vector() {}
|
||||
ZT_INLINE Vector()
|
||||
{}
|
||||
|
||||
template< typename I >
|
||||
ZT_INLINE Vector(I begin,I end) : std::vector< V, Utils::Mallocator < V > >(begin,end) {}
|
||||
ZT_INLINE Vector(I begin,I end) :
|
||||
std::vector< V >(begin, end)
|
||||
{}
|
||||
};
|
||||
|
||||
template< typename V >
|
||||
class List : public std::list< V, Utils::Mallocator < V > >
|
||||
{
|
||||
};
|
||||
class List : public std::list< V >
|
||||
{};
|
||||
|
||||
template< typename V >
|
||||
class Set : public std::set< V, std::less< V >, Utils::Mallocator < V > >
|
||||
{
|
||||
};
|
||||
class Set : public std::set< V, std::less< V > >
|
||||
{};
|
||||
|
||||
class String : public std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >
|
||||
{
|
||||
public:
|
||||
ZT_INLINE String() {}
|
||||
ZT_INLINE String(const String &s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >(s.c_str()) {}
|
||||
ZT_INLINE String(const std::string &s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >(s.c_str()) {}
|
||||
ZT_INLINE String(const char *const s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >(s) {}
|
||||
ZT_INLINE String &operator=(const char *const s) { assign(s); return *this; }
|
||||
ZT_INLINE String &operator=(const std::string &s) { assign(s.c_str()); return *this; }
|
||||
};
|
||||
typedef std::string String;
|
||||
|
||||
} // ZeroTier
|
||||
|
||||
|
|
|
@ -21,23 +21,14 @@ Dictionary::Dictionary()
|
|||
Dictionary::~Dictionary()
|
||||
{}
|
||||
|
||||
Vector< uint8_t > &Dictionary::operator[](const char *k)
|
||||
{
|
||||
if (k)
|
||||
return m_entries[s_key(k)];
|
||||
else return m_entries[""];
|
||||
}
|
||||
Vector< uint8_t > &Dictionary::operator[](const char *const k)
|
||||
{ return m_entries[s_key(k)]; }
|
||||
|
||||
const Vector< uint8_t > &Dictionary::operator[](const char *k) const
|
||||
const Vector< uint8_t > &Dictionary::operator[](const char *const k) const
|
||||
{
|
||||
static const Vector< uint8_t > s_emptyEntry;
|
||||
if (k) {
|
||||
SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(s_key(k)));
|
||||
return (e == m_entries.end()) ? s_emptyEntry : e->second;
|
||||
} else {
|
||||
SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(""));
|
||||
return (e == m_entries.end()) ? s_emptyEntry : e->second;
|
||||
}
|
||||
const SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(s_key(k)));
|
||||
return (e == m_entries.end()) ? s_emptyEntry : e->second;
|
||||
}
|
||||
|
||||
void Dictionary::add(const char *k, bool v)
|
||||
|
@ -50,16 +41,16 @@ void Dictionary::add(const char *k, bool v)
|
|||
|
||||
void Dictionary::add(const char *k, const Address &v)
|
||||
{
|
||||
Vector< uint8_t > &e = (*this)[k];
|
||||
e.resize(ZT_ADDRESS_STRING_SIZE_MAX);
|
||||
v.toString((char *)e.data());
|
||||
char tmp[ZT_ADDRESS_STRING_SIZE_MAX];
|
||||
v.toString(tmp);
|
||||
add(k, tmp);
|
||||
}
|
||||
|
||||
void Dictionary::add(const char *k, const char *v)
|
||||
{
|
||||
if ((v) && (*v)) {
|
||||
Vector< uint8_t > &e = (*this)[k];
|
||||
e.clear();
|
||||
Vector< uint8_t > &e = (*this)[k];
|
||||
e.clear();
|
||||
if (v) {
|
||||
while (*v)
|
||||
e.push_back((uint8_t)*(v++));
|
||||
}
|
||||
|
@ -68,7 +59,7 @@ void Dictionary::add(const char *k, const char *v)
|
|||
void Dictionary::add(const char *k, const void *data, unsigned int len)
|
||||
{
|
||||
Vector< uint8_t > &e = (*this)[k];
|
||||
if (len != 0) {
|
||||
if (likely(len != 0)) {
|
||||
e.assign((const uint8_t *)data, (const uint8_t *)data + len);
|
||||
} else {
|
||||
e.clear();
|
||||
|
@ -150,48 +141,48 @@ bool Dictionary::decode(const void *data, unsigned int len)
|
|||
Vector< uint8_t > *v = nullptr;
|
||||
bool escape = false;
|
||||
for (unsigned int di = 0; di < len; ++di) {
|
||||
uint8_t c = reinterpret_cast<const uint8_t *>(data)[di];
|
||||
if (!c) break;
|
||||
if (v) {
|
||||
if (escape) {
|
||||
escape = false;
|
||||
switch (c) {
|
||||
case 48:
|
||||
v->push_back(0);
|
||||
break;
|
||||
case 101:
|
||||
v->push_back(61);
|
||||
break;
|
||||
case 110:
|
||||
v->push_back(10);
|
||||
break;
|
||||
case 114:
|
||||
v->push_back(13);
|
||||
break;
|
||||
default:
|
||||
v->push_back(c);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (c == (uint8_t)'\n') {
|
||||
k.clear();
|
||||
v = nullptr;
|
||||
} else if (c == 92) { // backslash
|
||||
escape = true;
|
||||
const uint8_t c = reinterpret_cast<const uint8_t *>(data)[di];
|
||||
if (c) {
|
||||
if (v) {
|
||||
if (escape) {
|
||||
escape = false;
|
||||
switch (c) {
|
||||
case 48:
|
||||
v->push_back(0);
|
||||
break;
|
||||
case 101:
|
||||
v->push_back(61);
|
||||
break;
|
||||
case 110:
|
||||
v->push_back(10);
|
||||
break;
|
||||
case 114:
|
||||
v->push_back(13);
|
||||
break;
|
||||
default:
|
||||
v->push_back(c);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
v->push_back(c);
|
||||
if (c == (uint8_t)'\n') {
|
||||
k.clear();
|
||||
v = nullptr;
|
||||
} else if (c == 92) { // backslash
|
||||
escape = true;
|
||||
} else {
|
||||
v->push_back(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (c == (uint8_t)'=') {
|
||||
v = &m_entries[k];
|
||||
} else if ((c < 33) || (c > 126) || (c == 92)) {
|
||||
return false;
|
||||
} else {
|
||||
k.push_back(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((c < 33) || (c > 126) || (c == 92)) {
|
||||
return false;
|
||||
} else if (c == (uint8_t)'=') {
|
||||
k.push_back(0);
|
||||
v = &m_entries[k];
|
||||
} else {
|
||||
k.push_back(c);
|
||||
}
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -209,4 +200,19 @@ char *Dictionary::arraySubscript(char buf[256],const char *name,const unsigned l
|
|||
return buf;
|
||||
}
|
||||
|
||||
String Dictionary::s_key(const char *k) noexcept
|
||||
{
|
||||
String buf;
|
||||
if (likely(k != nullptr)) {
|
||||
for (;;) {
|
||||
const char c = *(k++);
|
||||
if ((c >= 33) && (c <= 126) && (c != 61) && (c != 92)) // printable ASCII with no spaces, equals, or backslash
|
||||
buf.push_back(c);
|
||||
else if (c == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -268,6 +268,7 @@ public:
|
|||
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];
|
||||
Utils::hex(v, buf);
|
||||
unsigned int i = 0;
|
||||
|
@ -370,6 +371,14 @@ public:
|
|||
return mlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append #sub where sub is a hexadecimal string to 'name' and store in 'buf'
|
||||
*
|
||||
* @param buf Buffer to store subscript key
|
||||
* @param name Root name
|
||||
* @param sub Subscript index
|
||||
* @return Pointer to 'buf'
|
||||
*/
|
||||
static char *arraySubscript(char buf[256],const char *name,const unsigned long sub) noexcept;
|
||||
|
||||
private:
|
||||
|
@ -407,27 +416,16 @@ private:
|
|||
ZT_INLINE static void s_appendKey(V &out, const char *k)
|
||||
{
|
||||
for (;;) {
|
||||
char c = *(k++);
|
||||
if (c == 0)
|
||||
break;
|
||||
const char c = *(k++);
|
||||
if ((c >= 33) && (c <= 126) && (c != 61) && (c != 92)) // printable ASCII with no spaces, equals, or backslash
|
||||
out.push_back((uint8_t)c);
|
||||
else if (c == 0)
|
||||
break;
|
||||
}
|
||||
out.push_back((uint8_t)'=');
|
||||
}
|
||||
|
||||
ZT_INLINE static String s_key(const char *k) noexcept
|
||||
{
|
||||
String buf;
|
||||
for(;;) {
|
||||
char c = *(k++);
|
||||
if (c == 0)
|
||||
break;
|
||||
if ((c >= 33) && (c <= 126) && (c != 61) && (c != 92)) // printable ASCII with no spaces, equals, or backslash
|
||||
buf.push_back(c);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
static String s_key(const char *k) noexcept;
|
||||
|
||||
// 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
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
#include "Poly1305.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Locator.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -93,10 +94,8 @@ struct p_CompareLittleEndian
|
|||
};
|
||||
|
||||
// This is a simpler memory-intensive frankenhash for V1 identity generation.
|
||||
bool identityV1ProofOfWorkCriteria(const void *in, const unsigned int len)
|
||||
bool identityV1ProofOfWorkCriteria(const void *in, const unsigned int len, uint64_t *const w)
|
||||
{
|
||||
uint64_t w[ZT_IDENTITY_V1_POW_MEMORY_SIZE / 8];
|
||||
|
||||
// Fill work buffer with pseudorandom bytes using a construction that should be
|
||||
// relatively hostile to GPU acceleration. GPUs usually implement branching by
|
||||
// executing all branches and then selecting the answer, which means this
|
||||
|
@ -165,29 +164,36 @@ bool Identity::generate(const Type t)
|
|||
break;
|
||||
|
||||
case P384: {
|
||||
for (;;) {
|
||||
// Loop until we pass the PoW criteria. The nonce is only 8 bits, so generate
|
||||
// some new key material every time it wraps. The ECC384 generator is slightly
|
||||
// faster so use that one.
|
||||
m_pub[0] = 0; // zero nonce
|
||||
C25519::generateCombined(m_pub + 1, m_priv + 1);
|
||||
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
//uint64_t w[ZT_IDENTITY_V1_POW_MEMORY_SIZE / 8];
|
||||
uint64_t *const w = (uint64_t *)malloc(ZT_IDENTITY_V1_POW_MEMORY_SIZE);
|
||||
if (!w)
|
||||
return false;
|
||||
try {
|
||||
for (;;) {
|
||||
if (identityV1ProofOfWorkCriteria(m_pub, sizeof(m_pub)))
|
||||
break;
|
||||
if (++m_pub[0] == 0)
|
||||
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
}
|
||||
// Loop until we pass the PoW criteria. The nonce is only 8 bits, so generate
|
||||
// some new key material every time it wraps. The ECC384 generator is slightly
|
||||
// faster so use that one.
|
||||
m_pub[0] = 0; // zero nonce
|
||||
C25519::generateCombined(m_pub + 1, m_priv + 1);
|
||||
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
for (;;) {
|
||||
if (identityV1ProofOfWorkCriteria(m_pub, sizeof(m_pub), w))
|
||||
break;
|
||||
if (++m_pub[0] == 0)
|
||||
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
}
|
||||
|
||||
// If we passed PoW then check that the address is valid, otherwise loop
|
||||
// back around and run the whole process again.
|
||||
m_computeHash();
|
||||
const Address addr(m_fp.hash);
|
||||
if (!addr.isReserved()) {
|
||||
m_fp.address = addr;
|
||||
break;
|
||||
// If we passed PoW then check that the address is valid, otherwise loop
|
||||
// back around and run the whole process again.
|
||||
m_computeHash();
|
||||
const Address addr(m_fp.hash);
|
||||
if (!addr.isReserved()) {
|
||||
m_fp.address = addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
free(w);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -215,7 +221,12 @@ bool Identity::locallyValidate() const noexcept
|
|||
case P384: {
|
||||
if (Address(m_fp.hash) != m_fp.address)
|
||||
return false;
|
||||
return identityV1ProofOfWorkCriteria(m_pub, sizeof(m_pub));
|
||||
uint64_t *const w = (uint64_t *)malloc(ZT_IDENTITY_V1_POW_MEMORY_SIZE);
|
||||
if (!w)
|
||||
return false;
|
||||
const bool valid = identityV1ProofOfWorkCriteria(m_pub, sizeof(m_pub), w);
|
||||
free(w);
|
||||
return valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <immintrin.h>
|
||||
#include <tmmintrin.h>
|
||||
#include <mmintrin.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -283,6 +283,7 @@ static bool ZTT_deepCompareCertificates(const Certificate &a, const Certificate
|
|||
return false;
|
||||
if ((a.subject.uniqueIdProofSignature == nullptr) != (b.subject.uniqueIdProofSignature == nullptr))
|
||||
return false;
|
||||
|
||||
if ((a.subject.uniqueId != nullptr) && (a.subject.uniqueIdProofSignature != nullptr)) {
|
||||
if (
|
||||
(memcmp(a.subject.uniqueId, b.subject.uniqueId, a.subject.uniqueIdSize) != 0) ||
|
||||
|
@ -1082,10 +1083,9 @@ extern "C" const char *ZTT_crypto()
|
|||
}
|
||||
|
||||
{
|
||||
char tmp[4096];
|
||||
char tmp[256];
|
||||
|
||||
ZT_T_PRINTF("[crypto] Testing Certificate..." ZT_EOL_S);
|
||||
Certificate cert;
|
||||
|
||||
ZT_T_PRINTF(" Create test subject and issuer identities... ");
|
||||
Identity testSubjectId, testIssuerId;
|
||||
|
@ -1100,53 +1100,57 @@ extern "C" const char *ZTT_crypto()
|
|||
ZT_T_PRINTF("OK %s" ZT_EOL_S, tmp);
|
||||
|
||||
ZT_T_PRINTF(" Create and sign certificate... ");
|
||||
cert.subject.timestamp = now();
|
||||
cert.addSubjectIdentity(testSubjectId);
|
||||
cert.addSubjectNetwork(12345, testSubjectId.fingerprint());
|
||||
cert.addSubjectUpdateUrl("https://www.zerotier.com/");
|
||||
ZT_SETSTR(cert.subject.name.serialNo, "serialNo");
|
||||
ZT_SETSTR(cert.subject.name.commonName, "commonName");
|
||||
ZT_SETSTR(cert.subject.name.country, "country");
|
||||
ZT_SETSTR(cert.subject.name.organization, "organization");
|
||||
ZT_SETSTR(cert.subject.name.unit, "unit");
|
||||
ZT_SETSTR(cert.subject.name.locality, "locality");
|
||||
ZT_SETSTR(cert.subject.name.province, "province");
|
||||
ZT_SETSTR(cert.subject.name.streetAddress, "streetAddress");
|
||||
ZT_SETSTR(cert.subject.name.postalCode, "postalCode");
|
||||
ZT_SETSTR(cert.subject.name.email, "email");
|
||||
ZT_SETSTR(cert.subject.name.url, "url");
|
||||
ZT_SETSTR(cert.subject.name.host, "host");
|
||||
cert.timestamp = cert.subject.timestamp;
|
||||
cert.validity[0] = 0;
|
||||
cert.validity[1] = 9223372036854775807LL;
|
||||
Utils::copy<sizeof(ZT_Certificate_Subject)>(&cert.issuerName, &cert.subject.name);
|
||||
cert.setSubjectUniqueId(uniqueId, uniqueIdPrivate);
|
||||
cert.sign(testIssuerId);
|
||||
Vector< uint8_t > enc(cert.encode());
|
||||
SharedPtr<Certificate> cert(new Certificate());
|
||||
cert->subject.timestamp = now();
|
||||
cert->addSubjectIdentity(testSubjectId);
|
||||
cert->addSubjectNetwork(12345, testSubjectId.fingerprint());
|
||||
cert->addSubjectUpdateUrl("https://www.zerotier.com/");
|
||||
ZT_SETSTR(cert->subject.name.serialNo, "serialNo");
|
||||
ZT_SETSTR(cert->subject.name.commonName, "commonName");
|
||||
ZT_SETSTR(cert->subject.name.country, "country");
|
||||
ZT_SETSTR(cert->subject.name.organization, "organization");
|
||||
ZT_SETSTR(cert->subject.name.unit, "unit");
|
||||
ZT_SETSTR(cert->subject.name.locality, "locality");
|
||||
ZT_SETSTR(cert->subject.name.province, "province");
|
||||
ZT_SETSTR(cert->subject.name.streetAddress, "streetAddress");
|
||||
ZT_SETSTR(cert->subject.name.postalCode, "postalCode");
|
||||
ZT_SETSTR(cert->subject.name.email, "email");
|
||||
ZT_SETSTR(cert->subject.name.url, "url");
|
||||
ZT_SETSTR(cert->subject.name.host, "host");
|
||||
cert->timestamp = cert->subject.timestamp;
|
||||
cert->validity[0] = 0;
|
||||
cert->validity[1] = 9223372036854775807LL;
|
||||
Utils::copy<sizeof(ZT_Certificate_Name)>(&cert->issuerName, &cert->subject.name);
|
||||
cert->setSubjectUniqueId(uniqueId, uniqueIdPrivate);
|
||||
cert->sign(testIssuerId);
|
||||
Vector< uint8_t > enc(cert->encode());
|
||||
ZT_T_PRINTF("OK (%d bytes)" ZT_EOL_S, (int)enc.size());
|
||||
|
||||
ZT_T_PRINTF(" Testing certificate verify... ");
|
||||
if (!cert.verify()) {
|
||||
if (!cert->verify()) {
|
||||
ZT_T_PRINTF("FAILED (verify original)" ZT_EOL_S);
|
||||
return "Verify original certificate";
|
||||
}
|
||||
ZT_T_PRINTF("OK" ZT_EOL_S);
|
||||
|
||||
ZT_T_PRINTF(" Test certificate decode from marshaled format... ");
|
||||
Certificate cert2;
|
||||
if (!cert2.decode(enc)) {
|
||||
SharedPtr<Certificate> cert2(new Certificate());
|
||||
if (!cert2->decode(enc)) {
|
||||
ZT_T_PRINTF("FAILED (decode)" ZT_EOL_S);
|
||||
return "Certificate decode";
|
||||
}
|
||||
if (!ZTT_deepCompareCertificates(cert, cert2)) {
|
||||
if (!ZTT_deepCompareCertificates(*cert, *cert2)) {
|
||||
ZT_T_PRINTF("FAILED (compare decoded with original)" ZT_EOL_S);
|
||||
return "Certificate decode and compare";
|
||||
}
|
||||
if (!cert2.verify()) {
|
||||
if (!cert2->verify()) {
|
||||
ZT_T_PRINTF("FAILED (verify decoded certificate)");
|
||||
return "Verify decoded certificate";
|
||||
}
|
||||
ZT_T_PRINTF("OK" ZT_EOL_S);
|
||||
|
||||
cert.zero();
|
||||
cert2.zero();
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
ZT_T_PRINTF(ZT_EOL_S "[crypto] Unexpected exception: %s" ZT_EOL_S, e.what());
|
||||
|
|
|
@ -762,79 +762,6 @@ static ZT_INLINE void zero(void *const dest) noexcept
|
|||
static ZT_INLINE void zero(void *const dest, const unsigned long len) noexcept
|
||||
{ memset(dest, 0, len); }
|
||||
|
||||
/**
|
||||
* Simple malloc/free based C++ STL allocator.
|
||||
*
|
||||
* This is used to make sure our containers don't use weird libc++
|
||||
* allocators but instead use whatever malloc() is, which in turn
|
||||
* can be overridden by things like jemaclloc or tcmalloc.
|
||||
*
|
||||
* @tparam T Allocated type
|
||||
*/
|
||||
template< typename T >
|
||||
struct Mallocator
|
||||
{
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template< class U >
|
||||
struct rebind
|
||||
{
|
||||
typedef Mallocator< U > other;
|
||||
};
|
||||
ZT_INLINE Mallocator() noexcept
|
||||
{}
|
||||
|
||||
ZT_INLINE Mallocator(const Mallocator &) noexcept
|
||||
{}
|
||||
|
||||
template< class U >
|
||||
ZT_INLINE Mallocator(const Mallocator< U > &) noexcept
|
||||
{}
|
||||
|
||||
ZT_INLINE ~Mallocator() noexcept
|
||||
{}
|
||||
|
||||
ZT_INLINE pointer allocate(size_type s, void const * = nullptr)
|
||||
{
|
||||
if (0 == s)
|
||||
return nullptr;
|
||||
pointer temp = (pointer)malloc(s * sizeof(T));
|
||||
if (temp == nullptr)
|
||||
throw BadAllocException;
|
||||
return temp;
|
||||
}
|
||||
|
||||
ZT_INLINE pointer address(reference x) const
|
||||
{ return &x; }
|
||||
|
||||
ZT_INLINE const_pointer address(const_reference x) const
|
||||
{ return &x; }
|
||||
|
||||
ZT_INLINE void deallocate(pointer p, size_type)
|
||||
{ free(p); }
|
||||
|
||||
ZT_INLINE size_type max_size() const noexcept
|
||||
{ return std::numeric_limits< size_t >::max() / sizeof(T); }
|
||||
|
||||
ZT_INLINE void construct(pointer p, const T &val)
|
||||
{ new((void *)p) T(val); }
|
||||
|
||||
ZT_INLINE void destroy(pointer p)
|
||||
{ p->~T(); }
|
||||
|
||||
constexpr bool operator==(const Mallocator &) const noexcept
|
||||
{ return true; }
|
||||
|
||||
constexpr bool operator!=(const Mallocator &) const noexcept
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
Loading…
Add table
Reference in a new issue