diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -354,6 +354,12 @@ // 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_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 // NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, // including accesses to the special files under `/dev`. This implementation @@ -367,8 +373,10 @@ // constructor *must* be "/dev/urandom" -- anything else is an error. #if defined(__OpenBSD__) # define _LIBCPP_USING_ARC4_RANDOM -#elif defined(__Fuchsia__) || defined(__wasi__) +#elif defined(__wasi__) # define _LIBCPP_USING_GETENTROPY +#elif defined(__Fuchsia__) +# define _LIBCPP_USING_FUCHSIA_CPRNG #elif defined(__native_client__) # define _LIBCPP_USING_NACL_RANDOM #elif defined(_LIBCPP_WIN32API) diff --git a/libcxx/src/random.cpp b/libcxx/src/random.cpp --- a/libcxx/src/random.cpp +++ b/libcxx/src/random.cpp @@ -36,6 +36,8 @@ # endif #elif defined(_LIBCPP_USING_NACL_RANDOM) # include +#elif defined(_LIBCPP_USING_FUCHSIA_CPRNG) +# include #endif @@ -170,6 +172,27 @@ 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 #error "Random device not implemented for this architecture" #endif @@ -189,7 +212,7 @@ return std::numeric_limits::digits; return ent; -#elif defined(__OpenBSD__) +#elif defined(__OpenBSD__) || defined(_LIBCPP_USING_FUCHSIA_CPRNG) return std::numeric_limits::digits; #else return 0;