Make sure that the requested number of random bytes is fully read, even if a single read() invocation returned fewer than "count" bytes.

This commit is contained in:
LoRd_MuldeR 2022-02-08 22:46:33 +01:00
parent 956e79ecc6
commit c63c3bffe6
Signed by: mulder
GPG Key ID: 2B5913365F57E03F
3 changed files with 38 additions and 16 deletions

View File

@ -8,7 +8,7 @@
/* Intel(R) oneAPI DPC++/C++ Compiler */
#if defined(__INTEL_LLVM_COMPILER) && (!defined(__GNUC__))
# define __GNUC__ 9
# define __GNUC__ 10
#endif
/* Compiler compatibility */

View File

@ -28,6 +28,7 @@ static INLINE size_t MIN_SIZE(const size_t a, const size_t b) { return (a > b) ?
#ifdef _WIN32
# include <Windows.h>
# include <io.h>
#else
# include <unistd.h>
# include <pthread.h>
@ -88,12 +89,14 @@ static void win32_call_once(CALL_ONCE_TYPE *const control, void (*init_routine)(
// Random bytes
// ==========================================================================
#define MAX_COUNT 1048576U
/* Global state */
static CALL_ONCE_TYPE s_random_is_initialized = CALL_ONCE_INIT;
#if defined(_WIN32)
typedef BOOLEAN(WINAPI *rtlgenrandom_t)(void *buffer, ULONG length);
typedef BOOLEAN(WINAPI *ptr_genrandom_t)(void *buffer, ULONG length);
static HMODULE s_advapi32 = NULL;
static rtlgenrandom_t s_rtlgenrandom = NULL;
static ptr_genrandom_t s_genrandom = NULL;
#else
static const char *const DEV_RANDOM[] = { "/dev/urandom", "/dev/arandom", "/dev/random", NULL };
static int s_random_fd = -1;
@ -102,8 +105,11 @@ static int s_random_fd = -1;
/* De-initialize CSRNG */
static void exit_random_source(void)
{
#if defined(_WIN32)
s_rtlgenrandom = NULL;
#ifdef _WIN32
if (s_genrandom)
{
s_genrandom = NULL;
}
if (s_advapi32)
{
FreeLibrary(s_advapi32);
@ -121,10 +127,10 @@ static void exit_random_source(void)
/* Initialize CSRNG */
static void init_random_source(void)
{
#if defined(_WIN32)
#ifdef _WIN32
if ((s_advapi32 = LoadLibraryW(L"advapi32.dll")))
{
s_rtlgenrandom = (rtlgenrandom_t) GetProcAddress(s_advapi32, "SystemFunction036");
s_genrandom = (ptr_genrandom_t) GetProcAddress(s_advapi32, "SystemFunction036");
}
#else
#if defined(GETENTROPY)
@ -151,27 +157,43 @@ init_completed: ;
/* Generate random bytes */
size_t slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length)
{
size_t offset;
CALL_ONCE(&s_random_is_initialized, init_random_source);
#if defined(_WIN32)
if (s_rtlgenrandom)
#ifdef _WIN32
if (s_genrandom)
{
const ULONG count = (ULONG) MIN_SIZE(length, ULONG_MAX);
return s_rtlgenrandom(buffer, count) ? count : 0U;
ULONG count;
for (offset = 0U; offset < length; offset += count)
{
count = (ULONG) MIN_SIZE(length - offset, MAX_COUNT);
if (!s_genrandom(buffer + offset, count))
{
break; /*failed*/
}
}
return offset;
}
return 0U;
#else
if (s_random_fd >= 0)
{
const ssize_t result = read(s_random_fd, buffer, length);
return (result < 0) ? 0U : ((size_t)result);
ssize_t count;
for (offset = 0; offset < length; offset += (size_t)count)
{
if (!((count = read(s_random_fd, buffer + offset, MIN_SIZE(length - offset, MAX_COUNT))) > 0))
{
break; /*failed*/
}
}
return offset;
}
#if defined(GETENTROPY)
else
{
size_t offset, count;
size_t count;
for (offset = 0U; offset < length; offset += count)
{
count = MIN_SIZE(length - offset, 256U);
count = MIN_SIZE(length - offset, 256U); /*the maximum permitted value is 256*/
if (GETENTROPY(buffer + offset, count) < 0)
{
break; /*failed*/

View File

@ -8,6 +8,6 @@
#define LIB_VERSION_MAJOR 1
#define LIB_VERSION_MINOR 1
#define LIB_VERSION_PATCH 1
#define LIB_VERSION_PATCH 2
#endif