xref: /aosp_15_r20/external/cronet/base/rand_util_win.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/rand_util.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <windows.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
10*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include <algorithm>
13*6777b538SAndroid Build Coastguard Worker #include <atomic>
14*6777b538SAndroid Build Coastguard Worker #include <limits>
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
18*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/crypto.h"
19*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/rand.h"
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // Prototype for ProcessPrng.
22*6777b538SAndroid Build Coastguard Worker // See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
23*6777b538SAndroid Build Coastguard Worker extern "C" {
24*6777b538SAndroid Build Coastguard Worker BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData);
25*6777b538SAndroid Build Coastguard Worker }
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker namespace base {
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker namespace internal {
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker namespace {
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
34*6777b538SAndroid Build Coastguard Worker // rand_util_posix.cc.
35*6777b538SAndroid Build Coastguard Worker std::atomic<bool> g_use_boringssl;
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker BASE_FEATURE(kUseBoringSSLForRandBytes,
38*6777b538SAndroid Build Coastguard Worker              "UseBoringSSLForRandBytes",
39*6777b538SAndroid Build Coastguard Worker              FEATURE_DISABLED_BY_DEFAULT);
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker }  // namespace
42*6777b538SAndroid Build Coastguard Worker 
ConfigureBoringSSLBackedRandBytesFieldTrial()43*6777b538SAndroid Build Coastguard Worker void ConfigureBoringSSLBackedRandBytesFieldTrial() {
44*6777b538SAndroid Build Coastguard Worker   g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
45*6777b538SAndroid Build Coastguard Worker                         std::memory_order_relaxed);
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker 
UseBoringSSLForRandBytes()48*6777b538SAndroid Build Coastguard Worker bool UseBoringSSLForRandBytes() {
49*6777b538SAndroid Build Coastguard Worker   return g_use_boringssl.load(std::memory_order_relaxed);
50*6777b538SAndroid Build Coastguard Worker }
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker }  // namespace internal
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker namespace {
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker // Import bcryptprimitives!ProcessPrng rather than cryptbase!RtlGenRandom to
57*6777b538SAndroid Build Coastguard Worker // avoid opening a handle to \\Device\KsecDD in the renderer.
GetProcessPrng()58*6777b538SAndroid Build Coastguard Worker decltype(&ProcessPrng) GetProcessPrng() {
59*6777b538SAndroid Build Coastguard Worker   HMODULE hmod = LoadLibraryW(L"bcryptprimitives.dll");
60*6777b538SAndroid Build Coastguard Worker   CHECK(hmod);
61*6777b538SAndroid Build Coastguard Worker   decltype(&ProcessPrng) process_prng_fn =
62*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<decltype(&ProcessPrng)>(
63*6777b538SAndroid Build Coastguard Worker           GetProcAddress(hmod, "ProcessPrng"));
64*6777b538SAndroid Build Coastguard Worker   CHECK(process_prng_fn);
65*6777b538SAndroid Build Coastguard Worker   return process_prng_fn;
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker 
RandBytes(span<uint8_t> output,bool avoid_allocation)68*6777b538SAndroid Build Coastguard Worker void RandBytes(span<uint8_t> output, bool avoid_allocation) {
69*6777b538SAndroid Build Coastguard Worker   if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
70*6777b538SAndroid Build Coastguard Worker     // Ensure BoringSSL is initialized so it can use things like RDRAND.
71*6777b538SAndroid Build Coastguard Worker     CRYPTO_library_init();
72*6777b538SAndroid Build Coastguard Worker     // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
73*6777b538SAndroid Build Coastguard Worker     (void)RAND_bytes(output.data(), output.size());
74*6777b538SAndroid Build Coastguard Worker     return;
75*6777b538SAndroid Build Coastguard Worker   }
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker   static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng();
78*6777b538SAndroid Build Coastguard Worker   BOOL success =
79*6777b538SAndroid Build Coastguard Worker       process_prng_fn(static_cast<BYTE*>(output.data()), output.size());
80*6777b538SAndroid Build Coastguard Worker   // ProcessPrng is documented to always return TRUE.
81*6777b538SAndroid Build Coastguard Worker   CHECK(success);
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker }  // namespace
85*6777b538SAndroid Build Coastguard Worker 
RandBytes(span<uint8_t> output)86*6777b538SAndroid Build Coastguard Worker void RandBytes(span<uint8_t> output) {
87*6777b538SAndroid Build Coastguard Worker   RandBytes(output, /*avoid_allocation=*/false);
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
RandBytes(void * output,size_t output_length)90*6777b538SAndroid Build Coastguard Worker void RandBytes(void* output, size_t output_length) {
91*6777b538SAndroid Build Coastguard Worker   RandBytes(make_span(static_cast<uint8_t*>(output), output_length),
92*6777b538SAndroid Build Coastguard Worker             /*avoid_allocation=*/false);
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker namespace internal {
96*6777b538SAndroid Build Coastguard Worker 
RandDoubleAvoidAllocation()97*6777b538SAndroid Build Coastguard Worker double RandDoubleAvoidAllocation() {
98*6777b538SAndroid Build Coastguard Worker   uint64_t number;
99*6777b538SAndroid Build Coastguard Worker   RandBytes(as_writable_bytes(make_span(&number, 1u)),
100*6777b538SAndroid Build Coastguard Worker             /*avoid_allocation=*/true);
101*6777b538SAndroid Build Coastguard Worker   // This transformation is explained in rand_util.cc.
102*6777b538SAndroid Build Coastguard Worker   return (number >> 11) * 0x1.0p-53;
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker }  // namespace internal
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker }  // namespace base
108