[libcxx] Use Fuchsia-native CPRNG for std::random_device

Use the zx_cprng_draw system call directly rather than going
through the libc getentropy function.  The libc function is a
trivial wrapper around the system call, and is not a standard C
function.  Avoiding it reduces the Fuchsia libc ABI surface that
libc++ depends on.

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D116498
This commit is contained in:
Roland McGrath 2022-01-02 11:53:53 -08:00
parent 1e50d06466
commit 3064dd8ccf
2 changed files with 33 additions and 2 deletions

View File

@ -354,6 +354,12 @@
// When this option is used, the token passed to `std::random_device`'s // When this option is used, the token passed to `std::random_device`'s
// constructor *must* be "/dev/urandom" -- anything else is an error. // constructor *must* be "/dev/urandom" -- anything else is an error.
// //
// _LIBCPP_USING_FUCHSIA_CPRNG
// Use Fuchsia's zx_cprng_draw() system call, which is specified to
// deliver high-quality entropy and cannot fail.
// When this option is used, the token passed to `std::random_device`'s
// constructor *must* be "/dev/urandom" -- anything else is an error.
//
// _LIBCPP_USING_NACL_RANDOM // _LIBCPP_USING_NACL_RANDOM
// NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, // NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access,
// including accesses to the special files under `/dev`. This implementation // including accesses to the special files under `/dev`. This implementation
@ -367,8 +373,10 @@
// constructor *must* be "/dev/urandom" -- anything else is an error. // constructor *must* be "/dev/urandom" -- anything else is an error.
#if defined(__OpenBSD__) #if defined(__OpenBSD__)
# define _LIBCPP_USING_ARC4_RANDOM # define _LIBCPP_USING_ARC4_RANDOM
#elif defined(__Fuchsia__) || defined(__wasi__) #elif defined(__wasi__)
# define _LIBCPP_USING_GETENTROPY # define _LIBCPP_USING_GETENTROPY
#elif defined(__Fuchsia__)
# define _LIBCPP_USING_FUCHSIA_CPRNG
#elif defined(__native_client__) #elif defined(__native_client__)
# define _LIBCPP_USING_NACL_RANDOM # define _LIBCPP_USING_NACL_RANDOM
#elif defined(_LIBCPP_WIN32API) #elif defined(_LIBCPP_WIN32API)

View File

@ -36,6 +36,8 @@
# endif # endif
#elif defined(_LIBCPP_USING_NACL_RANDOM) #elif defined(_LIBCPP_USING_NACL_RANDOM)
# include <nacl/nacl_random.h> # include <nacl/nacl_random.h>
#elif defined(_LIBCPP_USING_FUCHSIA_CPRNG)
# include <zircon/syscalls.h>
#endif #endif
@ -170,6 +172,27 @@ random_device::operator()()
return r; return r;
} }
#elif defined(_LIBCPP_USING_FUCHSIA_CPRNG)
random_device::random_device(const string& __token) {
if (__token != "/dev/urandom")
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
}
random_device::~random_device() {}
unsigned random_device::operator()() {
// Implicitly link against the vDSO system call ABI without
// requiring the final link to specify -lzircon explicitly when
// statically linking libc++.
# pragma comment(lib, "zircon")
// The system call cannot fail. It returns only when the bits are ready.
unsigned r;
_zx_cprng_draw(&r, sizeof(r));
return r;
}
#else #else
#error "Random device not implemented for this architecture" #error "Random device not implemented for this architecture"
#endif #endif
@ -189,7 +212,7 @@ random_device::entropy() const noexcept
return std::numeric_limits<result_type>::digits; return std::numeric_limits<result_type>::digits;
return ent; return ent;
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__) || defined(_LIBCPP_USING_FUCHSIA_CPRNG)
return std::numeric_limits<result_type>::digits; return std::numeric_limits<result_type>::digits;
#else #else
return 0; return 0;