1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/rand_util.h"
16 #include "base/check.h"
17 #include "base/feature_list.h"
18 #include "third_party/boringssl/src/include/openssl/crypto.h"
19 #include "third_party/boringssl/src/include/openssl/rand.h"
21 // Prototype for ProcessPrng.
22 // See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
24 BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData);
33 // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
34 // rand_util_posix.cc.
35 std::atomic<bool> g_use_boringssl;
37 BASE_FEATURE(kUseBoringSSLForRandBytes,
38 "UseBoringSSLForRandBytes",
39 FEATURE_DISABLED_BY_DEFAULT);
43 void ConfigureBoringSSLBackedRandBytesFieldTrial() {
44 g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
45 std::memory_order_relaxed);
48 bool UseBoringSSLForRandBytes() {
49 return g_use_boringssl.load(std::memory_order_relaxed);
52 } // namespace internal
56 // Import bcryptprimitives!ProcessPrng rather than cryptbase!RtlGenRandom to
57 // avoid opening a handle to \\Device\KsecDD in the renderer.
58 decltype(&ProcessPrng) GetProcessPrng() {
59 HMODULE hmod = LoadLibraryW(L"bcryptprimitives.dll");
61 decltype(&ProcessPrng) process_prng_fn =
62 reinterpret_cast<decltype(&ProcessPrng)>(
63 GetProcAddress(hmod, "ProcessPrng"));
64 CHECK(process_prng_fn);
65 return process_prng_fn;
68 void RandBytes(void* output, size_t output_length, bool avoid_allocation) {
69 if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
70 // Ensure BoringSSL is initialized so it can use things like RDRAND.
71 CRYPTO_library_init();
72 // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
73 (void)RAND_bytes(static_cast<uint8_t*>(output), output_length);
77 static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng();
78 BOOL success = process_prng_fn(static_cast<BYTE*>(output), output_length);
79 // ProcessPrng is documented to always return TRUE.
85 void RandBytes(void* output, size_t output_length) {
86 RandBytes(output, output_length, /*avoid_allocation=*/false);
91 double RandDoubleAvoidAllocation() {
93 RandBytes(&number, sizeof(number), /*avoid_allocation=*/true);
94 // This transformation is explained in rand_util.cc.
95 return (number >> 11) * 0x1.0p-53;
98 } // namespace internal