Coverage Report

Created: 2021-02-21 07:20

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