aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2025-02-06 17:56:34 +0100
committerThijs Schreijer <thijs@thijsschreijer.nl>2025-02-10 09:01:58 +0100
commit0cb19e1617d735e815e9747a53b6d9f3b3bd568b (patch)
tree6d30d538a13b35dd5b94574f286d5084786e254c
parentee7524563af91aa4f0336088c7f85dc1d68b0066 (diff)
downloadluasystem-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
-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 25114c3..3d95d9f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,8 @@ The scope of what is covered by the version number excludes:
33- Feat: when detecting character display width, also accept unicode codepoints (integers), 33- Feat: when detecting character display width, also accept unicode codepoints (integers),
34 since the Lua utf8 library returns codepoints, not strings 34 since the Lua utf8 library returns codepoints, not strings
35- Fix: NetBSD fix compilation, undeclared directives 35- Fix: NetBSD fix compilation, undeclared directives
36- Refactor: random bytes; remove deprecated API usage on Windows, move to
37 binary api instead of /dev/urandom file on linux and bsd
36 38
37### version 0.4.5, released 18-Dec-2024 39### version 0.4.5, released 18-Dec-2024
38 40
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);