Coverage Report

Created: 2020-05-23 13:54

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