PolicyManager: Add a random number provider.
This patch adds a new provider with a single variable that returns a
random value from /dev/urandom every time it is called. The variable
is exported to all the policy implementations (currently none) in the
policy_manager/all_variables.h file.
BUG=None
TEST=unittests.
Change-Id: I6efdecd0f37f1a706b5a0dfd3a77ac4205e35aa0
Reviewed-on: https://chromium-review.googlesource.com/181537
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/policy_manager/random_provider.cc b/policy_manager/random_provider.cc
new file mode 100644
index 0000000..f2373b0
--- /dev/null
+++ b/policy_manager/random_provider.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2014 The Chromium OS 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 <stdio.h>
+#include <unistd.h>
+
+#include <base/file_path.h>
+#include <base/file_util.h>
+
+#include "policy_manager/random_provider.h"
+#include "policy_manager/random_vars.h"
+
+using std::string;
+
+namespace {
+
+// The device providing randomness.
+const char* kRandomDevice = "/dev/urandom";
+
+} // namespace
+
+namespace chromeos_policy_manager {
+
+// The random variable class implementation.
+class RandomVariable : public Variable<uint64> {
+ public:
+ RandomVariable(FILE* fp) : fp_(fp) {}
+ virtual ~RandomVariable() {}
+
+ protected:
+ virtual const uint64* GetValue(base::TimeDelta /* timeout */,
+ string* errmsg) {
+ uint8 buf[sizeof(uint64)];
+ unsigned int buf_rd = 0;
+
+ while (buf_rd < sizeof(uint64)) {
+ int rd = fread(buf + buf_rd, 1, sizeof(uint64) - buf_rd, fp_.get());
+ if (rd == 0 || ferror(fp_.get())) {
+ // Either EOF on fp or read failed.
+ if (errmsg)
+ *errmsg = string("Error reading from the random device: ")
+ + kRandomDevice;
+ return NULL;
+ }
+ buf_rd += rd;
+ }
+ // Convert the result to a uint64.
+ uint64 result = 0;
+ for (unsigned int i = 0; i < sizeof(uint64); ++i)
+ result = (result << 8) | buf[i];
+
+ return new uint64(result);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RandomVariable);
+
+ file_util::ScopedFILE fp_;
+};
+
+
+// RandomProvider implementation.
+
+bool RandomProvider::Init(void) {
+ // Check for double Init()
+ if (var_random_seed != NULL)
+ return false;
+
+ FILE* fp = fopen(kRandomDevice, "r");
+ if (!fp)
+ return false;
+ var_random_seed = new RandomVariable(fp);
+ return true;
+}
+
+void RandomProvider::Finalize(void) {
+ if (var_random_seed) {
+ delete var_random_seed;
+ var_random_seed = NULL;
+ }
+}
+
+} // namespace chromeos_policy_manager