1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2008 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/rand_util.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/rand_util_c.h"
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <fcntl.h>
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <unistd.h>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_util.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/lazy_instance.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We keep the file descriptor for /dev/urandom around so we don't need to
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// reopen it (which is expensive), and since we may not even be able to reopen
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// it if we are later put in a sandbox. This class wraps the file descriptor so
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we can use LazyInstance to handle opening it on the first access.
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass URandomFd {
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  URandomFd() {
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_ = open("/dev/urandom", O_RDONLY);
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CHECK_GE(fd_, 0) << "Cannot open /dev/urandom: " << errno;
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~URandomFd() {
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    close(fd_);
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int fd() const { return fd_; }
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int fd_;
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbase::LazyInstance<URandomFd> g_urandom_fd(base::LINKER_INITIALIZED);
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuint64 RandUint64() {
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint64 number;
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int urandom_fd = g_urandom_fd.Pointer()->fd();
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool success = file_util::ReadFromFD(urandom_fd,
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       reinterpret_cast<char*>(&number),
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       sizeof(number));
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(success);
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return number;
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint GetUrandomFD(void) {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return g_urandom_fd.Pointer()->fd();
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
62