Skip to content

Commit 4ffda1f

Browse files
sipaFuzzbawls
authored andcommitted
Document RNG design in random.h
1 parent 2b6381e commit 4ffda1f

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

src/random.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,14 @@ namespace {
282282

283283
class RNGState {
284284
Mutex m_mutex;
285+
/* The RNG state consists of 256 bits of entropy, taken from the output of
286+
* one operation's SHA512 output, and fed as input to the next one.
287+
* Carrying 256 bits of entropy should be sufficient to guarantee
288+
* unpredictability as long as any entropy source was ever unpredictable
289+
* to an attacker. To protect against situations where an attacker might
290+
* observe the RNG's state, fresh entropy is always mixed when
291+
* GetStrongRandBytes is called.
292+
*/
285293
unsigned char m_state[32] GUARDED_BY(m_mutex) = {0};
286294
uint64_t m_counter GUARDED_BY(m_mutex) = 0;
287295
bool m_strongly_seeded GUARDED_BY(m_mutex) = false;

src/random.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,49 @@
1414
#include <stdint.h>
1515
#include <limits>
1616

17+
/**
18+
* Overall design of the RNG and entropy sources.
19+
*
20+
* We maintain a single global 256-bit RNG state for all high-quality randomness.
21+
* The following (classes of) functions interact with that state by mixing in new
22+
* entropy, and optionally extracting random output from it:
23+
*
24+
* - The GetRand*() class of functions, as well as construction of FastRandomContext objects,
25+
* perform 'fast' seeding, consisting of mixing in:
26+
* - A stack pointer (indirectly committing to calling thread and call stack)
27+
* - A high-precision timestamp (rdtsc when available, c++ high_resolution_clock otherwise)
28+
* - Hardware RNG (rdrand) when available.
29+
* These entropy sources are very fast, and only designed to protect against situations
30+
* where a VM state restore/copy results in multiple systems with the same randomness.
31+
* FastRandomContext on the other hand does not protect against this once created, but
32+
* is even faster (and acceptable to use inside tight loops).
33+
*
34+
* - The GetStrongRand*() class of function perform 'slow' seeding, including everything
35+
* that fast seeding includes, but additionally:
36+
* - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if
37+
* this entropy source fails.
38+
* - Bytes from OpenSSL's RNG (which itself may be seeded from various sources)
39+
* - Another high-precision timestamp (indirectly committing to a benchmark of all the
40+
* previous sources).
41+
* These entropy sources are slower, but designed to make sure the RNG state contains
42+
* fresh data that is unpredictable to attackers.
43+
*
44+
* - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally:
45+
* - A high-precision timestamp before and after sleeping 1ms.
46+
* - (On Windows) Once every 10 minutes, performance monitoring data from the OS.
47+
* These just exploit the fact the system is idle to improve the quality of the RNG
48+
* slightly.
49+
*
50+
* On first use of the RNG (regardless of what function is called first), all entropy
51+
* sources used in the 'slow' seeder are included, but also:
52+
* - (On Windows) Performance monitoring data from the OS.
53+
* - (On Windows) Through OpenSSL, the screen contents.
54+
*
55+
* When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
56+
* (up to) the first 32 bytes of H are produced as output, while the last 32 bytes
57+
* become the new RNG state.
58+
*/
59+
1760
/**
1861
* Generate random data via the internal PRNG.
1962
*

0 commit comments

Comments
 (0)