blob: bced7083754bf7f80056f0b95466d722b079e4c2 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]05f9b682008-09-29 22:18:012// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Tom Sepez8726d30e2025-01-29 02:11:085#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/390223051): Remove C-library calls to fix the errors.
7#pragma allow_unsafe_libc_calls
8#endif
9
[email protected]05f9b682008-09-29 22:18:0110#include "base/rand_util.h"
11
Mark Mentovai5d6e7632023-08-11 17:21:4312#include <errno.h>
[email protected]05f9b682008-09-29 22:18:0113#include <fcntl.h>
Mark Mentovai5d6e7632023-08-11 17:21:4314#include <stddef.h>
15#include <stdint.h>
16#include <sys/syscall.h>
17#include <sys/utsname.h>
18#include <unistd.h>
[email protected]05f9b682008-09-29 22:18:0119
Hans Wennborgc3cffa62020-04-27 10:09:1220#include "base/check.h"
Mark Mentovai5d6e7632023-08-11 17:21:4321#include "base/compiler_specific.h"
Austin Sullivana41f7f62024-01-09 20:11:5022#include "base/containers/span.h"
Mark Mentovai5d6e7632023-08-11 17:21:4323#include "base/feature_list.h"
[email protected]e3177dd52014-08-13 20:22:1424#include "base/files/file_util.h"
Mark Mentovai5d6e7632023-08-11 17:21:4325#include "base/metrics/histogram_macros.h"
26#include "base/no_destructor.h"
mark4cec4942017-02-28 23:56:0027#include "base/posix/eintr_wrapper.h"
Anand Ravic4987db2025-03-10 21:32:0928#include "base/system/sys_info.h"
Mark Mentovai5d6e7632023-08-11 17:21:4329#include "base/time/time.h"
Chris Palmer254cd5f2020-08-12 20:37:0730#include "build/build_config.h"
31
Mark Mentovai5d6e7632023-08-11 17:21:4332#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL)
33#include "third_party/lss/linux_syscall_support.h"
34#elif BUILDFLAG(IS_MAC)
Alison Galed965ba02024-04-26 21:50:5435// TODO(crbug.com/40641285): Waiting for this header to appear in the iOS SDK.
Mark Mentovai5d6e7632023-08-11 17:21:4336// (See below.)
37#include <sys/random.h>
38#endif
39
Daniel Chengb6bbf5a62022-09-09 18:26:3440#if !BUILDFLAG(IS_NACL)
Daniel Chengb6bbf5a62022-09-09 18:26:3441#include "third_party/boringssl/src/include/openssl/rand.h"
42#endif
43
44namespace base {
45
[email protected]09e5f47a2009-06-26 10:00:0246namespace {
47
Xiaohan Wang38e4ebb2022-01-19 06:57:4348#if BUILDFLAG(IS_AIX)
Chris Palmer3b3588b2020-08-28 17:04:2149// AIX has no 64-bit support for O_CLOEXEC.
50static constexpr int kOpenFlags = O_RDONLY;
51#else
52static constexpr int kOpenFlags = O_RDONLY | O_CLOEXEC;
53#endif
54
Mark Mentovai5d6e7632023-08-11 17:21:4355// We keep the file descriptor for /dev/urandom around so we don't need to
56// reopen it (which is expensive), and since we may not even be able to reopen
57// it if we are later put in a sandbox. This class wraps the file descriptor so
58// we can use a static-local variable to handle opening it on the first access.
59class URandomFd {
60 public:
61 URandomFd() : fd_(HANDLE_EINTR(open("/dev/urandom", kOpenFlags))) {
62 CHECK(fd_ >= 0) << "Cannot open /dev/urandom";
63 }
64
65 ~URandomFd() { close(fd_); }
66
67 int fd() const { return fd_; }
68
69 private:
70 const int fd_;
71};
72
73#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
74 BUILDFLAG(IS_ANDROID)) && \
75 !BUILDFLAG(IS_NACL)
Mark Mentovai5d6e7632023-08-11 17:21:4376
77bool KernelSupportsGetRandom() {
Anand Ravic4987db2025-03-10 21:32:0978 return base::SysInfo::KernelVersionNumber::Current() >=
79 base::SysInfo::KernelVersionNumber(3, 17);
Mark Mentovai5d6e7632023-08-11 17:21:4380}
81
82bool GetRandomSyscall(void* output, size_t output_length) {
83 // We have to call `getrandom` via Linux Syscall Support, rather than through
84 // the libc wrapper, because we might not have an up-to-date libc (e.g. on
85 // some bots).
86 const ssize_t r =
87 HANDLE_EINTR(syscall(__NR_getrandom, output, output_length, 0));
88
89 // Return success only on total success. In case errno == ENOSYS (or any other
90 // error), we'll fall through to reading from urandom below.
91 if (output_length == static_cast<size_t>(r)) {
92 MSAN_UNPOISON(output, output_length);
93 return true;
94 }
95 return false;
96}
97#endif // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
98 // BUILDFLAG(IS_ANDROID)) && !BUILDFLAG(IS_NACL)
99
Mark Mentovai5d6e7632023-08-11 17:21:43100} // namespace
101
102namespace internal {
103
Mark Mentovai5d6e7632023-08-11 17:21:43104namespace {
105
106#if !BUILDFLAG(IS_NACL)
107// The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
108// rand_util_win.cc.
109std::atomic<bool> g_use_boringssl;
110
111BASE_FEATURE(kUseBoringSSLForRandBytes,
112 "UseBoringSSLForRandBytes",
113 FEATURE_DISABLED_BY_DEFAULT);
114
115} // namespace
116
117void ConfigureBoringSSLBackedRandBytesFieldTrial() {
118 g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
119 std::memory_order_relaxed);
120}
121
122bool UseBoringSSLForRandBytes() {
123 return g_use_boringssl.load(std::memory_order_relaxed);
124}
125#endif
126
127} // namespace internal
128
129namespace {
130
danakj95305d272024-05-09 20:38:44131void RandBytesInternal(span<uint8_t> output, bool avoid_allocation) {
Mark Mentovai5d6e7632023-08-11 17:21:43132#if !BUILDFLAG(IS_NACL)
133 // The BoringSSL experiment takes priority over everything else.
134 if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
Mark Mentovai5d6e7632023-08-11 17:21:43135 // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
Austin Sullivana41f7f62024-01-09 20:11:50136 (void)RAND_bytes(output.data(), output.size());
Mark Mentovai5d6e7632023-08-11 17:21:43137 return;
138 }
139#endif
140#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
141 BUILDFLAG(IS_ANDROID)) && \
142 !BUILDFLAG(IS_NACL)
Morten Stenshorne214ec702024-11-04 22:54:08143 // On Android it is mandatory to check that the kernel _version_ has the
144 // support for a syscall before calling. The same check is made on Linux and
145 // ChromeOS to avoid making a syscall that predictably returns ENOSYS.
146 static const bool kernel_has_support = KernelSupportsGetRandom();
147 if (kernel_has_support && GetRandomSyscall(output.data(), output.size())) {
148 return;
Mark Mentovai5d6e7632023-08-11 17:21:43149 }
150#elif BUILDFLAG(IS_MAC)
Alison Galed965ba02024-04-26 21:50:54151 // TODO(crbug.com/40641285): Enable this on iOS too, when sys/random.h arrives
Mark Mentovai5d6e7632023-08-11 17:21:43152 // in its SDK.
Austin Sullivana41f7f62024-01-09 20:11:50153 if (getentropy(output.data(), output.size()) == 0) {
Mark Mentovai5d6e7632023-08-11 17:21:43154 return;
155 }
156#endif
157
158 // If the OS-specific mechanisms didn't work, fall through to reading from
159 // urandom.
160 //
Alison Galed965ba02024-04-26 21:50:54161 // TODO(crbug.com/40641285): When we no longer need to support old Linux
Mark Mentovai5d6e7632023-08-11 17:21:43162 // kernels, we can get rid of this /dev/urandom branch altogether.
163 const int urandom_fd = GetUrandomFD();
Austin Sullivana41f7f62024-01-09 20:11:50164 const bool success = ReadFromFD(urandom_fd, as_writable_chars(output));
Mark Mentovai5d6e7632023-08-11 17:21:43165 CHECK(success);
[email protected]c910c5a2014-01-23 02:14:28166}
167
Egor Pasko1c7e6242022-09-20 12:45:39168} // namespace
169
170namespace internal {
171
172double RandDoubleAvoidAllocation() {
173 uint64_t number;
danakj95305d272024-05-09 20:38:44174 RandBytesInternal(byte_span_from_ref(number), /*avoid_allocation=*/true);
Egor Pasko1c7e6242022-09-20 12:45:39175 // This transformation is explained in rand_util.cc.
176 return (number >> 11) * 0x1.0p-53;
177}
178
179} // namespace internal
180
Austin Sullivana41f7f62024-01-09 20:11:50181void RandBytes(span<uint8_t> output) {
danakj95305d272024-05-09 20:38:44182 RandBytesInternal(output, /*avoid_allocation=*/false);
Egor Pasko1c7e6242022-09-20 12:45:39183}
184
Lei Zhange3e126d782020-01-07 21:36:00185int GetUrandomFD() {
Mark Mentovai5d6e7632023-08-11 17:21:43186 static NoDestructor<URandomFd> urandom_fd;
187 return urandom_fd->fd();
[email protected]1d87fad2010-03-04 20:18:55188}
[email protected]ead8c1f2012-05-30 14:26:13189
190} // namespace base