Botan  1.11.31
hmac_rng.cpp
Go to the documentation of this file.
1 /*
2 * HMAC_RNG
3 * (C) 2008,2009,2013,2015,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/hmac_rng.h>
9 #include <botan/entropy_src.h>
10 #include <botan/internal/os_utils.h>
11 #include <algorithm>
12 
13 namespace Botan {
14 
15 HMAC_RNG::HMAC_RNG(std::unique_ptr<MessageAuthenticationCode> prf,
16  RandomNumberGenerator& underlying_rng,
17  Entropy_Sources& entropy_sources,
18  size_t reseed_interval) :
19  Stateful_RNG(underlying_rng, reseed_interval),
20  m_prf(std::move(prf))
21  {
22  BOTAN_ASSERT_NONNULL(m_prf);
23 
24  if(!m_prf->valid_keylength(m_prf->output_length()))
25  {
26  throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name());
27  }
28 
29  m_extractor.reset(m_prf->clone());
30  this->clear();
31  }
32 
33 HMAC_RNG::HMAC_RNG(std::unique_ptr<MessageAuthenticationCode> prf,
34  RandomNumberGenerator& underlying_rng,
35  size_t reseed_interval) :
36  Stateful_RNG(underlying_rng, reseed_interval),
37  m_prf(std::move(prf))
38  {
39  BOTAN_ASSERT_NONNULL(m_prf);
40 
41  if(!m_prf->valid_keylength(m_prf->output_length()))
42  {
43  throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name());
44  }
45 
46  m_extractor.reset(m_prf->clone());
47  this->clear();
48  }
49 
50 HMAC_RNG::HMAC_RNG(std::unique_ptr<MessageAuthenticationCode> prf,
51  Entropy_Sources& entropy_sources,
52  size_t reseed_interval) :
53  Stateful_RNG(entropy_sources, reseed_interval),
54  m_prf(std::move(prf)),
55  m_extractor(m_prf->clone())
56  {
57  BOTAN_ASSERT_NONNULL(m_prf);
58 
59  if(!m_prf->valid_keylength(m_prf->output_length()))
60  {
61  throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name());
62  }
63 
64  m_extractor.reset(m_prf->clone());
65  this->clear();
66  }
67 
68 HMAC_RNG::HMAC_RNG(std::unique_ptr<MessageAuthenticationCode> prf) :
69  Stateful_RNG(),
70  m_prf(std::move(prf))
71  {
72  BOTAN_ASSERT_NONNULL(m_prf);
73 
74  if(!m_prf->valid_keylength(m_prf->output_length()))
75  {
76  throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name());
77  }
78 
79  m_extractor.reset(m_prf->clone());
80  this->clear();
81  }
82 
84  {
86  m_counter = 0;
87 
88  // First PRF inputs are all zero, as specified in section 2
89  m_K.resize(m_prf->output_length());
90  zeroise(m_K);
91 
92  /*
93  Normally we want to feedback PRF outputs to the extractor function
94  to ensure a single bad poll does not reduce entropy. Thus in reseed
95  we'll want to invoke the PRF before we reset the PRF key, but until
96  the first reseed the PRF is unkeyed. Rather than trying to keep
97  track of this, just set the initial PRF key to constant zero.
98  Since all PRF inputs in the first reseed are constants, this
99  amounts to suffixing the seed in the first poll with a fixed
100  constant string.
101 
102  The PRF key will not be used to generate outputs until after reseed
103  sets m_seeded to true.
104  */
105  std::vector<byte> prf_zero_key(m_extractor->output_length());
106  m_prf->set_key(prf_zero_key.data(), prf_zero_key.size());
107 
108  /*
109  Use PRF("Botan HMAC_RNG XTS") as the intitial XTS key.
110 
111  This will be used during the first extraction sequence; XTS values
112  after this one are generated using the PRF.
113 
114  If I understand the E-t-E paper correctly (specifically Section 4),
115  using this fixed initial extractor key is safe to do.
116  */
117  m_extractor->set_key(m_prf->process("Botan HMAC_RNG XTS"));
118  }
119 
120 void HMAC_RNG::new_K_value(byte label)
121  {
122  m_prf->update(m_K);
123  m_prf->update_be(last_pid());
124  m_prf->update_be(OS::get_processor_timestamp());
125  m_prf->update_be(OS::get_system_timestamp_ns());
126  m_prf->update_be(m_counter++);
127  m_prf->update(label);
128  m_prf->final(m_K.data());
129  }
130 
131 /*
132 * Generate a buffer of random bytes
133 */
134 void HMAC_RNG::randomize(byte out[], size_t length)
135  {
136  reseed_check();
137 
138  while(length)
139  {
140  new_K_value(Running);
141 
142  const size_t copied = std::min<size_t>(length, m_prf->output_length());
143 
144  copy_mem(out, m_K.data(), copied);
145  out += copied;
146  length -= copied;
147  }
148 
149  new_K_value(BlockFinished);
150  }
151 
153  size_t poll_bits,
154  std::chrono::milliseconds timeout)
155  {
156  new_K_value(Reseed);
157  m_extractor->update(m_K); // m_K is the PRF output
158 
159  /*
160  * This ends up calling add_entropy which provides input to the extractor
161  */
162  size_t bits_collected = Stateful_RNG::reseed(srcs, poll_bits, timeout);
163 
164  /*
165  Now derive the new PRK using everything that has been fed into
166  the extractor, and set the PRF key to that
167  */
168  m_prf->set_key(m_extractor->final());
169 
170  // Now generate a new PRF output to use as the XTS extractor salt
171  new_K_value(ExtractorSeed);
172  m_extractor->set_key(m_K);
173 
174  // Reset state
175  zeroise(m_K);
176  m_counter = 0;
177 
178  return bits_collected;
179  }
180 
181 /*
182 * Add user-supplied entropy to the extractor input then set remaining
183 * output length to for a reseed on next use.
184 */
185 void HMAC_RNG::add_entropy(const byte input[], size_t length)
186  {
187  m_extractor->update(input, length);
188  force_reseed();
189  }
190 
191 /*
192 * Return the name of this type
193 */
194 std::string HMAC_RNG::name() const
195  {
196  return "HMAC_RNG(" + m_extractor->name() + "," + m_prf->name() + ")";
197  }
198 
199 }
void add_entropy(const byte[], size_t) override
Definition: hmac_rng.cpp:185
Definition: bigint.h:619
void clear() override
std::string name() const override
Definition: hmac_rng.cpp:194
uint64_t get_processor_timestamp()
Definition: os_utils.cpp:41
uint32_t last_pid() const
Definition: stateful_rng.h:96
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:66
void clear() override
Definition: hmac_rng.cpp:83
uint64_t get_system_timestamp_ns()
Definition: os_utils.cpp:88
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:43
Definition: alg_id.cpp:13
size_t reseed(Entropy_Sources &srcs, size_t poll_bits, std::chrono::milliseconds poll_timeout) override
Definition: hmac_rng.cpp:152
size_t reseed(Entropy_Sources &srcs, size_t poll_bits=BOTAN_RNG_RESEED_POLL_BITS, std::chrono::milliseconds poll_timeout=BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override
void randomize(byte buf[], size_t len) override
Definition: hmac_rng.cpp:134
HMAC_RNG(std::unique_ptr< MessageAuthenticationCode > prf, RandomNumberGenerator &underlying_rng, Entropy_Sources &entropy_sources, size_t reseed_interval=BOTAN_RNG_DEFAULT_RESEED_INTERVAL)
Definition: hmac_rng.cpp:15
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:191
std::uint8_t byte
Definition: types.h:31