diff --git a/CMakeLists.txt b/CMakeLists.txt index e725bff71..88865c37a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,11 +296,15 @@ if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD") endif() if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - list(APPEND uv_sources src/unix/random-getrandom.c) + list(APPEND uv_sources + src/unix/random-arc4random.c + src/unix/random-getrandom.c) endif() if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") - list(APPEND uv_sources src/unix/random-getentropy.c) + list(APPEND uv_sources + src/unix/random-arc4random.c + src/unix/random-getentropy.c) endif() if(APPLE) @@ -334,7 +338,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") endif() if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") - list(APPEND uv_sources src/unix/netbsd.c) + list(APPEND uv_sources + src/unix/random-arc4random.c + src/unix/random-getentropy.c + src/unix/netbsd.c) list(APPEND uv_libraries kvm) endif() diff --git a/Makefile.am b/Makefile.am index 8a41f18ab..6814eafd5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -436,6 +436,7 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/fsevents.c \ src/unix/kqueue.c \ src/unix/proctitle.c \ + src/unix/random-arc4random.c \ src/unix/random-getentropy.c test_run_tests_LDFLAGS += -lutil -lm endif @@ -457,6 +458,7 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/freebsd.c \ src/unix/kqueue.c \ src/unix/posix-hrtime.c \ + src/unix/random-arc4random.c \ src/unix/random-getrandom.c test_run_tests_LDFLAGS += -lutil -lm endif @@ -512,7 +514,9 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/bsd-proctitle.c \ src/unix/kqueue.c \ src/unix/netbsd.c \ - src/unix/posix-hrtime.c + src/unix/posix-hrtime.c \ + src/unix/random-arc4random.c \ + src/unix/random-getentropy.c test_run_tests_LDFLAGS += -lutil -lm endif @@ -523,6 +527,7 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/kqueue.c \ src/unix/openbsd.c \ src/unix/posix-hrtime.c \ + src/unix/random-arc4random.c \ src/unix/random-getentropy.c test_run_tests_LDFLAGS += -lutil -lm endif diff --git a/docs/src/misc.rst b/docs/src/misc.rst index db95e2dde..4a90b65a1 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -868,10 +868,14 @@ API - Linux, Android: :man:`getrandom(2)` if available, or :man:`urandom(4)` after reading from `/dev/random` once, or the `KERN_RANDOM` :man:`sysctl(2)`. - - FreeBSD: `getrandom(2) _`, + - FreeBSD: `arc4random(3) _`, + or `getrandom(2) _`, or `/dev/urandom` after reading from `/dev/random` once. - - NetBSD: `KERN_ARND` `sysctl(7) _` - - macOS, OpenBSD: `getentropy(2) _` + - NetBSD: `arc4random(3) _`, + or `getentropy(3) _` if available, + or `KERN_ARND` `sysctl(7) _` + - macOS, OpenBSD: `arc4random(3) _`, + or `getentropy(2) _` if available, or `/dev/urandom` after reading from `/dev/random` once. - AIX: `/dev/random`. - IBM i: `/dev/urandom`. diff --git a/src/random.c b/src/random.c index 402678cb6..c6c5bc31a 100644 --- a/src/random.c +++ b/src/random.c @@ -35,14 +35,29 @@ static int uv__random(void* buf, size_t buflen) { rc = uv__random_readpath("/dev/urandom", buf, buflen); #elif defined(_AIX) || defined(__QNX__) rc = uv__random_readpath("/dev/random", buf, buflen); -#elif defined(__APPLE__) || defined(__OpenBSD__) || \ - (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) +#elif defined(__APPLE__) || defined(__OpenBSD__) + rc = uv__random_arc4random(buf, buflen); + if (rc == UV_ENOSYS) + rc = uv__random_getentropy(buf, buflen); + if (rc == UV_ENOSYS) + rc = uv__random_devurandom(buf, buflen); +#elif defined(__ANDROID_API__) && __ANDROID_API__ >= 28 rc = uv__random_getentropy(buf, buflen); if (rc == UV_ENOSYS) rc = uv__random_devurandom(buf, buflen); #elif defined(__NetBSD__) - rc = uv__random_sysctl(buf, buflen); -#elif defined(__FreeBSD__) || defined(__linux__) + rc = uv__random_arc4random(buf, buflen); + if (rc == UV_ENOSYS) + rc = uv__random_getentropy(buf, buflen); /* Since NetBSD 10.1 */ + if (rc == UV_ENOSYS) + rc = uv__random_sysctl(buf, buflen); +#elif defined(__FreeBSD__) + rc = uv__random_arc4random(buf, buflen); + if (rc == UV_ENOSYS) + rc = uv__random_getrandom(buf, buflen); + if (rc == UV_ENOSYS) + rc = uv__random_devurandom(buf, buflen); +#elif defined(__linux__) rc = uv__random_getrandom(buf, buflen); if (rc == UV_ENOSYS) rc = uv__random_devurandom(buf, buflen); diff --git a/src/unix/internal.h b/src/unix/internal.h index c9704a8bd..2bc74a514 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -404,6 +404,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen); void uv__wait_children(uv_loop_t* loop); /* random */ +int uv__random_arc4random(void* buf, size_t buflen); int uv__random_devurandom(void* buf, size_t buflen); int uv__random_getrandom(void* buf, size_t buflen); int uv__random_getentropy(void* buf, size_t buflen); diff --git a/src/unix/random-arc4random.c b/src/unix/random-arc4random.c new file mode 100644 index 000000000..0596465d1 --- /dev/null +++ b/src/unix/random-arc4random.c @@ -0,0 +1,49 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +typedef int (*uv__arc4random_cb)(void*, size_t); + +static uv__arc4random_cb uv__arc4random; +static uv_once_t once = UV_ONCE_INIT; + + +static void uv__random_arc4random_init(void) { + uv__arc4random = (uv__arc4random_cb) dlsym(RTLD_DEFAULT, "arc4random_buf"); +} + + +int uv__random_arc4random(void* buf, size_t buflen) { + uv_once(&once, uv__random_arc4random_init); + + if (uv__arc4random == NULL) + return UV_ENOSYS; + + if (uv__arc4random(buf, buflen)) + return UV__ERR(errno); + + return 0; +}