Botan  2.6.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 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
14  RandomNumberGenerator& underlying_rng,
15  size_t reseed_interval,
16  size_t max_number_of_bytes_per_request) :
17  Stateful_RNG(underlying_rng, reseed_interval),
18  m_mac(std::move(prf)),
19  m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
20  {
21  BOTAN_ASSERT_NONNULL(m_mac);
22 
23  if(m_max_number_of_bytes_per_request == 0 || m_max_number_of_bytes_per_request > 64 * 1024)
24  {
25  throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
26  }
27 
28  clear();
29  }
30 
31 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
32  RandomNumberGenerator& underlying_rng,
33  Entropy_Sources& entropy_sources,
34  size_t reseed_interval,
35  size_t max_number_of_bytes_per_request ) :
36  Stateful_RNG(underlying_rng, entropy_sources, reseed_interval),
37  m_mac(std::move(prf)),
38  m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
39  {
40  BOTAN_ASSERT_NONNULL(m_mac);
41 
42  if(m_max_number_of_bytes_per_request == 0 || m_max_number_of_bytes_per_request > 64 * 1024)
43  {
44  throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
45  }
46 
47  clear();
48  }
49 
50 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
51  Entropy_Sources& entropy_sources,
52  size_t reseed_interval,
53  size_t max_number_of_bytes_per_request) :
54  Stateful_RNG(entropy_sources, reseed_interval),
55  m_mac(std::move(prf)),
56  m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
57  {
58  BOTAN_ASSERT_NONNULL(m_mac);
59 
60  if(m_max_number_of_bytes_per_request == 0 || m_max_number_of_bytes_per_request > 64 * 1024)
61  {
62  throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
63  }
64 
65  clear();
66  }
67 
68 HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf) :
69  Stateful_RNG(),
70  m_mac(std::move(prf)),
71  m_max_number_of_bytes_per_request(64*1024)
72  {
73  BOTAN_ASSERT_NONNULL(m_mac);
74  clear();
75  }
76 
78  {
80 
81  m_V.resize(m_mac->output_length());
82  for(size_t i = 0; i != m_V.size(); ++i)
83  m_V[i] = 0x01;
84  m_mac->set_key(std::vector<uint8_t>(m_mac->output_length(), 0x00));
85  }
86 
87 std::string HMAC_DRBG::name() const
88  {
89  return "HMAC_DRBG(" + m_mac->name() + ")";
90  }
91 
92 void HMAC_DRBG::randomize(uint8_t output[], size_t output_len)
93  {
94  randomize_with_input(output, output_len, nullptr, 0);
95  }
96 
97 /*
98 * HMAC_DRBG generation
99 * See NIST SP800-90A section 10.1.2.5
100 */
101 void HMAC_DRBG::randomize_with_input(uint8_t output[], size_t output_len,
102  const uint8_t input[], size_t input_len)
103  {
104  while(output_len > 0)
105  {
106  size_t this_req = std::min(m_max_number_of_bytes_per_request, output_len);
107  output_len -= this_req;
108 
109  reseed_check();
110 
111  if(input_len > 0)
112  {
113  update(input, input_len);
114  }
115 
116  while(this_req)
117  {
118  const size_t to_copy = std::min(this_req, m_V.size());
119  m_mac->update(m_V.data(), m_V.size());
120  m_mac->final(m_V.data());
121  copy_mem(output, m_V.data(), to_copy);
122 
123  output += to_copy;
124  this_req -= to_copy;
125  }
126 
127  update(input, input_len);
128  }
129 
130  }
131 
132 /*
133 * Reset V and the mac key with new values
134 * See NIST SP800-90A section 10.1.2.2
135 */
136 void HMAC_DRBG::update(const uint8_t input[], size_t input_len)
137  {
138  m_mac->update(m_V);
139  m_mac->update(0x00);
140  m_mac->update(input, input_len);
141  m_mac->set_key(m_mac->final());
142 
143  m_mac->update(m_V.data(), m_V.size());
144  m_mac->final(m_V.data());
145 
146  if(input_len > 0)
147  {
148  m_mac->update(m_V);
149  m_mac->update(0x01);
150  m_mac->update(input, input_len);
151  m_mac->set_key(m_mac->final());
152 
153  m_mac->update(m_V.data(), m_V.size());
154  m_mac->final(m_V.data());
155  }
156  }
157 
158 void HMAC_DRBG::add_entropy(const uint8_t input[], size_t input_len)
159  {
160  update(input, input_len);
161 
162  if(8*input_len >= security_level())
163  {
165  }
166  }
167 
169  {
170  // security strength of the hash function
171  // for pre-image resistance (see NIST SP 800-57)
172  // SHA-160: 128 bits, SHA-224, SHA-512/224: 192 bits,
173  // SHA-256, SHA-512/256, SHA-384, SHA-512: >= 256 bits
174  // NIST SP 800-90A only supports up to 256 bits though
175  if(m_mac->output_length() < 32)
176  {
177  return (m_mac->output_length() - 4) * 8;
178  }
179  else
180  {
181  return 32 * 8;
182  }
183  }
184 }
void add_entropy(const uint8_t input[], size_t input_len) override
Definition: hmac_drbg.cpp:158
std::string name() const override
Definition: hmac_drbg.cpp:87
void randomize_with_input(uint8_t output[], size_t output_len, const uint8_t input[], size_t input_len) override
Definition: hmac_drbg.cpp:101
Definition: bigint.h:719
void clear() override
HMAC_DRBG(std::unique_ptr< MessageAuthenticationCode > prf)
Definition: hmac_drbg.cpp:68
size_t security_level() const override
Definition: hmac_drbg.cpp:168
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:82
void randomize(uint8_t output[], size_t output_len) override
Definition: hmac_drbg.cpp:92
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
void clear() override
Definition: hmac_drbg.cpp:77