LCOV - code coverage report
Current view: top level - src - random.h (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 45 56 80.4 %
Date: 2024-05-24 10:43:37 Functions: 12 33 36.4 %
Branches: 26 76 34.2 %

           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 <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                 :      58400 : 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                 :      58400 :     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                 :       3777 : 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   [ +  -  +  - ]:       3777 :     assert(max.count() > 0);
      95   [ -  +  -  + ]:       3777 :     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                 :      98182 :     void FillBitBuffer()
     156                 :            :     {
     157                 :      98182 :         bitbuf = rand64();
     158                 :      98182 :         bitbuf_size = 64;
     159                 :      98182 :     }
     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                 :     142493 :     uint64_t rand64() noexcept
     177                 :            :     {
     178   [ +  +  +  - ]:     142493 :         if (requires_seed) RandomSeed();
     179                 :     142493 :         std::array<std::byte, 8> buf;
     180         [ +  - ]:     142493 :         rng.Keystream(buf);
     181   [ +  -  +  - ]:     142493 :         return ReadLE64(UCharCast(buf.data()));
     182                 :     142493 :     }
     183                 :            : 
     184                 :            :     /** Generate a random (bits)-bit integer. */
     185                 :     606691 :     uint64_t randbits(int bits) noexcept
     186                 :            :     {
     187         [ +  + ]:     606691 :         if (bits == 0) {
     188                 :       5347 :             return 0;
     189         [ +  + ]:     601344 :         } else if (bits > 32) {
     190                 :      44311 :             return rand64() >> (64 - bits);
     191                 :            :         } else {
     192   [ +  +  +  - ]:     557033 :             if (bitbuf_size < bits) FillBitBuffer();
     193                 :     557033 :             uint64_t ret = bitbuf & (~uint64_t{0} >> (64 - bits));
     194                 :     557033 :             bitbuf >>= bits;
     195                 :     557033 :             bitbuf_size -= bits;
     196                 :     557033 :             return ret;
     197                 :     557033 :         }
     198                 :     606691 :     }
     199                 :            : 
     200                 :            :     /** Generate a random integer in the range [0..range).
     201                 :            :      * Precondition: range > 0.
     202                 :            :      */
     203                 :     446863 :     uint64_t randrange(uint64_t range) noexcept
     204                 :            :     {
     205         [ +  - ]:     446863 :         assert(range);
     206                 :     446863 :         --range;
     207                 :     446863 :         int bits = std::bit_width(range);
     208                 :     606691 :         while (true) {
     209                 :     606691 :             uint64_t ret = randbits(bits);
     210         [ +  + ]:     606691 :             if (ret <= range) return ret;
     211         [ +  + ]:     606691 :         }
     212                 :     446863 :     }
     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                 :          0 :     uint32_t rand32() noexcept { return randbits(32); }
     223                 :            : 
     224                 :            :     /** generate a random uint256. */
     225                 :            :     uint256 rand256() noexcept;
     226                 :            : 
     227                 :            :     /** Generate a random boolean. */
     228                 :          0 :     bool randbool() noexcept { return randbits(1); }
     229                 :            : 
     230                 :            :     /** Return the time point advanced by a uniform random duration. */
     231                 :            :     template <typename Tp>
     232                 :          0 :     Tp rand_uniform_delay(const Tp& time, typename Tp::duration range)
     233                 :            :     {
     234                 :          0 :         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                 :          0 :     typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
     240                 :            :     {
     241                 :            :         using Dur = typename Chrono::duration;
     242   [ #  #  #  #  :          0 :         return range.count() > 0 ? /* interval [0..range) */ Dur{randrange(range.count())} :
             #  #  #  # ]
     243   [ #  #  #  #  :          0 :                range.count() < 0 ? /* interval (range..0] */ -Dur{randrange(-range.count())} :
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     244   [ #  #  #  # ]:          0 :                                    /* interval [0..0] */ Dur{0};
     245                 :            :     };
     246                 :            : 
     247                 :            :     // Compatibility with the UniformRandomBitGenerator concept
     248                 :            :     typedef uint64_t result_type;
     249                 :          0 :     static constexpr uint64_t min() { return 0; }
     250                 :          0 :     static constexpr uint64_t max() { return std::numeric_limits<uint64_t>::max(); }
     251                 :          0 :     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                 :       2126 : void Shuffle(I first, I last, R&& rng)
     266                 :            : {
     267   [ +  +  #  #  :      78009 :     while (first != last) {
             #  #  #  # ]
     268                 :      75883 :         size_t j = rng.randrange(last - first);
     269   [ +  +  #  #  :      75883 :         if (j) {
             #  #  #  # ]
     270                 :            :             using std::swap;
     271                 :      70204 :             swap(*first, *(first + j));
     272                 :      70204 :         }
     273                 :      75883 :         ++first;
     274                 :      75883 :     }
     275                 :       2126 : }
     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

Generated by: LCOV version 1.16