diff --git a/core/Blob.hpp b/core/Blob.hpp index 77874e52f..72d41d9aa 100644 --- a/core/Blob.hpp +++ b/core/Blob.hpp @@ -32,6 +32,9 @@ struct Blob ZT_INLINE Blob() noexcept { Utils::zero(data); } explicit ZT_INLINE Blob(const void *const d) noexcept { Utils::copy(data,d); } + ZT_INLINE unsigned long hashCode() const noexcept + { return (unsigned long)Utils::fnv1a32(data, S); } + ZT_INLINE operator bool() const noexcept { return !Utils::allZero(data); } ZT_INLINE bool operator==(const Blob &b) const noexcept { return (memcmp(data,b.data,S) == 0); } diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 4a58379db..51566c922 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -14,6 +14,7 @@ set(core_headers C25519.hpp CapabilityCredential.hpp Certificate.hpp + Defaults.hpp MembershipCredential.hpp OwnershipCredential.hpp Constants.hpp @@ -64,6 +65,7 @@ set(core_src C25519.cpp CapabilityCredential.cpp Certificate.cpp + Defaults.cpp MembershipCredential.cpp OwnershipCredential.cpp Credential.cpp diff --git a/core/Certificate.cpp b/core/Certificate.cpp index 93c137f2f..035cd50a5 100644 --- a/core/Certificate.cpp +++ b/core/Certificate.cpp @@ -152,7 +152,6 @@ void Certificate::addUpdateUrl(const char *url) Vector< uint8_t > Certificate::encode(const bool omitSignature) const { - char tmp[256]; Vector< uint8_t > enc; Dictionary d; diff --git a/core/Certificate.hpp b/core/Certificate.hpp index 358c6549a..4317e6e90 100644 --- a/core/Certificate.hpp +++ b/core/Certificate.hpp @@ -47,6 +47,9 @@ namespace ZeroTier { */ class Certificate : public ZT_Certificate { + friend class SharedPtr< Certificate >; + friend class SharedPtr< const Certificate >; + public: ZT_INLINE Certificate() noexcept { this->clear(); } @@ -174,6 +177,8 @@ private: Vector< ZT_Certificate_Network > m_subjectNetworks; Vector< const uint8_t * > m_subjectCertificates; Vector< const char * > m_updateUrls; + + std::atomic __refCount; }; } // namespace ZeroTier diff --git a/core/Defaults.cpp b/core/Defaults.cpp new file mode 100644 index 000000000..b47d1a50d --- /dev/null +++ b/core/Defaults.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c)2013-2020 ZeroTier, Inc. + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. + * + * Change Date: 2024-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2.0 of the Apache License. + */ +/****/ + +#include "Defaults.hpp" + +namespace ZeroTier { +} // namespace ZeroTier diff --git a/core/Defaults.hpp b/core/Defaults.hpp new file mode 100644 index 000000000..51d89c864 --- /dev/null +++ b/core/Defaults.hpp @@ -0,0 +1,21 @@ +/* + * Copyright (c)2013-2020 ZeroTier, Inc. + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. + * + * Change Date: 2024-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2.0 of the Apache License. + */ +/****/ + +#ifndef ZT_DEFAULTS_HPP +#define ZT_DEFAULTS_HPP + +namespace ZeroTier { + +} // namespace ZeroTier + +#endif diff --git a/core/SharedPtr.hpp b/core/SharedPtr.hpp index 79ac9b181..07e1d017c 100644 --- a/core/SharedPtr.hpp +++ b/core/SharedPtr.hpp @@ -177,6 +177,9 @@ public: return 0; } + ZT_INLINE unsigned long hashCode() const noexcept + { return (unsigned long)Utils::hash64((uint64_t)((uintptr_t)m_ptr)); } + ZT_INLINE bool operator==(const SharedPtr &sp) const noexcept { return (m_ptr == sp.m_ptr); } diff --git a/core/Topology.cpp b/core/Topology.cpp index 187b37dbc..028ef3d4b 100644 --- a/core/Topology.cpp +++ b/core/Topology.cpp @@ -431,8 +431,7 @@ void Topology::m_updateRootPeers_l_roots_certs(void *tPtr) // Populate m_roots from certificate subject identities from certificates flagged // as local root set certificates. - for (Map< FCV< uint8_t, ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE >, std::pair< SharedPtr< const Certificate >, unsigned int > >::const_iterator c(m_certsBySubjectUniqueId.begin()); c != m_certsBySubjectUniqueId.end(); - ++c) { + for (SortedMap< FCV< uint8_t, ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE >, std::pair< SharedPtr< const Certificate >, unsigned int > >::const_iterator c(m_certsBySubjectUniqueId.begin()); c != m_certsBySubjectUniqueId.end(); ++c) { if ((c->second.second & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ZEROTIER_ROOT_SET) != 0) { for (unsigned int i = 0; i < c->second.first->subject.identityCount; ++i) m_roots[*reinterpret_cast(c->second.first->subject.identities[i].identity)].insert(c->second.first); diff --git a/core/Topology.hpp b/core/Topology.hpp index 0be320f34..eb40c616f 100644 --- a/core/Topology.hpp +++ b/core/Topology.hpp @@ -273,7 +273,7 @@ private: Map< SHA384Hash, std::pair< SharedPtr< const Certificate >, unsigned int > > m_certs; Map< Fingerprint, Map< SharedPtr< const Certificate >, unsigned int > > m_certsBySubjectIdentity; - Map< FCV< uint8_t, ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE >, std::pair< SharedPtr< const Certificate >, unsigned int > > m_certsBySubjectUniqueId; + SortedMap< FCV< uint8_t, ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE >, std::pair< SharedPtr< const Certificate >, unsigned int > > m_certsBySubjectUniqueId; }; } // namespace ZeroTier diff --git a/core/Utils.hpp b/core/Utils.hpp index 973b002f4..d1c238cde 100644 --- a/core/Utils.hpp +++ b/core/Utils.hpp @@ -55,9 +55,11 @@ namespace Utils { #define ZT_ROL32(x, r) (((x) << (r)) | ((x) >> (32 - (r)))) #ifdef ZT_ARCH_X64 + struct CPUIDRegisters { CPUIDRegisters() noexcept; + bool rdrand; bool aes; bool avx; @@ -68,6 +70,7 @@ struct CPUIDRegisters bool sha; bool fsrm; }; + extern const CPUIDRegisters CPUID; #endif @@ -772,45 +775,7 @@ static ZT_INLINE void copy(void *const dest, const void *const src, unsigned int */ template< unsigned int L > static ZT_INLINE void zero(void *const dest) noexcept -{ -#ifdef ZT_ARCH_X64 - uint8_t *volatile d = reinterpret_cast(dest); - __m128i z = _mm_setzero_si128(); - for (unsigned int i = 0; i < (L >> 6U); ++i) { - _mm_storeu_si128(reinterpret_cast<__m128i *>(d), z); - _mm_storeu_si128(reinterpret_cast<__m128i *>(d + 16), z); - _mm_storeu_si128(reinterpret_cast<__m128i *>(d + 32), z); - _mm_storeu_si128(reinterpret_cast<__m128i *>(d + 48), z); - d += 64; - } - if ((L & 32U) != 0) { - _mm_storeu_si128(reinterpret_cast<__m128i *>(d), z); - _mm_storeu_si128(reinterpret_cast<__m128i *>(d + 16), z); - d += 32; - } - if ((L & 16U) != 0) { - _mm_storeu_si128(reinterpret_cast<__m128i *>(d), z); - d += 16; - } - if ((L & 8U) != 0) { - *reinterpret_cast(d) = 0; - d += 8; - } - if ((L & 4U) != 0) { - *reinterpret_cast(d) = 0; - d += 4; - } - if ((L & 2U) != 0) { - *reinterpret_cast(d) = 0; - d += 2; - } - if ((L & 1U) != 0) { - *d = 0; - } -#else - memset(dest,0,L); -#endif -} +{ memset(dest, 0, L); } /** * Zero memory block whose size is known at run time diff --git a/pkg/zerotier/node.go b/pkg/zerotier/node.go index ddb7726b8..d3c006494 100644 --- a/pkg/zerotier/node.go +++ b/pkg/zerotier/node.go @@ -724,7 +724,7 @@ func (n *Node) pathLookup(id *Identity) (net.IP, int) { return nil, 0 } -func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) { +func (n *Node) makeStateObjectPath(objType int, id []uint64) (string, bool) { var fp string secret := false switch objType { @@ -744,13 +744,17 @@ func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) { fp = path.Join(n.basePath, "networks.d") _ = os.Mkdir(fp, 0755) fp = path.Join(fp, fmt.Sprintf("%.16x.conf", id[0])) - case C.ZT_STATE_OBJECT_ROOTS: - fp = path.Join(n.basePath, "roots") + case C.ZT_STATE_OBJECT_TRUST_STORE: + fp = path.Join(n.basePath, "truststore") + case C.ZT_STATE_OBJECT_CERT: + fp = path.Join(n.basePath, "certs.d") + _ = os.Mkdir(fp, 0755) + fp = path.Join(fp, Base32StdLowerCase.EncodeToString((*[48]byte)(unsafe.Pointer(&id[0]))[:])) } return fp, secret } -func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) { +func (n *Node) stateObjectPut(objType int, id []uint64, data []byte) { fp, secret := n.makeStateObjectPath(objType, id) if len(fp) > 0 { fileMode := os.FileMode(0644) @@ -764,14 +768,14 @@ func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) { } } -func (n *Node) stateObjectDelete(objType int, id [2]uint64) { +func (n *Node) stateObjectDelete(objType int, id []uint64) { fp, _ := n.makeStateObjectPath(objType, id) if len(fp) > 0 { _ = os.Remove(fp) } } -func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) { +func (n *Node) stateObjectGet(objType int, id []uint64) ([]byte, bool) { fp, _ := n.makeStateObjectPath(objType, id) if len(fp) > 0 { fd, err := ioutil.ReadFile(fp) @@ -854,21 +858,19 @@ func goStateObjectPutFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Poin return } - id2 := *((*[2]uint64)(id)) + // NOTE: this is unsafe and depends on node.stateObjectDelete() and node.stateObjectPut() + // not accessing beyond the expected number of elements in the id. + id2 := (*[6]uint64)(id) var data2 []byte if len > 0 { data2 = C.GoBytes(data, len) } - node.runWaitGroup.Add(1) - go func() { - if len < 0 { - node.stateObjectDelete(int(objType), id2) - } else { - node.stateObjectPut(int(objType), id2, data2) - } - node.runWaitGroup.Done() - }() + if len < 0 { + node.stateObjectDelete(int(objType), id2[:]) + } else { + node.stateObjectPut(int(objType), id2[:], data2) + } } //export goStateObjectGetFunc @@ -879,7 +881,7 @@ func goStateObjectGetFunc(gn unsafe.Pointer, objType C.int, id, dataP unsafe.Poi } *((*uintptr)(dataP)) = 0 - tmp, found := node.stateObjectGet(int(objType), *((*[2]uint64)(id))) + tmp, found := node.stateObjectGet(int(objType), ((*[6]uint64)(id))[:]) if found && len(tmp) > 0 { cData := C.ZT_malloc(C.ulong(len(tmp))) // GoGlue sends free() to the core as the free function if uintptr(cData) == 0 {