2022-09-19 01:34:57 +00:00
|
|
|
/***
|
|
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
File: AuRNGEntropy.cpp
|
2022-09-19 01:34:57 +00:00
|
|
|
Date: 2022-9-17
|
|
|
|
File: RNG.cpp
|
|
|
|
Date: 2021-6-11
|
|
|
|
Author: Reece
|
|
|
|
***/
|
|
|
|
#include <Source/RuntimeInternal.hpp>
|
2022-11-17 07:46:07 +00:00
|
|
|
#include "AuRNG.hpp"
|
|
|
|
#include "AuRNGEntropy.hpp"
|
2022-09-19 01:34:57 +00:00
|
|
|
|
|
|
|
#if defined(AURORA_PLATFORM_WIN32)
|
|
|
|
#include <bcrypt.h>
|
2023-07-09 10:26:17 +00:00
|
|
|
|
|
|
|
#if !defined(BCRYPT_RNG_ALG_HANDLE)
|
|
|
|
#define BCRYPT_RNG_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x00000081)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define USE_OLD_NTCRYPT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
2022-09-19 01:34:57 +00:00
|
|
|
#include <bcrypt.h>
|
|
|
|
#endif
|
|
|
|
|
2023-07-09 10:26:17 +00:00
|
|
|
#if defined(USE_OLD_NTCRYPT)
|
|
|
|
#include <wincrypt.h>
|
|
|
|
#endif
|
|
|
|
|
2022-09-19 01:34:57 +00:00
|
|
|
#if defined(AURORA_IS_POSIX_DERIVED)
|
|
|
|
#include <cstdio>
|
2022-12-16 00:41:01 +00:00
|
|
|
#include <fcntl.h>
|
2022-09-19 01:34:57 +00:00
|
|
|
#endif
|
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
#include "AuWELL.hpp"
|
2022-09-19 01:34:57 +00:00
|
|
|
|
|
|
|
namespace Aurora::RNG
|
|
|
|
{
|
|
|
|
#if defined(AURORA_IS_POSIX_DERIVED)
|
2023-07-10 19:56:45 +00:00
|
|
|
static int gDevURand { -1 };
|
2022-09-19 01:34:57 +00:00
|
|
|
|
|
|
|
void EntropyInit()
|
|
|
|
{
|
2022-12-16 03:48:04 +00:00
|
|
|
gDevURand = ::open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
2022-09-19 01:34:57 +00:00
|
|
|
if (gDevURand <= 0)
|
|
|
|
{
|
2022-12-16 03:48:04 +00:00
|
|
|
gDevURand = ::open("/dev/random", O_RDONLY | O_CLOEXEC);
|
2022-09-19 01:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gDevURand <= 0)
|
|
|
|
{
|
|
|
|
gDevURand = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
static AuUInt32 RngUnix(AuUInt8 *pBuf, AuUInt32 uLen)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
|
|
|
if (gDevURand == -1)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
return ::read(gDevURand, pBuf, uLen);
|
2022-09-19 01:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(AURORA_IS_MODERNNT_DERIVED)
|
|
|
|
|
|
|
|
#if defined(USE_OLD_NTCRYPT)
|
|
|
|
static HCRYPTPROV gCryptoProv;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void EntropyInit()
|
|
|
|
{
|
|
|
|
#if defined(USE_OLD_NTCRYPT)
|
2023-07-09 10:26:17 +00:00
|
|
|
if (pBCryptGenRandom)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
2023-07-09 10:26:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-11 16:58:20 +00:00
|
|
|
if (pRtlGenRandom)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-09 10:26:17 +00:00
|
|
|
if (pCryptAcquireContextW)
|
|
|
|
{
|
|
|
|
if (!pCryptAcquireContextW(&gCryptoProv, NULL,
|
|
|
|
MS_DEF_PROV_W, PROV_RSA_FULL,
|
|
|
|
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)))
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
2023-07-09 10:26:17 +00:00
|
|
|
if (!pCryptAcquireContextW(&gCryptoProv, NULL,
|
|
|
|
MS_DEF_PROV_W, PROV_RSA_FULL,
|
|
|
|
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
|
|
|
|
{
|
|
|
|
gCryptoProv = 0;
|
|
|
|
}
|
2022-09-19 01:34:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
static AuUInt32 RngWin32(AuUInt8 *pBuf, AuUInt32 uLen)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
2023-07-09 10:26:17 +00:00
|
|
|
if (pBCryptGenRandom)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
2023-07-11 16:58:20 +00:00
|
|
|
if (AuSwInfo::IsWindows10OrGreater() ||
|
|
|
|
AuBuild::kCurrentPlatform != AuBuild::EPlatform::ePlatformWin32)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
2023-07-11 16:58:20 +00:00
|
|
|
if (pRtlGenRandom)
|
|
|
|
{
|
|
|
|
if (pRtlGenRandom(pBuf, uLen))
|
|
|
|
{
|
|
|
|
return uLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pBCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, reinterpret_cast<PUCHAR>(pBuf), uLen, 0) == 0)
|
|
|
|
{
|
|
|
|
return uLen;
|
|
|
|
}
|
2022-09-19 01:34:57 +00:00
|
|
|
}
|
|
|
|
|
2023-07-09 10:26:17 +00:00
|
|
|
if (pBCryptGenRandom(NULL, reinterpret_cast<PUCHAR>(pBuf), uLen, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
|
|
|
|
{
|
|
|
|
return uLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-11 16:58:20 +00:00
|
|
|
if (pRtlGenRandom)
|
|
|
|
{
|
|
|
|
if (pRtlGenRandom(pBuf, uLen))
|
|
|
|
{
|
|
|
|
return uLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-09 10:26:17 +00:00
|
|
|
#if defined(USE_OLD_NTCRYPT)
|
|
|
|
if (gCryptoProv)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
2023-07-09 10:26:17 +00:00
|
|
|
if (pCryptGenRandom(gCryptoProv, uLen, pBuf))
|
|
|
|
{
|
|
|
|
return uLen;
|
|
|
|
}
|
2022-09-19 01:34:57 +00:00
|
|
|
}
|
2023-07-09 10:26:17 +00:00
|
|
|
#endif
|
2022-09-19 01:34:57 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
void EntropyInit()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2023-07-11 16:58:20 +00:00
|
|
|
static AuUInt64 RngTimeClock()
|
|
|
|
{
|
|
|
|
#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)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
2023-07-11 16:58:20 +00:00
|
|
|
AuUInt64 t1;
|
|
|
|
int l, acc, bits, a, b, c;
|
2022-09-19 01:34:57 +00:00
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
l = uLen;
|
2023-07-11 16:58:20 +00:00
|
|
|
acc = a = b = c = 0;
|
2022-09-19 01:34:57 +00:00
|
|
|
bits = 8;
|
|
|
|
|
2023-07-11 16:58:20 +00:00
|
|
|
void *pASLRSeed = &RngTimeBased;
|
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
while (uLen--)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
|
|
|
while (bits--) // for each bit in byte
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2023-07-11 16:58:20 +00:00
|
|
|
t1 = RngTimeClock();
|
|
|
|
while (t1 == RngTimeClock()) // spin within 1 microseconds
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
|
|
|
a ^= 1; // flip
|
|
|
|
}
|
|
|
|
|
2023-07-11 16:58:20 +00:00
|
|
|
t1 = RngTimeClock();
|
|
|
|
while (t1 == RngTimeClock()) // spin within 1 microseconds
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
|
|
|
b ^= 1; // flip
|
|
|
|
}
|
2023-07-11 16:58:20 +00:00
|
|
|
}
|
|
|
|
while (a == b); // ensure theres enough entropy for a deviation to occur
|
2022-09-19 01:34:57 +00:00
|
|
|
acc = (acc << 1) | a; // push the first bit state
|
|
|
|
}
|
|
|
|
|
2023-07-11 16:58:20 +00:00
|
|
|
*pBuf = AuFnv1a32Runtime(&acc, sizeof(acc)) ^
|
|
|
|
AuFnv1a32Runtime(&c, sizeof(c)) ^
|
|
|
|
AuFnv1a32Runtime(&pASLRSeed, sizeof(pASLRSeed));
|
|
|
|
|
|
|
|
c = *pBuf++;
|
2022-09-19 01:34:57 +00:00
|
|
|
|
|
|
|
acc = 0;
|
|
|
|
bits = 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2022-11-17 07:46:07 +00:00
|
|
|
AuUInt32 RngGetBytes(AuUInt8 *pBuffer, AuUInt32 uBytes)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
|
|
|
AuUInt32 x;
|
|
|
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
2022-11-17 07:46:07 +00:00
|
|
|
x = RngWin32(pBuffer, uBytes);
|
2022-09-19 01:34:57 +00:00
|
|
|
if (x != 0)
|
|
|
|
{
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
#elif defined(AURORA_IS_POSIX_DERIVED)
|
2022-12-16 00:41:01 +00:00
|
|
|
x = RngUnix(pBuffer, uBytes);
|
2022-09-19 01:34:57 +00:00
|
|
|
if (x != 0)
|
|
|
|
{
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
#endif
|
2023-07-11 16:58:20 +00:00
|
|
|
x = RngTimeBased(pBuffer, uBytes);
|
2022-09-19 01:34:57 +00:00
|
|
|
if (x != 0)
|
|
|
|
{
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntropyDeinit()
|
|
|
|
{
|
|
|
|
#if defined(AURORA_IS_POSIX_DERIVED)
|
2022-12-16 17:18:12 +00:00
|
|
|
if (gDevURand > 0)
|
2022-09-19 01:34:57 +00:00
|
|
|
{
|
|
|
|
::close(gDevURand);
|
2023-07-10 19:56:45 +00:00
|
|
|
gDevURand = -1;
|
2022-09-19 01:34:57 +00:00
|
|
|
}
|
|
|
|
#elif defined(AURORA_IS_MODERNNT_DERIVED) && defined(USE_OLD_NTCRYPT)
|
2023-07-09 10:26:17 +00:00
|
|
|
if (pBCryptGenRandom)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-11 16:58:20 +00:00
|
|
|
if (pRtlGenRandom)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-09 10:26:17 +00:00
|
|
|
if (pCryptReleaseContext)
|
|
|
|
{
|
|
|
|
pCryptReleaseContext(gCryptoProv, 0);
|
|
|
|
}
|
2022-09-19 01:34:57 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|