[*] Harden time based RNG
[*] RNG needs specific optimal paths for Win10 and older oses [+] Internal RtlGenRandom
This commit is contained in:
parent
655f1839c5
commit
adefbbe16b
@ -49,6 +49,12 @@ namespace Aurora
|
||||
} \
|
||||
}
|
||||
|
||||
#define ADD_GET_PROC_INTERNAL_MAP(name, proc, symbol) \
|
||||
if (h ## name) \
|
||||
{ \
|
||||
p ## proc = AuReinterpretCast<decltype(p ## proc)>(GetProcAddress(h ## name, #symbol)); \
|
||||
}
|
||||
|
||||
if (pRtlGetVersion)
|
||||
{
|
||||
return;
|
||||
@ -84,6 +90,8 @@ namespace Aurora
|
||||
ADD_GET_PROC(AdvancedApi, CryptReleaseContext)
|
||||
ADD_GET_PROC(AdvancedApi, CryptGenRandom)
|
||||
|
||||
ADD_GET_PROC_INTERNAL_MAP(AdvancedApi, RtlGenRandom, SystemFunction036)
|
||||
|
||||
ADD_GET_PROC(BCrypt, BCryptGenRandom)
|
||||
|
||||
#else
|
||||
|
@ -196,6 +196,11 @@ namespace Aurora
|
||||
PULONG ActualResolution
|
||||
);
|
||||
|
||||
inline BOOLEAN(__stdcall *pRtlGenRandom)(
|
||||
PVOID RandomBuffer,
|
||||
ULONG RandomBufferLength
|
||||
);
|
||||
|
||||
inline bool gUseNativeWaitMutex {};
|
||||
inline bool gUseNativeWaitCondvar {};
|
||||
inline bool gUseNativeWaitSemapahore {};
|
||||
|
@ -79,6 +79,11 @@ namespace Aurora::RNG
|
||||
return;
|
||||
}
|
||||
|
||||
if (pRtlGenRandom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (pCryptAcquireContextW)
|
||||
{
|
||||
if (!pCryptAcquireContextW(&gCryptoProv, NULL,
|
||||
@ -100,15 +105,32 @@ namespace Aurora::RNG
|
||||
{
|
||||
if (pBCryptGenRandom)
|
||||
{
|
||||
#if !defined(AURORA_DONT_PREFER_WIN32_USERLAND_AES_RNG)
|
||||
if (AuSwInfo::IsWindows10OrGreater() &&
|
||||
pBCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, reinterpret_cast<PUCHAR>(pBuf), uLen, 0) == 0)
|
||||
if (AuSwInfo::IsWindows10OrGreater() ||
|
||||
AuBuild::kCurrentPlatform != AuBuild::EPlatform::ePlatformWin32)
|
||||
{
|
||||
if (pRtlGenRandom)
|
||||
{
|
||||
if (pRtlGenRandom(pBuf, uLen))
|
||||
{
|
||||
return uLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (pBCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, reinterpret_cast<PUCHAR>(pBuf), uLen, 0) == 0)
|
||||
{
|
||||
return uLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (pBCryptGenRandom(NULL, reinterpret_cast<PUCHAR>(pBuf), uLen, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
|
||||
{
|
||||
return uLen;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pBCryptGenRandom(NULL, reinterpret_cast<PUCHAR>(pBuf), uLen, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
|
||||
if (pRtlGenRandom)
|
||||
{
|
||||
if (pRtlGenRandom(pBuf, uLen))
|
||||
{
|
||||
return uLen;
|
||||
}
|
||||
@ -136,44 +158,58 @@ namespace Aurora::RNG
|
||||
|
||||
#endif
|
||||
|
||||
static AuUInt32 RngStdC(AuUInt8 *pBuf, AuUInt32 uLen)
|
||||
static AuUInt64 RngTimeClock()
|
||||
{
|
||||
clock_t t1;
|
||||
int l, acc, bits, a, b;
|
||||
#if 0
|
||||
return clock(); // [...] resolution of 1 posix clock() tick (this is usually 1,000,000 == CLOCKS_PER_SEC per posix, but it can be 1k)
|
||||
#else
|
||||
return AuTime::SteadyClockNS() / 1000ull;
|
||||
#endif
|
||||
}
|
||||
|
||||
static AuUInt32 RngTimeBased(AuUInt8 *pBuf, AuUInt32 uLen)
|
||||
{
|
||||
AuUInt64 t1;
|
||||
int l, acc, bits, a, b, c;
|
||||
|
||||
l = uLen;
|
||||
acc = a = b = 0;
|
||||
acc = a = b = c = 0;
|
||||
bits = 8;
|
||||
|
||||
void *pASLRSeed = &RngTimeBased;
|
||||
|
||||
while (uLen--)
|
||||
{
|
||||
while (bits--) // for each bit in byte
|
||||
{
|
||||
do
|
||||
{
|
||||
t1 = clock();
|
||||
while (t1 == clock()) // spin within the resolution of 1 posix clock() tick (this is usually 1,000,000 == CLOCKS_PER_SEC per posix, but it can be 1k)
|
||||
t1 = RngTimeClock();
|
||||
while (t1 == RngTimeClock()) // spin within 1 microseconds
|
||||
{
|
||||
a ^= 1; // flip
|
||||
}
|
||||
|
||||
t1 = clock();
|
||||
while (t1 == clock())
|
||||
t1 = RngTimeClock();
|
||||
while (t1 == RngTimeClock()) // spin within 1 microseconds
|
||||
{
|
||||
b ^= 1; // flip
|
||||
}
|
||||
} while (a == b); // ensure theres enough entropy for a deviation to occur
|
||||
}
|
||||
while (a == b); // ensure theres enough entropy for a deviation to occur
|
||||
acc = (acc << 1) | a; // push the first bit state
|
||||
}
|
||||
|
||||
*pBuf++ = acc;
|
||||
*pBuf = AuFnv1a32Runtime(&acc, sizeof(acc)) ^
|
||||
AuFnv1a32Runtime(&c, sizeof(c)) ^
|
||||
AuFnv1a32Runtime(&pASLRSeed, sizeof(pASLRSeed));
|
||||
|
||||
c = *pBuf++;
|
||||
|
||||
acc = 0;
|
||||
bits = 8;
|
||||
}
|
||||
|
||||
// TODO: Is that whitening algorithm enough or should we work towards a continuous hash stream?
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
@ -193,7 +229,7 @@ namespace Aurora::RNG
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
x = RngStdC(pBuffer, uBytes);
|
||||
x = RngTimeBased(pBuffer, uBytes);
|
||||
if (x != 0)
|
||||
{
|
||||
return x;
|
||||
@ -215,6 +251,11 @@ namespace Aurora::RNG
|
||||
return;
|
||||
}
|
||||
|
||||
if (pRtlGenRandom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (pCryptReleaseContext)
|
||||
{
|
||||
pCryptReleaseContext(gCryptoProv, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user