Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2022 The Bitcoin Core developers 3 : // Distributed under the MIT software license, see the accompanying 4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : 6 : #ifndef BITCOIN_RANDOM_H 7 : #define BITCOIN_RANDOM_H 8 : 9 : #include <crypto/chacha20.h> 10 : #include <crypto/common.h> 11 : #include <span.h> 12 : #include <uint256.h> 13 : 14 : #include <cassert> 15 : #include <chrono> 16 : #include <cstdint> 17 : #include <limits> 18 : #include <vector> 19 : 20 : /** 21 : * Overall design of the RNG and entropy sources. 22 : * 23 : * We maintain a single global 256-bit RNG state for all high-quality randomness. 24 : * The following (classes of) functions interact with that state by mixing in new 25 : * entropy, and optionally extracting random output from it: 26 : * 27 : * - The GetRand*() class of functions, as well as construction of FastRandomContext objects, 28 : * perform 'fast' seeding, consisting of mixing in: 29 : * - A stack pointer (indirectly committing to calling thread and call stack) 30 : * - A high-precision timestamp (rdtsc when available, c++ high_resolution_clock otherwise) 31 : * - 64 bits from the hardware RNG (rdrand) when available. 32 : * These entropy sources are very fast, and only designed to protect against situations 33 : * where a VM state restore/copy results in multiple systems with the same randomness. 34 : * FastRandomContext on the other hand does not protect against this once created, but 35 : * is even faster (and acceptable to use inside tight loops). 36 : * 37 : * - The GetStrongRand*() class of function perform 'slow' seeding, including everything 38 : * that fast seeding includes, but additionally: 39 : * - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if 40 : * this entropy source fails. 41 : * - Another high-precision timestamp (indirectly committing to a benchmark of all the 42 : * previous sources). 43 : * These entropy sources are slower, but designed to make sure the RNG state contains 44 : * fresh data that is unpredictable to attackers. 45 : * 46 : * - RandAddPeriodic() seeds everything that fast seeding includes, but additionally: 47 : * - A high-precision timestamp 48 : * - Dynamic environment data (performance monitoring, ...) 49 : * - Strengthen the entropy for 10 ms using repeated SHA512. 50 : * This is run once every minute. 51 : * 52 : * On first use of the RNG (regardless of what function is called first), all entropy 53 : * sources used in the 'slow' seeder are included, but also: 54 : * - 256 bits from the hardware RNG (rdseed or rdrand) when available. 55 : * - Dynamic environment data (performance monitoring, ...) 56 : * - Static environment data 57 : * - Strengthen the entropy for 100 ms using repeated SHA512. 58 : * 59 : * When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and 60 : * (up to) the first 32 bytes of H are produced as output, while the last 32 bytes 61 : * become the new RNG state. 62 : */ 63 : 64 : /** 65 : * Generate random data via the internal PRNG. 66 : * 67 : * These functions are designed to be fast (sub microsecond), but do not necessarily 68 : * meaningfully add entropy to the PRNG state. 69 : * 70 : * Thread-safe. 71 : */ 72 : void GetRandBytes(Span<unsigned char> bytes) noexcept; 73 : /** Generate a uniform random integer in the range [0..range). Precondition: range > 0 */ 74 : uint64_t GetRandInternal(uint64_t nMax) noexcept; 75 : /** Generate a uniform random integer of type T in the range [0..nMax) 76 : * nMax defaults to std::numeric_limits<T>::max() 77 : * Precondition: nMax > 0, T is an integral type, no larger than uint64_t 78 : */ 79 : template<typename T> 80 183719 : T GetRand(T nMax=std::numeric_limits<T>::max()) noexcept { 81 : static_assert(std::is_integral<T>(), "T must be integral"); 82 : static_assert(std::numeric_limits<T>::max() <= std::numeric_limits<uint64_t>::max(), "GetRand only supports up to uint64_t"); 83 183719 : return T(GetRandInternal(nMax)); 84 : } 85 : /** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */ 86 : template <typename D> 87 0 : D GetRandomDuration(typename std::common_type<D>::type max) noexcept 88 : // Having the compiler infer the template argument from the function argument 89 : // is dangerous, because the desired return value generally has a different 90 : // type than the function argument. So std::common_type is used to force the 91 : // call site to specify the type of the return value. 92 : { 93 0 : assert(max.count() > 0); 94 0 : return D{GetRand(max.count())}; 95 : }; 96 : constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>; 97 : constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>; 98 : 99 : /** 100 : * Return a timestamp in the future sampled from an exponential distribution 101 : * (https://en.wikipedia.org/wiki/Exponential_distribution). This distribution 102 : * is memoryless and should be used for repeated network events (e.g. sending a 103 : * certain type of message) to minimize leaking information to observers. 104 : * 105 : * The probability of an event occurring before time x is 1 - e^-(x/a) where a 106 : * is the average interval between events. 107 : * */ 108 : std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval); 109 : 110 : uint256 GetRandHash() noexcept; 111 : 112 : /** 113 : * Gather entropy from various sources, feed it into the internal PRNG, and 114 : * generate random data using it. 115 : * 116 : * This function will cause failure whenever the OS RNG fails. 117 : * 118 : * Thread-safe. 119 : */ 120 : void GetStrongRandBytes(Span<unsigned char> bytes) noexcept; 121 : 122 : /** 123 : * Gather entropy from various expensive sources, and feed them to the PRNG state. 124 : * 125 : * Thread-safe. 126 : */ 127 : void RandAddPeriodic() noexcept; 128 : 129 : /** 130 : * Gathers entropy from the low bits of the time at which events occur. Should 131 : * be called with a uint32_t describing the event at the time an event occurs. 132 : * 133 : * Thread-safe. 134 : */ 135 : void RandAddEvent(const uint32_t event_info) noexcept; 136 : 137 : /** 138 : * Fast randomness source. This is seeded once with secure random data, but 139 : * is completely deterministic and does not gather more entropy after that. 140 : * 141 : * This class is not thread-safe. 142 : */ 143 : class FastRandomContext 144 : { 145 : private: 146 : bool requires_seed; 147 : ChaCha20 rng; 148 : 149 : uint64_t bitbuf; 150 : int bitbuf_size; 151 : 152 : void RandomSeed(); 153 : 154 3 : void FillBitBuffer() 155 : { 156 3 : bitbuf = rand64(); 157 3 : bitbuf_size = 64; 158 3 : } 159 : 160 : public: 161 : explicit FastRandomContext(bool fDeterministic = false) noexcept; 162 : 163 : /** Initialize with explicit seed (only for testing) */ 164 : explicit FastRandomContext(const uint256& seed) noexcept; 165 : 166 : // Do not permit copying a FastRandomContext (move it, or create a new one to get reseeded). 167 : FastRandomContext(const FastRandomContext&) = delete; 168 : FastRandomContext(FastRandomContext&&) = delete; 169 : FastRandomContext& operator=(const FastRandomContext&) = delete; 170 : 171 : /** Move a FastRandomContext. If the original one is used again, it will be reseeded. */ 172 : FastRandomContext& operator=(FastRandomContext&& from) noexcept; 173 : 174 : /** Generate a random 64-bit integer. */ 175 177091 : uint64_t rand64() noexcept 176 : { 177 177091 : if (requires_seed) RandomSeed(); 178 : std::array<std::byte, 8> buf; 179 177091 : rng.Keystream(buf); 180 177091 : return ReadLE64(UCharCast(buf.data())); 181 : } 182 : 183 : /** Generate a random (bits)-bit integer. */ 184 183719 : uint64_t randbits(int bits) noexcept 185 : { 186 183719 : if (bits == 0) { 187 6628 : return 0; 188 177091 : } else if (bits > 32) { 189 177088 : return rand64() >> (64 - bits); 190 : } else { 191 3 : if (bitbuf_size < bits) FillBitBuffer(); 192 3 : uint64_t ret = bitbuf & (~uint64_t{0} >> (64 - bits)); 193 3 : bitbuf >>= bits; 194 3 : bitbuf_size -= bits; 195 3 : return ret; 196 : } 197 183719 : } 198 : 199 : /** Generate a random integer in the range [0..range). 200 : * Precondition: range > 0. 201 : */ 202 183719 : uint64_t randrange(uint64_t range) noexcept 203 : { 204 183719 : assert(range); 205 183719 : --range; 206 183719 : int bits = CountBits(range); 207 183719 : while (true) { 208 183719 : uint64_t ret = randbits(bits); 209 183719 : if (ret <= range) return ret; 210 : } 211 : } 212 : 213 : /** Generate random bytes. */ 214 : template <typename B = unsigned char> 215 : std::vector<B> randbytes(size_t len); 216 : 217 : /** Fill a byte Span with random bytes. */ 218 : void fillrand(Span<std::byte> output); 219 : 220 : /** Generate a random 32-bit integer. */ 221 0 : uint32_t rand32() noexcept { return randbits(32); } 222 : 223 : /** generate a random uint256. */ 224 : uint256 rand256() noexcept; 225 : 226 : /** Generate a random boolean. */ 227 0 : bool randbool() noexcept { return randbits(1); } 228 : 229 : /** Return the time point advanced by a uniform random duration. */ 230 : template <typename Tp> 231 0 : Tp rand_uniform_delay(const Tp& time, typename Tp::duration range) 232 : { 233 0 : return time + rand_uniform_duration<Tp>(range); 234 : } 235 : 236 : /** Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive). */ 237 : template <typename Chrono> 238 0 : typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept 239 : { 240 : using Dur = typename Chrono::duration; 241 0 : return range.count() > 0 ? /* interval [0..range) */ Dur{randrange(range.count())} : 242 0 : range.count() < 0 ? /* interval (range..0] */ -Dur{randrange(-range.count())} : 243 0 : /* interval [0..0] */ Dur{0}; 244 : }; 245 : 246 : // Compatibility with the UniformRandomBitGenerator concept 247 : typedef uint64_t result_type; 248 0 : static constexpr uint64_t min() { return 0; } 249 0 : static constexpr uint64_t max() { return std::numeric_limits<uint64_t>::max(); } 250 0 : inline uint64_t operator()() noexcept { return rand64(); } 251 : }; 252 : 253 : /** More efficient than using std::shuffle on a FastRandomContext. 254 : * 255 : * This is more efficient as std::shuffle will consume entropy in groups of 256 : * 64 bits at the time and throw away most. 257 : * 258 : * This also works around a bug in libstdc++ std::shuffle that may cause 259 : * type::operator=(type&&) to be invoked on itself, which the library's 260 : * debug mode detects and panics on. This is a known issue, see 261 : * https://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle 262 : */ 263 : template <typename I, typename R> 264 0 : void Shuffle(I first, I last, R&& rng) 265 : { 266 0 : while (first != last) { 267 0 : size_t j = rng.randrange(last - first); 268 0 : if (j) { 269 : using std::swap; 270 0 : swap(*first, *(first + j)); 271 0 : } 272 0 : ++first; 273 : } 274 0 : } 275 : 276 : /* Number of random bytes returned by GetOSRand. 277 : * When changing this constant make sure to change all call sites, and make 278 : * sure that the underlying OS APIs for all platforms support the number. 279 : * (many cap out at 256 bytes). 280 : */ 281 : static const int NUM_OS_RANDOM_BYTES = 32; 282 : 283 : /** Get 32 bytes of system entropy. Do not use this in application code: use 284 : * GetStrongRandBytes instead. 285 : */ 286 : void GetOSRand(unsigned char* ent32); 287 : 288 : /** Check that OS randomness is available and returning the requested number 289 : * of bytes. 290 : */ 291 : bool Random_SanityCheck(); 292 : 293 : /** 294 : * Initialize global RNG state and log any CPU features that are used. 295 : * 296 : * Calling this function is optional. RNG state will be initialized when first 297 : * needed if it is not called. 298 : */ 299 : void RandomInit(); 300 : 301 : #endif // BITCOIN_RANDOM_H