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