Branch data 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 : 1874 : 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 : 1874 : 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 : 375 : 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 [ + - # # ]: 375 : assert(max.count() > 0); 94 [ - + # # ]: 375 : 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 : 5486 : void FillBitBuffer() 155 : : { 156 : 5486 : bitbuf = rand64(); 157 : 5486 : bitbuf_size = 64; 158 : 5486 : } 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 : 5506 : uint64_t rand64() noexcept 176 : : { 177 [ + + + - ]: 5506 : if (requires_seed) RandomSeed(); 178 : : std::array<std::byte, 8> buf; 179 [ + - ]: 5506 : rng.Keystream(buf); 180 [ + - + - ]: 5506 : return ReadLE64(UCharCast(buf.data())); 181 : : } 182 : : 183 : : /** Generate a random (bits)-bit integer. */ 184 : 7142 : uint64_t randbits(int bits) noexcept 185 : : { 186 [ + + ]: 7142 : if (bits == 0) { 187 : 1476 : return 0; 188 [ + + ]: 5666 : } else if (bits > 32) { 189 : 20 : return rand64() >> (64 - bits); 190 : : } else { 191 [ + + + - ]: 5646 : if (bitbuf_size < bits) FillBitBuffer(); 192 : 5646 : uint64_t ret = bitbuf & (~uint64_t{0} >> (64 - bits)); 193 : 5646 : bitbuf >>= bits; 194 : 5646 : bitbuf_size -= bits; 195 : 5646 : return ret; 196 : : } 197 : 7142 : } 198 : : 199 : : /** Generate a random integer in the range [0..range). 200 : : * Precondition: range > 0. 201 : : */ 202 : 6928 : uint64_t randrange(uint64_t range) noexcept 203 : : { 204 [ + - ]: 6928 : assert(range); 205 : 6928 : --range; 206 [ - + ]: 6928 : int bits = CountBits(range); 207 : 7142 : while (true) { 208 : 7142 : uint64_t ret = randbits(bits); 209 [ + + ]: 7142 : 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