blob: 0b772cbae8916dbf24bdc215745afed94cd51839 [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
5#include "base/rand_util.h"
6
[email protected]8c37218a2014-01-24 00:01:147#include <windows.h>
Bruce Dawsona1e1cfcb2022-11-22 20:04:358
avi9b6f42932015-12-26 22:15:149#include <stddef.h>
10#include <stdint.h>
[email protected]05f9b682008-09-29 22:18:0111
[email protected]8c37218a2014-01-24 00:01:1412#include <algorithm>
Daniel Chengb6bbf5a62022-09-09 18:26:3413#include <atomic>
[email protected]8c37218a2014-01-24 00:01:1414#include <limits>
15
Hans Wennborgc3cffa62020-04-27 10:09:1216#include "base/check.h"
Daniel Chengb6bbf5a62022-09-09 18:26:3417#include "base/feature_list.h"
Daniel Chengb6bbf5a62022-09-09 18:26:3418#include "third_party/boringssl/src/include/openssl/rand.h"
[email protected]05f9b682008-09-29 22:18:0119
Alex Goughd28e61a2023-07-11 18:45:3420// Prototype for ProcessPrng.
21// See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
22extern "C" {
23BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData);
24}
25
[email protected]05f9b682008-09-29 22:18:0126namespace base {
27
Mark Mentovai5d6e7632023-08-11 17:21:4328namespace internal {
29
30namespace {
31
32// The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
33// rand_util_posix.cc.
34std::atomic<bool> g_use_boringssl;
35
36BASE_FEATURE(kUseBoringSSLForRandBytes,
37 "UseBoringSSLForRandBytes",
38 FEATURE_DISABLED_BY_DEFAULT);
39
40} // namespace
41
42void ConfigureBoringSSLBackedRandBytesFieldTrial() {
43 g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
44 std::memory_order_relaxed);
45}
46
47bool UseBoringSSLForRandBytes() {
48 return g_use_boringssl.load(std::memory_order_relaxed);
49}
50
51} // namespace internal
52
Egor Pasko1c7e6242022-09-20 12:45:3953namespace {
54
Alex Goughd28e61a2023-07-11 18:45:3455// Import bcryptprimitives!ProcessPrng rather than cryptbase!RtlGenRandom to
56// avoid opening a handle to \\Device\KsecDD in the renderer.
57decltype(&ProcessPrng) GetProcessPrng() {
58 HMODULE hmod = LoadLibraryW(L"bcryptprimitives.dll");
59 CHECK(hmod);
60 decltype(&ProcessPrng) process_prng_fn =
61 reinterpret_cast<decltype(&ProcessPrng)>(
62 GetProcAddress(hmod, "ProcessPrng"));
63 CHECK(process_prng_fn);
64 return process_prng_fn;
65}
66
danakj95305d272024-05-09 20:38:4467void RandBytesInternal(span<uint8_t> output, bool avoid_allocation) {
Mark Mentovai5d6e7632023-08-11 17:21:4368 if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
Daniel Chengb6bbf5a62022-09-09 18:26:3469 // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
Austin Sullivana41f7f62024-01-09 20:11:5070 (void)RAND_bytes(output.data(), output.size());
Daniel Chengb6bbf5a62022-09-09 18:26:3471 return;
72 }
73
Alex Goughd28e61a2023-07-11 18:45:3474 static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng();
Austin Sullivana41f7f62024-01-09 20:11:5075 BOOL success =
76 process_prng_fn(static_cast<BYTE*>(output.data()), output.size());
Alex Goughd28e61a2023-07-11 18:45:3477 // ProcessPrng is documented to always return TRUE.
78 CHECK(success);
[email protected]c910c5a2014-01-23 02:14:2879}
80
Egor Pasko1c7e6242022-09-20 12:45:3981} // namespace
82
Austin Sullivana41f7f62024-01-09 20:11:5083void RandBytes(span<uint8_t> output) {
danakj95305d272024-05-09 20:38:4484 RandBytesInternal(output, /*avoid_allocation=*/false);
Egor Pasko1c7e6242022-09-20 12:45:3985}
86
87namespace internal {
88
89double RandDoubleAvoidAllocation() {
90 uint64_t number;
danakj95305d272024-05-09 20:38:4491 RandBytesInternal(byte_span_from_ref(number),
92 /*avoid_allocation=*/true);
Egor Pasko1c7e6242022-09-20 12:45:3993 // This transformation is explained in rand_util.cc.
94 return (number >> 11) * 0x1.0p-53;
95}
96
97} // namespace internal
98
[email protected]05f9b682008-09-29 22:18:0199} // namespace base