tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rand_util_win.cc (2879B)


      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 #if !defined(MOZ_SANDBOX)
     19 #include "third_party/boringssl/src/include/openssl/crypto.h"
     20 #include "third_party/boringssl/src/include/openssl/rand.h"
     21 #endif
     22 
     23 // Prototype for ProcessPrng.
     24 // See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
     25 extern "C" {
     26 BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData);
     27 }
     28 
     29 namespace base {
     30 
     31 #if !defined(MOZ_SANDBOX)
     32 namespace internal {
     33 
     34 namespace {
     35 
     36 // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
     37 // rand_util_posix.cc.
     38 std::atomic<bool> g_use_boringssl;
     39 
     40 BASE_FEATURE(kUseBoringSSLForRandBytes,
     41             "UseBoringSSLForRandBytes",
     42             FEATURE_DISABLED_BY_DEFAULT);
     43 
     44 }  // namespace
     45 
     46 void ConfigureBoringSSLBackedRandBytesFieldTrial() {
     47  g_use_boringssl.store(FeatureList::IsEnabled(kUseBoringSSLForRandBytes),
     48                        std::memory_order_relaxed);
     49 }
     50 
     51 bool UseBoringSSLForRandBytes() {
     52  return g_use_boringssl.load(std::memory_order_relaxed);
     53 }
     54 
     55 }  // namespace internal
     56 #endif
     57 
     58 namespace {
     59 
     60 // Import bcryptprimitives!ProcessPrng rather than cryptbase!RtlGenRandom to
     61 // avoid opening a handle to \\Device\KsecDD in the renderer.
     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 
     72 void RandBytes(void* output, size_t output_length, bool avoid_allocation) {
     73 #if !defined(MOZ_SANDBOX)
     74  if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
     75    // Ensure BoringSSL is initialized so it can use things like RDRAND.
     76    CRYPTO_library_init();
     77    // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
     78    (void)RAND_bytes(static_cast<uint8_t*>(output), output_length);
     79    return;
     80  }
     81 #endif
     82 
     83  static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng();
     84  BOOL success = process_prng_fn(static_cast<BYTE*>(output), output_length);
     85  // ProcessPrng is documented to always return TRUE.
     86  CHECK(success);
     87 }
     88 
     89 }  // namespace
     90 
     91 void RandBytes(void* output, size_t output_length) {
     92  RandBytes(output, output_length, /*avoid_allocation=*/false);
     93 }
     94 
     95 namespace internal {
     96 
     97 double RandDoubleAvoidAllocation() {
     98  uint64_t number;
     99  RandBytes(&number, sizeof(number), /*avoid_allocation=*/true);
    100  // This transformation is explained in rand_util.cc.
    101  return (number >> 11) * 0x1.0p-53;
    102 }
    103 
    104 }  // namespace internal
    105 
    106 }  // namespace base