Botan 2.19.5 Crypto and TLS for C&

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
133std::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
193 size_t HMAC_DRBG::security_level() const
194 {
195 return m_security_level;
196 }
197}
BOTAN_ASSERT_NONNULL
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:107
Botan::Entropy_Sources
Definition: entropy_src.h:57
Botan::HMAC_DRBG::name
std::string name() const override
Definition: hmac_drbg.cpp:133
Botan::HMAC_DRBG::security_level
size_t security_level() const override
Definition: hmac_drbg.cpp:193
Botan::HMAC_DRBG::max_number_of_bytes_per_request
size_t max_number_of_bytes_per_request() const override
Definition: hmac_drbg.h:131
Botan::HMAC_DRBG::HMAC_DRBG
HMAC_DRBG(std::unique_ptr< MessageAuthenticationCode > prf)
Definition: hmac_drbg.cpp:101
Botan::MessageAuthenticationCode
Definition: mac.h:23
Botan::RandomNumberGenerator
Definition: rng.h:26
Botan::Stateful_RNG
Definition: stateful_rng.h:27
Botan::Stateful_RNG::reseed_interval
size_t reseed_interval() const
Definition: stateful_rng.h:128
Botan::Stateful_RNG::clear
void clear() override final
Definition: stateful_rng.cpp:17
T
fe T
Definition: ge.cpp:37
Botan
Definition: alg_id.cpp:13
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:133
std
Definition: bigint.h:1155