[go: nahoru, domu]

blob: 299e54300a09dab5a795ac1d8b4df757b2996166 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
mark@chromium.org05f9b682008-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
dalecurtis@chromium.org8c37218a2014-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>
mark@chromium.org05f9b682008-09-29 22:18:0111
dalecurtis@chromium.org8c37218a2014-01-24 00:01:1412#include <algorithm>
Daniel Chengb6bbf5a62022-09-09 18:26:3413#include <atomic>
dalecurtis@chromium.org8c37218a2014-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"
18#include "third_party/boringssl/src/include/openssl/crypto.h"
19#include "third_party/boringssl/src/include/openssl/rand.h"
mark@chromium.org05f9b682008-09-29 22:18:0120
Alex Goughd28e61a2023-07-11 18:45:3421// Prototype for ProcessPrng.
22// See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
23extern "C" {
24BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData);
25}
26
mark@chromium.org05f9b682008-09-29 22:18:0127namespace base {
28
Mark Mentovai5d6e7632023-08-11 17:21:4329namespace internal {
30
31namespace {
32
33// The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
34// rand_util_posix.cc.
35std::atomic<bool> g_use_boringssl;
36
37BASE_FEATURE(kUseBoringSSLForRandBytes,
38 "UseBoringSSLForRandBytes",
39 FEATURE_DISABLED_BY_DEFAULT);
40
41} // namespace
42
43void ConfigureBoringSSLBackedRandBytesFieldTrial() {
44 g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
45 std::memory_order_relaxed);
46}
47
48bool UseBoringSSLForRandBytes() {
49 return g_use_boringssl.load(std::memory_order_relaxed);
50}
51
52} // namespace internal
53
Egor Pasko1c7e6242022-09-20 12:45:3954namespace {
55
Alex Goughd28e61a2023-07-11 18:45:3456// Import bcryptprimitives!ProcessPrng rather than cryptbase!RtlGenRandom to
57// avoid opening a handle to \\Device\KsecDD in the renderer.
58decltype(&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
Austin Sullivana41f7f62024-01-09 20:11:5068void RandBytes(span<uint8_t> output, bool avoid_allocation) {
Mark Mentovai5d6e7632023-08-11 17:21:4369 if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
Daniel Chengb6bbf5a62022-09-09 18:26:3470 // 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.
Austin Sullivana41f7f62024-01-09 20:11:5073 (void)RAND_bytes(output.data(), output.size());
Daniel Chengb6bbf5a62022-09-09 18:26:3474 return;
75 }
76
Alex Goughd28e61a2023-07-11 18:45:3477 static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng();
Austin Sullivana41f7f62024-01-09 20:11:5078 BOOL success =
79 process_prng_fn(static_cast<BYTE*>(output.data()), output.size());
Alex Goughd28e61a2023-07-11 18:45:3480 // ProcessPrng is documented to always return TRUE.
81 CHECK(success);
dalecurtis@chromium.orgc910c5a2014-01-23 02:14:2882}
83
Egor Pasko1c7e6242022-09-20 12:45:3984} // namespace
85
Austin Sullivana41f7f62024-01-09 20:11:5086void RandBytes(span<uint8_t> output) {
87 RandBytes(output, /*avoid_allocation=*/false);
88}
89
Egor Pasko1c7e6242022-09-20 12:45:3990void RandBytes(void* output, size_t output_length) {
Tom Sepez30d68422024-01-24 19:55:0991 RandBytes(make_span(static_cast<uint8_t*>(output), output_length),
Austin Sullivana41f7f62024-01-09 20:11:5092 /*avoid_allocation=*/false);
Egor Pasko1c7e6242022-09-20 12:45:3993}
94
95namespace internal {
96
97double RandDoubleAvoidAllocation() {
98 uint64_t number;
Austin Sullivana41f7f62024-01-09 20:11:5099 RandBytes(as_writable_bytes(make_span(&number, 1u)),
100 /*avoid_allocation=*/true);
Egor Pasko1c7e6242022-09-20 12:45:39101 // This transformation is explained in rand_util.cc.
102 return (number >> 11) * 0x1.0p-53;
103}
104
105} // namespace internal
106
mark@chromium.org05f9b682008-09-29 22:18:01107} // namespace base