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. 47 RandomSeedVariable(const string& name, FILE* fp) 48 : Variable<uint64_t>(name, kVariableModeConst), fp_(fp) {} 49 ~RandomSeedVariable() override {} 50 51 protected: 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 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