• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 25416417447

05 May 2026 05:54PM UTC coverage: 91.667% (+2.3%) from 89.323%
25416417447

push

github

web-flow
Merge pull request #5572 from randombit/jack/fix-5571

Avoid a hidden dependency of <algorithm> in secmem.h

110208 of 120227 relevant lines covered (91.67%)

11269830.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.92
/src/lib/rng/hmac_drbg/hmac_drbg.cpp
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/assert.h>
11
#include <botan/exceptn.h>
12
#include <botan/mac.h>
13
#include <botan/mem_ops.h>
14
#include <botan/internal/fmt.h>
15
#include <algorithm>
16

17
namespace Botan {
18

19
namespace {
20

21
size_t hmac_drbg_security_level(size_t mac_output_length) {
4,051✔
22
   // security strength of the hash function
23
   // for pre-image resistance (see NIST SP 800-57)
24
   // SHA-1: 128 bits
25
   // SHA-224, SHA-512/224: 192 bits,
26
   // SHA-256, SHA-512/256, SHA-384, SHA-512: >= 256 bits
27
   // NIST SP 800-90A only supports up to 256 bits though
28

29
   if(mac_output_length < 20) {
4,051✔
30
      throw Invalid_Argument(fmt("HMAC_DRBG MAC output length {} is too small", mac_output_length));
×
31
   }
32

33
   if(mac_output_length < 32) {
4,051✔
34
      return (mac_output_length - 4) * 8;
562✔
35
   } else {
36
      return 32 * 8;
37
   }
38
}
39

40
void check_limits(size_t reseed_interval, size_t max_number_of_bytes_per_request) {
129✔
41
   // SP800-90A permits up to 2^48, but it is not usable on 32 bit
42
   // platforms, so we only allow up to 2^24, which is still reasonably high
43
   if(reseed_interval == 0 || reseed_interval > static_cast<size_t>(1) << 24) {
129✔
44
      throw Invalid_Argument("Invalid value for reseed_interval");
2✔
45
   }
46

47
   if(max_number_of_bytes_per_request == 0 || max_number_of_bytes_per_request > 64 * 1024) {
127✔
48
      throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
2✔
49
   }
50
}
125✔
51

52
template <typename T>
53
std::unique_ptr<T> check_not_null(std::unique_ptr<T> obj) {
4,037✔
54
   BOTAN_ARG_CHECK(obj != nullptr, "Argument must not be null");
4,037✔
55
   return obj;
4,037✔
56
}
57

58
}  // namespace
59

60
HMAC_DRBG::~HMAC_DRBG() = default;
16,057✔
61

62
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
120✔
63
                     RandomNumberGenerator& underlying_rng,
64
                     size_t reseed_interval,
65
                     size_t max_number_of_bytes_per_request) :
120✔
66
      Stateful_RNG(underlying_rng, reseed_interval),
67
      m_mac(check_not_null(std::move(prf))),
120✔
68
      m_max_number_of_bytes_per_request(max_number_of_bytes_per_request),
120✔
69
      m_security_level(hmac_drbg_security_level(m_mac->output_length())) {
120✔
70
   check_limits(reseed_interval, max_number_of_bytes_per_request);
120✔
71

72
   clear();
116✔
73
}
120✔
74

75
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
4✔
76
                     RandomNumberGenerator& underlying_rng,
77
                     Entropy_Sources& entropy_sources,
78
                     size_t reseed_interval,
79
                     size_t max_number_of_bytes_per_request) :
4✔
80
      Stateful_RNG(underlying_rng, entropy_sources, reseed_interval),
81
      m_mac(check_not_null(std::move(prf))),
4✔
82
      m_max_number_of_bytes_per_request(max_number_of_bytes_per_request),
4✔
83
      m_security_level(hmac_drbg_security_level(m_mac->output_length())) {
4✔
84
   check_limits(reseed_interval, max_number_of_bytes_per_request);
4✔
85

86
   clear();
4✔
87
}
4✔
88

89
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
5✔
90
                     Entropy_Sources& entropy_sources,
91
                     size_t reseed_interval,
92
                     size_t max_number_of_bytes_per_request) :
5✔
93
      Stateful_RNG(entropy_sources, reseed_interval),
94
      m_mac(check_not_null(std::move(prf))),
5✔
95
      m_max_number_of_bytes_per_request(max_number_of_bytes_per_request),
5✔
96
      m_security_level(hmac_drbg_security_level(m_mac->output_length())) {
5✔
97
   check_limits(reseed_interval, max_number_of_bytes_per_request);
5✔
98

99
   clear();
5✔
100
}
5✔
101

102
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf) :
3,908✔
103
      m_mac(check_not_null(std::move(prf))),
3,908✔
104
      m_max_number_of_bytes_per_request(64 * 1024),
3,908✔
105
      m_security_level(hmac_drbg_security_level(m_mac->output_length())) {
3,908✔
106
   clear();
3,908✔
107
}
3,908✔
108

109
HMAC_DRBG::HMAC_DRBG(std::string_view hmac_hash) :
14✔
110
      m_mac(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hmac_hash))),
14✔
111
      m_max_number_of_bytes_per_request(64 * 1024),
14✔
112
      m_security_level(hmac_drbg_security_level(m_mac->output_length())) {
28✔
113
   clear();
14✔
114
}
14✔
115

116
void HMAC_DRBG::clear_state() {
11,636✔
117
   if(m_V.empty()) {
11,636✔
118
      const size_t output_length = m_mac->output_length();
4,047✔
119
      m_V.resize(output_length);
4,047✔
120
      m_T.resize(output_length);
4,047✔
121
   }
122

123
   std::fill(m_V.begin(), m_V.end(), 0x01);
11,636✔
124
   m_mac->set_key(std::vector<uint8_t>(m_V.size(), 0x00));
11,636✔
125
}
11,636✔
126

127
std::string HMAC_DRBG::name() const {
11✔
128
   return fmt("HMAC_DRBG({})", m_mac->name());
11✔
129
}
130

131
/*
132
* HMAC_DRBG generation
133
* See NIST SP800-90A section 10.1.2.5
134
*/
135
void HMAC_DRBG::generate_output(std::span<uint8_t> output, std::span<const uint8_t> input) {
130,750✔
136
   // This is an internal function, callers should have validated this beforehand
137
   BOTAN_ASSERT_NOMSG(!output.empty());
130,750✔
138

139
   if(!input.empty()) {
130,750✔
140
      update(input);
6,076✔
141
   }
142

143
   while(!output.empty()) {
738,949✔
144
      const size_t to_copy = std::min(output.size(), m_V.size());
608,199✔
145
      m_mac->update(m_V);
608,199✔
146
      m_mac->final(m_V);
608,199✔
147
      copy_mem(output.data(), m_V.data(), to_copy);
608,199✔
148

149
      output = output.subspan(to_copy);
608,199✔
150
   }
151

152
   update(input);
130,750✔
153
}
130,750✔
154

155
/*
156
* Reset V and the mac key with new values
157
* See NIST SP800-90A section 10.1.2.2
158
*/
159
void HMAC_DRBG::update(std::span<const uint8_t> input) {
154,310✔
160
   m_mac->update(m_V);
154,310✔
161
   m_mac->update(0x00);
154,310✔
162
   if(!input.empty()) {
154,310✔
163
      m_mac->update(input);
29,633✔
164
   }
165
   m_mac->final(m_T);
154,310✔
166
   m_mac->set_key(m_T);
154,310✔
167

168
   m_mac->update(m_V);
154,310✔
169
   m_mac->final(m_V);
154,310✔
170

171
   if(!input.empty()) {
154,310✔
172
      m_mac->update(m_V);
29,633✔
173
      m_mac->update(0x01);
29,633✔
174
      m_mac->update(input);
29,633✔
175
      m_mac->final(m_T);
29,633✔
176
      m_mac->set_key(m_T);
29,633✔
177

178
      m_mac->update(m_V);
29,633✔
179
      m_mac->final(m_V);
29,633✔
180
   }
181
}
154,310✔
182

183
size_t HMAC_DRBG::security_level() const {
17,804✔
184
   return m_security_level;
17,804✔
185
}
186
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc