random.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present 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  #include <util/check.h>
  14  
  15  #include <bit>
  16  #include <cassert>
  17  #include <chrono>
  18  #include <concepts>
  19  #include <cstdint>
  20  #include <limits>
  21  #include <type_traits>
  22  #include <vector>
  23  
  24  /**
  25   * Overall design of the RNG and entropy sources.
  26   *
  27   * We maintain a single global 256-bit RNG state for all high-quality randomness.
  28   * The following (classes of) functions interact with that state by mixing in new
  29   * entropy, and optionally extracting random output from it:
  30   *
  31   * - GetRandBytes, GetRandHash, GetRandDur, as well as construction of FastRandomContext
  32   *   objects, perform 'fast' seeding, consisting of mixing in:
  33   *   - A stack pointer (indirectly committing to calling thread and call stack)
  34   *   - A high-precision timestamp (rdtsc when available, c++ high_resolution_clock otherwise)
  35   *   - 64 bits from the hardware RNG (rdrand) when available.
  36   *   These entropy sources are very fast, and only designed to protect against situations
  37   *   where a VM state restore/copy results in multiple systems with the same randomness.
  38   *   FastRandomContext on the other hand does not protect against this once created, but
  39   *   is even faster (and acceptable to use inside tight loops).
  40   *
  41   * - The GetStrongRandBytes() function performs 'slow' seeding, including everything
  42   *   that fast seeding includes, but additionally:
  43   *   - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if
  44   *     this entropy source fails.
  45   *   - Another high-precision timestamp (indirectly committing to a benchmark of all the
  46   *     previous sources).
  47   *   These entropy sources are slower, but designed to make sure the RNG state contains
  48   *   fresh data that is unpredictable to attackers.
  49   *
  50   * - RandAddPeriodic() seeds everything that fast seeding includes, but additionally:
  51   *   - A high-precision timestamp
  52   *   - Dynamic environment data (clocks, resource usage, ...)
  53   *   - Strengthen the entropy for 10 ms using repeated SHA512.
  54   *   This is run once every minute.
  55   *
  56   * - On first use of the RNG (regardless of what function is called first), all entropy
  57   *   sources used in the 'slow' seeder are included, but also:
  58   *   - 256 bits from the hardware RNG (rdseed or rdrand) when available.
  59   *   - Dynamic environment data (performance monitoring, ...)
  60   *   - Static environment data
  61   *   - Strengthen the entropy for 100 ms using repeated SHA512.
  62   *
  63   * When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
  64   * (up to) the first 32 bytes of H are produced as output, while the last 32 bytes
  65   * become the new RNG state.
  66   *
  67   * During tests, the RNG can be put into a special deterministic mode, in which the output
  68   * of all RNG functions, with the exception of GetStrongRandBytes(), is replaced with the
  69   * output of a deterministic RNG. This deterministic RNG does not gather entropy, and is
  70   * unaffected by RandAddPeriodic() or RandAddEvent(). It produces pseudorandom data that
  71   * only depends on the seed it was initialized with, possibly until it is reinitialized.
  72  */
  73  
  74  
  75  /* ============================= INITIALIZATION AND ADDING ENTROPY ============================= */
  76  
  77  /**
  78   * Initialize global RNG state and log any CPU features that are used.
  79   *
  80   * Calling this function is optional. RNG state will be initialized when first
  81   * needed if it is not called.
  82   */
  83  void RandomInit();
  84  
  85  /**
  86   * Gather entropy from various expensive sources, and feed them to the PRNG state.
  87   *
  88   * Thread-safe.
  89   */
  90  void RandAddPeriodic() noexcept;
  91  
  92  /**
  93   * Gathers entropy from the low bits of the time at which events occur. Should
  94   * be called with a uint32_t describing the event at the time an event occurs.
  95   *
  96   * Thread-safe.
  97   */
  98  void RandAddEvent(uint32_t event_info) noexcept;
  99  
 100  
 101  /* =========================== BASE RANDOMNESS GENERATION FUNCTIONS ===========================
 102   *
 103   * All produced randomness is eventually generated by one of these functions.
 104   */
 105  
 106  /**
 107   * Generate random data via the internal PRNG.
 108   *
 109   * These functions are designed to be fast (sub microsecond), but do not necessarily
 110   * meaningfully add entropy to the PRNG state.
 111   *
 112   * In test mode (see SeedRandomForTest in src/test/util/random.h), the normal PRNG state is
 113   * bypassed, and a deterministic, seeded, PRNG is used instead.
 114   *
 115   * Thread-safe.
 116   */
 117  void GetRandBytes(std::span<unsigned char> bytes) noexcept;
 118  
 119  /**
 120   * Gather entropy from various sources, feed it into the internal PRNG, and
 121   * generate random data using it.
 122   *
 123   * This function will cause failure whenever the OS RNG fails.
 124   *
 125   * The normal PRNG is never bypassed here, even in test mode.
 126   *
 127   * Thread-safe.
 128   */
 129  void GetStrongRandBytes(std::span<unsigned char> bytes) noexcept;
 130  
 131  
 132  /* ============================= RANDOM NUMBER GENERATION CLASSES =============================
 133   *
 134   * In this section, 3 classes are defined:
 135   * - RandomMixin:            a base class that adds functionality to all RNG classes.
 136   * - FastRandomContext:      a cryptographic RNG (seeded through GetRandBytes in its default
 137   *                           constructor).
 138   * - InsecureRandomContext:  a non-cryptographic, very fast, RNG.
 139   */
 140  
 141  // Forward declaration of RandomMixin, used in RandomNumberGenerator concept.
 142  template<typename T>
 143  class RandomMixin;
 144  
 145  /** A concept for RandomMixin-based random number generators. */
 146  template<typename T>
 147  concept RandomNumberGenerator = requires(T& rng, std::span<std::byte> s) {
 148      // A random number generator must provide rand64().
 149      { rng.rand64() } noexcept -> std::same_as<uint64_t>;
 150      // A random number generator must derive from RandomMixin, which adds other rand* functions.
 151      requires std::derived_from<std::remove_reference_t<T>, RandomMixin<std::remove_reference_t<T>>>;
 152  };
 153  
 154  /** A concept for C++ std::chrono durations. */
 155  template<typename T>
 156  concept StdChronoDuration = requires {
 157      []<class Rep, class Period>(std::type_identity<std::chrono::duration<Rep, Period>>){}(
 158          std::type_identity<T>());
 159  };
 160  
 161  /** Given a uniformly random uint64_t, return an exponentially distributed double with mean 1. */
 162  double MakeExponentiallyDistributed(uint64_t uniform) noexcept;
 163  
 164  /** Mixin class that provides helper randomness functions.
 165   *
 166   * Intended to be used through CRTP: https://en.cppreference.com/w/cpp/language/crtp.
 167   * An RNG class FunkyRNG would derive publicly from RandomMixin<FunkyRNG>. This permits
 168   * RandomMixin from accessing the derived class's rand64() function, while also allowing
 169   * the derived class to provide more.
 170   *
 171   * The derived class must satisfy the RandomNumberGenerator concept.
 172   */
 173  template<typename T>
 174  class RandomMixin
 175  {
 176  private:
 177      uint64_t bitbuf{0};
 178      int bitbuf_size{0};
 179  
 180      /** Access the underlying generator.
 181       *
 182       * This also enforces the RandomNumberGenerator concept. We cannot declare that in the template
 183       * (no template<RandomNumberGenerator T>) because the type isn't fully instantiated yet there.
 184       */
 185      RandomNumberGenerator auto& Impl() noexcept { return static_cast<T&>(*this); }
 186  
 187  protected:
 188      constexpr void FlushCache() noexcept
 189      {
 190          bitbuf = 0;
 191          bitbuf_size = 0;
 192      }
 193  
 194  public:
 195      constexpr RandomMixin() noexcept = default;
 196  
 197      // Do not permit copying or moving an RNG.
 198      RandomMixin(const RandomMixin&) = delete;
 199      RandomMixin& operator=(const RandomMixin&) = delete;
 200      RandomMixin(RandomMixin&&) = delete;
 201      RandomMixin& operator=(RandomMixin&&) = delete;
 202  
 203      /** Generate a random (bits)-bit integer. */
 204      uint64_t randbits(int bits) noexcept
 205      {
 206          Assume(bits <= 64);
 207          // Requests for the full 64 bits are passed through.
 208          if (bits == 64) return Impl().rand64();
 209          uint64_t ret;
 210          if (bits <= bitbuf_size) {
 211              // If there is enough entropy left in bitbuf, return its bottom bits bits.
 212              ret = bitbuf;
 213              bitbuf >>= bits;
 214              bitbuf_size -= bits;
 215          } else {
 216              // If not, return all of bitbuf, supplemented with the (bits - bitbuf_size) bottom
 217              // bits of a newly generated 64-bit number on top. The remainder of that generated
 218              // number becomes the new bitbuf.
 219              uint64_t gen = Impl().rand64();
 220              ret = (gen << bitbuf_size) | bitbuf;
 221              bitbuf = gen >> (bits - bitbuf_size);
 222              bitbuf_size = 64 + bitbuf_size - bits;
 223          }
 224          // Return the bottom bits bits of ret.
 225          return ret & ((uint64_t{1} << bits) - 1);
 226      }
 227  
 228      /** Same as above, but with compile-time fixed bits count. */
 229      template<int Bits>
 230      uint64_t randbits() noexcept
 231      {
 232          static_assert(Bits >= 0 && Bits <= 64);
 233          if constexpr (Bits == 64) {
 234              return Impl().rand64();
 235          } else {
 236              uint64_t ret;
 237              if (Bits <= bitbuf_size) {
 238                  ret = bitbuf;
 239                  bitbuf >>= Bits;
 240                  bitbuf_size -= Bits;
 241              } else {
 242                  uint64_t gen = Impl().rand64();
 243                  ret = (gen << bitbuf_size) | bitbuf;
 244                  bitbuf = gen >> (Bits - bitbuf_size);
 245                  bitbuf_size = 64 + bitbuf_size - Bits;
 246              }
 247              constexpr uint64_t MASK = (uint64_t{1} << Bits) - 1;
 248              return ret & MASK;
 249          }
 250      }
 251  
 252      /** Generate a random integer in the range [0..range), with range > 0. */
 253      template<std::integral I>
 254      I randrange(I range) noexcept
 255      {
 256          static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
 257          Assume(range > 0);
 258          uint64_t maxval = range - 1U;
 259          int bits = std::bit_width(maxval);
 260          while (true) {
 261              uint64_t ret = Impl().randbits(bits);
 262              if (ret <= maxval) return ret;
 263          }
 264      }
 265  
 266      /** Fill a span with random bytes. */
 267      void fillrand(std::span<std::byte> span) noexcept
 268      {
 269          while (span.size() >= 8) {
 270              uint64_t gen = Impl().rand64();
 271              WriteLE64(span.data(), gen);
 272              span = span.subspan(8);
 273          }
 274          if (span.size() >= 4) {
 275              uint32_t gen = Impl().rand32();
 276              WriteLE32(span.data(), gen);
 277              span = span.subspan(4);
 278          }
 279          while (span.size()) {
 280              span[0] = std::byte(Impl().template randbits<8>());
 281              span = span.subspan(1);
 282          }
 283      }
 284  
 285      /** Generate a random integer in its entire (non-negative) range. */
 286      template<std::integral I>
 287      I rand() noexcept
 288      {
 289          static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
 290          static constexpr auto BITS = std::bit_width(uint64_t(std::numeric_limits<I>::max()));
 291          static_assert(std::numeric_limits<I>::max() == std::numeric_limits<uint64_t>::max() >> (64 - BITS));
 292          return I(Impl().template randbits<BITS>());
 293      }
 294  
 295      /** Generate random bytes. */
 296      template <BasicByte B = unsigned char>
 297      std::vector<B> randbytes(size_t len) noexcept
 298      {
 299          std::vector<B> ret(len);
 300          Impl().fillrand(MakeWritableByteSpan(ret));
 301          return ret;
 302      }
 303  
 304      /** Generate fixed-size random bytes. */
 305      template <size_t N, BasicByte B = std::byte>
 306      std::array<B, N> randbytes() noexcept
 307      {
 308          std::array<B, N> ret;
 309          Impl().fillrand(MakeWritableByteSpan(ret));
 310          return ret;
 311      }
 312  
 313      /** Generate a random 32-bit integer. */
 314      uint32_t rand32() noexcept { return Impl().template randbits<32>(); }
 315  
 316      /** generate a random uint256. */
 317      uint256 rand256() noexcept
 318      {
 319          uint256 ret;
 320          Impl().fillrand(MakeWritableByteSpan(ret));
 321          return ret;
 322      }
 323  
 324      /** Generate a random boolean. */
 325      bool randbool() noexcept { return Impl().template randbits<1>(); }
 326  
 327      /** Return the time point advanced by a uniform random duration. */
 328      template <typename Tp>
 329      Tp rand_uniform_delay(const Tp& time, typename Tp::duration range) noexcept
 330      {
 331          return time + Impl().template rand_uniform_duration<Tp>(range);
 332      }
 333  
 334      /** Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive). */
 335      template <typename Chrono> requires StdChronoDuration<typename Chrono::duration>
 336      typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
 337      {
 338          using Dur = typename Chrono::duration;
 339          return range.count() > 0 ? /* interval [0..range) */ Dur{Impl().randrange(range.count())} :
 340                 range.count() < 0 ? /* interval (range..0] */ -Dur{Impl().randrange(-range.count())} :
 341                                     /* interval [0..0] */ Dur{0};
 342      };
 343  
 344      /** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */
 345      template <StdChronoDuration Dur>
 346      Dur randrange(std::common_type_t<Dur> range) noexcept
 347      // Having the compiler infer the template argument from the function argument
 348      // is dangerous, because the desired return value generally has a different
 349      // type than the function argument. So std::common_type is used to force the
 350      // call site to specify the type of the return value.
 351      {
 352          return Dur{Impl().randrange(range.count())};
 353      }
 354  
 355      /**
 356       * Return a duration sampled from an exponential distribution
 357       * (https://en.wikipedia.org/wiki/Exponential_distribution). Successive events
 358       * whose intervals are distributed according to this form a memoryless Poisson
 359       * process. This should be used for repeated network events (e.g. sending a
 360       * certain type of message) to minimize leaking information to observers.
 361       *
 362       * The probability of an event occurring before time x is 1 - e^-(x/a) where a
 363       * is the average interval between events.
 364       * */
 365      std::chrono::microseconds rand_exp_duration(std::chrono::microseconds mean) noexcept
 366      {
 367          using namespace std::chrono_literals;
 368          auto unscaled = MakeExponentiallyDistributed(Impl().rand64());
 369          return std::chrono::duration_cast<std::chrono::microseconds>(unscaled * mean + 0.5us);
 370      }
 371  
 372      // Compatibility with the UniformRandomBitGenerator concept
 373      typedef uint64_t result_type;
 374      static constexpr uint64_t min() noexcept { return 0; }
 375      static constexpr uint64_t max() noexcept { return std::numeric_limits<uint64_t>::max(); }
 376      inline uint64_t operator()() noexcept { return Impl().rand64(); }
 377  };
 378  
 379  /**
 380   * Fast randomness source. This is seeded once with secure random data, but
 381   * is completely deterministic and does not gather more entropy after that.
 382   *
 383   * This class is not thread-safe.
 384   */
 385  class FastRandomContext : public RandomMixin<FastRandomContext>
 386  {
 387  private:
 388      bool requires_seed;
 389      ChaCha20 rng;
 390  
 391      void RandomSeed() noexcept;
 392  
 393  public:
 394      /** Construct a FastRandomContext with GetRandHash()-based entropy (or zero key if fDeterministic). */
 395      explicit FastRandomContext(bool fDeterministic = false) noexcept;
 396  
 397      /** Initialize with explicit seed (only for testing) */
 398      explicit FastRandomContext(const uint256& seed) noexcept;
 399  
 400      /** Reseed with explicit seed (only for testing). */
 401      void Reseed(const uint256& seed) noexcept;
 402  
 403      /** Generate a random 64-bit integer. */
 404      uint64_t rand64() noexcept
 405      {
 406          if (requires_seed) RandomSeed();
 407          std::array<std::byte, 8> buf;
 408          rng.Keystream(buf);
 409          return ReadLE64(buf.data());
 410      }
 411  
 412      /** Fill a byte span with random bytes. This overrides the RandomMixin version. */
 413      void fillrand(std::span<std::byte> output) noexcept;
 414  };
 415  
 416  /** xoroshiro128++ PRNG. Extremely fast, not appropriate for cryptographic purposes.
 417   *
 418   * Memory footprint is very small, period is 2^128 - 1.
 419   * This class is not thread-safe.
 420   *
 421   * Reference implementation available at https://prng.di.unimi.it/xoroshiro128plusplus.c
 422   * See https://prng.di.unimi.it/
 423   */
 424  class InsecureRandomContext : public RandomMixin<InsecureRandomContext>
 425  {
 426      uint64_t m_s0;
 427      uint64_t m_s1;
 428  
 429      [[nodiscard]] constexpr static uint64_t SplitMix64(uint64_t& seedval) noexcept
 430      {
 431          uint64_t z = (seedval += 0x9e3779b97f4a7c15);
 432          z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
 433          z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
 434          return z ^ (z >> 31);
 435      }
 436  
 437  public:
 438      constexpr explicit InsecureRandomContext(uint64_t seedval) noexcept
 439          : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) {}
 440  
 441      constexpr void Reseed(uint64_t seedval) noexcept
 442      {
 443          FlushCache();
 444          m_s0 = SplitMix64(seedval);
 445          m_s1 = SplitMix64(seedval);
 446      }
 447  
 448      constexpr uint64_t rand64() noexcept
 449      {
 450          uint64_t s0 = m_s0, s1 = m_s1;
 451          const uint64_t result = std::rotl(s0 + s1, 17) + s0;
 452          s1 ^= s0;
 453          m_s0 = std::rotl(s0, 49) ^ s1 ^ (s1 << 21);
 454          m_s1 = std::rotl(s1, 28);
 455          return result;
 456      }
 457  };
 458  
 459  
 460  /* ==================== CONVENIENCE FUNCTIONS FOR COMMONLY USED RANDOMNESS ==================== */
 461  
 462  /** Generate a random uint256. */
 463  inline uint256 GetRandHash() noexcept
 464  {
 465      uint256 hash;
 466      GetRandBytes(hash);
 467      return hash;
 468  }
 469  
 470  /* ============================= MISCELLANEOUS TEST-ONLY FUNCTIONS ============================= */
 471  
 472  /** Check that OS randomness is available and returning the requested number
 473   * of bytes.
 474   */
 475  bool Random_SanityCheck();
 476  
 477  #endif // BITCOIN_RANDOM_H
 478