[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
NOKEYCHECK=True
GitOrigin-RevId: 3064dd8ccffc561e0f01cfa930b9a481d90e7f4f
diff --git a/src/random.cpp b/src/random.cpp
index 286a457..5590db8 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -36,6 +36,8 @@
# endif
#elif defined(_LIBCPP_USING_NACL_RANDOM)
# include <nacl/nacl_random.h>
+#elif defined(_LIBCPP_USING_FUCHSIA_CPRNG)
+# include <zircon/syscalls.h>
#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<result_type>::digits;
return ent;
-#elif defined(__OpenBSD__)
+#elif defined(__OpenBSD__) || defined(_LIBCPP_USING_FUCHSIA_CPRNG)
return std::numeric_limits<result_type>::digits;
#else
return 0;