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