Browse Source

Kill ugly old getSecureRandom() and replace with simple wrapper for Windows CAPI and *nix /dev/urandom, and some build fixes.

Adam Ierymenko 11 years ago
parent
commit
502ea66f15

+ 1 - 1
node/Dictionary.cpp

@@ -110,7 +110,7 @@ bool Dictionary::verify(const Identity &id) const
 		if (sig == end())
 			return false;
 		std::string sigbin(Utils::unhex(sig->second));
-		return id.verify(buf.data(),buf.length(),sigbin.data(),sigbin.length());
+		return id.verify(buf.data(),(unsigned int)buf.length(),sigbin.data(),sigbin.length());
 	} catch ( ... ) {
 		return false;
 	}

+ 56 - 57
node/Utils.cpp

@@ -43,9 +43,12 @@
 #include <dirent.h>
 #endif
 
+#ifdef __WINDOWS__
+#include <wincrypt.h>
+#endif
+
 #include "Utils.hpp"
 #include "Mutex.hpp"
-#include "Salsa20.hpp"
 
 namespace ZeroTier {
 
@@ -189,68 +192,64 @@ unsigned int Utils::unhex(const char *hex,unsigned int maxlen,void *buf,unsigned
 
 void Utils::getSecureRandom(void *buf,unsigned int bytes)
 {
-	static Mutex randomLock;
-	static char randbuf[16384];
-	static unsigned int randptr = sizeof(randbuf);
-	static Salsa20 s20;
-	static bool randInitialized = false;
-
-	Mutex::Lock _l(randomLock);
-
-	// A Salsa20/8 instance is used to further mangle whatever our base
-	// random source happens to be.
-	if (!randInitialized) {
-		randInitialized = true;
-		memset(randbuf,0,sizeof(randbuf));
-		char s20key[33];
-		uint64_t s20iv = now();
-		Utils::snprintf(s20key,sizeof(s20key),"%.16llx%.16llx",(unsigned long long)now(),(unsigned long long)((void *)&s20iv));
-		s20.init(s20key,256,&s20iv,8);
+#ifdef __WINDOWS__
+
+	static HCRYPTPROV cryptProvider = NULL;
+	static Mutex globalLock;
+
+	Mutex::Lock _l(globalLock);
+
+	if (cryptProvider == NULL) {
+		if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) {
+			fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n");
+			exit(1);
+			return;
+		}
 	}
 
-	for(unsigned int i=0;i<bytes;++i) {
-		if (randptr >= sizeof(randbuf)) {
+	if (!CryptGenRandom(cryptProvider,(DWORD)bytes,(BYTE *)buf)) {
+		fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n");
+		exit(1);
+	}
+
+#else // not __WINDOWS__
+
 #ifdef __UNIX_LIKE__
-			{
-				int fd = ::open("/dev/urandom",O_RDONLY);
-				if (fd < 0) {
-					fprintf(stderr,"FATAL ERROR: unable to open /dev/urandom (%d)"ZT_EOL_S,errno);
-					exit(-1);
-				}
-				if ((int)::read(fd,randbuf,sizeof(randbuf)) != (int)sizeof(randbuf)) {
-					fprintf(stderr,"FATAL ERROR: unable to read from /dev/urandom"ZT_EOL_S);
-					exit(-1);
-				}
-				::close(fd);
-			}
-#else
-#ifdef __WINDOWS__
-			{
-				struct {
-					double nowf;
-					DWORD processId;
-					DWORD tickCount;
-					uint64_t nowi;
-					char padding[32];
-				} keyMaterial;
-				keyMaterial.nowf = Utils::nowf();
-				keyMaterial.processId = GetCurrentProcessId();
-				keyMaterial.tickCount = GetTickCount();
-				keyMaterial.nowi = Utils::now();
-				for(int i=0;i<sizeof(keyMaterial.padding);++i)
-					keyMaterial.padding[i] = (char)rand();
-				Salsa20 s20tmp(&keyMaterial,256,&(keyMaterial.nowi),8);
-				s20tmp.encrypt(randbuf,randbuf,sizeof(randbuf));
+
+	static char randomBuf[65536];
+	static unsigned int randomPtr = sizeof(randomBuf);
+	static int devURandomFd = -1;
+	static Mutex globalLock;
+
+	Mutex::Lock _l(globalLock);
+
+	if (devURandomFd <= 0) {
+		devURandomFd = ::open("/dev/urandom",O_RDONLY);
+		if (devURandomFd <= 0) {
+			fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\r\n");
+			exit(1);
+			return;
+		}
+	}
+
+	for(unsigned int i=0;i<bytes;++i) {
+		if (randomPtr >= sizeof(randomBuf)) {
+			if ((int)::read(devURandomFd,randomBuf,sizeof(randomBuf)) != (int)sizeof(randomBuf)) {
+				fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to read from /dev/urandom\r\n");
+				exit(1);
+				return;
 			}
-#else
-no getSecureRandom() implementation;
-#endif
-#endif
-			s20.encrypt(randbuf,randbuf,sizeof(randbuf));
-			randptr = 0;
+			randomPtr = 0;
 		}
-		((char *)buf)[i] = randbuf[randptr++];
+		((char *)buf)[i] = randomBuf[randomPtr++];
 	}
+
+#else // not __UNIX_LIKE__
+
+#error No getSecureRandom() implementation available.
+
+#endif // __UNIX_LIKE__
+#endif // __WINDOWS__
 }
 
 void Utils::lockDownFile(const char *path,bool isDir)

+ 0 - 1
windows/ZeroTierOne/ZeroTierOne.vcxproj

@@ -60,7 +60,6 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\ext\lz4\lz4.h" />
-    <ClInclude Include="..\..\ext\lz4\lz4hc.h" />
     <ClInclude Include="..\..\node\Address.hpp" />
     <ClInclude Include="..\..\node\AntiRecursion.hpp" />
     <ClInclude Include="..\..\node\Array.hpp" />

+ 3 - 6
windows/ZeroTierOne/ZeroTierOne.vcxproj.filters

@@ -90,9 +90,6 @@
     <ClCompile Include="..\..\node\Utils.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\main.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="ServiceBase.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -129,14 +126,14 @@
     <ClCompile Include="..\..\node\Dictionary.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\ext\lz4\lz4.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\ext\lz4\lz4hc.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\node\Address.hpp">
       <Filter>Header Files</Filter>
     </ClInclude>