1 //
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 //
16
17 #include "update_engine/update_manager/real_random_provider.h"
18
19 #include <stdio.h>
20 #include <unistd.h>
21
22 #include <string>
23
24 #include <base/files/file_path.h>
25 #include <base/files/scoped_file.h>
26 #include <base/strings/stringprintf.h>
27
28 #include "update_engine/update_manager/variable.h"
29
30 using std::string;
31
32 namespace {
33
34 // The device providing randomness.
35 const char* kRandomDevice = "/dev/urandom";
36
37 } // namespace
38
39 namespace chromeos_update_manager {
40
41 // A random seed variable.
42 class RandomSeedVariable : public Variable<uint64_t> {
43 public:
44 // RandomSeedVariable is initialized as kVariableModeConst to let the
45 // EvaluationContext cache the value between different evaluations of the same
46 // policy request.
RandomSeedVariable(const string & name,FILE * fp)47 RandomSeedVariable(const string& name, FILE* fp)
48 : Variable<uint64_t>(name, kVariableModeConst), fp_(fp) {}
~RandomSeedVariable()49 ~RandomSeedVariable() override {}
50
51 protected:
GetValue(base::TimeDelta,string * errmsg)52 const uint64_t* GetValue(base::TimeDelta /* timeout */,
53 string* errmsg) override {
54 uint64_t result;
55 // Aliasing via char pointer abides by the C/C++ strict-aliasing rules.
56 char* const buf = reinterpret_cast<char*>(&result);
57 unsigned int buf_rd = 0;
58
59 while (buf_rd < sizeof(result)) {
60 int rd = fread(buf + buf_rd, 1, sizeof(result) - buf_rd, fp_.get());
61 if (rd == 0 || ferror(fp_.get())) {
62 // Either EOF on fp or read failed.
63 if (errmsg) {
64 *errmsg = base::StringPrintf(
65 "Error reading from the random device: %s", kRandomDevice);
66 }
67 return nullptr;
68 }
69 buf_rd += rd;
70 }
71
72 return new uint64_t(result);
73 }
74
75 private:
76 base::ScopedFILE fp_;
77
78 DISALLOW_COPY_AND_ASSIGN(RandomSeedVariable);
79 };
80
Init(void)81 bool RealRandomProvider::Init(void) {
82 FILE* fp = fopen(kRandomDevice, "r");
83 if (!fp)
84 return false;
85 var_seed_.reset(new RandomSeedVariable("seed", fp));
86 return true;
87 }
88
89 } // namespace chromeos_update_manager
90