|
|
|
|
@ -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) |
|
|
|
|
|