A bunch of compile fixes, and an edge case fix in Dictionary.

This commit is contained in:
Adam Ierymenko 2020-06-30 20:31:41 -07:00
parent 53b85a2bbb
commit 3f4809457f
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
10 changed files with 293 additions and 303 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -110,6 +110,7 @@
#include <xmmintrin.h>
#include <emmintrin.h>
#include <immintrin.h>
#include <tmmintrin.h>
#include <mmintrin.h>
#endif

View file

@ -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());

View file

@ -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