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