Botan  2.13.0
Crypto and TLS for C++11
hmac_drbg.cpp
Go to the documentation of this file.
1 /*
2 * HMAC_DRBG
3 * (C) 2014,2015,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/hmac_drbg.h>
9 #include <algorithm>
10 
11 namespace Botan {
12 
13 namespace {
14 
15 void check_limits(size_t reseed_interval,
16  size_t max_number_of_bytes_per_request)
17  {
18  // SP800-90A permits up to 2^48, but it is not usable on 32 bit
19  // platforms, so we only allow up to 2^24, which is still reasonably high
20  if(reseed_interval == 0 || reseed_interval > static_cast<size_t>(1) << 24)
21  {
22  throw Invalid_Argument("Invalid value for reseed_interval");
23  }
24 
25  if(max_number_of_bytes_per_request == 0 || max_number_of_bytes_per_request > 64 * 1024)
26  {
27  throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
28  }
29  }
30 
31 }
32 
33 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
34  RandomNumberGenerator& underlying_rng,
35  size_t reseed_interval,
36  size_t max_number_of_bytes_per_request) :
37  Stateful_RNG(underlying_rng, reseed_interval),
38  m_mac(std::move(prf)),
39  m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
40  {
41  BOTAN_ASSERT_NONNULL(m_mac);
42 
44 
45  clear();
46  }
47 
48 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
49  RandomNumberGenerator& underlying_rng,
50  Entropy_Sources& entropy_sources,
51  size_t reseed_interval,
52  size_t max_number_of_bytes_per_request) :
53  Stateful_RNG(underlying_rng, entropy_sources, reseed_interval),
54  m_mac(std::move(prf)),
55  m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
56  {
57  BOTAN_ASSERT_NONNULL(m_mac);
58 
60 
61  clear();
62  }
63 
64 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
65  Entropy_Sources& entropy_sources,
66  size_t reseed_interval,
67  size_t max_number_of_bytes_per_request) :
68  Stateful_RNG(entropy_sources, reseed_interval),
69  m_mac(std::move(prf)),
70  m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
71  {
72  BOTAN_ASSERT_NONNULL(m_mac);
73 
75 
76  clear();
77  }
78 
79 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf) :
80  Stateful_RNG(),
81  m_mac(std::move(prf)),
82  m_max_number_of_bytes_per_request(64*1024)
83  {
84  BOTAN_ASSERT_NONNULL(m_mac);
85  clear();
86  }
87 
89  {
91 
92  const size_t output_length = m_mac->output_length();
93 
94  m_V.resize(output_length);
95  for(size_t i = 0; i != m_V.size(); ++i)
96  m_V[i] = 0x01;
97  m_mac->set_key(std::vector<uint8_t>(output_length, 0x00));
98  }
99 
100 std::string HMAC_DRBG::name() const
101  {
102  return "HMAC_DRBG(" + m_mac->name() + ")";
103  }
104 
105 void HMAC_DRBG::randomize(uint8_t output[], size_t output_len)
106  {
107  randomize_with_input(output, output_len, nullptr, 0);
108  }
109 
110 /*
111 * HMAC_DRBG generation
112 * See NIST SP800-90A section 10.1.2.5
113 */
114 void HMAC_DRBG::randomize_with_input(uint8_t output[], size_t output_len,
115  const uint8_t input[], size_t input_len)
116  {
117  while(output_len > 0)
118  {
119  size_t this_req = std::min(m_max_number_of_bytes_per_request, output_len);
120  output_len -= this_req;
121 
122  reseed_check();
123 
124  if(input_len > 0)
125  {
126  update(input, input_len);
127  }
128 
129  while(this_req)
130  {
131  const size_t to_copy = std::min(this_req, m_V.size());
132  m_mac->update(m_V.data(), m_V.size());
133  m_mac->final(m_V.data());
134  copy_mem(output, m_V.data(), to_copy);
135 
136  output += to_copy;
137  this_req -= to_copy;
138  }
139 
140  update(input, input_len);
141  }
142 
143  }
144 
145 /*
146 * Reset V and the mac key with new values
147 * See NIST SP800-90A section 10.1.2.2
148 */
149 void HMAC_DRBG::update(const uint8_t input[], size_t input_len)
150  {
151  secure_vector<uint8_t> T(m_V.size());
152  m_mac->update(m_V);
153  m_mac->update(0x00);
154  m_mac->update(input, input_len);
155  m_mac->final(T.data());
156  m_mac->set_key(T);
157 
158  m_mac->update(m_V.data(), m_V.size());
159  m_mac->final(m_V.data());
160 
161  if(input_len > 0)
162  {
163  m_mac->update(m_V);
164  m_mac->update(0x01);
165  m_mac->update(input, input_len);
166  m_mac->final(T.data());
167  m_mac->set_key(T);
168 
169  m_mac->update(m_V.data(), m_V.size());
170  m_mac->final(m_V.data());
171  }
172  }
173 
174 void HMAC_DRBG::add_entropy(const uint8_t input[], size_t input_len)
175  {
176  update(input, input_len);
177 
178  if(8*input_len >= security_level())
179  {
181  }
182  }
183 
185  {
186  // security strength of the hash function
187  // for pre-image resistance (see NIST SP 800-57)
188  // SHA-160: 128 bits, SHA-224, SHA-512/224: 192 bits,
189  // SHA-256, SHA-512/256, SHA-384, SHA-512: >= 256 bits
190  // NIST SP 800-90A only supports up to 256 bits though
191 
192  const size_t output_length = m_mac->output_length();
193 
194  if(output_length < 32)
195  {
196  return (output_length - 4) * 8;
197  }
198  else
199  {
200  return 32 * 8;
201  }
202  }
203 }
void add_entropy(const uint8_t input[], size_t input_len) override
Definition: hmac_drbg.cpp:174
std::string name() const override
Definition: hmac_drbg.cpp:100
void randomize_with_input(uint8_t output[], size_t output_len, const uint8_t input[], size_t input_len) override
Definition: hmac_drbg.cpp:114
Definition: bigint.h:1135
void clear() override
size_t reseed_interval() const
Definition: stateful_rng.h:120
HMAC_DRBG(std::unique_ptr< MessageAuthenticationCode > prf)
Definition: hmac_drbg.cpp:79
size_t security_level() const override
Definition: hmac_drbg.cpp:184
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:107
size_t max_number_of_bytes_per_request() const override
Definition: hmac_drbg.h:146
void randomize(uint8_t output[], size_t output_len) override
Definition: hmac_drbg.cpp:105
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:132
Definition: alg_id.cpp:13
fe T
Definition: ge.cpp:37
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
void clear() override
Definition: hmac_drbg.cpp:88