fuchsia: Implement rand_util
There's no /dev/urandom on Fuchsia, but mx_cprng_draw() is similar to
base::RandBytes().
Ref: https://fuchsia.googlesource.com/magenta/+/HEAD/docs/syscalls/cprng_draw.md
Makes RandUtilTest.* pass.
Bug: 706592
Change-Id: Idd16d322b965be498d733aa29a2d7764145408d7
Reviewed-on: https://chromium-review.googlesource.com/520607
Commit-Queue: Scott Graham <scottmg@chromium.org>
Reviewed-by: Nico Weber <thakis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#476410}
diff --git a/base/BUILD.gn b/base/BUILD.gn
index a265f98..679683c 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1234,6 +1234,7 @@
"process/launch_posix.cc",
"process/process_handle_posix.cc",
"process/process_posix.cc",
+ "rand_util_posix.cc",
]
sources += [
@@ -1248,6 +1249,7 @@
"process/process_fuchsia.cc",
"process/process_handle_fuchsia.cc",
"process/process_metrics_fuchsia.cc",
+ "rand_util_fuchsia.cc",
"sys_info_fuchsia.cc",
"threading/platform_thread_fuchsia.cc",
"time/time_conversion_posix.cc",
diff --git a/base/rand_util.h b/base/rand_util.h
index 881dbd50..286d69c 100644
--- a/base/rand_util.h
+++ b/base/rand_util.h
@@ -53,7 +53,7 @@
// See crypto/ for cryptographically secure random number generation APIs.
BASE_EXPORT std::string RandBytesAsString(size_t length);
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
BASE_EXPORT int GetUrandomFD();
#endif
diff --git a/base/rand_util_fuchsia.cc b/base/rand_util_fuchsia.cc
new file mode 100644
index 0000000..e902d16
--- /dev/null
+++ b/base/rand_util_fuchsia.cc
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/rand_util.h"
+
+#include <magenta/syscalls.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+namespace base {
+
+uint64_t RandUint64() {
+ uint64_t number;
+ RandBytes(&number, sizeof(number));
+ return number;
+}
+
+void RandBytes(void* output, size_t output_length) {
+ size_t remaining = output_length;
+ unsigned char* cur = reinterpret_cast<unsigned char*>(output);
+ do {
+ // The syscall has a maximum number of bytes that can be read at once.
+ size_t read_len =
+ std::min(remaining, static_cast<size_t>(MX_CPRNG_DRAW_MAX_LEN));
+
+ size_t actual;
+ mx_status_t status = mx_cprng_draw(cur, read_len, &actual);
+ CHECK(status == NO_ERROR && read_len == actual);
+
+ CHECK(remaining >= actual);
+ remaining -= actual;
+ cur += actual;
+ } while (remaining > 0);
+}
+
+} // namespace base
diff --git a/base/rand_util_unittest.cc b/base/rand_util_unittest.cc
index 4f46b807..dc61e9f 100644
--- a/base/rand_util_unittest.cc
+++ b/base/rand_util_unittest.cc
@@ -134,6 +134,17 @@
FAIL() << "Didn't achieve all bit values in maximum number of tries.";
}
+TEST(RandUtilTest, RandBytesLonger) {
+ // Fuchsia can only retrieve 256 bytes of entropy at a time, so make sure we
+ // handle longer requests than that.
+ std::string random_string0 = base::RandBytesAsString(255);
+ EXPECT_EQ(255u, random_string0.size());
+ std::string random_string1 = base::RandBytesAsString(1023);
+ EXPECT_EQ(1023u, random_string1.size());
+ std::string random_string2 = base::RandBytesAsString(4097);
+ EXPECT_EQ(4097u, random_string2.size());
+}
+
// Benchmark test for RandBytes(). Disabled since it's intentionally slow and
// does not test anything that isn't already tested by the existing RandBytes()
// tests.