blob: ed0eb4d2968c49475433683d5f78d93efc120dab [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2014 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Alex Deymoca0aaa62014-01-06 10:39:58 -080016
Alex Deymoaab50e32014-11-10 19:55:35 -080017#include "update_engine/update_manager/real_random_provider.h"
18
Alex Deymoca0aaa62014-01-06 10:39:58 -080019#include <stdio.h>
20#include <unistd.h>
21
Alex Vakulenko072359c2014-07-18 11:41:07 -070022#include <string>
23
Alex Vakulenko75039d72014-03-25 12:36:28 -070024#include <base/files/file_path.h>
Ben Chan736fcb52014-05-21 18:28:22 -070025#include <base/files/scoped_file.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070026#include <base/strings/stringprintf.h>
Alex Deymoca0aaa62014-01-06 10:39:58 -080027
Alex Deymo63784a52014-05-28 10:46:14 -070028#include "update_engine/update_manager/variable.h"
Alex Deymoca0aaa62014-01-06 10:39:58 -080029
30using std::string;
31
32namespace {
33
34// The device providing randomness.
35const char* kRandomDevice = "/dev/urandom";
36
37} // namespace
38
Alex Deymo63784a52014-05-28 10:46:14 -070039namespace chromeos_update_manager {
Alex Deymoca0aaa62014-01-06 10:39:58 -080040
Gilad Arnold12db7012014-01-29 16:45:30 -080041// A random seed variable.
42class RandomSeedVariable : public Variable<uint64_t> {
Alex Deymoca0aaa62014-01-06 10:39:58 -080043 public:
Alex Deymo0e433692014-02-20 07:23:03 -080044 // RandomSeedVariable is initialized as kVariableModeConst to let the
45 // EvaluationContext cache the value between different evaluations of the same
46 // policy request.
Gilad Arnold12db7012014-01-29 16:45:30 -080047 RandomSeedVariable(const string& name, FILE* fp)
Alex Deymo0e433692014-02-20 07:23:03 -080048 : Variable<uint64_t>(name, kVariableModeConst), fp_(fp) {}
Alex Deymo610277e2014-11-11 21:18:11 -080049 ~RandomSeedVariable() override {}
Alex Deymoca0aaa62014-01-06 10:39:58 -080050
51 protected:
Yunlian Jiang35866ed2015-01-29 13:09:20 -080052 const uint64_t* GetValue(base::TimeDelta /* timeout */,
53 string* errmsg) override {
Gilad Arnold570ecb12014-01-29 10:52:29 -080054 uint64_t result;
55 // Aliasing via char pointer abides by the C/C++ strict-aliasing rules.
56 char* const buf = reinterpret_cast<char*>(&result);
Alex Deymoca0aaa62014-01-06 10:39:58 -080057 unsigned int buf_rd = 0;
58
Gilad Arnold570ecb12014-01-29 10:52:29 -080059 while (buf_rd < sizeof(result)) {
60 int rd = fread(buf + buf_rd, 1, sizeof(result) - buf_rd, fp_.get());
Alex Deymoca0aaa62014-01-06 10:39:58 -080061 if (rd == 0 || ferror(fp_.get())) {
62 // Either EOF on fp or read failed.
Gilad Arnold570ecb12014-01-29 10:52:29 -080063 if (errmsg) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070064 *errmsg = base::StringPrintf(
65 "Error reading from the random device: %s", kRandomDevice);
Gilad Arnold570ecb12014-01-29 10:52:29 -080066 }
Alex Vakulenko88b591f2014-08-28 16:48:57 -070067 return nullptr;
Alex Deymoca0aaa62014-01-06 10:39:58 -080068 }
69 buf_rd += rd;
70 }
Alex Deymoca0aaa62014-01-06 10:39:58 -080071
Gilad Arnold570ecb12014-01-29 10:52:29 -080072 return new uint64_t(result);
Alex Deymoca0aaa62014-01-06 10:39:58 -080073 }
74
75 private:
Ben Chan736fcb52014-05-21 18:28:22 -070076 base::ScopedFILE fp_;
Gilad Arnolda87340b2014-01-30 11:10:18 -080077
78 DISALLOW_COPY_AND_ASSIGN(RandomSeedVariable);
Alex Deymoca0aaa62014-01-06 10:39:58 -080079};
80
Alex Deymo42c30c32014-04-24 18:41:18 -070081bool RealRandomProvider::Init(void) {
Alex Deymoca0aaa62014-01-06 10:39:58 -080082 FILE* fp = fopen(kRandomDevice, "r");
83 if (!fp)
84 return false;
David Zeuthen21716e22014-04-23 15:42:05 -070085 var_seed_.reset(new RandomSeedVariable("seed", fp));
Alex Deymoca0aaa62014-01-06 10:39:58 -080086 return true;
87}
88
Alex Deymo63784a52014-05-28 10:46:14 -070089} // namespace chromeos_update_manager