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