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:
parent
956e79ecc6
commit
c63c3bffe6
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
/* Intel(R) oneAPI DPC++/C++ Compiler */
|
/* Intel(R) oneAPI DPC++/C++ Compiler */
|
||||||
#if defined(__INTEL_LLVM_COMPILER) && (!defined(__GNUC__))
|
#if defined(__INTEL_LLVM_COMPILER) && (!defined(__GNUC__))
|
||||||
# define __GNUC__ 9
|
# define __GNUC__ 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Compiler compatibility */
|
/* Compiler compatibility */
|
||||||
|
@ -28,6 +28,7 @@ static INLINE size_t MIN_SIZE(const size_t a, const size_t b) { return (a > b) ?
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <Windows.h>
|
# include <Windows.h>
|
||||||
|
# include <io.h>
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
@ -88,12 +89,14 @@ static void win32_call_once(CALL_ONCE_TYPE *const control, void (*init_routine)(
|
|||||||
// Random bytes
|
// Random bytes
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
#define MAX_COUNT 1048576U
|
||||||
|
|
||||||
/* Global state */
|
/* Global state */
|
||||||
static CALL_ONCE_TYPE s_random_is_initialized = CALL_ONCE_INIT;
|
static CALL_ONCE_TYPE s_random_is_initialized = CALL_ONCE_INIT;
|
||||||
#if defined(_WIN32)
|
#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 HMODULE s_advapi32 = NULL;
|
||||||
static rtlgenrandom_t s_rtlgenrandom = NULL;
|
static ptr_genrandom_t s_genrandom = NULL;
|
||||||
#else
|
#else
|
||||||
static const char *const DEV_RANDOM[] = { "/dev/urandom", "/dev/arandom", "/dev/random", NULL };
|
static const char *const DEV_RANDOM[] = { "/dev/urandom", "/dev/arandom", "/dev/random", NULL };
|
||||||
static int s_random_fd = -1;
|
static int s_random_fd = -1;
|
||||||
@ -102,8 +105,11 @@ static int s_random_fd = -1;
|
|||||||
/* De-initialize CSRNG */
|
/* De-initialize CSRNG */
|
||||||
static void exit_random_source(void)
|
static void exit_random_source(void)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#ifdef _WIN32
|
||||||
s_rtlgenrandom = NULL;
|
if (s_genrandom)
|
||||||
|
{
|
||||||
|
s_genrandom = NULL;
|
||||||
|
}
|
||||||
if (s_advapi32)
|
if (s_advapi32)
|
||||||
{
|
{
|
||||||
FreeLibrary(s_advapi32);
|
FreeLibrary(s_advapi32);
|
||||||
@ -121,10 +127,10 @@ static void exit_random_source(void)
|
|||||||
/* Initialize CSRNG */
|
/* Initialize CSRNG */
|
||||||
static void init_random_source(void)
|
static void init_random_source(void)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#ifdef _WIN32
|
||||||
if ((s_advapi32 = LoadLibraryW(L"advapi32.dll")))
|
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
|
#else
|
||||||
#if defined(GETENTROPY)
|
#if defined(GETENTROPY)
|
||||||
@ -151,27 +157,43 @@ init_completed: ;
|
|||||||
/* Generate random bytes */
|
/* Generate random bytes */
|
||||||
size_t slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length)
|
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);
|
CALL_ONCE(&s_random_is_initialized, init_random_source);
|
||||||
#if defined(_WIN32)
|
#ifdef _WIN32
|
||||||
if (s_rtlgenrandom)
|
if (s_genrandom)
|
||||||
{
|
{
|
||||||
const ULONG count = (ULONG) MIN_SIZE(length, ULONG_MAX);
|
ULONG count;
|
||||||
return s_rtlgenrandom(buffer, count) ? count : 0U;
|
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;
|
return 0U;
|
||||||
#else
|
#else
|
||||||
if (s_random_fd >= 0)
|
if (s_random_fd >= 0)
|
||||||
{
|
{
|
||||||
const ssize_t result = read(s_random_fd, buffer, length);
|
ssize_t count;
|
||||||
return (result < 0) ? 0U : ((size_t)result);
|
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)
|
#if defined(GETENTROPY)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t offset, count;
|
size_t count;
|
||||||
for (offset = 0U; offset < length; offset += 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)
|
if (GETENTROPY(buffer + offset, count) < 0)
|
||||||
{
|
{
|
||||||
break; /*failed*/
|
break; /*failed*/
|
||||||
|
@ -8,6 +8,6 @@
|
|||||||
|
|
||||||
#define LIB_VERSION_MAJOR 1
|
#define LIB_VERSION_MAJOR 1
|
||||||
#define LIB_VERSION_MINOR 1
|
#define LIB_VERSION_MINOR 1
|
||||||
#define LIB_VERSION_PATCH 1
|
#define LIB_VERSION_PATCH 2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user