Botan 3.9.0
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) :
94 m_mac(std::move(prf)),
95 m_max_number_of_bytes_per_request(64 * 1024),
96 m_security_level(hmac_drbg_security_level(m_mac->output_length())) {
98 clear();
99}
100
101HMAC_DRBG::HMAC_DRBG(std::string_view hmac_hash) :
102 m_mac(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hmac_hash))),
103 m_max_number_of_bytes_per_request(64 * 1024),
104 m_security_level(hmac_drbg_security_level(m_mac->output_length())) {
105 clear();
106}
107
109 if(m_V.empty()) {
110 const size_t output_length = m_mac->output_length();
111 m_V.resize(output_length);
112 m_T.resize(output_length);
113 }
114
115 std::fill(m_V.begin(), m_V.end(), 0x01);
116 m_mac->set_key(std::vector<uint8_t>(m_V.size(), 0x00));
117}
118
119std::string HMAC_DRBG::name() const {
120 return fmt("HMAC_DRBG({})", m_mac->name());
121}
122
123/*
124* HMAC_DRBG generation
125* See NIST SP800-90A section 10.1.2.5
126*/
127void HMAC_DRBG::generate_output(std::span<uint8_t> output, std::span<const uint8_t> input) {
128 BOTAN_ASSERT_NOMSG(!output.empty());
129
130 if(!input.empty()) {
131 update(input);
132 }
133
134 while(!output.empty()) {
135 const size_t to_copy = std::min(output.size(), m_V.size());
136 m_mac->update(m_V);
137 m_mac->final(m_V);
138 copy_mem(output.data(), m_V.data(), to_copy);
139
140 output = output.subspan(to_copy);
141 }
142
143 update(input);
144}
145
146/*
147* Reset V and the mac key with new values
148* See NIST SP800-90A section 10.1.2.2
149*/
150void HMAC_DRBG::update(std::span<const uint8_t> input) {
151 m_mac->update(m_V);
152 m_mac->update(0x00);
153 if(!input.empty()) {
154 m_mac->update(input);
155 }
156 m_mac->final(m_T);
157 m_mac->set_key(m_T);
158
159 m_mac->update(m_V);
160 m_mac->final(m_V);
161
162 if(!input.empty()) {
163 m_mac->update(m_V);
164 m_mac->update(0x01);
165 m_mac->update(input);
166 m_mac->final(m_T);
167 m_mac->set_key(m_T);
168
169 m_mac->update(m_V);
170 m_mac->final(m_V);
171 }
172}
173
175 return m_security_level;
176}
177} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
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
virtual void clear_state()=0
Stateful_RNG(RandomNumberGenerator &rng, Entropy_Sources &entropy_sources, size_t reseed_interval)
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:145
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53