This commit is contained in:
Adam Ierymenko 2019-08-28 14:16:14 -07:00
parent 8915b88de5
commit a92967a7c1
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3

View file

@ -37,6 +37,8 @@
#include "Utils.hpp" #include "Utils.hpp"
#include "Mutex.hpp" #include "Mutex.hpp"
#include "Salsa20.hpp" #include "Salsa20.hpp"
#include "AES.hpp"
#include "SHA512.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -140,14 +142,11 @@ unsigned int Utils::unhex(const char *h,unsigned int hlen,void *buf,unsigned int
void Utils::getSecureRandom(void *buf,unsigned int bytes) void Utils::getSecureRandom(void *buf,unsigned int bytes)
{ {
static Mutex globalLock; static Mutex globalLock;
static Salsa20 s20;
static bool initialized = false; static bool initialized = false;
static uint8_t randomBuf[131072]; static uint8_t randomBuf[131072];
static unsigned int randomPtr = sizeof(randomBuf); static unsigned long randomPtr = sizeof(randomBuf);
#ifdef __WINDOWS__ #ifdef __WINDOWS__
static HCRYPTPROV cryptProvider = NULL; static HCRYPTPROV cryptProvider = NULL;
#else
static int devURandomFd = -1;
#endif #endif
Mutex::Lock _l(globalLock); Mutex::Lock _l(globalLock);
@ -160,63 +159,46 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
* at almost no cost and with no real downside if the random source is * at almost no cost and with no real downside if the random source is
* good. */ * good. */
if (unlikely(!initialized)) { if (unlikely(!initialized)) {
initialized = true;
uint64_t s20Key[4];
s20Key[0] = (uint64_t)time(nullptr);
#ifdef __WINDOWS__
s20Key[1] = (uint64_t)buf; // address of buf
#else
s20Key[1] = (uint64_t)getpid();
#endif
s20Key[2] = (uint64_t)s20Key; // address of s20Key[]
s20Key[3] = (uint64_t)&s20; // address of s20
s20.init(s20Key,s20Key);
#ifdef __WINDOWS__ #ifdef __WINDOWS__
if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) { 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"); fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n");
exit(1); exit(1);
} }
if (!CryptGenRandom(cryptProvider,(DWORD)sizeof(randomBuf),(BYTE *)randomBuf)) {
fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n");
exit(1);
}
#else #else
devURandomFd = ::open("/dev/urandom",O_RDONLY); int devURandomFd = ::open("/dev/urandom",O_RDONLY);
if (devURandomFd < 0) { if (devURandomFd < 0) {
fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n"); fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n");
exit(1); exit(1);
} }
if ((int)::read(devURandomFd,randomBuf,sizeof(randomBuf)) != (int)sizeof(randomBuf)) {
::close(devURandomFd);
fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to read from /dev/urandom\n");
exit(1);
}
close(devURandomFd);
#endif #endif
initialized = true;
} }
#ifdef __WINDOWS__
for(unsigned int i=0;i<bytes;++i) { for(unsigned int i=0;i<bytes;++i) {
if (unlikely(randomPtr >= sizeof(randomBuf))) { if (randomPtr >= sizeof(randomBuf)) {
randomPtr = 0; uint8_t h[64];
if (!CryptGenRandom(cryptProvider,(DWORD)sizeof(randomBuf),(BYTE *)randomBuf)) { SHA512(h,randomBuf,sizeof(randomBuf));
fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n"); if (AES::HW_ACCEL) {
exit(1); AES c(h);
c.ctr(h + 32,randomBuf,sizeof(randomBuf),randomBuf);
} else {
Salsa20 c(h,h + 32);
c.crypt12(randomBuf,randomBuf,sizeof(randomBuf));
} }
s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf)); randomPtr = 0;
} }
((uint8_t *)buf)[i] = randomBuf[randomPtr++]; ((uint8_t *)buf)[i] = randomBuf[randomPtr++];
} }
#else // not __WINDOWS__
for(unsigned int i=0;i<bytes;++i) {
if (unlikely(randomPtr >= sizeof(randomBuf))) {
randomPtr = 0;
if ((int)::read(devURandomFd,randomBuf,sizeof(randomBuf)) != (int)sizeof(randomBuf)) {
::close(devURandomFd);
fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to read from /dev/urandom\n");
exit(1);
}
s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf));
}
((uint8_t *)buf)[i] = randomBuf[randomPtr++];
}
#endif // __WINDOWS__ or not
} }
int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize) int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize)