From 652c7e8f37fa94e1060289f30a841b72bc37fa0b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 23:23:16 -0500 Subject: [PATCH] Locator work --- node/Constants.hpp | 3 +++ node/Identity.hpp | 7 +++-- node/Locator.hpp | 66 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/node/Constants.hpp b/node/Constants.hpp index fef155e38..73023ae0c 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -627,6 +627,9 @@ */ #define ZT_THREAD_MIN_STACK_SIZE 1048576 +#define ZT_CRYPTO_ALG_C25519 0 +#define ZT_CRYPTO_ALG_P384 1 + // Exceptions thrown in core ZT code #define ZT_EXCEPTION_OUT_OF_BOUNDS 100 #define ZT_EXCEPTION_OUT_OF_MEMORY 101 diff --git a/node/Identity.hpp b/node/Identity.hpp index 29e0ef00c..eeaf2fd7a 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -55,10 +55,13 @@ namespace ZeroTier { class Identity { public: + /** + * Identity type -- numeric values of these enums are protocol constants + */ enum Type { - C25519 = 0, // Curve25519 and Ed25519 (1.0 and 2.0, default) - P384 = 1 // NIST P-384 ECDH and ECDSA (2.0+ only) + C25519 = ZT_CRYPTO_ALG_C25519, // Type 0 -- Curve25519 and Ed25519 (1.0 and 2.0, default) + P384 = ZT_CRYPTO_ALG_P384 // Type 1 -- NIST P-384 ECDH and ECDSA (2.0+ only) }; Identity() { memset(reinterpret_cast(this),0,sizeof(Identity)); } diff --git a/node/Locator.hpp b/node/Locator.hpp index 5634ae51a..4249d8693 100644 --- a/node/Locator.hpp +++ b/node/Locator.hpp @@ -33,6 +33,7 @@ #include "Utils.hpp" #include "Buffer.hpp" #include "SHA512.hpp" +#include "Str.hpp" #include #include @@ -68,6 +69,7 @@ public: if (_virtual.size() < ZT_LOCATOR_MAX_VIRTUAL_ADDRESSES) _virtual.push_back(zt); } + inline void finish(const Identity &id,const int64_t ts) { _ts = ts; @@ -103,35 +105,75 @@ public: { if ((_signatureLength == 0)||(_signatureLength > sizeof(_signature))) return false; - Buffer<16384> *tmp; + Buffer<65536> *tmp = nullptr; try { - tmp = new Buffer<16384>(); // 16384 would be huge + tmp = new Buffer<65536>(); serialize(*tmp,true); const bool ok = (_signedBy) ? _signedBy.verify(tmp->data(),tmp->size(),_signature,_signatureLength) : _id.verify(tmp->data(),tmp->size(),_signature,_signatureLength); delete tmp; return ok; } catch ( ... ) { - delete tmp; + if (tmp) delete tmp; return false; } } - inline std::pair< Str,std::vector > makeTxtRecords(const uint8_t p384SigningKeyPrivate[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]) + inline std::vector makeTxtRecords(const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t p384SigningKeyPrivate[ZT_ECC384_PUBLIC_KEY_SIZE]) { uint8_t s384[48],dnsSig[ZT_ECC384_SIGNATURE_SIZE]; - char dnsSigTxtF0[64],dnsSigTxtF1[64],dnsSigTxtF2[64]; + char enc[256]; - Buffer<16384> *tmp = new Buffer<16384>(); // 16384 would be huge + Buffer<65536> *const tmp = new Buffer<65536>(); serialize(*tmp,false); SHA384(s384,tmp->data(),tmp->size()); ECC384ECDSASign(p384SigningKeyPrivate,s384,dnsSig); + tmp->append(dnsSig,ZT_ECC384_SIGNATURE_SIZE); - Utils::b32e(dnsSig,32,dnsSigTxtF0,sizeof(dnsSigTxtF0)); - Utils::b32e(dnsSig+32,32,dnsSigTxtF0,sizeof(dnsSigTxtF0)); - Utils::b32e(dnsSig+64,32,dnsSigTxtF0,sizeof(dnsSigTxtF0)); - Str name; + // Blob must be broken into multiple TXT records that must remain sortable so they are prefixed by a hex value. + // 186-byte chunks yield 248-byte base64 chunks which leaves some margin below the limit of 255. + std::vector txtRecords; + for(unsigned int p=0;psize();p+=186) { + unsigned int rem = tmp->size() - p; + if (rem > 186) rem = 186; + Utils::b64e(((const uint8_t *)tmp->data()) + p,rem,enc,sizeof(enc)); + txtRecords.push_back(Str()); + txtRecords.back() << Utils::HEXCHARS[(p >> 4) & 0xf] << Utils::HEXCHARS[p & 0xf] << enc; + } delete tmp; + return txtRecords; + } + + template + inline bool decodeTxtRecords(I start,I end,const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]) + { + uint8_t dec[256],s384[48]; + Buffer<65536> *tmp = nullptr; + try { + tmp = new Buffer<65536>(); + while (start != end) { + tmp->append(dec,Utils::b64d(start->c_str(),dec,sizeof(dec))); + ++start; + } + + if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) { + delete tmp; + return false; + } + SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE); + if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE))) { + delete tmp; + return false; + } + + deserialize(*tmp,0); + + delete tmp; + return verify(); + } catch ( ... ) { + if (tmp) delete tmp; + return false; + } } template @@ -139,11 +181,11 @@ public: { if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); - b.append((uint8_t)0; // version/flags, currently 0 + b.append((uint8_t)0); // version/flags, currently 0 b.append((uint64_t)_ts); _id.serialise(b,false); if (_signedBy) { - b.append((uint8_t)1); // number of signers + b.append((uint8_t)1); // number of signers, current max is 1 _signedBy.serialize(b,false); } else { b.append((uint8_t)0); // signer is _id