• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "base/rand_util.h"
11 
12 #include <windows.h>
13 
14 #include <stddef.h>
15 #include <stdint.h>
16 
17 #include <algorithm>
18 #include <atomic>
19 #include <limits>
20 
21 #include "base/check.h"
22 #include "base/feature_list.h"
23 #include "third_party/boringssl/src/include/openssl/rand.h"
24 
25 // Prototype for ProcessPrng.
26 // See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
27 extern "C" {
28 BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData);
29 }
30 
31 namespace base {
32 
33 namespace internal {
34 
35 namespace {
36 
37 // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
38 // rand_util_posix.cc.
39 std::atomic<bool> g_use_boringssl;
40 
41 BASE_FEATURE(kUseBoringSSLForRandBytes,
42              "UseBoringSSLForRandBytes",
43              FEATURE_DISABLED_BY_DEFAULT);
44 
45 }  // namespace
46 
ConfigureBoringSSLBackedRandBytesFieldTrial()47 void ConfigureBoringSSLBackedRandBytesFieldTrial() {
48   g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
49                         std::memory_order_relaxed);
50 }
51 
UseBoringSSLForRandBytes()52 bool UseBoringSSLForRandBytes() {
53   return g_use_boringssl.load(std::memory_order_relaxed);
54 }
55 
56 }  // namespace internal
57 
58 namespace {
59 
60 // Import bcryptprimitives!ProcessPrng rather than cryptbase!RtlGenRandom to
61 // avoid opening a handle to \\Device\KsecDD in the renderer.
GetProcessPrng()62 decltype(&ProcessPrng) GetProcessPrng() {
63   HMODULE hmod = LoadLibraryW(L"bcryptprimitives.dll");
64   CHECK(hmod);
65   decltype(&ProcessPrng) process_prng_fn =
66       reinterpret_cast<decltype(&ProcessPrng)>(
67           GetProcAddress(hmod, "ProcessPrng"));
68   CHECK(process_prng_fn);
69   return process_prng_fn;
70 }
71 
RandBytesInternal(span<uint8_t> output,bool avoid_allocation)72 void RandBytesInternal(span<uint8_t> output, bool avoid_allocation) {
73   if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
74     // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
75     (void)RAND_bytes(output.data(), output.size());
76     return;
77   }
78 
79   static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng();
80   BOOL success =
81       process_prng_fn(static_cast<BYTE*>(output.data()), output.size());
82   // ProcessPrng is documented to always return TRUE.
83   CHECK(success);
84 }
85 
86 }  // namespace
87 
RandBytes(span<uint8_t> output)88 void RandBytes(span<uint8_t> output) {
89   RandBytesInternal(output, /*avoid_allocation=*/false);
90 }
91 
92 namespace internal {
93 
RandDoubleAvoidAllocation()94 double RandDoubleAvoidAllocation() {
95   uint64_t number;
96   RandBytesInternal(byte_span_from_ref(number),
97                     /*avoid_allocation=*/true);
98   // This transformation is explained in rand_util.cc.
99   return (number >> 11) * 0x1.0p-53;
100 }
101 
102 }  // namespace internal
103 
104 }  // namespace base
105