Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / rand_util_win.cc
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 #include "base/rand_util.h"
6
7 #include <windows.h>
8
9 #include <stddef.h>
10 #include <stdint.h>
11
12 #include <algorithm>
13 #include <atomic>
14 #include <limits>
15
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"
20
21 // Prototype for ProcessPrng.
22 // See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
23 extern "C" {
24 BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData);
25 }
26
27 namespace base {
28
29 namespace internal {
30
31 namespace {
32
33 // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
34 // rand_util_posix.cc.
35 std::atomic<bool> g_use_boringssl;
36
37 BASE_FEATURE(kUseBoringSSLForRandBytes,
38              "UseBoringSSLForRandBytes",
39              FEATURE_DISABLED_BY_DEFAULT);
40
41 }  // namespace
42
43 void ConfigureBoringSSLBackedRandBytesFieldTrial() {
44   g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
45                         std::memory_order_relaxed);
46 }
47
48 bool UseBoringSSLForRandBytes() {
49   return g_use_boringssl.load(std::memory_order_relaxed);
50 }
51
52 }  // namespace internal
53
54 namespace {
55
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");
60   CHECK(hmod);
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;
66 }
67
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);
74     return;
75   }
76
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.
80   CHECK(success);
81 }
82
83 }  // namespace
84
85 void RandBytes(void* output, size_t output_length) {
86   RandBytes(output, output_length, /*avoid_allocation=*/false);
87 }
88
89 namespace internal {
90
91 double RandDoubleAvoidAllocation() {
92   uint64_t number;
93   RandBytes(&number, sizeof(number), /*avoid_allocation=*/true);
94   // This transformation is explained in rand_util.cc.
95   return (number >> 11) * 0x1.0p-53;
96 }
97
98 }  // namespace internal
99
100 }  // namespace base