diff options
author | Thijs Schreijer <thijs@thijsschreijer.nl> | 2025-02-06 17:56:34 +0100 |
---|---|---|
committer | Thijs Schreijer <thijs@thijsschreijer.nl> | 2025-02-10 09:01:58 +0100 |
commit | 0cb19e1617d735e815e9747a53b6d9f3b3bd568b (patch) | |
tree | 6d30d538a13b35dd5b94574f286d5084786e254c /src | |
parent | ee7524563af91aa4f0336088c7f85dc1d68b0066 (diff) | |
download | luasystem-0cb19e1617d735e815e9747a53b6d9f3b3bd568b.tar.gz luasystem-0cb19e1617d735e815e9747a53b6d9f3b3bd568b.tar.bz2 luasystem-0cb19e1617d735e815e9747a53b6d9f3b3bd568b.zip |
refactor(random): on linux+bsd use api instead of /dev/urandom
the api is faster and equally good
Diffstat (limited to 'src')
-rw-r--r-- | src/random.c | 34 |
1 files changed, 29 insertions, 5 deletions
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 | /*** |
23 | Generate random bytes. | 28 | Generate random bytes. |
24 | This uses `BCryptGenRandom()` on Windows, and `/dev/urandom` on other platforms. It will return the | 29 | This uses `BCryptGenRandom()` on Windows, `getrandom()` on Linux, `arc4random_buf` on BSD, |
30 | and `/dev/urandom` on other platforms. It will return the | ||
25 | requested number of bytes, or an error, never a partial result. | 31 | requested 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); |