Botan 3.4.0
Crypto and TLS for C&
stateful_rng.h
Go to the documentation of this file.
1/*
2* (C) 2016 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_STATEFUL_RNG_H_
8#define BOTAN_STATEFUL_RNG_H_
9
10#include <botan/mutex.h>
11#include <botan/rng.h>
12
13namespace Botan {
14
15/**
16* Inherited by RNGs which maintain in-process state, like HMAC_DRBG.
17* On Unix these RNGs are vulnerable to problems with fork, where the
18* RNG state is duplicated, and the parent and child process RNGs will
19* produce identical output until one of them reseeds. Stateful_RNG
20* reseeds itself whenever a fork is detected, or after a set number of
21* bytes have been output.
22*
23* Not implemented by RNGs which access an external RNG, such as the
24* system PRNG or a hardware RNG.
25*/
27 public:
28 /**
29 * @param rng is a reference to some RNG which will be used
30 * to perform the periodic reseeding
31 * @param entropy_sources will be polled to perform reseeding periodically
32 * @param reseed_interval specifies a limit of how many times
33 * the RNG will be called before automatic reseeding is performed
34 */
35 Stateful_RNG(RandomNumberGenerator& rng, Entropy_Sources& entropy_sources, size_t reseed_interval) :
36 m_underlying_rng(&rng), m_entropy_sources(&entropy_sources), m_reseed_interval(reseed_interval) {}
37
38 /**
39 * @param rng is a reference to some RNG which will be used
40 * to perform the periodic reseeding
41 * @param reseed_interval specifies a limit of how many times
42 * the RNG will be called before automatic reseeding is performed
43 */
44 Stateful_RNG(RandomNumberGenerator& rng, size_t reseed_interval) :
45 m_underlying_rng(&rng), m_reseed_interval(reseed_interval) {}
46
47 /**
48 * @param entropy_sources will be polled to perform reseeding periodically
49 * @param reseed_interval specifies a limit of how many times
50 * the RNG will be called before automatic reseeding is performed
51 */
52 Stateful_RNG(Entropy_Sources& entropy_sources, size_t reseed_interval) :
53 m_entropy_sources(&entropy_sources), m_reseed_interval(reseed_interval) {}
54
55 /**
56 * In this case, automatic reseeding is impossible
57 */
58 Stateful_RNG() : m_reseed_interval(0) {}
59
60 /**
61 * Consume this input and mark the RNG as initialized regardless
62 * of the length of the input or the current seeded state of
63 * the RNG.
64 */
65 void initialize_with(std::span<const uint8_t> input);
66
67 void initialize_with(const uint8_t input[], size_t length) { this->initialize_with(std::span(input, length)); }
68
69 bool is_seeded() const final;
70
71 bool accepts_input() const final { return true; }
72
73 /**
74 * Mark state as requiring a reseed on next use
75 */
76 void force_reseed();
77
78 void reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS) final;
79
80 /**
81 * Poll provided sources for up to poll_bits bits of entropy
82 * or until the timeout expires. Returns estimate of the number
83 * of bits collected.
84 */
85 size_t reseed(Entropy_Sources& srcs,
86 size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
87 std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override;
88
89 /**
90 * @return intended security level of this DRBG
91 */
92 virtual size_t security_level() const = 0;
93
94 /**
95 * Some DRBGs have a notion of the maximum number of bytes per
96 * request. Longer requests (to randomize) will be treated as
97 * multiple requests, and may initiate reseeding multiple times,
98 * depending on the values of max_number_of_bytes_per_request and
99 * reseed_interval(). This function returns zero if the RNG in
100 * question does not have such a notion.
101 *
102 * @return max number of bytes per request (or zero)
103 */
104 virtual size_t max_number_of_bytes_per_request() const = 0;
105
106 size_t reseed_interval() const { return m_reseed_interval; }
107
108 void clear() final;
109
110 protected:
111 void reseed_check();
112
113 virtual void generate_output(std::span<uint8_t> output, std::span<const uint8_t> input) = 0;
114
115 virtual void update(std::span<const uint8_t> input) = 0;
116
117 virtual void clear_state() = 0;
118
119 private:
120 void generate_batched_output(std::span<uint8_t> output, std::span<const uint8_t> input);
121
122 void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) final;
123
124 void reset_reseed_counter();
125
126 mutable recursive_mutex_type m_mutex;
127
128 // A non-owned and possibly null pointer to shared RNG
129 RandomNumberGenerator* m_underlying_rng = nullptr;
130
131 // A non-owned and possibly null pointer to a shared Entropy_Source
132 Entropy_Sources* m_entropy_sources = nullptr;
133
134 const size_t m_reseed_interval;
135 uint32_t m_last_pid = 0;
136
137 /*
138 * Set to 1 after a successful seeding, then incremented. Reset
139 * to 0 by clear() or a fork. This logic is used even if
140 * automatic reseeding is disabled (via m_reseed_interval = 0)
141 */
142 size_t m_reseed_counter = 0;
143};
144
145} // namespace Botan
146
147#endif
size_t reseed_interval() const
virtual size_t security_level() const =0
Stateful_RNG(RandomNumberGenerator &rng, size_t reseed_interval)
Stateful_RNG(RandomNumberGenerator &rng, Entropy_Sources &entropy_sources, size_t reseed_interval)
void initialize_with(const uint8_t input[], size_t length)
Stateful_RNG(Entropy_Sources &entropy_sources, size_t reseed_interval)
virtual size_t max_number_of_bytes_per_request() const =0
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition compiler.h:31
#define BOTAN_RNG_RESEED_DEFAULT_TIMEOUT
Definition build.h:438
#define BOTAN_RNG_RESEED_POLL_BITS
Definition build.h:436