Coverage Report

Created: 2021-05-04 09:02

/src/botan/src/lib/rng/hmac_drbg/hmac_drbg.cpp
Line
Count
Source (jump to first uncovered line)
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
0
   {
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
0
   if(mac_output_length < 32)
25
0
      {
26
0
      return (mac_output_length - 4) * 8;
27
0
      }
28
0
   else
29
0
      {
30
0
      return 32 * 8;
31
0
      }
32
0
   }
33
34
void check_limits(size_t reseed_interval,
35
                  size_t max_number_of_bytes_per_request)
36
0
   {
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
0
   if(reseed_interval == 0 || reseed_interval > static_cast<size_t>(1) << 24)
40
0
      {
41
0
      throw Invalid_Argument("Invalid value for reseed_interval");
42
0
      }
43
44
0
   if(max_number_of_bytes_per_request == 0 || max_number_of_bytes_per_request > 64 * 1024)
45
0
      {
46
0
      throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
47
0
      }
48
0
   }
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
0
   {
61
0
   BOTAN_ASSERT_NONNULL(m_mac);
62
63
0
   check_limits(reseed_interval, max_number_of_bytes_per_request);
64
65
0
   clear();
66
0
   }
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
0
   {
78
0
   BOTAN_ASSERT_NONNULL(m_mac);
79
80
0
   check_limits(reseed_interval, max_number_of_bytes_per_request);
81
82
0
   clear();
83
0
   }
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
0
   {
94
0
   BOTAN_ASSERT_NONNULL(m_mac);
95
96
0
   check_limits(reseed_interval, max_number_of_bytes_per_request);
97
98
0
   clear();
99
0
   }
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
0
   {
107
0
   BOTAN_ASSERT_NONNULL(m_mac);
108
0
   clear();
109
0
   }
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
0
   {
117
0
   clear();
118
0
   }
119
120
void HMAC_DRBG::clear_state()
121
0
   {
122
0
   if(m_V.size() == 0)
123
0
      {
124
0
      const size_t output_length = m_mac->output_length();
125
0
      m_V.resize(output_length);
126
0
      }
127
128
0
   for(size_t i = 0; i != m_V.size(); ++i)
129
0
      m_V[i] = 0x01;
130
0
   m_mac->set_key(std::vector<uint8_t>(m_V.size(), 0x00));
131
0
   }
132
133
std::string HMAC_DRBG::name() const
134
0
   {
135
0
   return "HMAC_DRBG(" + m_mac->name() + ")";
136
0
   }
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
0
   {
145
0
   if(input_len > 0)
146
0
      {
147
0
      update(input, input_len);
148
0
      }
149
150
0
   while(output_len > 0)
151
0
      {
152
0
      const size_t to_copy = std::min(output_len, m_V.size());
153
0
      m_mac->update(m_V.data(), m_V.size());
154
0
      m_mac->final(m_V.data());
155
0
      copy_mem(output, m_V.data(), to_copy);
156
157
0
      output += to_copy;
158
0
      output_len -= to_copy;
159
0
      }
160
161
0
   update(input, input_len);
162
0
   }
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
0
   {
170
0
   secure_vector<uint8_t> T(m_V.size());
171
0
   m_mac->update(m_V);
172
0
   m_mac->update(0x00);
173
0
   m_mac->update(input, input_len);
174
0
   m_mac->final(T.data());
175
0
   m_mac->set_key(T);
176
177
0
   m_mac->update(m_V.data(), m_V.size());
178
0
   m_mac->final(m_V.data());
179
180
0
   if(input_len > 0)
181
0
      {
182
0
      m_mac->update(m_V);
183
0
      m_mac->update(0x01);
184
0
      m_mac->update(input, input_len);
185
0
      m_mac->final(T.data());
186
0
      m_mac->set_key(T);
187
188
0
      m_mac->update(m_V.data(), m_V.size());
189
0
      m_mac->final(m_V.data());
190
0
      }
191
0
   }
192
193
size_t HMAC_DRBG::security_level() const
194
0
   {
195
0
   return m_security_level;
196
0
   }
197
}