Improve usage of getrandom for generating bytes

This commit is contained in:
2025-08-02 22:07:18 +10:00
parent a8803bb539
commit aab2cd3af4
6 changed files with 41 additions and 87 deletions
+1 -1
View File
@@ -331,7 +331,7 @@ DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date);
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
// NOTE: Other /////////////////////////////////////////////////////////////////////////////////////
DN_API bool DN_OS_SecureRNGBytes (void *buffer, DN_U32 size);
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);
DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path);
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
+13 -21
View File
@@ -162,32 +162,24 @@ DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time)
return result;
}
DN_API bool DN_OS_SecureRNGBytes(void *buffer, DN_U32 size)
DN_API void DN_OS_GenBytesSecure(void *buffer, DN_U32 size)
{
#if defined(DN_PLATFORM_EMSCRIPTEN)
DN_InvalidCodePath;
(void)buffer;
(void)size;
return false;
#else
if (!buffer || size < 0)
return false;
if (size == 0)
return true;
DN_AssertF(size <= 32,
"We can increase this by chunking the buffer and filling 32 bytes at a time. *Nix "
"guarantees 32 "
"bytes can always be fulfilled by this system at a time");
// TODO(doyle):
// https://github.com/jedisct1/libsodium/blob/master/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c
// TODO(doyle): https://man7.org/linux/man-pages/man2/getrandom.2.html
DN_U32 read_bytes = 0;
do {
read_bytes =
getrandom(buffer, size, 0); // NOTE: EINTR can not be triggered if size <= 32 bytes
} while (read_bytes != size || errno == EAGAIN);
return true;
DN_Assert(buffer && size);
DN_USize bytes_written = 0;
while (bytes_written < size) {
DN_USize bytes_remaining = size - bytes_written;
DN_USize need_amount = DN_Min(bytes_remaining, 32);
DN_USize bytes_read = 0;
do {
bytes_read = getrandom((DN_U8 *)buffer + bytes_written, need_amount, 0);
} while (bytes_read != need_amount || errno == EAGAIN || errno == EINTR);
bytes_written += bytes_read;
}
#endif
}
+5 -13
View File
@@ -223,24 +223,16 @@ DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(DN_U64 time)
return result;
}
DN_API bool DN_OS_SecureRNGBytes(void *buffer, DN_U32 size)
DN_API void DN_OS_GenBytesSecure(void *buffer, DN_U32 size)
{
DN_Assert(g_dn_os_core_);
DN_W32Core *w32 = DN_CAST(DN_W32Core *) g_dn_os_core_->platform_context;
if (!buffer || size < 0 || !w32->bcrypt_init_success)
return false;
if (size == 0)
return true;
DN_Assert(w32->bcrypt_init_success);
long gen_status = BCryptGenRandom(w32->bcrypt_rng_handle, DN_CAST(unsigned char *) buffer, size, 0 /*flags*/);
if (gen_status != 0) {
DN_LOG_ErrorF("Failed to generate random bytes: %d", gen_status);
return false;
}
return true;
// NOTE: This can only fail if the handle is invalid or one or more parameters are invalid. We
// validate our parameters so this shouldn't be the case.
DN_Assert(gen_status == 0);
}
DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)