aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2025-02-06 17:56:34 +0100
committerThijs <thijs@thijsschreijer.nl>2025-02-06 21:22:47 +0100
commit6cd431d64d604ccfaa9c6174acb8878d2cf82e93 (patch)
tree6794ca9710c07748e5550e71e316c008824aea31
parent6f4b532a2142c605aa23f1d78a1b48bd09af669f (diff)
downloadluasystem-refactor/random.tar.gz
luasystem-refactor/random.tar.bz2
luasystem-refactor/random.zip
refactor(random): on linux+bsd use api instead of /dev/urandomrefactor/random
the api is faster and equally good
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/random.c34
2 files changed, 31 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7ae7189..9a127e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,8 @@ The scope of what is covered by the version number excludes:
31### unreleased 31### unreleased
32 32
33- Fix: NetBSD fix compilation, undeclared directives 33- Fix: NetBSD fix compilation, undeclared directives
34- Refactor: random bytes; remove deprecated API usage on Windows, move to
35 binary api instead of /dev/urandom file on linux and bsd
34 36
35### version 0.4.5, released 18-Dec-2024 37### version 0.4.5, released 18-Dec-2024
36 38
diff --git a/src/random.c b/src/random.c
index ee544c4..70bf13b 100644
--- a/src/random.c
+++ b/src/random.c
@@ -13,15 +13,21 @@
13 #include <windows.h> 13 #include <windows.h>
14 #include <bcrypt.h> 14 #include <bcrypt.h>
15#else 15#else
16#include <errno.h> 16 #include <errno.h>
17#include <unistd.h> 17 #include <unistd.h>
18#include <string.h> 18 #include <string.h>
19 #if defined(__linux__)
20 #include <sys/random.h> // getrandom()
21 #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
22 #include <stdlib.h> // arc4random_buf()
23 #endif
19#endif 24#endif
20 25
21 26
22/*** 27/***
23Generate random bytes. 28Generate random bytes.
24This uses `BCryptGenRandom()` on Windows, and `/dev/urandom` on other platforms. It will return the 29This uses `BCryptGenRandom()` on Windows, `getrandom()` on Linux, `arc4random_buf` on BSD,
30and `/dev/urandom` on other platforms. It will return the
25requested number of bytes, or an error, never a partial result. 31requested number of bytes, or an error, never a partial result.
26@function random 32@function random
27@tparam[opt=1] int length number of bytes to get 33@tparam[opt=1] int length number of bytes to get
@@ -53,6 +59,7 @@ static int lua_get_random_bytes(lua_State* L) {
53 ssize_t total_read = 0; 59 ssize_t total_read = 0;
54 60
55#ifdef _WIN32 61#ifdef _WIN32
62 // Use BCryptGenRandom() on Windows
56 if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, num_bytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) { 63 if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, num_bytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
57 DWORD error = GetLastError(); 64 DWORD error = GetLastError();
58 lua_pushnil(L); 65 lua_pushnil(L);
@@ -60,8 +67,25 @@ static int lua_get_random_bytes(lua_State* L) {
60 return 2; 67 return 2;
61 } 68 }
62 69
70#elif defined(__linux__)
71 // Use getrandom() on Linux (Kernel 3.17+, 2014)
72 while (total_read < num_bytes) {
73 ssize_t n = getrandom(buffer + total_read, num_bytes - total_read, 0);
74 if (n < 0) {
75 if (errno == EINTR) continue; // Retry on interrupt
76 lua_pushnil(L);
77 lua_pushfstring(L, "getrandom() failed: %s", strerror(errno));
78 return 2;
79 }
80 total_read += n;
81 }
82
83#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
84 // Use arc4random_buf() on BSD/macOS
85 arc4random_buf(buffer, num_bytes);
86
63#else 87#else
64 // for macOS/unixes use /dev/urandom for non-blocking 88 // fall back to /dev/urandom for anything else
65 int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); 89 int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
66 if (fd < 0) { 90 if (fd < 0) {
67 lua_pushnil(L); 91 lua_pushnil(L);