• 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

88.89
/src/tests/test_pbkdf.cpp
1
/*
2
* (C) 2014,2015,2019 Jack Lloyd
3
* (C) 2018 Ribose Inc
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_PBKDF)
11
   #include <botan/pbkdf.h>
12
   #include <botan/pwdhash.h>
13
#endif
14

15
#if defined(BOTAN_HAS_RFC4880)
16
   #include <botan/rfc4880.h>
17
#endif
18

19
namespace Botan_Tests {
20

21
namespace {
22

23
#if defined(BOTAN_HAS_PBKDF)
24
class PBKDF_KAT_Tests final : public Text_Based_Test {
×
25
   public:
26
      PBKDF_KAT_Tests() : Text_Based_Test("pbkdf", "Iterations,Salt,Passphrase,Output") {}
3✔
27

28
      Test::Result run_one_test(const std::string& pbkdf_name, const VarMap& vars) override {
28✔
29
         const size_t iterations = vars.get_req_sz("Iterations");
28✔
30
         const std::vector<uint8_t> salt = vars.get_req_bin("Salt");
28✔
31
         const std::string passphrase = vars.get_req_str("Passphrase");
28✔
32
         const std::vector<uint8_t> expected = vars.get_req_bin("Output");
28✔
33
         const size_t outlen = expected.size();
28✔
34

35
         Test::Result result(pbkdf_name);
56✔
36
         auto pbkdf = Botan::PBKDF::create(pbkdf_name);
28✔
37

38
         if(!pbkdf) {
28✔
39
            result.note_missing(pbkdf_name);
×
40
            return result;
41
         }
42

43
         result.test_eq("Expected name", pbkdf->name(), pbkdf_name);
56✔
44

45
         const Botan::secure_vector<uint8_t> derived =
28✔
46
            pbkdf->derive_key(outlen, passphrase, salt.data(), salt.size(), iterations).bits_of();
28✔
47
         result.test_eq("derived key", derived, expected);
28✔
48

49
         auto pwdhash_fam = Botan::PasswordHashFamily::create(pbkdf_name);
28✔
50

51
         if(!pwdhash_fam) {
28✔
52
            result.note_missing("No PasswordHashFamily for " + pbkdf_name);
×
53
            return result;
×
54
         }
55

56
         auto pwdhash = pwdhash_fam->from_params(iterations);
28✔
57

58
         std::vector<uint8_t> pwdhash_derived(outlen);
28✔
59
         pwdhash->hash(pwdhash_derived, passphrase, salt);
28✔
60

61
         result.test_eq("pwdhash derived key", pwdhash_derived, expected);
28✔
62

63
         return result;
28✔
64
      }
206✔
65
};
66

67
BOTAN_REGISTER_SMOKE_TEST("pbkdf", "pbkdf_kat", PBKDF_KAT_Tests);
68

69
class Pwdhash_Tests : public Test {
×
70
   public:
71
      std::vector<Test::Result> run() override {
1✔
72
         std::vector<Test::Result> results;
1✔
73

74
         const std::vector<std::string> all_pwdhash = {
1✔
75
            "Scrypt", "PBKDF2(SHA-256)", "OpenPGP-S2K(SHA-384)", "Argon2d", "Argon2i", "Argon2id", "Bcrypt-PBKDF"};
8✔
76

77
         const auto run_time = std::chrono::milliseconds(3);
1✔
78
         const auto tune_time = std::chrono::milliseconds(1);
1✔
79
         const size_t max_mem = 32;
1✔
80

81
         for(const std::string& pwdhash : all_pwdhash) {
8✔
82
            Test::Result result("Pwdhash " + pwdhash);
7✔
83
            auto pwdhash_fam = Botan::PasswordHashFamily::create(pwdhash);
7✔
84

85
            if(pwdhash_fam) {
7✔
86
               result.start_timer();
7✔
87

88
               const std::vector<uint8_t> salt(8);
7✔
89
               const std::string password = "test";
7✔
90

91
               auto tuned_pwhash = pwdhash_fam->tune(32, run_time, max_mem, tune_time);
7✔
92

93
               std::vector<uint8_t> output1(32);
7✔
94
               tuned_pwhash->hash(output1, password, salt);
7✔
95

96
               std::unique_ptr<Botan::PasswordHash> pwhash;
7✔
97

98
               if(pwdhash_fam->name() == "Scrypt" || pwdhash_fam->name().find("Argon2") == 0) {
15✔
99
                  pwhash = pwdhash_fam->from_params(
4✔
100
                     tuned_pwhash->memory_param(), tuned_pwhash->iterations(), tuned_pwhash->parallelism());
8✔
101
               } else {
102
                  pwhash = pwdhash_fam->from_params(tuned_pwhash->iterations());
3✔
103
               }
104

105
               std::vector<uint8_t> output2(32);
7✔
106
               pwhash->hash(output2, password, salt);
7✔
107

108
               result.test_eq("PasswordHash produced same output when run with same params", output1, output2);
7✔
109

110
               auto default_pwhash = pwdhash_fam->default_params();
7✔
111
               std::vector<uint8_t> output3(32);
7✔
112
               default_pwhash->hash(output3, password, salt);
7✔
113

114
               result.end_timer();
7✔
115
            } else
42✔
116
               result.test_note("No such algo " + pwdhash);
×
117

118
            results.push_back(result);
7✔
119
         }
7✔
120

121
         return results;
1✔
122
      }
1✔
123
};
124

125
BOTAN_REGISTER_TEST("pbkdf", "pwdhash", Pwdhash_Tests);
126

127
#endif
128

129
#if defined(BOTAN_HAS_PBKDF_BCRYPT)
130

131
class Bcrypt_PBKDF_KAT_Tests final : public Text_Based_Test {
×
132
   public:
133
      Bcrypt_PBKDF_KAT_Tests() : Text_Based_Test("bcrypt_pbkdf.vec", "Passphrase,Salt,Iterations,Output") {}
3✔
134

135
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
36✔
136
         const size_t rounds = vars.get_req_sz("Iterations");
36✔
137
         const std::vector<uint8_t> salt = vars.get_req_bin("Salt");
36✔
138
         const std::string passphrase = vars.get_req_str("Passphrase");
36✔
139
         const std::vector<uint8_t> expected = vars.get_req_bin("Output");
36✔
140

141
         Test::Result result("bcrypt PBKDF");
36✔
142

143
         auto pwdhash_fam = Botan::PasswordHashFamily::create("Bcrypt-PBKDF");
36✔
144

145
         if(!pwdhash_fam) {
36✔
146
            result.test_failure("Bcrypt-PBKDF is missing PasswordHashFamily");
×
147
            return result;
×
148
         }
149

150
         auto pwdhash = pwdhash_fam->from_iterations(rounds);
36✔
151

152
         std::vector<uint8_t> derived(expected.size());
36✔
153
         pwdhash->hash(derived, passphrase, salt);
36✔
154

155
         result.test_eq("derived key", derived, expected);
36✔
156

157
         return result;
36✔
158
      }
180✔
159
};
160

161
BOTAN_REGISTER_TEST("pbkdf", "bcrypt_pbkdf", Bcrypt_PBKDF_KAT_Tests);
162

163
#endif
164

165
#if defined(BOTAN_HAS_SCRYPT)
166

167
class Scrypt_KAT_Tests final : public Text_Based_Test {
×
168
   public:
169
      Scrypt_KAT_Tests() : Text_Based_Test("scrypt.vec", "Passphrase,Salt,N,R,P,Output") {}
3✔
170

171
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
15✔
172
         const size_t N = vars.get_req_sz("N");
15✔
173
         const size_t R = vars.get_req_sz("R");
15✔
174
         const size_t P = vars.get_req_sz("P");
15✔
175
         const std::vector<uint8_t> salt = vars.get_req_bin("Salt");
15✔
176
         const std::string passphrase = vars.get_req_str("Passphrase");
15✔
177
         const std::vector<uint8_t> expected = vars.get_req_bin("Output");
15✔
178

179
         Test::Result result("scrypt");
15✔
180

181
         if(N >= 1048576 && Test::run_long_tests() == false)
15✔
182
            return result;
183

184
         auto pwdhash_fam = Botan::PasswordHashFamily::create("Scrypt");
15✔
185

186
         if(!pwdhash_fam) {
15✔
187
            result.test_failure("Scrypt is missing PasswordHashFamily");
×
188
            return result;
×
189
         }
190

191
         auto pwdhash = pwdhash_fam->from_params(N, R, P);
15✔
192

193
         std::vector<uint8_t> pwdhash_derived(expected.size());
15✔
194
         pwdhash->hash(pwdhash_derived, passphrase, salt);
15✔
195

196
         result.test_eq("pwdhash derived key", pwdhash_derived, expected);
15✔
197

198
         return result;
15✔
199
      }
75✔
200
};
201

202
BOTAN_REGISTER_TEST("pbkdf", "scrypt", Scrypt_KAT_Tests);
203

204
#endif
205

206
#if defined(BOTAN_HAS_ARGON2)
207

208
class Argon2_KAT_Tests final : public Text_Based_Test {
×
209
   public:
210
      Argon2_KAT_Tests() : Text_Based_Test("argon2.vec", "Passphrase,Salt,P,M,T,Output", "Secret,AD") {}
3✔
211

212
      Test::Result run_one_test(const std::string& mode, const VarMap& vars) override {
1,071✔
213
         const size_t P = vars.get_req_sz("P");
1,071✔
214
         const size_t M = vars.get_req_sz("M");
1,071✔
215
         const size_t T = vars.get_req_sz("T");
1,071✔
216
         const std::vector<uint8_t> key = vars.get_opt_bin("Secret");
1,071✔
217
         const std::vector<uint8_t> ad = vars.get_opt_bin("AD");
1,071✔
218
         const std::vector<uint8_t> salt = vars.get_req_bin("Salt");
1,071✔
219
         const std::vector<uint8_t> passphrase = vars.get_req_bin("Passphrase");
1,071✔
220
         const std::vector<uint8_t> expected = vars.get_req_bin("Output");
1,071✔
221

222
         Test::Result result(mode);
2,142✔
223

224
         auto pwdhash_fam = Botan::PasswordHashFamily::create(mode);
1,071✔
225

226
         if(!pwdhash_fam) {
1,071✔
227
            result.test_failure("Argon2 is missing PasswordHashFamily");
×
228
            return result;
×
229
         }
230

231
         auto pwdhash = pwdhash_fam->from_params(M, T, P);
1,071✔
232

233
         const std::string passphrase_str(passphrase.begin(), passphrase.end());
1,071✔
234

235
         std::vector<uint8_t> pwdhash_derived(expected.size());
1,071✔
236
         pwdhash->hash(pwdhash_derived, passphrase_str, salt, ad, key);
1,071✔
237

238
         result.test_eq("pwdhash derived key", pwdhash_derived, expected);
1,071✔
239

240
         return result;
1,071✔
241
      }
6,768✔
242
};
243

244
BOTAN_REGISTER_SERIALIZED_TEST("pbkdf", "argon2", Argon2_KAT_Tests);
245

246
#endif
247

248
#if defined(BOTAN_HAS_PGP_S2K)
249

250
class PGP_S2K_Iter_Test final : public Test {
×
251
   public:
252
      std::vector<Test::Result> run() override {
1✔
253
         Test::Result result("PGP_S2K iteration encoding");
1✔
254

255
         // The maximum representable iteration count
256
         const size_t max_iter = 65011712;
1✔
257

258
         result.test_eq("Encoding of large value accepted", Botan::RFC4880_encode_count(max_iter * 2), size_t(255));
1✔
259
         result.test_eq("Encoding of small value accepted", Botan::RFC4880_encode_count(0), size_t(0));
1✔
260

261
         for(size_t c = 0; c != 256; ++c) {
257✔
262
            const size_t dec = Botan::RFC4880_decode_count(static_cast<uint8_t>(c));
256✔
263
            const size_t comp_dec = (16 + (c & 0x0F)) << ((c >> 4) + 6);
256✔
264
            result.test_eq("Decoded value matches PGP formula", dec, comp_dec);
256✔
265

266
            const size_t enc = Botan::RFC4880_encode_count(comp_dec);
256✔
267
            result.test_eq("Encoded value matches PGP formula", enc, c);
512✔
268
         }
269

270
         uint8_t last_enc = 0;
271

272
         for(size_t i = 0; i <= max_iter; i += 64) {
1,015,810✔
273
            const uint8_t enc = Botan::RFC4880_encode_count(i);
1,015,809✔
274
            result.test_lte("Encoded value non-decreasing", last_enc, enc);
1,015,809✔
275

276
            /*
277
            The iteration count as encoded may not be exactly the
278
            value requested, but should never be less
279
            */
280
            const size_t dec = Botan::RFC4880_decode_count(enc);
1,015,809✔
281
            result.test_gte("Decoded value is >= requested", dec, i);
1,015,809✔
282

283
            last_enc = enc;
1,015,809✔
284
         }
285

286
         return std::vector<Test::Result>{result};
3✔
287
      }
1✔
288
};
289

290
BOTAN_REGISTER_TEST("pbkdf", "pgp_s2k_iter", PGP_S2K_Iter_Test);
291

292
#endif
293

294
}
295

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

© 2025 Coveralls, Inc