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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

82.93
/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
1
/*
2
* PBKDF2
3
* (C) 1999-2007 Jack Lloyd
4
* (C) 2018 Ribose Inc
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/pbkdf2.h>
10

11
#include <botan/exceptn.h>
12
#include <botan/internal/fmt.h>
13
#include <botan/internal/timer.h>
14

15
namespace Botan {
16

17
namespace {
18

19
void pbkdf2_set_key(MessageAuthenticationCode& prf, const char* password, size_t password_len) {
449✔
20
   try {
449✔
21
      prf.set_key(cast_char_ptr_to_uint8(password), password_len);
449✔
22
   } catch(Invalid_Key_Length&) { throw Invalid_Argument("PBKDF2 cannot accept passphrase of the given size"); }
×
23
}
449✔
24

25
size_t tune_pbkdf2(MessageAuthenticationCode& prf,
144✔
26
                   size_t output_length,
27
                   std::chrono::milliseconds msec,
28
                   std::chrono::milliseconds tune_time = std::chrono::milliseconds(10)) {
29
   if(output_length == 0)
144✔
30
      output_length = 1;
31

32
   const size_t prf_sz = prf.output_length();
144✔
33
   BOTAN_ASSERT_NOMSG(prf_sz > 0);
144✔
34
   secure_vector<uint8_t> U(prf_sz);
144✔
35

36
   const size_t trial_iterations = 2000;
144✔
37

38
   // Short output ensures we only need a single PBKDF2 block
39

40
   Timer timer("PBKDF2");
144✔
41

42
   prf.set_key(nullptr, 0);
144✔
43

44
   timer.run_until_elapsed(tune_time, [&]() {
144✔
45
      uint8_t out[12] = {0};
289✔
46
      uint8_t salt[12] = {0};
289✔
47
      pbkdf2(prf, out, sizeof(out), salt, sizeof(salt), trial_iterations);
289✔
48
   });
289✔
49

50
   if(timer.events() == 0)
144✔
51
      return trial_iterations;
52

53
   const uint64_t duration_nsec = timer.value() / timer.events();
144✔
54

55
   const uint64_t desired_nsec = static_cast<uint64_t>(msec.count()) * 1000000;
144✔
56

57
   if(duration_nsec > desired_nsec)
144✔
58
      return trial_iterations;
59

60
   const size_t blocks_needed = (output_length + prf_sz - 1) / prf_sz;
38✔
61

62
   const size_t multiplier = static_cast<size_t>(desired_nsec / duration_nsec / blocks_needed);
38✔
63

64
   if(multiplier == 0)
38✔
65
      return trial_iterations;
66
   else
67
      return trial_iterations * multiplier;
38✔
68
}
288✔
69

70
}
71

72
size_t pbkdf2(MessageAuthenticationCode& prf,
×
73
              uint8_t out[],
74
              size_t out_len,
75
              std::string_view password,
76
              const uint8_t salt[],
77
              size_t salt_len,
78
              size_t iterations,
79
              std::chrono::milliseconds msec) {
80
   if(iterations == 0) {
×
81
      iterations = tune_pbkdf2(prf, out_len, msec);
×
82
   }
83

84
   PBKDF2 pbkdf2(prf, iterations);
×
85

86
   pbkdf2.derive_key(out, out_len, password.data(), password.size(), salt, salt_len);
×
87

88
   return iterations;
×
89
}
×
90

91
void pbkdf2(MessageAuthenticationCode& prf,
1,414✔
92
            uint8_t out[],
93
            size_t out_len,
94
            const uint8_t salt[],
95
            size_t salt_len,
96
            size_t iterations) {
97
   if(iterations == 0)
1,414✔
98
      throw Invalid_Argument("PBKDF2: Invalid iteration count");
×
99

100
   clear_mem(out, out_len);
1,414✔
101

102
   if(out_len == 0)
1,414✔
103
      return;
×
104

105
   const size_t prf_sz = prf.output_length();
1,414✔
106
   BOTAN_ASSERT_NOMSG(prf_sz > 0);
1,414✔
107

108
   secure_vector<uint8_t> U(prf_sz);
1,414✔
109

110
   uint32_t counter = 1;
1,414✔
111
   while(out_len) {
88,535✔
112
      const size_t prf_output = std::min<size_t>(prf_sz, out_len);
87,121✔
113

114
      prf.update(salt, salt_len);
87,121✔
115
      prf.update_be(counter++);
87,121✔
116
      prf.final(U.data());
87,121✔
117

118
      xor_buf(out, U.data(), prf_output);
87,121✔
119

120
      for(size_t i = 1; i != iterations; ++i) {
9,278,778✔
121
         prf.update(U);
9,191,657✔
122
         prf.final(U.data());
9,191,657✔
123
         xor_buf(out, U.data(), prf_output);
9,191,657✔
124
      }
125

126
      out_len -= prf_output;
87,121✔
127
      out += prf_output;
87,121✔
128
   }
129
}
1,414✔
130

131
// PBKDF interface
132
size_t PKCS5_PBKDF2::pbkdf(uint8_t key[],
66✔
133
                           size_t key_len,
134
                           std::string_view password,
135
                           const uint8_t salt[],
136
                           size_t salt_len,
137
                           size_t iterations,
138
                           std::chrono::milliseconds msec) const {
139
   if(iterations == 0) {
66✔
140
      iterations = tune_pbkdf2(*m_mac, key_len, msec);
×
141
   }
142

143
   PBKDF2 pbkdf2(*m_mac, iterations);
66✔
144

145
   pbkdf2.derive_key(key, key_len, password.data(), password.size(), salt, salt_len);
66✔
146

147
   return iterations;
66✔
148
}
66✔
149

150
std::string PKCS5_PBKDF2::name() const { return fmt("PBKDF2({})", m_mac->name()); }
15✔
151

152
std::unique_ptr<PBKDF> PKCS5_PBKDF2::new_object() const { return std::make_unique<PKCS5_PBKDF2>(m_mac->new_object()); }
×
153

154
// PasswordHash interface
155

156
PBKDF2::PBKDF2(const MessageAuthenticationCode& prf, size_t olen, std::chrono::milliseconds msec) :
×
157
      m_prf(prf.new_object()), m_iterations(tune_pbkdf2(*m_prf, olen, msec)) {}
×
158

159
std::string PBKDF2::to_string() const { return fmt("PBKDF2({},{})", m_prf->name(), m_iterations); }
4✔
160

161
void PBKDF2::derive_key(uint8_t out[],
449✔
162
                        size_t out_len,
163
                        const char* password,
164
                        const size_t password_len,
165
                        const uint8_t salt[],
166
                        size_t salt_len) const {
167
   pbkdf2_set_key(*m_prf, password, password_len);
449✔
168
   pbkdf2(*m_prf, out, out_len, salt, salt_len, m_iterations);
449✔
169
}
449✔
170

171
std::string PBKDF2_Family::name() const { return fmt("PBKDF2({})", m_prf->name()); }
2✔
172

173
std::unique_ptr<PasswordHash> PBKDF2_Family::tune(size_t output_len,
144✔
174
                                                  std::chrono::milliseconds msec,
175
                                                  size_t /*max_memory_usage_mb*/,
176
                                                  std::chrono::milliseconds tune_time) const {
177
   auto iterations = tune_pbkdf2(*m_prf, output_len, msec, tune_time);
144✔
178
   return std::make_unique<PBKDF2>(*m_prf, iterations);
144✔
179
}
180

181
std::unique_ptr<PasswordHash> PBKDF2_Family::default_params() const { return std::make_unique<PBKDF2>(*m_prf, 150000); }
2✔
182

183
std::unique_ptr<PasswordHash> PBKDF2_Family::from_params(size_t iter, size_t /*i2*/, size_t /*i3*/) const {
193✔
184
   return std::make_unique<PBKDF2>(*m_prf, iter);
193✔
185
}
186

187
std::unique_ptr<PasswordHash> PBKDF2_Family::from_iterations(size_t iter) const {
44✔
188
   return std::make_unique<PBKDF2>(*m_prf, iter);
44✔
189
}
190

191
}
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