[go: nahoru, domu]

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.