diff --git a/Single_Header/dn_single_header.cpp b/Single_Header/dn_single_header.cpp index 8b1ac3e..4d5603b 100644 --- a/Single_Header/dn_single_header.cpp +++ b/Single_Header/dn_single_header.cpp @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-07-30 18:54:02 +// Generated by the DN single header generator 2025-08-02 22:07:04 #define DN_BASE_INC_CPP @@ -6513,32 +6513,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 } @@ -8105,24 +8097,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) diff --git a/Single_Header/dn_single_header.h b/Single_Header/dn_single_header.h index 9eff096..ee3593c 100644 --- a/Single_Header/dn_single_header.h +++ b/Single_Header/dn_single_header.h @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-07-30 18:54:02 +// Generated by the DN single header generator 2025-08-02 22:07:04 #if !defined(DN_BASE_INC_H) #define DN_BASE_INC_H @@ -6097,7 +6097,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); diff --git a/Source/Extra/dn_tests.cpp b/Source/Extra/dn_tests.cpp index 42ff5a0..5c8b79b 100644 --- a/Source/Extra/dn_tests.cpp +++ b/Source/Extra/dn_tests.cpp @@ -1821,27 +1821,13 @@ static DN_UTCore DN_Tests_OS() #if defined(DN_OS_INC_CPP) || 1 DN_UT_LogF(&result, "DN_OS\n"); { - for (DN_UT_Test(&result, "Generate secure RNG bytes with nullptr")) { - DN_B32 os_result = DN_OS_SecureRNGBytes(nullptr, 1); - DN_UT_Assert(&result, os_result == false); - } - for (DN_UT_Test(&result, "Generate secure RNG 32 bytes")) { char const ZERO[32] = {}; char buf[32] = {}; - bool os_result = DN_OS_SecureRNGBytes(buf, DN_ArrayCountU(buf)); - DN_UT_Assert(&result, os_result); + DN_OS_GenBytesSecure(buf, DN_ArrayCountU(buf)); DN_UT_Assert(&result, DN_Memcmp(buf, ZERO, DN_ArrayCountU(buf)) != 0); } - for (DN_UT_Test(&result, "Generate secure RNG 0 bytes")) { - char buf[32] = {}; - buf[0] = 'Z'; - DN_B32 os_result = DN_OS_SecureRNGBytes(buf, 0); - DN_UT_Assert(&result, os_result); - DN_UT_Assert(&result, buf[0] == 'Z'); - } - for (DN_UT_Test(&result, "Query executable directory")) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_Str8 os_result = DN_OS_EXEDir(tmem.arena); diff --git a/Source/OS/dn_os.h b/Source/OS/dn_os.h index 0fa0218..484482f 100644 --- a/Source/OS/dn_os.h +++ b/Source/OS/dn_os.h @@ -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); diff --git a/Source/OS/dn_os_posix.cpp b/Source/OS/dn_os_posix.cpp index 966760e..ae4ca2e 100644 --- a/Source/OS/dn_os_posix.cpp +++ b/Source/OS/dn_os_posix.cpp @@ -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 } diff --git a/Source/OS/dn_os_w32.cpp b/Source/OS/dn_os_w32.cpp index ea6e858..5dc0a20 100644 --- a/Source/OS/dn_os_w32.cpp +++ b/Source/OS/dn_os_w32.cpp @@ -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)