#include "rivide/utils/random.h"
#include "rivide/rivide_config.h"
static rivide_rng_callback_t g_rng_callback = (rivide_rng_callback_t)0;
rivide_status_t rivide_set_rng_callback(rivide_rng_callback_t callback) {
if (!callback) {
return RIVIDE_ERR_NULL_PTR;
}
g_rng_callback = callback;
return RIVIDE_SUCCESS;
}
#if defined(RIVIDE_PLATFORM_LINUX)
#include <sys/random.h>
static rivide_status_t rivide_os_randombytes(uint8_t *buf, size_t len) {
while (len > 0) {
ssize_t ret = getrandom(buf, len, 0);
if (ret < 0) {
return RIVIDE_ERR_RNG_FAILURE;
}
buf += (size_t)ret;
len -= (size_t)ret;
}
return RIVIDE_SUCCESS;
}
#elif defined(RIVIDE_PLATFORM_MACOS)
#include <sys/random.h>
static rivide_status_t rivide_os_randombytes(uint8_t *buf, size_t len) {
while (len > 0) {
size_t chunk = (len > 256) ? 256 : len;
if (getentropy(buf, chunk) != 0) {
return RIVIDE_ERR_RNG_FAILURE;
}
buf += chunk;
len -= chunk;
}
return RIVIDE_SUCCESS;
}
#elif defined(RIVIDE_PLATFORM_WINDOWS)
#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS
#include <ntstatus.h>
#include <bcrypt.h>
#ifdef _MSC_VER
#pragma comment(lib, "bcrypt.lib")
#endif
static rivide_status_t rivide_os_randombytes(uint8_t *buf, size_t len) {
NTSTATUS status = BCryptGenRandom(NULL, buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
if (status != 0) {
return RIVIDE_ERR_RNG_FAILURE;
}
return RIVIDE_SUCCESS;
}
#elif defined(RIVIDE_PLATFORM_BSD)
#include <unistd.h>
static rivide_status_t rivide_os_randombytes(uint8_t *buf, size_t len) {
while (len > 0) {
size_t chunk = (len > 256) ? 256 : len;
if (getentropy(buf, chunk) != 0) {
return RIVIDE_ERR_RNG_FAILURE;
}
buf += chunk;
len -= chunk;
}
return RIVIDE_SUCCESS;
}
#else
static rivide_status_t rivide_os_randombytes(uint8_t *buf, size_t len) {
(void)buf;
(void)len;
return RIVIDE_ERR_RNG_FAILURE;
}
#endif
rivide_status_t rivide_randombytes(uint8_t *buf, size_t len) {
if (!buf && len > 0) {
return RIVIDE_ERR_NULL_PTR;
}
if (len == 0) {
return RIVIDE_SUCCESS;
}
if (g_rng_callback) {
return g_rng_callback(buf, len);
}
return rivide_os_randombytes(buf, len);
}