Coverage Report

Created: 2021-04-07 06:07

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