Coverage Report

Created: 2023-01-25 06:35

/src/botan/build/include/botan/stateful_rng.h
Line
Count
Source (jump to first uncovered line)
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/rng.h>
11
#include <botan/mutex.h>
12
13
namespace 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
*/
26
class BOTAN_PUBLIC_API(2,0) Stateful_RNG : public RandomNumberGenerator
27
   {
28
   public:
29
      /**
30
      * @param rng is a reference to some RNG which will be used
31
      * to perform the periodic reseeding
32
      * @param entropy_sources will be polled to perform reseeding periodically
33
      * @param reseed_interval specifies a limit of how many times
34
      * the RNG will be called before automatic reseeding is performed
35
      */
36
      Stateful_RNG(RandomNumberGenerator& rng,
37
                   Entropy_Sources& entropy_sources,
38
                   size_t reseed_interval) :
39
         m_underlying_rng(&rng),
40
         m_entropy_sources(&entropy_sources),
41
         m_reseed_interval(reseed_interval)
42
0
         {}
43
44
      /**
45
      * @param rng is a reference to some RNG which will be used
46
      * to perform the periodic reseeding
47
      * @param reseed_interval specifies a limit of how many times
48
      * the RNG will be called before automatic reseeding is performed
49
      */
50
      Stateful_RNG(RandomNumberGenerator& rng, size_t reseed_interval) :
51
         m_underlying_rng(&rng),
52
         m_reseed_interval(reseed_interval)
53
0
         {}
54
55
      /**
56
      * @param entropy_sources will be polled to perform reseeding periodically
57
      * @param reseed_interval specifies a limit of how many times
58
      * the RNG will be called before automatic reseeding is performed
59
      */
60
      Stateful_RNG(Entropy_Sources& entropy_sources, size_t reseed_interval) :
61
         m_entropy_sources(&entropy_sources),
62
         m_reseed_interval(reseed_interval)
63
0
         {}
64
65
      /**
66
      * In this case, automatic reseeding is impossible
67
      */
68
7
      Stateful_RNG() : m_reseed_interval(0) {}
69
70
      /**
71
      * Consume this input and mark the RNG as initialized regardless
72
      * of the length of the input or the current seeded state of
73
      * the RNG.
74
      */
75
      void initialize_with(const uint8_t input[], size_t length);
76
77
      bool is_seeded() const override final;
78
79
0
      bool accepts_input() const override final { return true; }
80
81
      /**
82
      * Mark state as requiring a reseed on next use
83
      */
84
      void force_reseed();
85
86
      void reseed_from_rng(RandomNumberGenerator& rng,
87
                           size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS) override final;
88
89
      void add_entropy(const uint8_t input[], size_t input_len) override final;
90
91
      void randomize(uint8_t output[], size_t output_len) override final;
92
93
      void randomize_with_input(uint8_t output[], size_t output_len,
94
                                const uint8_t input[], size_t input_len) override final;
95
96
      /**
97
      * Overrides default implementation and also includes the current
98
      * process ID and the reseed counter.
99
      */
100
      void randomize_with_ts_input(uint8_t output[], size_t output_len) override final;
101
102
      /**
103
      * Poll provided sources for up to poll_bits bits of entropy
104
      * or until the timeout expires. Returns estimate of the number
105
      * of bits collected.
106
      */
107
      size_t reseed(Entropy_Sources& srcs,
108
                    size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
109
                    std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override;
110
111
      /**
112
      * @return intended security level of this DRBG
113
      */
114
      virtual size_t security_level() const = 0;
115
116
      /**
117
      * Some DRBGs have a notion of the maximum number of bytes per
118
      * request.  Longer requests (to randomize) will be treated as
119
      * multiple requests, and may initiate reseeding multiple times,
120
      * depending on the values of max_number_of_bytes_per_request and
121
      * reseed_interval(). This function returns zero if the RNG in
122
      * question does not have such a notion.
123
      *
124
      * @return max number of bytes per request (or zero)
125
      */
126
      virtual size_t max_number_of_bytes_per_request() const = 0;
127
128
0
      size_t reseed_interval() const { return m_reseed_interval; }
129
130
      void clear() override final;
131
132
   protected:
133
      void reseed_check();
134
135
      virtual void generate_output(uint8_t output[], size_t output_len,
136
                                   const uint8_t input[], size_t input_len) = 0;
137
138
      virtual void update(const uint8_t input[], size_t input_len) = 0;
139
140
      virtual void clear_state() = 0;
141
142
   private:
143
      void reset_reseed_counter();
144
145
      mutable recursive_mutex_type m_mutex;
146
147
      // A non-owned and possibly null pointer to shared RNG
148
      RandomNumberGenerator* m_underlying_rng = nullptr;
149
150
      // A non-owned and possibly null pointer to a shared Entropy_Source
151
      Entropy_Sources* m_entropy_sources = nullptr;
152
153
      const size_t m_reseed_interval;
154
      uint32_t m_last_pid = 0;
155
156
      /*
157
      * Set to 1 after a successful seeding, then incremented.  Reset
158
      * to 0 by clear() or a fork. This logic is used even if
159
      * automatic reseeding is disabled (via m_reseed_interval = 0)
160
      */
161
      size_t m_reseed_counter = 0;
162
   };
163
164
}
165
166
#endif