1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_RAND_UTIL_H_
#define BASE_RAND_UTIL_H_
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <string>
#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "build/build_config.h"
#if !BUILDFLAG(IS_NACL)
#include "third_party/boringssl/src/include/openssl/rand.h"
#endif
namespace memory_simulator {
class MemoryHolder;
}
namespace base {
class TimeDelta;
namespace internal {
#if BUILDFLAG(IS_ANDROID)
// Sets the implementation of RandBytes according to the corresponding
// base::Feature. Thread safe: allows to switch while RandBytes() is in use.
void ConfigureRandBytesFieldTrial();
#endif
#if !BUILDFLAG(IS_NACL)
void ConfigureBoringSSLBackedRandBytesFieldTrial();
#endif
// Returns a random double in range [0, 1). For use in allocator shim to avoid
// infinite recursion. Thread-safe.
BASE_EXPORT double RandDoubleAvoidAllocation();
} // namespace internal
// Returns a random number in range [0, UINT64_MAX]. Thread-safe.
BASE_EXPORT uint64_t RandUint64();
// Returns a random number between min and max (inclusive). Thread-safe.
//
// TODO(crbug.com/1488681): Change from fully-closed to half-closed (i.e.
// exclude `max`) to parallel other APIs here.
BASE_EXPORT int RandInt(int min, int max);
// Returns a random number in range [0, range). Thread-safe.
BASE_EXPORT uint64_t RandGenerator(uint64_t range);
// Returns a random double in range [0, 1). Thread-safe.
BASE_EXPORT double RandDouble();
// Returns a random float in range [0, 1). Thread-safe.
BASE_EXPORT float RandFloat();
// Returns a random duration in [`start`, `limit`). Thread-safe.
//
// REQUIRES: `start` < `limit`
BASE_EXPORT TimeDelta RandTimeDelta(TimeDelta start, TimeDelta limit);
// Returns a random duration in [`TimeDelta()`, `limit`). Thread-safe.
//
// REQUIRES: `limit.is_positive()`
BASE_EXPORT TimeDelta RandTimeDeltaUpTo(TimeDelta limit);
// Given input |bits|, convert with maximum precision to a double in
// the range [0, 1). Thread-safe.
BASE_EXPORT double BitsToOpenEndedUnitInterval(uint64_t bits);
// Given input `bits`, convert with maximum precision to a float in the range
// [0, 1). Thread-safe.
BASE_EXPORT float BitsToOpenEndedUnitIntervalF(uint64_t bits);
// Fills |output_length| bytes of |output| with random data. Thread-safe.
//
// Although implementations are required to use a cryptographically secure
// random number source, code outside of base/ that relies on this should use
// crypto::RandBytes instead to ensure the requirement is easily discoverable.
BASE_EXPORT void RandBytes(void* output, size_t output_length);
// Fills a string of length |length| with random data and returns it.
// |length| should be nonzero. Thread-safe.
//
// Note that this is a variation of |RandBytes| with a different return type.
// The returned string is likely not ASCII/UTF-8. Use with care.
//
// Although implementations are required to use a cryptographically secure
// random number source, code outside of base/ that relies on this should use
// crypto::RandBytes instead to ensure the requirement is easily discoverable.
BASE_EXPORT std::string RandBytesAsString(size_t length);
// An STL UniformRandomBitGenerator backed by RandUint64.
class RandomBitGenerator {
public:
using result_type = uint64_t;
static constexpr result_type min() { return 0; }
static constexpr result_type max() { return UINT64_MAX; }
result_type operator()() const { return RandUint64(); }
RandomBitGenerator() = default;
~RandomBitGenerator() = default;
};
#if !BUILDFLAG(IS_NACL)
class NonAllocatingRandomBitGenerator {
public:
using result_type = uint64_t;
static constexpr result_type min() { return 0; }
static constexpr result_type max() { return UINT64_MAX; }
result_type operator()() const {
uint64_t result;
RAND_get_system_entropy_for_custom_prng(reinterpret_cast<uint8_t*>(&result),
sizeof(result));
return result;
}
NonAllocatingRandomBitGenerator() = default;
~NonAllocatingRandomBitGenerator() = default;
};
#endif
// Shuffles [first, last) randomly. Thread-safe.
template <typename Itr>
void RandomShuffle(Itr first, Itr last) {
std::shuffle(first, last, RandomBitGenerator());
}
#if BUILDFLAG(IS_POSIX)
BASE_EXPORT int GetUrandomFD();
#endif
class MetricsSubSampler;
// Fast, insecure pseudo-random number generator.
//
// WARNING: This is not the generator you are looking for. This has significant
// caveats:
// - It is non-cryptographic, so easy to miuse
// - It is neither fork() nor clone()-safe.
// - Synchronization is up to the client.
//
// Always prefer base::Rand*() above, unless you have a use case where its
// overhead is too high, or system calls are disallowed.
//
// Performance: As of 2021, rough overhead on Linux on a desktop machine of
// base::RandUint64() is ~800ns per call (it performs a system call). On Windows
// it is lower. On the same machine, this generator's cost is ~2ns per call,
// regardless of platform.
//
// This is different from |Rand*()| above as it is guaranteed to never make a
// system call to generate a new number, except to seed it. This should *never*
// be used for cryptographic applications, and is not thread-safe.
//
// It is seeded using base::RandUint64() in the constructor, meaning that it
// doesn't need to be seeded. It can be re-seeded though, with
// ReseedForTesting(). Its period is long enough that it should not need to be
// re-seeded during use.
//
// Uses the XorShift128+ generator under the hood.
class BASE_EXPORT InsecureRandomGenerator {
public:
// Never use outside testing, not enough entropy.
void ReseedForTesting(uint64_t seed);
uint32_t RandUint32();
uint64_t RandUint64();
// In [0, 1).
double RandDouble();
private:
InsecureRandomGenerator();
// State.
uint64_t a_ = 0, b_ = 0;
// Before adding a new friend class, make sure that the overhead of
// base::Rand*() is too high, using something more representative than a
// microbenchmark.
// Uses the generator to fill memory pages with random content to make them
// hard to compress, in a simulation tool not bundled with Chrome. CPU
// overhead must be minimized to correctly measure memory effects.
friend class memory_simulator::MemoryHolder;
// Uses the generator to sub-sample metrics.
friend class MetricsSubSampler;
FRIEND_TEST_ALL_PREFIXES(RandUtilTest,
InsecureRandomGeneratorProducesBothValuesOfAllBits);
FRIEND_TEST_ALL_PREFIXES(RandUtilTest, InsecureRandomGeneratorChiSquared);
FRIEND_TEST_ALL_PREFIXES(RandUtilTest, InsecureRandomGeneratorRandDouble);
FRIEND_TEST_ALL_PREFIXES(RandUtilPerfTest, InsecureRandomRandUint64);
};
class BASE_EXPORT MetricsSubSampler {
public:
MetricsSubSampler();
bool ShouldSample(double probability);
// Disables subsampling in a scope. Useful for testing.
class BASE_EXPORT ScopedDisableForTesting {
public:
ScopedDisableForTesting();
~ScopedDisableForTesting();
};
private:
InsecureRandomGenerator generator_;
};
} // namespace base
#endif // BASE_RAND_UTIL_H_
|