1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/*
* EntropySource
* (C) 2008,2009,2014,2015,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#ifndef BOTAN_ENTROPY_H__
#define BOTAN_ENTROPY_H__
#include <botan/secmem.h>
#include <string>
#include <chrono>
#include <functional>
namespace Botan {
class RandomNumberGenerator;
/**
* Class used to accumulate the poll results of EntropySources
*/
class BOTAN_DLL Entropy_Accumulator final
{
public:
/**
* Initialize an Entropy_Accumulator
*
* @param accum will be called with poll results, first params the data and
* length, the second a best estimate of min-entropy for the entire buffer;
* out of an abundance of caution this will be zero for many sources.
* accum should return true if it wants the polling to stop, though it may
* still be called again a few more times, and should be careful to return
* true then as well.
*/
explicit Entropy_Accumulator(std::function<bool (const byte[], size_t, double)> accum) :
m_accum_fn(accum) {}
/**
* @return if our polling goal has been achieved
*/
bool polling_goal_achieved() const { return m_done; }
bool polling_finished() const { return m_done; }
/**
* Add entropy to the accumulator
* @param bytes the input bytes
* @param length specifies how many bytes the input is
* @param entropy_bits_per_byte is a best guess at how much
* entropy per byte is in this input
*/
void add(const void* bytes, size_t length, double entropy_bits_per_byte)
{
m_done = m_accum_fn(reinterpret_cast<const byte*>(bytes),
length, entropy_bits_per_byte * length) || m_done;
}
/**
* Add entropy to the accumulator
* @param v is some value
* @param entropy_bits_per_byte is a best guess at how much
* entropy per byte is in this input
*/
template<typename T>
void add(const T& v, double entropy_bits_per_byte)
{
add(&v, sizeof(T), entropy_bits_per_byte);
}
secure_vector<byte>& get_io_buf(size_t sz) { m_io_buf.resize(sz); return m_io_buf; }
private:
std::function<bool (const byte[], size_t, double)> m_accum_fn;
secure_vector<byte> m_io_buf;
bool m_done = false;
};
/**
* Abstract interface to a source of entropy
*/
class BOTAN_DLL Entropy_Source
{
public:
/*
* Return a new entropy source of a particular type, or null
* Each entropy source may require substantial resources (eg, a file handle
* or socket instance), so try to share them among multiple RNGs, or just
* use the preconfigured global list accessed by global_entropy_sources()
*/
static std::unique_ptr<Entropy_Source> create(const std::string& type);
/**
* @return name identifying this entropy source
*/
virtual std::string name() const = 0;
/**
* Perform an entropy gathering poll
* @param accum is an accumulator object that will be given entropy
*/
virtual void poll(Entropy_Accumulator& accum) = 0;
virtual ~Entropy_Source() {}
};
class BOTAN_DLL Entropy_Sources final
{
public:
static Entropy_Sources& global_sources();
void add_source(std::unique_ptr<Entropy_Source> src);
std::vector<std::string> enabled_sources() const;
size_t poll(RandomNumberGenerator& rng,
size_t bits,
std::chrono::milliseconds timeout);
bool poll_just(Entropy_Accumulator& accum, const std::string& src);
Entropy_Sources() {}
explicit Entropy_Sources(const std::vector<std::string>& sources);
~Entropy_Sources();
private:
std::vector<Entropy_Source*> m_srcs;
};
}
#endif
|