diff --git a/cmd/zerotier/cli/help.go b/cmd/zerotier/cli/help.go index e393cb2cb..b483a1de5 100644 --- a/cmd/zerotier/cli/help.go +++ b/cmd/zerotier/cli/help.go @@ -38,7 +38,7 @@ Commands: status Show node status and configuration join [-options] Join a virtual network -a Token to submit to controller - -c Controller identity or fingerprint + -c Controller identity or fingerprint leave Leave a virtual network networks List VL2 virtual networks network [command] [option] - Network management commands @@ -58,8 +58,8 @@ Commands: root [command] - Root management commands add [endpoint] Designate a peer as a root remove
Un-designate a peer as a root - subscribe Subscribe to a root set - unsubscribe Unsubscribe from a root set + subscribe [] Subscribe to a set of roots + unsubscribe Unsubscribe from a set of roots set [option] [value] - Get or set a core config option port Primary P2P port secondaryport Secondary P2P port (0 to disable) @@ -75,7 +75,7 @@ Commands: auth
Authorize a peer deauth
Deauthorize a peer identity [args] - Identity management commands - new [c25519|p384] Create identity (default: c25519) + new [c25519 | p384] Create identity (default: c25519) getpublic Extract only public part of identity fingerprint Get an identity's fingerprint validate Locally validate an identity diff --git a/cmd/zerotier/cli/root.go b/cmd/zerotier/cli/root.go index 53dba84e4..887709826 100644 --- a/cmd/zerotier/cli/root.go +++ b/cmd/zerotier/cli/root.go @@ -21,10 +21,6 @@ func Root(basePath, authToken string, args []string, jsonOutput bool) { case "remove": - case "subscribe": - - case "unsubscribe": - } } } diff --git a/core/Constants.hpp b/core/Constants.hpp index f1ae08432..a81b68ce2 100644 --- a/core/Constants.hpp +++ b/core/Constants.hpp @@ -224,10 +224,6 @@ */ #define ZT_SIGNATURE_BUFFER_SIZE 96 -// Internal cryptographic algorithm IDs (these match relevant identity types) -#define ZT_CRYPTO_ALG_C25519 0 -#define ZT_CRYPTO_ALG_P384 1 - /* Ethernet frame types that might be relevant to us */ #define ZT_ETHERTYPE_IPV4 0x0800 #define ZT_ETHERTYPE_ARP 0x0806 diff --git a/core/Containers.hpp b/core/Containers.hpp index 35e9a2d4b..cfca4ce46 100644 --- a/core/Containers.hpp +++ b/core/Containers.hpp @@ -20,8 +20,11 @@ #include "Utils.hpp" #ifdef __CPP11__ + #include + #endif + #include #include #include @@ -34,42 +37,52 @@ namespace ZeroTier { struct intl_MapHasher { - template - std::size_t operator()(const O &obj) const noexcept { return (std::size_t)obj.hashCode(); } - std::size_t operator()(const uint64_t i) const noexcept { 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); } - std::size_t operator()(const uint32_t i) const noexcept { 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); } + template< typename O > + std::size_t operator()(const O &obj) const noexcept + { return (std::size_t)obj.hashCode(); } + + std::size_t operator()(const uint64_t i) const noexcept + { 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); } + + std::size_t operator()(const uint32_t i) const noexcept + { 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); } }; -template -class Map : public std::unordered_map< K,V,intl_MapHasher,std::equal_to,Utils::Mallocator< std::pair > > -{ +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 > > + +> { public: - ZT_INLINE V *get(const K &key) noexcept - { - typename Map::iterator i(this->find(key)); - if (i == this->end()) - return nullptr; - return &(i->second); - } +ZT_INLINE V *get(const K &key) noexcept +{ + typename Map::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 Map::const_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 Map::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->emplace(key,value); - } +ZT_INLINE void set(const K &key, const V &value) +{ this->emplace(key, value); } }; -template -class MultiMap : public std::unordered_multimap< K,V,intl_MapHasher,std::equal_to,Utils::Mallocator< std::pair > > +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 > > + +> { }; @@ -96,9 +109,7 @@ public: } ZT_INLINE void set(const K &key,const V &value) - { - (*this)[key] = value; - } + { (*this)[key] = value; } }; template @@ -108,60 +119,104 @@ class MultiMap : public std::multimap< K,V,std::less,Utils::Mallocator< std:: #endif -template -class SortedMap : public std::map< K,V,std::less,Utils::Mallocator< std::pair > > +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 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 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; } - ZT_INLINE void set(const K &key,const V &value) - { - (*this)[key] = value; - } }; -template -class Vector : public std::vector< V,Utils::Mallocator > +template< typename V > +class Vector : public std::vector< V, Utils::Mallocator < V > + +> { public: - ZT_INLINE Vector() {} - template - ZT_INLINE Vector(I begin,I end) : std::vector< V,Utils::Mallocator >(begin,end) {} +ZT_INLINE Vector() +{} + +template< typename I > +ZT_INLINE Vector(I +begin, +I end +) : std::vector< V, Utils::Mallocator < V > >(begin,end) { +} }; -template -class List : public std::list< V,Utils::Mallocator > +template< typename V > +class List : public std::list< V, Utils::Mallocator < V > + +> { }; -template -class Set : public std::set< V,std::less,Utils::Mallocator > +template< typename V > +class Set : public std::set< V, std::less< V >, Utils::Mallocator < V > + +> { }; -class String : public std::basic_string< char,std::char_traits,Utils::Mallocator > +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,Utils::Mallocator >(s.c_str()) {} - ZT_INLINE String(const std::string &s) : std::basic_string< char,std::char_traits,Utils::Mallocator >(s.c_str()) {} - ZT_INLINE String(const char *const s) : std::basic_string< char,std::char_traits,Utils::Mallocator >(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; } +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; +} + }; } // ZeroTier diff --git a/core/Dictionary.cpp b/core/Dictionary.cpp index 15777a584..8ac5698c9 100644 --- a/core/Dictionary.cpp +++ b/core/Dictionary.cpp @@ -12,27 +12,23 @@ /****/ #include "Dictionary.hpp" +#include "SHA512.hpp" namespace ZeroTier { -static const FCV s_signatureFingerprint("@Si", 4); -static const FCV s_signatureData("@Ss", 4); - Dictionary::Dictionary() { } Vector &Dictionary::operator[](const char *k) { - FCV key; - return m_entries[s_key(key, k)]; + return m_entries[s_key(k)]; } const Vector &Dictionary::operator[](const char *k) const { static const Vector s_emptyEntry; - FCV key; - SortedMap, Vector >::const_iterator e(m_entries.find(s_key(key, k))); + SortedMap< String, Vector >::const_iterator e(m_entries.find(s_key(k))); return (e == m_entries.end()) ? s_emptyEntry : e->second; } @@ -131,8 +127,8 @@ void Dictionary::clear() void Dictionary::encode(Vector &out, const bool omitSignatureFields) const { out.clear(); - for (SortedMap, Vector >::const_iterator ti(m_entries.begin());ti != m_entries.end();++ti) { - if ((!omitSignatureFields) || ((ti->first != s_signatureFingerprint) && (ti->first != s_signatureData))) { + for (SortedMap< String, Vector >::const_iterator ti(m_entries.begin());ti != m_entries.end();++ti) { + if ((!omitSignatureFields) || ((ti->first != ZT_DICTIONARY_SIGNATURE_KEY))) { s_appendKey(out, ti->first.data()); for (Vector::const_iterator i(ti->second.begin());i != ti->second.end();++i) s_appendValueByte(out, *i); @@ -145,7 +141,7 @@ void Dictionary::encode(Vector &out, const bool omitSignatureFields) co bool Dictionary::decode(const void *data, unsigned int len) { clear(); - FCV k; + String k; Vector *v = nullptr; bool escape = false; for (unsigned int di = 0;di < len;++di) { @@ -197,4 +193,59 @@ bool Dictionary::decode(const void *data, unsigned int len) return true; } +void Dictionary::sign( + const uint8_t c25519PrivateKey[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE], + const uint8_t c25519PublicKey[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE], + const uint8_t p384PrivateKey[ZT_ECC384_PRIVATE_KEY_SIZE], + const uint8_t p384PublicKey[ZT_ECC384_PUBLIC_KEY_SIZE]) +{ + Vector buf; + encode(buf, true); + + uint8_t c25519Signature[ZT_C25519_SIGNATURE_LEN]; + C25519::sign(c25519PrivateKey, c25519PublicKey, buf.data(), (unsigned int)buf.size(), c25519Signature); + + uint8_t hbuf[ZT_ECC384_SIGNATURE_HASH_SIZE]; + static_assert(ZT_ECC384_SIGNATURE_HASH_SIZE == ZT_SHA384_DIGEST_SIZE,"size mismatch"); + SHA384(hbuf, buf.data(), (unsigned int)buf.size()); + uint8_t p384Signature[ZT_ECC384_SIGNATURE_SIZE]; + ECC384ECDSASign(p384PrivateKey, hbuf, p384Signature); + + SHA384(hbuf, c25519PublicKey, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, p384PublicKey, ZT_ECC384_PUBLIC_KEY_SIZE); + + Dictionary signature; + signature["kh"].assign(hbuf, hbuf + ZT_SHA384_DIGEST_SIZE); + signature["ed25519"].assign(c25519Signature, c25519Signature + ZT_C25519_SIGNATURE_LEN); + signature["p384"].assign(p384Signature, p384Signature + ZT_ECC384_SIGNATURE_SIZE); + signature.encode((*this)[ZT_DICTIONARY_SIGNATURE_KEY], true); +} + +bool Dictionary::verify( + const uint8_t c25519PublicKey[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE], + const uint8_t p384PublicKey[ZT_ECC384_PUBLIC_KEY_SIZE]) const +{ + try { + const Vector< uint8_t > &data = (*this)[ZT_DICTIONARY_SIGNATURE_KEY]; + if (data.empty()) + return false; + Dictionary signature; + if (!signature.decode(data.data(), (unsigned int)data.size())) + return false; + const Vector< uint8_t > &p384Signature = signature["p384"]; + const Vector< uint8_t > &c25519Signature = signature["ed25519"]; + if ((p384Signature.size() != ZT_ECC384_SIGNATURE_SIZE) || (c25519Signature.size() != ZT_C25519_SIGNATURE_LEN)) + return false; + + Vector< uint8_t > buf; + encode(buf, true); + + if (C25519::verify(c25519PublicKey, buf.data(), (unsigned int)buf.size(), c25519Signature.data(), (unsigned int)c25519Signature.size())) { + uint8_t hbuf[ZT_ECC384_SIGNATURE_HASH_SIZE]; + SHA384(hbuf, buf.data(), (unsigned int)buf.size()); + return ECC384ECDSAVerify(p384PublicKey, hbuf, p384Signature.data()); + } + } catch ( ... ) {} + return false; +} + } // namespace ZeroTier diff --git a/core/Dictionary.hpp b/core/Dictionary.hpp index 21644226f..2d5a40b98 100644 --- a/core/Dictionary.hpp +++ b/core/Dictionary.hpp @@ -18,8 +18,11 @@ #include "Utils.hpp" #include "Address.hpp" #include "Buf.hpp" -#include "FCV.hpp" #include "Containers.hpp" +#include "C25519.hpp" +#include "ECC384.hpp" + +#define ZT_DICTIONARY_SIGNATURE_KEY "@S" namespace ZeroTier { @@ -29,9 +32,7 @@ class Identity; * A simple key-value store for short keys * * This data structure is used for network configurations, node meta-data, - * and other open-definition protocol objects. It consists of a key-value - * store with short (max: 7 characters) keys that map to strings, blobs, - * or integers with the latter being by convention in hex format. + * and other open-definition protocol objects. * * If this seems a little odd, it is. It dates back to the very first alpha * versions of ZeroTier and if it were redesigned today we'd use some kind @@ -45,6 +46,9 @@ class Identity; class Dictionary { public: + typedef SortedMap< String, Vector < uint8_t > > + ::const_iterator const_iterator; + Dictionary(); /** @@ -53,7 +57,7 @@ public: * @param k Key to look up * @return Reference to value */ - Vector &operator[](const char *k); + Vector &operator[](const char *k); /** * Get a const reference to a value @@ -61,37 +65,52 @@ public: * @param k Key to look up * @return Reference to value or to empty vector if not found */ - const Vector &operator[](const char *k) const; + const Vector &operator[](const char *k) const; + + /** + * @return Start of key->value pairs + */ + ZT_INLINE const_iterator begin() const noexcept + { return m_entries.begin(); } + + /** + * @return End of key->value pairs + */ + ZT_INLINE const_iterator end() const noexcept + { return m_entries.end(); } /** * Add a boolean as '1' or '0' */ - void add(const char *k,bool v); + void add(const char *k, bool v); /** * Add an integer as a hexadecimal string value + * + * @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) { char buf[17]; add(k,Utils::hex(v,buf)); } - ZT_INLINE void add(const char *const k,const int64_t v) { char buf[17]; add(k,Utils::hex((uint64_t)v,buf)); } - ZT_INLINE void add(const char *const k,const uint32_t v) { char buf[17]; add(k,Utils::hex((uint64_t)v,buf)); } - ZT_INLINE void add(const char *const k,const int32_t v) { char buf[17]; add(k,Utils::hex((uint64_t)v,buf)); } - ZT_INLINE void add(const char *const k,const uint16_t v) { char buf[17]; add(k,Utils::hex((uint64_t)v,buf)); } - ZT_INLINE void add(const char *const k,const int16_t v) { char buf[17]; add(k,Utils::hex((uint64_t)v,buf)); } + template< typename I > + ZT_INLINE void add(const char *const k, I v) + { + char buf[17]; + add(k, Utils::hex((uint64_t)(v), buf)); + } /** * 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 a boolean @@ -100,7 +119,7 @@ public: * @param dfl Default value (default: false) * @return Value of key or default if not found */ - bool getB(const char *k,bool dfl = false) const; + bool getB(const char *k, bool dfl = false) const; /** * Get an integer @@ -109,7 +128,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 @@ -121,7 +140,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 @@ -130,13 +149,13 @@ public: * @param obj Object to unmarshal() into * @return True if unmarshal was successful */ - template - 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 &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); + return (obj.unmarshal(d.data(), (unsigned int)d.size()) > 0); } /** @@ -147,12 +166,14 @@ public: /** * @return Number of entries */ - ZT_INLINE unsigned int size() const noexcept { return m_entries.size(); } + ZT_INLINE unsigned int size() const noexcept + { return m_entries.size(); } /** * @return True if dictionary is not empty */ - ZT_INLINE bool empty() const noexcept { return m_entries.empty(); } + ZT_INLINE bool empty() const noexcept + { return m_entries.empty(); } /** * Encode to a string in the supplied vector @@ -160,7 +181,7 @@ public: * @param out String encoded dictionary * @param omitSignatureFields If true omit the signature fields from encoding (default: false) */ - void encode(Vector &out,bool omitSignatureFields = false) const; + void encode(Vector &out, bool omitSignatureFields = false) const; /** * Decode a string encoded dictionary @@ -172,7 +193,35 @@ 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); + + /** + * Sign this dictionary with both an Ed25519 key and a NIST P-384 key. + * + * This is currently used just for signing root sets for the root subscribe + * feature. It uses both key types for more crypto cowbell. + * + * @param c25519PrivateKey Curve25519 combined key (C25519 and ed25519), though only ed25519 part is used + * @param c25519PublicKey Public part of Curve25519 combined key + * @param p384PrivateKey NIST P-384 private key + * @param p384PublicKey NIST P-384 public key + */ + void sign( + const uint8_t c25519PrivateKey[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE], + const uint8_t c25519PublicKey[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE], + const uint8_t p384PrivateKey[ZT_ECC384_PRIVATE_KEY_SIZE], + const uint8_t p384PublicKey[ZT_ECC384_PUBLIC_KEY_SIZE]); + + /** + * Verify this dictionary's signature + * + * @param c25519PublicKey Curve25519 public key + * @param p384PublicKey P-384 public key + * @return True if signatures are valid + */ + bool verify( + const uint8_t c25519PublicKey[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE], + const uint8_t p384PublicKey[ZT_ECC384_PUBLIC_KEY_SIZE]) const; /** * Append a key=value pair to a buffer (vector or FCV) @@ -181,10 +230,10 @@ public: * @param k Key (must be <= 8 characters) * @param v Value */ - template - 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); + s_appendKey(out, k); out.push_back((uint8_t)(v ? '1' : '0')); out.push_back((uint8_t)'\n'); } @@ -196,12 +245,12 @@ public: * @param k Key (must be <= 8 characters) * @param v Value */ - template - 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); + s_appendKey(out, k); const uint64_t a = v.toInt(); - static_assert(ZT_ADDRESS_LENGTH_HEX == 10,"this must be rewritten for any change in address length"); + static_assert(ZT_ADDRESS_LENGTH_HEX == 10, "this must be rewritten for any change in address length"); out.push_back((uint8_t)Utils::HEXCHARS[(a >> 36U) & 0xfU]); out.push_back((uint8_t)Utils::HEXCHARS[(a >> 32U) & 0xfU]); out.push_back((uint8_t)Utils::HEXCHARS[(a >> 28U) & 0xfU]); @@ -222,31 +271,44 @@ public: * @param k Key (must be <= 8 characters) * @param v Value */ - template - 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) { char buf[17]; - Utils::hex(v,buf); + Utils::hex(v, buf); unsigned int i = 0; while (buf[i]) out.push_back((uint8_t)buf[i++]); out.push_back((uint8_t)'\n'); } - template - ZT_INLINE static void append(V &out,const char *const k,const int64_t v) { append(out,k,(uint64_t)v); } - template - ZT_INLINE static void append(V &out,const char *const k,const uint32_t v) { append(out,k,(uint64_t)v); } - template - ZT_INLINE static void append(V &out,const char *const k,const int32_t v) { append(out,k,(uint64_t)v); } - template - ZT_INLINE static void append(V &out,const char *const k,const uint16_t v) { append(out,k,(uint64_t)v); } - template - ZT_INLINE static void append(V &out,const char *const k,const int16_t v) { append(out,k,(uint64_t)v); } - template - ZT_INLINE static void append(V &out,const char *const k,const uint8_t v) { append(out,k,(uint64_t)v); } - template - 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 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 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 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 int8_t v) + { append(out, k, (uint64_t)v); } /** * Append a key=value pair to a buffer (vector or FCV) @@ -255,13 +317,13 @@ public: * @param k Key (must be <= 8 characters) * @param v Value */ - template - 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); + 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'); } } @@ -274,12 +336,12 @@ public: * @param v Value * @param vlen Value length in bytes */ - template - 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(v)[i]); + s_appendKey(out, k); + for (unsigned int i = 0; i < vlen; ++i) + s_appendValueByte(out, reinterpret_cast(v)[i]); out.push_back((uint8_t)'\n'); } @@ -290,11 +352,9 @@ public: * @param k Key (must be <= 8 characters) * @param pid Packet ID */ - template - 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 @@ -304,23 +364,23 @@ public: * @param v Marshal-able object * @return Bytes appended or negative on error (return value of marshal()) */ - template - 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[4096]; // large enough for any current object if (T::marshalSizeMax() > sizeof(tmp)) return -1; const int mlen = v.marshal(tmp); if (mlen > 0) - append(out,k,tmp,(unsigned int)mlen); + append(out, k, tmp, (unsigned int)mlen); return mlen; } private: - template - ZT_INLINE static void s_appendValueByte(V &out,const uint8_t c) + template< typename V > + ZT_INLINE static void s_appendValueByte(V &out, const uint8_t c) { - switch(c) { + switch (c) { case 0: out.push_back(92); // backslash out.push_back(48); @@ -347,34 +407,35 @@ private: } } - template - ZT_INLINE static void s_appendKey(V &out,const char *const k) + template< typename V > + ZT_INLINE static void s_appendKey(V &out, const char *const k) { - for(unsigned int i=0;i<7;++i) { + for (unsigned int i = 0; i < 7; ++i) { const char kc = k[i]; if (kc == 0) break; - if ((kc >= 33)&&(kc <= 126)&&(kc != 61)&&(kc != 92)) // printable ASCII with no spaces, equals, or backslash + if ((kc >= 33) && (kc <= 126) && (kc != 61) && (kc != 92)) // printable ASCII with no spaces, equals, or backslash out.push_back((uint8_t)kc); } out.push_back((uint8_t)'='); } - ZT_INLINE static FCV &s_key(FCV &buf,const char *k) noexcept + ZT_INLINE static String s_key(const char *k) noexcept { + String buf; buf.clear(); - for(unsigned int i=0;i<7;++i) { + for (unsigned int i = 0; i < 7; ++i) { const char kc = k[i]; if (kc == 0) break; - if ((kc >= 33)&&(kc <= 126)&&(kc != 61)&&(kc != 92)) // printable ASCII with no spaces, equals, or backslash + if ((kc >= 33) && (kc <= 126) && (kc != 61) && (kc != 92)) // printable ASCII with no spaces, equals, or backslash buf.push_back(kc); } buf.push_back(0); return buf; } - SortedMap< FCV,Vector > m_entries; + SortedMap > m_entries; }; } // namespace ZeroTier diff --git a/core/EphemeralKey.hpp b/core/EphemeralKey.hpp index e8ece0c10..b10902e55 100644 --- a/core/EphemeralKey.hpp +++ b/core/EphemeralKey.hpp @@ -47,7 +47,7 @@ public: enum Type { TYPE_NIL = 0, - TYPE_C25519_P384 = ZT_CRYPTO_ALG_P384 + TYPE_C25519_P384 = 1 }; /** diff --git a/pkg/zerotier/misc.go b/pkg/zerotier/misc.go index fca5648f6..ee3450225 100644 --- a/pkg/zerotier/misc.go +++ b/pkg/zerotier/misc.go @@ -13,6 +13,9 @@ package zerotier +// #include "../../serviceiocore/GoGlue.h" +import "C" + import ( "encoding/base32" "encoding/binary"