AuroraRuntime/Source/RNG/RNGEntropy.cpp
Reece Wilson 8a2947ffc5 [+] RMD128+BScFwd based HashCash (bcrypt DoS mitigation, acc creation, antibot, etc)
[*] Refactor bcrypt api: HashPW[Ex] -> HashPassword[Ex]
[+] ByteBuffer::GetOrAllocateLinearWriteable
[+] ByteBuffer::Can[Read/Write](n)
[+] ByteBuffer::GetLinear[Read/Writable]able(n)
[*] Split RNG.cpp into two files
[+] EHashType::eSHA2_48 (_32, _64 was already in place. missed 48/384 bit)
[+] AuCrypto::HMAC and IHMACContext
(AuHashing)
[+] EHashType::eSHA3_28
[+] EHashType::eSHA3_32
[+] EHashType::eSHA3_48
[+] EHashType::eSHA3_64
(AuCrypto)
[+] EHashType::eSHA2_48_384
[+] EHashType::eSHA2_64_512
[+] EHashType::eSHA3_28_224
[+] EHashType::eSHA3_32_256
[+] EHashType::eSHA3_48_384
[+] EHashType::eSHA3_64_512
[*] (IRandomDevice) class -> struct
[*] Bugfix: cast in Promise<SuccessValue_t, ErrorValue_t>::WriteIntoError
[+] Missing AuHashing namespace alias
[*] Time util: pad ms when fraction of a second to 3 digits
2022-09-19 02:34:57 +01:00

191 lines
4.0 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RNGEntropy.cpp
Date: 2022-9-17
File: RNG.cpp
Date: 2021-6-11
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "RNG.hpp"
#include "RNGEntropy.hpp"
#if defined(AURORA_PLATFORM_WIN32)
#include <wincrypt.h>
#include <bcrypt.h>
#include <bcrypt.h>
#endif
#if defined(AURORA_IS_POSIX_DERIVED)
#include <cstdio>
#endif
#include "WELL.hpp"
namespace Aurora::RNG
{
#if defined(AURORA_IS_POSIX_DERIVED)
static int gDevURand;
void EntropyInit()
{
gDevURand = ::open("/dev/urandom", O_RDONLY);
if (gDevURand <= 0)
{
gDevURand = ::open("/dev/random", O_RDONLY);
}
if (gDevURand <= 0)
{
gDevURand = -1;
}
}
static AuUInt32 RngUnix(AuUInt8 *buf, AuUInt32 len)
{
if (gDevURand == -1)
{
return 0;
}
return ::read(gDevURand, buf, len);
}
#elif defined(AURORA_IS_MODERNNT_DERIVED)
#if defined(USE_OLD_NTCRYPT)
static HCRYPTPROV gCryptoProv;
#endif
void EntropyInit()
{
#if defined(USE_OLD_NTCRYPT)
if (!CryptAcquireContext(&gCryptoProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)))
{
if (!CryptAcquireContext(&gCryptoProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
{
gCryptoProv = 0;
}
}
#endif
}
static AuUInt32 RngWin32(AuUInt8 *buf, AuUInt32 len)
{
#if defined(USE_OLD_NTCRYPT)
if (!gCryptoProv)
{
return 0;
}
if (!::CryptGenRandom(gCryptoProv, len, buf))
{
return 0;
}
return len;
#else
#if !defined(AURORA_DONT_PREFER_WIN32_USERLAND_AES_RNG)
if (::BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, reinterpret_cast<PUCHAR>(buf), len, 0) == 0)
{
return len;
}
#endif
if (::BCryptGenRandom(NULL, reinterpret_cast<PUCHAR>(buf), len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
{
return len;
}
return 0;
#endif
}
#else
void EntropyInit()
{
}
#endif
static AuUInt32 RngStdC(AuUInt8 *buf, AuUInt32 len)
{
clock_t t1;
int l, acc, bits, a, b;
l = len;
acc = a = b = 0;
bits = 8;
while (len--)
{
while (bits--) // for each bit in byte
{
do
{
t1 = clock();
while (t1 == clock()) // spin within the resolution of 1 C clock() tick
{
a ^= 1; // flip
}
t1 = clock();
while (t1 == clock())
{
b ^= 1; // flip
}
} while (a == b); // ensure theres enough entropy for a deviation to occur
acc = (acc << 1) | a; // push the first bit state
}
*buf++ = acc;
acc = 0;
bits = 8;
}
return l;
}
AuUInt32 RngGetBytes(AuUInt8 *out, AuUInt32 outlen)
{
AuUInt32 x;
#if defined(AURORA_IS_MODERNNT_DERIVED)
x = RngWin32(out, outlen);
if (x != 0)
{
return x;
}
#elif defined(AURORA_IS_POSIX_DERIVED)
x = RngUnix(out, outlen);
if (x != 0)
{
return x;
}
#endif
x = RngStdC(out, outlen);
if (x != 0)
{
return x;
}
return 0;
}
void EntropyDeinit()
{
#if defined(AURORA_IS_POSIX_DERIVED)
if (gDevURand <= 0)
{
::close(gDevURand);
}
#elif defined(AURORA_IS_MODERNNT_DERIVED) && defined(USE_OLD_NTCRYPT)
CryptReleaseContext(gCryptoProv, 0);
#endif
}
}