Coverage Report

Created: 2019-09-11 14:12

/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
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
14
                     RandomNumberGenerator& underlying_rng,
15
                     size_t reseed_interval,
16
                     size_t max_number_of_bytes_per_request) :
17
   Stateful_RNG(underlying_rng, reseed_interval),
18
   m_mac(std::move(prf)),
19
   m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
20
0
   {
21
0
   BOTAN_ASSERT_NONNULL(m_mac);
22
0
23
0
   if(m_max_number_of_bytes_per_request == 0 || m_max_number_of_bytes_per_request > 64 * 1024)
24
0
      {
25
0
      throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
26
0
      }
27
0
28
0
   clear();
29
0
   }
30
31
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
32
                     RandomNumberGenerator& underlying_rng,
33
                     Entropy_Sources& entropy_sources,
34
                     size_t reseed_interval,
35
                     size_t max_number_of_bytes_per_request ) :
36
   Stateful_RNG(underlying_rng, entropy_sources, reseed_interval),
37
   m_mac(std::move(prf)),
38
   m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
39
0
   {
40
0
   BOTAN_ASSERT_NONNULL(m_mac);
41
0
42
0
   if(m_max_number_of_bytes_per_request == 0 || m_max_number_of_bytes_per_request > 64 * 1024)
43
0
      {
44
0
      throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
45
0
      }
46
0
47
0
   clear();
48
0
   }
49
50
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf,
51
                     Entropy_Sources& entropy_sources,
52
                     size_t reseed_interval,
53
                     size_t max_number_of_bytes_per_request) :
54
   Stateful_RNG(entropy_sources, reseed_interval),
55
   m_mac(std::move(prf)),
56
   m_max_number_of_bytes_per_request(max_number_of_bytes_per_request)
57
0
   {
58
0
   BOTAN_ASSERT_NONNULL(m_mac);
59
0
60
0
   if(m_max_number_of_bytes_per_request == 0 || m_max_number_of_bytes_per_request > 64 * 1024)
61
0
      {
62
0
      throw Invalid_Argument("Invalid value for max_number_of_bytes_per_request");
63
0
      }
64
0
65
0
   clear();
66
0
   }
67
68
HMAC_DRBG::HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf) :
69
   Stateful_RNG(),
70
   m_mac(std::move(prf)),
71
   m_max_number_of_bytes_per_request(64*1024)
72
0
   {
73
0
   BOTAN_ASSERT_NONNULL(m_mac);
74
0
   clear();
75
0
   }
76
77
void HMAC_DRBG::clear()
78
0
   {
79
0
   Stateful_RNG::clear();
80
0
81
0
   m_V.resize(m_mac->output_length());
82
0
   for(size_t i = 0; i != m_V.size(); ++i)
83
0
      m_V[i] = 0x01;
84
0
   m_mac->set_key(std::vector<uint8_t>(m_mac->output_length(), 0x00));
85
0
   }
86
87
std::string HMAC_DRBG::name() const
88
0
   {
89
0
   return "HMAC_DRBG(" + m_mac->name() + ")";
90
0
   }
91
92
void HMAC_DRBG::randomize(uint8_t output[], size_t output_len)
93
0
   {
94
0
   randomize_with_input(output, output_len, nullptr, 0);
95
0
   }
96
97
/*
98
* HMAC_DRBG generation
99
* See NIST SP800-90A section 10.1.2.5
100
*/
101
void HMAC_DRBG::randomize_with_input(uint8_t output[], size_t output_len,
102
                                     const uint8_t input[], size_t input_len)
103
0
   {
104
0
   while(output_len > 0)
105
0
      {
106
0
      size_t this_req = std::min(m_max_number_of_bytes_per_request, output_len);
107
0
      output_len -= this_req;
108
0
109
0
      reseed_check();
110
0
111
0
      if(input_len > 0)
112
0
         {
113
0
         update(input, input_len);
114
0
         }
115
0
116
0
      while(this_req)
117
0
         {
118
0
         const size_t to_copy = std::min(this_req, m_V.size());
119
0
         m_mac->update(m_V.data(), m_V.size());
120
0
         m_mac->final(m_V.data());
121
0
         copy_mem(output, m_V.data(), to_copy);
122
0
123
0
         output += to_copy;
124
0
         this_req -= to_copy;
125
0
         }
126
0
127
0
      update(input, input_len);
128
0
      }
129
0
130
0
   }
131
132
/*
133
* Reset V and the mac key with new values
134
* See NIST SP800-90A section 10.1.2.2
135
*/
136
void HMAC_DRBG::update(const uint8_t input[], size_t input_len)
137
0
   {
138
0
   m_mac->update(m_V);
139
0
   m_mac->update(0x00);
140
0
   m_mac->update(input, input_len);
141
0
   m_mac->set_key(m_mac->final());
142
0
143
0
   m_mac->update(m_V.data(), m_V.size());
144
0
   m_mac->final(m_V.data());
145
0
146
0
   if(input_len > 0)
147
0
      {
148
0
      m_mac->update(m_V);
149
0
      m_mac->update(0x01);
150
0
      m_mac->update(input, input_len);
151
0
      m_mac->set_key(m_mac->final());
152
0
153
0
      m_mac->update(m_V.data(), m_V.size());
154
0
      m_mac->final(m_V.data());
155
0
      }
156
0
   }
157
158
void HMAC_DRBG::add_entropy(const uint8_t input[], size_t input_len)
159
0
   {
160
0
   update(input, input_len);
161
0
162
0
   if(8*input_len >= security_level())
163
0
      {
164
0
      reset_reseed_counter();
165
0
      }
166
0
   }
167
168
size_t HMAC_DRBG::security_level() const
169
0
   {
170
0
   // security strength of the hash function
171
0
   // for pre-image resistance (see NIST SP 800-57)
172
0
   // SHA-160: 128 bits, SHA-224, SHA-512/224: 192 bits,
173
0
   // SHA-256, SHA-512/256, SHA-384, SHA-512: >= 256 bits
174
0
   // NIST SP 800-90A only supports up to 256 bits though
175
0
   if(m_mac->output_length() < 32)
176
0
      {
177
0
      return (m_mac->output_length() - 4) * 8;
178
0
      }
179
0
   else
180
0
      {
181
0
      return 32 * 8;
182
0
      }
183
0
   }
184
}