diff options
-rw-r--r-- | src/cli/speed.cpp | 21 | ||||
-rwxr-xr-x | src/scripts/test_cli.py | 29 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 11 | ||||
-rw-r--r-- | src/tests/test_pbkdf.cpp | 106 |
4 files changed, 148 insertions, 19 deletions
diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp index 3ba6da24f..f7e9da1cf 100644 --- a/src/cli/speed.cpp +++ b/src/cli/speed.cpp @@ -1636,11 +1636,11 @@ class Speed final : public Command } } - void bench_pk_sig(const Botan::Private_Key& key, - const std::string& nm, - const std::string& provider, - const std::string& padding, - std::chrono::milliseconds msec) + size_t bench_pk_sig(const Botan::Private_Key& key, + const std::string& nm, + const std::string& provider, + const std::string& padding, + std::chrono::milliseconds msec) { std::vector<uint8_t> message, signature, bad_signature; @@ -1690,8 +1690,12 @@ class Speed final : public Command } } + const size_t events = std::min(sig_timer->events(), ver_timer->events()); + record_result(sig_timer); record_result(ver_timer); + + return events; } #endif @@ -1925,7 +1929,8 @@ class Speed final : public Command })); record_result(keygen_timer); - bench_pk_sig(*key, params, provider, "", msec); + if(bench_pk_sig(*key, params, provider, "", msec) == 1) + break; } } #endif @@ -1981,7 +1986,7 @@ class Speed final : public Command std::chrono::milliseconds msec) { - for(size_t N : { 8192, 16384, 32768, 65536, 1 << 17, 1 << 18, 1 << 19 }) + for(size_t N : { 8192, 16384, 32768, 65536 }) { for(size_t r : { 1, 8, 16 }) { @@ -2006,10 +2011,8 @@ class Speed final : public Command record_result(scrypt_timer); - /* if(scrypt_timer->events() == 1) break; - */ } } } diff --git a/src/scripts/test_cli.py b/src/scripts/test_cli.py index 2f5e5bba4..d38a990d9 100755 --- a/src/scripts/test_cli.py +++ b/src/scripts/test_cli.py @@ -46,8 +46,6 @@ def test_cli(cmd, cmd_options, expected_output=None, cmd_input=None): TESTS_RUN += 1 - logging.debug("Running %s %s", cmd, cmd_options) - fixed_drbg_seed = "802" * 32 opt_list = [] @@ -60,6 +58,8 @@ def test_cli(cmd, cmd_options, expected_output=None, cmd_input=None): drbg_options = ['--rng-type=drbg', '--drbg-seed=' + fixed_drbg_seed] cmdline = [CLI_PATH, cmd] + drbg_options + opt_list + logging.debug("Executing '%s'" % (' '.join([CLI_PATH, cmd] + opt_list))) + stdout = None stderr = None @@ -283,6 +283,26 @@ mlLtJ5JvZ0/p6zP3x+Y9yPIrAR8L/acG5ItSrAKXzzuqQQZMv4aN shutil.rmtree(tmp_dir) +def cli_pbkdf_tune_tests(): + if not check_for_command("pbkdf_tune"): + return + + expected = re.compile(r'For (default|[1-9][0-9]*) ms selected Scrypt\([0-9]+,[0-9]+,[0-9]+\) using [0-9]+ MiB') + + output = test_cli("pbkdf_tune", ["--check", "1", "10", "50", "default"], None).split('\n') + + for line in output: + if expected.match(line) is None: + logging.error("Unexpected line '%s'" % (line)) + + expected_pbkdf2 = re.compile(r'For (default|[1-9][0-9]*) ms selected PBKDF2\(HMAC\(SHA-256\),[0-9]+\)') + + output = test_cli("pbkdf_tune", ["--algo=PBKDF2(SHA-256)", "--check", "1", "10", "50", "default"], None).split('\n') + + for line in output: + if expected_pbkdf2.match(line) is None: + logging.error("Unexpected line '%s'" % (line)) + def cli_psk_db_tests(): if not check_for_command("psk_get"): return @@ -601,7 +621,7 @@ def cli_speed_tests(): output = test_cli("speed", ["--msec=%d" % (msec), "scrypt"], None).split('\n') - format_re = re.compile(r'^scrypt-[0-9]+-[0-9]+-[0-9]+ [0-9]+ /sec; [0-9]+\.[0-9]+ ms/op .*\([0-9]+ (op|ops) in [0-9]+ ms\)') + format_re = re.compile(r'^scrypt-[0-9]+-[0-9]+-[0-9]+ \([0-9]+ MiB\) [0-9]+ /sec; [0-9]+\.[0-9]+ ms/op .*\([0-9]+ (op|ops) in [0-9]+ ms\)') for line in output: if format_re.match(line) is None: @@ -688,6 +708,7 @@ def main(args=None): cli_pk_encrypt_tests, cli_pk_workfactor_tests, cli_psk_db_tests, + cli_pbkdf_tune_tests, cli_rng_tests, cli_speed_tests, cli_timing_test_tests, @@ -701,7 +722,7 @@ def main(args=None): fn_name = fn.__name__ if test_regex is not None: - if test_regex.match(fn_name) is None: + if test_regex.search(fn_name) is None: continue start = time.time() diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index ba941be95..e2c50b4e9 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -2,6 +2,7 @@ * (C) 2015 Jack Lloyd * (C) 2016 René Korthaus * (C) 2018 Ribose Inc, Krzysztof Kwiatkowski +* (C) 2018 Ribose Inc * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -924,6 +925,16 @@ class FFI_Unit_Tests final : public Test TEST_FFI_OK(botan_scrypt, (output.data(), output.size(), pass, salt, sizeof(salt), 8, 1, 1)); result.test_eq("scrypt output", output, "4B9B888D695288E002CC4F9D90808A4D296A45CE4471AFBB"); + + size_t N, r, p; + TEST_FFI_OK(botan_pwdhash_timed, ("Scrypt", 50, &r, &p, &N, output.data(), output.size(), + "bunny", 5, salt, sizeof(salt))); + + std::vector<uint8_t> cmp(output.size()); + + TEST_FFI_OK(botan_pwdhash, ("Scrypt", N, r, p, cmp.data(), cmp.size(), + "bunny", 5, salt, sizeof(salt))); + result.test_eq("recomputed scrypt", cmp, output); #else TEST_FFI_RC(BOTAN_FFI_ERROR_NOT_IMPLEMENTED, botan_scrypt, (output.data(), output.size(), pass, salt, sizeof(salt), 8, 1, 1)); diff --git a/src/tests/test_pbkdf.cpp b/src/tests/test_pbkdf.cpp index eb344b2ea..20a25165b 100644 --- a/src/tests/test_pbkdf.cpp +++ b/src/tests/test_pbkdf.cpp @@ -1,5 +1,6 @@ /* * (C) 2014,2015 Jack Lloyd +* (C) 2018 Ribose Inc * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,6 +9,7 @@ #if defined(BOTAN_HAS_PBKDF) #include <botan/pbkdf.h> + #include <botan/pwdhash.h> #endif #if defined(BOTAN_HAS_PGP_S2K) @@ -49,9 +51,25 @@ class PBKDF_KAT_Tests final : public Text_Based_Test const Botan::secure_vector<uint8_t> derived = pbkdf->derive_key(outlen, passphrase, salt.data(), salt.size(), iterations).bits_of(); - result.test_eq("derived key", derived, expected); + auto pwdhash_fam = Botan::PasswordHashFamily::create(pbkdf_name); + + if(!pwdhash_fam) + { + result.note_missing("No PasswordHashFamily for " + pbkdf_name); + return result; + } + + auto pwdhash = pwdhash_fam->from_params(iterations); + + std::vector<uint8_t> pwdhash_derived(outlen); + pwdhash->derive_key(pwdhash_derived.data(), pwdhash_derived.size(), + passphrase.c_str(), passphrase.size(), + salt.data(), salt.size()); + + result.test_eq("pwdhash derived key", pwdhash_derived, expected); + return result; } @@ -59,6 +77,65 @@ class PBKDF_KAT_Tests final : public Text_Based_Test BOTAN_REGISTER_TEST("pbkdf", PBKDF_KAT_Tests); +class Pwdhash_Tests : public Test + { + public: + std::vector<Test::Result> run() override + { + std::vector<Test::Result> results; + + for(std::string pwdhash : { "Scrypt", "PBKDF2(SHA-256)", "OpenPGP-S2K(SHA-384)"}) + { + Test::Result result("Pwdhash " + pwdhash); + auto pwdhash_fam = Botan::PasswordHashFamily::create(pwdhash); + + if(pwdhash_fam) + { + const std::vector<uint8_t> salt(8); + const std::string password = "test"; + + auto pwdhash_tune = pwdhash_fam->tune(32, std::chrono::milliseconds(50)); + + std::vector<uint8_t> output1(32); + pwdhash_tune->derive_key(output1.data(), output1.size(), + password.c_str(), password.size(), + salt.data(), salt.size()); + + std::unique_ptr<Botan::PasswordHash> pwhash; + + if(pwdhash_fam->name() == "Scrypt") + { + pwhash = pwdhash_fam->from_params(pwdhash_tune->memory_param(), + pwdhash_tune->iterations(), + pwdhash_tune->parallelism()); + } + else + { + pwhash = pwdhash_fam->from_params(pwdhash_tune->iterations()); + } + + std::vector<uint8_t> output2(32); + pwdhash_tune->derive_key(output2.data(), output2.size(), + password.c_str(), password.size(), + salt.data(), salt.size()); + + result.test_eq("PasswordHash produced same output when run with same params", + output1, output2); + + + //auto pwdhash_tuned = pwdhash_fam->tune(32, std::chrono::milliseconds(150)); + + } + + results.push_back(result); + } + + return results; + } + }; + +BOTAN_REGISTER_TEST("pwdhash", Pwdhash_Tests); + #endif #if defined(BOTAN_HAS_SCRYPT) @@ -89,6 +166,23 @@ class Scrypt_KAT_Tests final : public Text_Based_Test result.test_eq("derived key", output, expected); + auto pwdhash_fam = Botan::PasswordHashFamily::create("Scrypt"); + + if(!pwdhash_fam) + { + result.test_failure("Scrypt is missing PasswordHashFamily"); + return result; + } + + auto pwdhash = pwdhash_fam->from_params(N, R, P); + + std::vector<uint8_t> pwdhash_derived(expected.size()); + pwdhash->derive_key(pwdhash_derived.data(), pwdhash_derived.size(), + passphrase.c_str(), passphrase.size(), + salt.data(), salt.size()); + + result.test_eq("pwdhash derived key", pwdhash_derived, expected); + return result; } @@ -111,13 +205,13 @@ class PGP_S2K_Iter_Test final : public Test const size_t max_iter = 65011712; result.test_eq("Encoding of large value accepted", - Botan::OpenPGP_S2K::encode_count(max_iter * 2), size_t(255)); + Botan::RFC4880_encode_count(max_iter * 2), size_t(255)); result.test_eq("Encoding of small value accepted", - Botan::OpenPGP_S2K::encode_count(0), size_t(0)); + Botan::RFC4880_encode_count(0), size_t(0)); for(size_t c = 0; c != 256; ++c) { - const size_t dec = Botan::OpenPGP_S2K::decode_count(static_cast<uint8_t>(c)); + const size_t dec = Botan::RFC4880_decode_count(static_cast<uint8_t>(c)); const size_t comp_dec = (16 + (c & 0x0F)) << ((c >> 4) + 6); result.test_eq("Decoded value matches PGP formula", dec, comp_dec); } @@ -126,14 +220,14 @@ class PGP_S2K_Iter_Test final : public Test for(size_t i = 0; i <= max_iter; i += 64) { - const uint8_t enc = Botan::OpenPGP_S2K::encode_count(i); + const uint8_t enc = Botan::RFC4880_encode_count(i); result.test_lte("Encoded value non-decreasing", last_enc, enc); /* The iteration count as encoded may not be exactly the value requested, but should never be less */ - const size_t dec = Botan::OpenPGP_S2K::decode_count(enc); + const size_t dec = Botan::RFC4880_decode_count(enc); result.test_gte("Decoded value is >= requested", dec, i); last_enc = enc; |