blob: 47cb31d46acba1ab767062db758b7fa7532ab96e [file] [log] [blame]
Alex Deymoca0aaa62014-01-06 10:39:58 -08001// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Deymoaab50e32014-11-10 19:55:35 -08005#include "update_engine/update_manager/real_random_provider.h"
6
Alex Deymoca0aaa62014-01-06 10:39:58 -08007#include <stdio.h>
8#include <unistd.h>
9
Alex Vakulenko072359c2014-07-18 11:41:07 -070010#include <string>
11
Alex Vakulenko75039d72014-03-25 12:36:28 -070012#include <base/files/file_path.h>
Ben Chan736fcb52014-05-21 18:28:22 -070013#include <base/files/scoped_file.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070014#include <base/strings/stringprintf.h>
Alex Deymoca0aaa62014-01-06 10:39:58 -080015
Alex Deymo63784a52014-05-28 10:46:14 -070016#include "update_engine/update_manager/variable.h"
Alex Deymoca0aaa62014-01-06 10:39:58 -080017
18using std::string;
19
20namespace {
21
22// The device providing randomness.
23const char* kRandomDevice = "/dev/urandom";
24
25} // namespace
26
Alex Deymo63784a52014-05-28 10:46:14 -070027namespace chromeos_update_manager {
Alex Deymoca0aaa62014-01-06 10:39:58 -080028
Gilad Arnold12db7012014-01-29 16:45:30 -080029// A random seed variable.
30class RandomSeedVariable : public Variable<uint64_t> {
Alex Deymoca0aaa62014-01-06 10:39:58 -080031 public:
Alex Deymo0e433692014-02-20 07:23:03 -080032 // RandomSeedVariable is initialized as kVariableModeConst to let the
33 // EvaluationContext cache the value between different evaluations of the same
34 // policy request.
Gilad Arnold12db7012014-01-29 16:45:30 -080035 RandomSeedVariable(const string& name, FILE* fp)
Alex Deymo0e433692014-02-20 07:23:03 -080036 : Variable<uint64_t>(name, kVariableModeConst), fp_(fp) {}
Gilad Arnold12db7012014-01-29 16:45:30 -080037 virtual ~RandomSeedVariable() {}
Alex Deymoca0aaa62014-01-06 10:39:58 -080038
39 protected:
Gilad Arnold570ecb12014-01-29 10:52:29 -080040 virtual const uint64_t* GetValue(base::TimeDelta /* timeout */,
41 string* errmsg) {
42 uint64_t result;
43 // Aliasing via char pointer abides by the C/C++ strict-aliasing rules.
44 char* const buf = reinterpret_cast<char*>(&result);
Alex Deymoca0aaa62014-01-06 10:39:58 -080045 unsigned int buf_rd = 0;
46
Gilad Arnold570ecb12014-01-29 10:52:29 -080047 while (buf_rd < sizeof(result)) {
48 int rd = fread(buf + buf_rd, 1, sizeof(result) - buf_rd, fp_.get());
Alex Deymoca0aaa62014-01-06 10:39:58 -080049 if (rd == 0 || ferror(fp_.get())) {
50 // Either EOF on fp or read failed.
Gilad Arnold570ecb12014-01-29 10:52:29 -080051 if (errmsg) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070052 *errmsg = base::StringPrintf(
53 "Error reading from the random device: %s", kRandomDevice);
Gilad Arnold570ecb12014-01-29 10:52:29 -080054 }
Alex Vakulenko88b591f2014-08-28 16:48:57 -070055 return nullptr;
Alex Deymoca0aaa62014-01-06 10:39:58 -080056 }
57 buf_rd += rd;
58 }
Alex Deymoca0aaa62014-01-06 10:39:58 -080059
Gilad Arnold570ecb12014-01-29 10:52:29 -080060 return new uint64_t(result);
Alex Deymoca0aaa62014-01-06 10:39:58 -080061 }
62
63 private:
Ben Chan736fcb52014-05-21 18:28:22 -070064 base::ScopedFILE fp_;
Gilad Arnolda87340b2014-01-30 11:10:18 -080065
66 DISALLOW_COPY_AND_ASSIGN(RandomSeedVariable);
Alex Deymoca0aaa62014-01-06 10:39:58 -080067};
68
Alex Deymo42c30c32014-04-24 18:41:18 -070069bool RealRandomProvider::Init(void) {
Alex Deymoca0aaa62014-01-06 10:39:58 -080070 FILE* fp = fopen(kRandomDevice, "r");
71 if (!fp)
72 return false;
David Zeuthen21716e22014-04-23 15:42:05 -070073 var_seed_.reset(new RandomSeedVariable("seed", fp));
Alex Deymoca0aaa62014-01-06 10:39:58 -080074 return true;
75}
76
Alex Deymo63784a52014-05-28 10:46:14 -070077} // namespace chromeos_update_manager