• 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 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_RAND_UTIL_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_RAND_UTIL_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
12 #include "base/allocator/partition_allocator/partition_alloc_base/gtest_prod_util.h"
13 #include "build/build_config.h"
14 
15 namespace partition_alloc {
16 class RandomGenerator;
17 }  // namespace partition_alloc
18 
19 namespace partition_alloc::internal::base {
20 
21 // Returns a random number in range [0, UINT64_MAX]. Thread-safe.
22 PA_COMPONENT_EXPORT(PARTITION_ALLOC) uint64_t RandUint64();
23 
24 // Returns a random number in range [0, range).  Thread-safe.
25 PA_COMPONENT_EXPORT(PARTITION_ALLOC) uint64_t RandGenerator(uint64_t range);
26 
27 // Fills |output_length| bytes of |output| with random data. Thread-safe.
28 //
29 // Although implementations are required to use a cryptographically secure
30 // random number source, code outside of base/ that relies on this should use
31 // crypto::RandBytes instead to ensure the requirement is easily discoverable.
32 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
33 void RandBytes(void* output, size_t output_length);
34 
35 // Fast, insecure pseudo-random number generator.
36 //
37 // WARNING: This is not the generator you are looking for. This has significant
38 // caveats:
39 //   - It is non-cryptographic, so easy to miuse
40 //   - It is neither fork() nor clone()-safe.
41 //   - Synchronization is up to the client.
42 //
43 // Always prefer base::Rand*() above, unless you have a use case where its
44 // overhead is too high, or system calls are disallowed.
45 //
46 // Performance: As of 2021, rough overhead on Linux on a desktop machine of
47 // base::RandUint64() is ~800ns per call (it performs a system call). On Windows
48 // it is lower. On the same machine, this generator's cost is ~2ns per call,
49 // regardless of platform.
50 //
51 // This is different from |Rand*()| above as it is guaranteed to never make a
52 // system call to generate a new number, except to seed it.  This should *never*
53 // be used for cryptographic applications, and is not thread-safe.
54 //
55 // It is seeded using base::RandUint64() in the constructor, meaning that it
56 // doesn't need to be seeded. It can be re-seeded though, with
57 // ReseedForTesting(). Its period is long enough that it should not need to be
58 // re-seeded during use.
59 //
60 // Uses the XorShift128+ generator under the hood.
PA_COMPONENT_EXPORT(PARTITION_ALLOC)61 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) InsecureRandomGenerator {
62  public:
63   // Never use outside testing, not enough entropy.
64   void ReseedForTesting(uint64_t seed);
65 
66   uint32_t RandUint32();
67   uint64_t RandUint64();
68 
69  private:
70   InsecureRandomGenerator();
71   // State.
72   uint64_t a_ = 0, b_ = 0;
73 
74   // Before adding a new friend class, make sure that the overhead of
75   // base::Rand*() is too high, using something more representative than a
76   // microbenchmark.
77   //
78   // PartitionAlloc allocations should not take more than 40-50ns per
79   // malloc()/free() pair, otherwise high-level benchmarks regress, and does not
80   // need a secure PRNG, as it's used for ASLR and zeroing some allocations at
81   // free() time.
82   friend class ::partition_alloc::RandomGenerator;
83 
84   PA_FRIEND_TEST_ALL_PREFIXES(
85       PartitionAllocBaseRandUtilTest,
86       InsecureRandomGeneratorProducesBothValuesOfAllBits);
87   PA_FRIEND_TEST_ALL_PREFIXES(PartitionAllocBaseRandUtilTest,
88                               InsecureRandomGeneratorChiSquared);
89   PA_FRIEND_TEST_ALL_PREFIXES(PartitionAllocBaseRandUtilTest,
90                               InsecureRandomGeneratorRandDouble);
91 };
92 
93 }  // namespace partition_alloc::internal::base
94 
95 #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_RAND_UTIL_H_
96