Coverage Report

Created: 2024-02-25 06:16

/src/botan/src/lib/entropy/entropy_srcs.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Entropy Source Polling
3
* (C) 2008-2010,2015 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/entropy_src.h>
9
10
#include <botan/rng.h>
11
12
#if defined(BOTAN_HAS_SYSTEM_RNG)
13
   #include <botan/system_rng.h>
14
#endif
15
16
#if defined(BOTAN_HAS_PROCESSOR_RNG)
17
   #include <botan/processor_rng.h>
18
#endif
19
20
#if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED)
21
   #include <botan/internal/rdseed.h>
22
#endif
23
24
#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
25
   #include <botan/internal/es_win32.h>
26
#endif
27
28
#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
29
   #include <botan/internal/getentropy.h>
30
#endif
31
32
namespace Botan {
33
34
namespace {
35
36
#if defined(BOTAN_HAS_SYSTEM_RNG)
37
38
class System_RNG_EntropySource final : public Entropy_Source {
39
   public:
40
0
      size_t poll(RandomNumberGenerator& rng) override {
41
0
         const size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS;
42
0
         rng.reseed_from_rng(system_rng(), poll_bits);
43
0
         return poll_bits;
44
0
      }
45
46
0
      std::string name() const override { return "system_rng"; }
47
};
48
49
#endif
50
51
#if defined(BOTAN_HAS_PROCESSOR_RNG)
52
53
class Processor_RNG_EntropySource final : public Entropy_Source {
54
   public:
55
0
      size_t poll(RandomNumberGenerator& rng) override {
56
         /*
57
         * Intel's documentation for RDRAND at
58
         * https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
59
         * claims that software can guarantee a reseed event by polling enough data:
60
         * "There is an upper bound of 511 samples per seed in the implementation
61
         * where samples are 128 bits in size and can provide two 64-bit random
62
         * numbers each."
63
         *
64
         * By requesting 65536 bits we are asking for 512 samples and thus are assured
65
         * that at some point in producing the output, at least one reseed of the
66
         * internal state will occur.
67
         *
68
         * The reseeding conditions of the POWER and ARM processor RNGs are not known
69
         * but probably work in a somewhat similar manner. The exact amount requested
70
         * may be tweaked if and when such conditions become publically known.
71
         */
72
0
         const size_t poll_bits = 65536;
73
0
         rng.reseed_from_rng(m_hwrng, poll_bits);
74
         // Avoid trusting a black box, don't count this as contributing entropy:
75
0
         return 0;
76
0
      }
77
78
0
      std::string name() const override { return m_hwrng.name(); }
79
80
   private:
81
      Processor_RNG m_hwrng;
82
};
83
84
#endif
85
86
}  // namespace
87
88
0
std::unique_ptr<Entropy_Source> Entropy_Source::create(std::string_view name) {
89
0
#if defined(BOTAN_HAS_SYSTEM_RNG)
90
0
   if(name == "system_rng") {
91
0
      return std::make_unique<System_RNG_EntropySource>();
92
0
   }
93
0
#endif
94
95
0
#if defined(BOTAN_HAS_PROCESSOR_RNG)
96
0
   if(name == "hwrng") {
97
0
      if(Processor_RNG::available()) {
98
0
         return std::make_unique<Processor_RNG_EntropySource>();
99
0
      }
100
0
   }
101
0
#endif
102
103
0
#if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED)
104
0
   if(name == "rdseed") {
105
0
      return std::make_unique<Intel_Rdseed>();
106
0
   }
107
0
#endif
108
109
0
#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
110
0
   if(name == "getentropy") {
111
0
      return std::make_unique<Getentropy>();
112
0
   }
113
0
#endif
114
115
#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
116
   if(name == "system_stats") {
117
      return std::make_unique<Win32_EntropySource>();
118
   }
119
#endif
120
121
0
   BOTAN_UNUSED(name);
122
0
   return nullptr;
123
0
}
124
125
0
void Entropy_Sources::add_source(std::unique_ptr<Entropy_Source> src) {
126
0
   if(src) {
127
0
      m_srcs.push_back(std::move(src));
128
0
   }
129
0
}
130
131
0
std::vector<std::string> Entropy_Sources::enabled_sources() const {
132
0
   std::vector<std::string> sources;
133
0
   sources.reserve(m_srcs.size());
134
0
   for(const auto& src : m_srcs) {
135
0
      sources.push_back(src->name());
136
0
   }
137
0
   return sources;
138
0
}
139
140
0
size_t Entropy_Sources::poll(RandomNumberGenerator& rng, size_t poll_bits, std::chrono::milliseconds timeout) {
141
0
   typedef std::chrono::system_clock clock;
142
143
0
   auto deadline = clock::now() + timeout;
144
145
0
   size_t bits_collected = 0;
146
147
0
   for(auto& src : m_srcs) {
148
0
      bits_collected += src->poll(rng);
149
150
0
      if(bits_collected >= poll_bits || clock::now() > deadline) {
151
0
         break;
152
0
      }
153
0
   }
154
155
0
   return bits_collected;
156
0
}
157
158
0
size_t Entropy_Sources::poll_just(RandomNumberGenerator& rng, std::string_view the_src) {
159
0
   for(auto& src : m_srcs) {
160
0
      if(src->name() == the_src) {
161
0
         return src->poll(rng);
162
0
      }
163
0
   }
164
165
0
   return 0;
166
0
}
167
168
0
Entropy_Sources::Entropy_Sources(const std::vector<std::string>& sources) {
169
0
   for(auto&& src_name : sources) {
170
0
      add_source(Entropy_Source::create(src_name));
171
0
   }
172
0
}
173
174
0
Entropy_Sources& Entropy_Sources::global_sources() {
175
0
   static Entropy_Sources global_entropy_sources(BOTAN_ENTROPY_DEFAULT_SOURCES);
176
177
0
   return global_entropy_sources;
178
0
}
179
180
}  // namespace Botan