Browse Source

Locator work

Adam Ierymenko 6 years ago
parent
commit
652c7e8f37
3 changed files with 62 additions and 14 deletions
  1. 3 0
      node/Constants.hpp
  2. 5 2
      node/Identity.hpp
  3. 54 12
      node/Locator.hpp

+ 3 - 0
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

+ 5 - 2
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<void *>(this),0,sizeof(Identity)); }

+ 54 - 12
node/Locator.hpp

@@ -33,6 +33,7 @@
 #include "Utils.hpp"
 #include "Buffer.hpp"
 #include "SHA512.hpp"
+#include "Str.hpp"
 
 #include <algorithm>
 #include <vector>
@@ -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<Str> > makeTxtRecords(const uint8_t p384SigningKeyPrivate[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE])
+	inline std::vector<Str> 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<Str> txtRecords;
+		for(unsigned int p=0;p<tmp->size();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<typename I>
+	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<unsigned int C>
@@ -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