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