Coverage Report

Created: 2023-06-07 07:00

/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/mutex.h>
11
#include <botan/rng.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
   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
0
            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
0
            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
0
            m_entropy_sources(&entropy_sources), m_reseed_interval(reseed_interval) {}
54
55
      /**
56
      * In this case, automatic reseeding is impossible
57
      */
58
1
      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
0
      void initialize_with(const uint8_t input[], size_t length) { this->initialize_with(std::span(input, length)); }
68
69
      bool is_seeded() const override final;
70
71
0
      bool accepts_input() const override 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) override 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
0
      size_t reseed_interval() const { return m_reseed_interval; }
107
108
      void clear() override 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) override 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