From 81dcb29da8ec47dc30ffd0fb960adfa86168bb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ka=C4=9Fan=20Can=20=C5=9Eit?= Date: Sat, 9 Nov 2024 01:46:49 +0300 Subject: [PATCH] =?UTF-8?q?Duration=20values=20=E2=80=8B=E2=80=8Bof=20the?= =?UTF-8?q?=20tests=20were=20presented=20in=20seconds.=20=20Sensitivity=20?= =?UTF-8?q?was=20determined=20as=20six=20digits.=20Time=20values=20?= =?UTF-8?q?=E2=80=8B=E2=80=8Bwere=20added=20to=20ensure=20consistency=20fo?= =?UTF-8?q?r=20tests=20without=20time=20measurement.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test_aead.cpp | 6 + src/tests/test_alt_name.cpp | 2 + src/tests/test_asn1.cpp | 22 ++- src/tests/test_bigint.cpp | 56 +++++++- src/tests/test_bufcomp.cpp | 2 + src/tests/test_certstor.cpp | 10 +- src/tests/test_certstor_flatfile.cpp | 2 + src/tests/test_certstor_system.cpp | 26 +++- src/tests/test_crystals.cpp | 40 ++++++ src/tests/test_ct_utils.cpp | 20 +++ src/tests/test_dh.cpp | 2 + src/tests/test_dilithium.cpp | 10 +- src/tests/test_dl_group.cpp | 5 + src/tests/test_dlies.cpp | 2 + src/tests/test_ec_group.cpp | 29 +++- src/tests/test_ecies.cpp | 12 ++ src/tests/test_ed25519.cpp | 2 + src/tests/test_ed448.cpp | 3 + src/tests/test_ffi.cpp | 2 + src/tests/test_filters.cpp | 38 ++++++ src/tests/test_frodokem.cpp | 2 + src/tests/test_gf2m.cpp | 2 + src/tests/test_hash.cpp | 13 ++ src/tests/test_hash_id.cpp | 2 + src/tests/test_hss_lms.cpp | 18 +++ src/tests/test_keccak_helpers.cpp | 18 +++ src/tests/test_kyber.cpp | 4 + src/tests/test_modes.cpp | 8 ++ src/tests/test_mp.cpp | 9 +- src/tests/test_name_constraint.cpp | 2 + src/tests/test_ocsp.cpp | 24 ++++ src/tests/test_octetstring.cpp | 16 +++ src/tests/test_oid.cpp | 10 ++ src/tests/test_os_utils.cpp | 15 +- src/tests/test_otp.cpp | 4 + src/tests/test_pbkdf.cpp | 2 + src/tests/test_pem.cpp | 2 + src/tests/test_pk_pad.cpp | 2 + src/tests/test_psk_db.cpp | 4 + src/tests/test_pubkey.cpp | 2 + src/tests/test_rng_behavior.cpp | 41 ++++++ src/tests/test_roughtime.cpp | 15 ++ src/tests/test_rsa.cpp | 4 + src/tests/test_simd.cpp | 2 + src/tests/test_sodium.cpp | 44 ++++++ src/tests/test_sphincsplus_utils.cpp | 10 ++ src/tests/test_strong_type.cpp | 46 +++++++ src/tests/test_tests.cpp | 4 + src/tests/test_thread_utils.cpp | 2 + src/tests/test_tls.cpp | 18 +++ src/tests/test_tls_cipher_state.cpp | 28 ++++ src/tests/test_tls_handshake_layer_13.cpp | 34 +++++ src/tests/test_tls_handshake_state_13.cpp | 10 ++ src/tests/test_tls_handshake_transitions.cpp | 10 ++ src/tests/test_tls_hybrid_kem_key.cpp | 71 ++++++++-- src/tests/test_tls_messages.cpp | 4 + src/tests/test_tls_record_layer_13.cpp | 104 ++++++++++++++ src/tests/test_tls_rfc8448.cpp | 136 +++++++++++++++++++ src/tests/test_tls_session_manager.cpp | 98 ++++++++++++- src/tests/test_tls_signature_scheme.cpp | 4 + src/tests/test_tls_transcript_hash_13.cpp | 20 +++ src/tests/test_uri.cpp | 8 ++ src/tests/test_utils.cpp | 62 ++++++++- src/tests/test_utils_buffer.cpp | 48 +++++++ src/tests/test_x25519.cpp | 2 + src/tests/test_x509_path.cpp | 64 +++++++-- src/tests/test_xmss.cpp | 10 ++ src/tests/test_xof.cpp | 6 + src/tests/tests.cpp | 9 +- src/tests/unit_ecdsa.cpp | 19 +++ src/tests/unit_tls.cpp | 2 + src/tests/unit_tls_policy.cpp | 18 +++ src/tests/unit_x509.cpp | 55 +++++++- 73 files changed, 1416 insertions(+), 42 deletions(-) diff --git a/src/tests/test_aead.cpp b/src/tests/test_aead.cpp index cc0ff27725a..9b67bf2b908 100644 --- a/src/tests/test_aead.cpp +++ b/src/tests/test_aead.cpp @@ -32,6 +32,7 @@ class AEAD_Tests final : public Text_Based_Test { const bool is_siv = algo.find("/SIV") != std::string::npos; Test::Result result(algo); + result.start_timer(); auto enc = Botan::AEAD_Mode::create(algo, Botan::Cipher_Dir::Encryption); @@ -177,6 +178,7 @@ class AEAD_Tests final : public Text_Based_Test { [&]() { enc->set_associated_data(ad.data(), ad.size()); }); } + result.end_timer(); return result; } @@ -190,6 +192,7 @@ class AEAD_Tests final : public Text_Based_Test { const bool is_siv = algo.find("/SIV") != std::string::npos; Test::Result result(algo); + result.start_timer(); auto dec = Botan::AEAD_Mode::create(algo, Botan::Cipher_Dir::Decryption); @@ -381,6 +384,7 @@ class AEAD_Tests final : public Text_Based_Test { [&]() { dec->set_associated_data(ad.data(), ad.size()); }); } + result.end_timer(); return result; } @@ -392,6 +396,7 @@ class AEAD_Tests final : public Text_Based_Test { const std::vector ad = vars.get_opt_bin("AD"); Test::Result result(algo); + result.start_timer(); auto enc = Botan::AEAD_Mode::create(algo, Botan::Cipher_Dir::Encryption); auto dec = Botan::AEAD_Mode::create(algo, Botan::Cipher_Dir::Decryption); @@ -433,6 +438,7 @@ class AEAD_Tests final : public Text_Based_Test { // test dec result.merge(test_dec(key, nonce, expected, input, ad, algo, this->rng())); + result.end_timer(); return result; } }; diff --git a/src/tests/test_alt_name.cpp b/src/tests/test_alt_name.cpp index 2eeca962126..18b92a49875 100644 --- a/src/tests/test_alt_name.cpp +++ b/src/tests/test_alt_name.cpp @@ -19,6 +19,7 @@ class X509_Alt_Name_Tests final : public Test { public: std::vector run() override { Test::Result result("X509 AlternativeName tests"); + result.start_timer(); const std::vector uri_names = { "https://example.com", "https://example.org", "https://sub.example.net"}; @@ -90,6 +91,7 @@ class X509_Alt_Name_Tests final : public Test { result.test_eq("Expected number of DNs", recoded.directory_names().size(), 2); result.test_eq("Expected number of Othernames", recoded.other_names().size(), 2); + result.end_timer(); return {result}; } }; diff --git a/src/tests/test_asn1.cpp b/src/tests/test_asn1.cpp index 1658e5d23c0..a0ecaad2b5b 100644 --- a/src/tests/test_asn1.cpp +++ b/src/tests/test_asn1.cpp @@ -21,6 +21,7 @@ namespace { Test::Result test_ber_stack_recursion() { Test::Result result("BER stack recursion"); + result.start_timer(); // OSS-Fuzz #813 GitHub #989 @@ -36,12 +37,13 @@ Test::Result test_ber_stack_recursion() { } catch(Botan::Decoding_Error&) {} result.test_success("No crash"); - + result.end_timer(); return result; } Test::Result test_ber_eoc_decoding_limits() { Test::Result result("BER nested indefinite length"); + result.start_timer(); // OSS-Fuzz #4353 @@ -71,12 +73,13 @@ Test::Result test_ber_eoc_decoding_limits() { } result.test_eq("EOC limited to prevent stack exhaustion", max_eoc_allowed, 16); - + result.end_timer(); return result; } Test::Result test_asn1_utf8_ascii_parsing() { Test::Result result("ASN.1 ASCII parsing"); + result.start_timer(); try { // \x13 - ASN1 tag for 'printable string' @@ -95,11 +98,13 @@ Test::Result test_asn1_utf8_ascii_parsing() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_asn1_utf8_parsing() { Test::Result result("ASN.1 UTF-8 parsing"); + result.start_timer(); try { // \x0C - ASN1 tag for 'UTF8 string' @@ -118,11 +123,13 @@ Test::Result test_asn1_utf8_parsing() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_asn1_ucs2_parsing() { Test::Result result("ASN.1 BMP string (UCS-2) parsing"); + result.start_timer(); try { // \x1E - ASN1 tag for 'BMP (UCS-2) string' @@ -142,11 +149,13 @@ Test::Result test_asn1_ucs2_parsing() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_asn1_ucs4_parsing() { Test::Result result("ASN.1 universal string (UCS-4) parsing"); + result.start_timer(); try { // \x1C - ASN1 tag for 'universal string' @@ -166,11 +175,13 @@ Test::Result test_asn1_ucs4_parsing() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_asn1_ascii_encoding() { Test::Result result("ASN.1 ASCII encoding"); + result.start_timer(); try { // UTF-8 encoded (ASCII chars only) word 'Moscow' @@ -192,11 +203,13 @@ Test::Result test_asn1_ascii_encoding() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_asn1_utf8_encoding() { Test::Result result("ASN.1 UTF-8 encoding"); + result.start_timer(); try { // UTF-8 encoded russian word for Moscow in cyrillic script @@ -218,11 +231,13 @@ Test::Result test_asn1_utf8_encoding() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_asn1_tag_underlying_type() { Test::Result result("ASN.1 class and type underlying type"); + result.start_timer(); if constexpr(std::is_same_v, std::underlying_type_t>) { if constexpr(!std::is_same_v, @@ -236,6 +251,7 @@ Test::Result test_asn1_tag_underlying_type() { result.test_failure("ASN1_Class and ASN1_Type have different underlying types"); } + result.end_timer(); return result; } @@ -299,6 +315,7 @@ class ASN1_Printer_Tests final : public Test { public: std::vector run() override { Test::Result result("ASN1_Pretty_Printer"); + result.start_timer(); Botan::ASN1_Pretty_Printer printer; @@ -317,6 +334,7 @@ class ASN1_Printer_Tests final : public Test { } } + result.end_timer(); return {result}; } }; diff --git a/src/tests/test_bigint.cpp b/src/tests/test_bigint.cpp index c8d4ddf35fb..186582e4048 100644 --- a/src/tests/test_bigint.cpp +++ b/src/tests/test_bigint.cpp @@ -46,6 +46,7 @@ class BigInt_Unit_Tests final : public Test { private: static Test::Result test_bigint_sizes() { Test::Result result("BigInt size functions"); + result.start_timer(); for(size_t bit : {1, 8, 16, 31, 32, 64, 97, 128, 179, 192, 512, 521}) { BigInt a; @@ -77,11 +78,13 @@ class BigInt_Unit_Tests final : public Test { } } + result.end_timer(); return result; } static Test::Result test_random_prime() { Test::Result result("BigInt prime generation"); + result.start_timer(); auto rng = Test::new_rng("random_prime"); @@ -114,11 +117,13 @@ class BigInt_Unit_Tests final : public Test { result.confirm("P is prime", Botan::is_prime(safe_prime, *rng)); result.confirm("(P-1)/2 is prime", Botan::is_prime((safe_prime - 1) / 2, *rng)); + result.end_timer(); return result; } static Test::Result test_encode() { Test::Result result("BigInt encoding functions"); + result.start_timer(); const auto n1 = Botan::BigInt::from_u64(0xffff); const auto n2 = Botan::BigInt::from_u64(1023); @@ -136,11 +141,13 @@ class BigInt_Unit_Tests final : public Test { } } + result.end_timer(); return result; } static Test::Result test_get_substring() { Test::Result result("BigInt get_substring"); + result.start_timer(); const size_t rbits = 1024; @@ -161,11 +168,13 @@ class BigInt_Unit_Tests final : public Test { } } + result.end_timer(); return result; } static Test::Result test_bigint_io() { Test::Result result("BigInt IO operators"); + result.start_timer(); const std::map str_to_val = {{"-13", -Botan::BigInt(13)}, {"0", Botan::BigInt(0)}, @@ -216,6 +225,7 @@ class BigInt_Unit_Tests final : public Test { oss << std::oct << n; }); + result.end_timer(); return result; } }; @@ -228,6 +238,7 @@ class BigInt_Cmp_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& op, const VarMap& vars) override { Test::Result result("BigInt Comparison " + op); + result.start_timer(); const BigInt x = vars.get_req_bn("X"); const BigInt y = vars.get_req_bn("Y"); @@ -255,6 +266,7 @@ class BigInt_Cmp_Test final : public Text_Based_Test { throw Test_Error("Unknown BigInt comparison type " + op); } + result.end_timer(); return result; } }; @@ -267,6 +279,7 @@ class BigInt_Add_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Addition"); + result.start_timer(); using Botan::BigInt; @@ -285,6 +298,7 @@ class BigInt_Add_Test final : public Text_Based_Test { e += a; result.test_eq("b += a", e, c); + result.end_timer(); return result; } }; @@ -297,6 +311,7 @@ class BigInt_Sub_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Subtraction"); + result.start_timer(); const BigInt a = vars.get_req_bn("In1"); const BigInt b = vars.get_req_bn("In2"); @@ -308,6 +323,7 @@ class BigInt_Sub_Test final : public Text_Based_Test { e -= b; result.test_eq("a -= b", e, c); + result.end_timer(); return result; } }; @@ -320,6 +336,7 @@ class BigInt_Mul_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Multiply"); + result.start_timer(); const BigInt a = vars.get_req_bn("In1"); const BigInt b = vars.get_req_bn("In2"); @@ -336,6 +353,7 @@ class BigInt_Mul_Test final : public Text_Based_Test { e *= a; result.test_eq("b *= a", e, c); + result.end_timer(); return result; } }; @@ -348,6 +366,7 @@ class BigInt_Sqr_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Square"); + result.start_timer(); const BigInt input = vars.get_req_bn("Input"); const BigInt output = vars.get_req_bn("Output"); @@ -355,6 +374,7 @@ class BigInt_Sqr_Test final : public Text_Based_Test { result.test_eq("a * a", input * input, output); result.test_eq("sqr(a)", square(input), output); + result.end_timer(); return result; } }; @@ -367,6 +387,7 @@ class BigInt_Div_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Divide"); + result.start_timer(); const BigInt a = vars.get_req_bn("In1"); const BigInt b = vars.get_req_bn("In2"); @@ -394,6 +415,7 @@ class BigInt_Div_Test final : public Text_Based_Test { result.test_eq("ct_divide q", ct_q, c); result.test_eq("ct_divide r", ct_q * b + ct_r, a); + result.end_timer(); return result; } }; @@ -406,6 +428,7 @@ class BigInt_Mod_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Mod"); + result.start_timer(); const BigInt a = vars.get_req_bn("In1"); const BigInt b = vars.get_req_bn("In2"); @@ -440,6 +463,7 @@ class BigInt_Mod_Test final : public Text_Based_Test { Botan::ct_divide(a, b, ct_q, ct_r); result.test_eq("ct_divide r", ct_r, expected); + result.end_timer(); return result; } }; @@ -452,6 +476,7 @@ class BigInt_GCD_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt GCD"); + result.start_timer(); const BigInt x = vars.get_req_bn("X"); const BigInt y = vars.get_req_bn("Y"); @@ -463,6 +488,7 @@ class BigInt_GCD_Test final : public Text_Based_Test { const BigInt g2 = Botan::gcd(y, x); result.test_eq("gcd", g2, expected); + result.end_timer(); return result; } }; @@ -475,6 +501,7 @@ class BigInt_Jacobi_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Jacobi"); + result.start_timer(); const BigInt a = vars.get_req_bn("A"); const BigInt n = vars.get_req_bn("N"); @@ -490,6 +517,7 @@ class BigInt_Jacobi_Test final : public Text_Based_Test { result.test_eq("jacobi", expected, "1"); } + result.end_timer(); return result; } }; @@ -502,6 +530,7 @@ class BigInt_Lshift_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Lshift"); + result.start_timer(); const BigInt value = vars.get_req_bn("Value"); const size_t shift = vars.get_req_bn("Shift").to_u32bit(); @@ -513,6 +542,7 @@ class BigInt_Lshift_Test final : public Text_Based_Test { e <<= shift; result.test_eq("a <<= s", e, output); + result.end_timer(); return result; } }; @@ -525,6 +555,7 @@ class BigInt_Rshift_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Rshift"); + result.start_timer(); const BigInt value = vars.get_req_bn("Value"); const size_t shift = vars.get_req_bn("Shift").to_u32bit(); @@ -536,6 +567,7 @@ class BigInt_Rshift_Test final : public Text_Based_Test { e >>= shift; result.test_eq("a >>= s", e, output); + result.end_timer(); return result; } }; @@ -544,6 +576,7 @@ BOTAN_REGISTER_TEST("math", "bn_rshift", BigInt_Rshift_Test); Test::Result test_const_time_left_shift() { Test::Result result("BigInt const time shift"); + const size_t bits = Test::run_long_tests() ? 4096 : 2048; auto rng = Test::new_rng("const_time_left_shift"); @@ -568,7 +601,6 @@ Test::Result test_const_time_left_shift() { } result.end_timer(); - return result; } @@ -578,6 +610,7 @@ class BigInt_Powmod_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Powmod"); + result.start_timer(); const BigInt base = vars.get_req_bn("Base"); const BigInt exponent = vars.get_req_bn("Exponent"); @@ -585,6 +618,7 @@ class BigInt_Powmod_Test final : public Text_Based_Test { const BigInt expected = vars.get_req_bn("Output"); result.test_eq("power_mod", Botan::power_mod(base, exponent, modulus), expected); + result.end_timer(); return result; } }; @@ -604,8 +638,9 @@ class BigInt_IsPrime_Test final : public Text_Based_Test { const bool is_prime = (header == "Prime"); Test::Result result("BigInt Test " + header); + result.start_timer(); result.test_eq("is_prime", Botan::is_prime(value, this->rng()), is_prime); - + result.end_timer(); return result; } }; @@ -622,7 +657,9 @@ class BigInt_IsSquare_Test final : public Text_Based_Test { const BigInt computed = Botan::is_perfect_square(value); Test::Result result("BigInt IsSquare"); + result.start_timer(); result.test_eq("is_perfect_square", computed, expected); + result.end_timer(); return result; } }; @@ -635,6 +672,7 @@ class BigInt_Sqrt_Modulo_Prime_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Sqrt Modulo Prime"); + result.start_timer(); const Botan::BigInt a = vars.get_req_bn("Input"); const Botan::BigInt p = vars.get_req_bn("Modulus"); @@ -649,6 +687,7 @@ class BigInt_Sqrt_Modulo_Prime_Test final : public Text_Based_Test { result.test_eq("square correct", a_sqrt2, a); } + result.end_timer(); return result; } }; @@ -661,6 +700,7 @@ class BigInt_InvMod_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt InvMod"); + result.start_timer(); const Botan::BigInt a = vars.get_req_bn("Input"); const Botan::BigInt mod = vars.get_req_bn("Modulus"); @@ -679,7 +719,7 @@ class BigInt_InvMod_Test final : public Text_Based_Test { result.confirm("no inverse with gcd > 1", gcd(a, mod) > 1); } */ - + result.end_timer(); return result; } }; @@ -692,6 +732,7 @@ class BigInt_Rand_Test final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("BigInt Random"); + result.start_timer(); const std::vector seed = vars.get_req_bin("Seed"); const Botan::BigInt min = vars.get_req_bn("Min"); @@ -703,6 +744,7 @@ class BigInt_Rand_Test final : public Text_Based_Test { result.test_eq("random_integer KAT", generated, expected); + result.end_timer(); return result; } }; @@ -723,6 +765,7 @@ class Lucas_Primality_Test final : public Test { }; Test::Result result("Lucas primality test"); + result.start_timer(); for(uint32_t i = 3; i <= lucas_max; i += 2) { Botan::Modular_Reducer mod_i(i); @@ -738,6 +781,7 @@ class Lucas_Primality_Test final : public Test { } } + result.end_timer(); return {result}; } }; @@ -765,6 +809,7 @@ class DSA_ParamGen_Test final : public Text_Based_Test { const size_t q_bits = Botan::to_u32bit(header_parts[0]); Test::Result result("DSA Parameter Generation"); + result.start_timer(); try { Botan::BigInt gen_P, gen_Q; @@ -776,6 +821,7 @@ class DSA_ParamGen_Test final : public Text_Based_Test { } } catch(Botan::Lookup_Error&) {} + result.end_timer(); return result; } }; @@ -788,6 +834,7 @@ std::vector test_bigint_serialization() { return { CHECK("BigInt binary serialization", [](Test::Result& res) { + res.start_timer(); Botan::BigInt a(0x1234567890ABCDEF); auto enc = a.serialize(); res.test_eq("BigInt::serialize", enc, Botan::hex_decode("1234567890ABCDEF")); @@ -796,10 +843,12 @@ std::vector test_bigint_serialization() { res.test_eq("BigInt::serialize", enc10, Botan::hex_decode("00001234567890ABCDEF")); res.test_throws("BigInt::serialize rejects short output", [&]() { a.serialize(7); }); + res.end_timer(); }), CHECK("BigInt truncated/padded binary serialization", [&](Test::Result& res) { + res.start_timer(); Botan::BigInt a(0xFEDCBA9876543210); std::vector enc1(a.bytes() - 1); @@ -828,6 +877,7 @@ std::vector test_bigint_serialization() { res.test_eq("BigInt::binary_encode", enc5, Botan::hex_decode("000000000000000000000000FEDCBA9876543210BAADC0FFEE")); + res.end_timer(); }), }; } diff --git a/src/tests/test_bufcomp.cpp b/src/tests/test_bufcomp.cpp index 0d835d36eff..00981b7d443 100644 --- a/src/tests/test_bufcomp.cpp +++ b/src/tests/test_bufcomp.cpp @@ -65,6 +65,7 @@ Test::Result test_buffered_computation_convenience_api() { // types as in and out parameters. Hence, we refrain from checking // the 'final' output everywhere. Test::Result result("Convenience API of Buffered_Computation"); + result.start_timer(); Test_Buf_Comp t(result); @@ -127,6 +128,7 @@ Test::Result test_buffered_computation_convenience_api() { check(result, out_strong_sec_vec, 12); + result.end_timer(); return result; } diff --git a/src/tests/test_certstor.cpp b/src/tests/test_certstor.cpp index bd5beb6e0ad..bdcd64d8c43 100644 --- a/src/tests/test_certstor.cpp +++ b/src/tests/test_certstor.cpp @@ -269,6 +269,7 @@ Test::Result test_certstor_sqlite3_find_all_certs_test(const std::vector& certsandkeys) { Test::Result result("Certificate Store - Find by subject hash"); + result.start_timer(); try { Botan::Certificate_Store_In_Memory store; @@ -284,6 +285,7 @@ Test::Result test_certstor_find_hash_subject(const std::vector(32, 0)); if(found) { result.test_failure("Certificate found for dummy hash"); + result.end_timer(); return result; } - + result.end_timer(); return result; } catch(std::exception& e) { result.test_failure(e.what()); + result.end_timer(); return result; } } Test::Result test_certstor_load_allcert() { Test::Result result("Certificate Store - Load every cert of every files"); + result.start_timer(); + // test_dir_bundled dir should contain only one file with 2 certificates // concatenated (ValidCert and root) const std::string test_dir_bundled = Test::data_dir("x509/misc/bundledcertdir"); @@ -320,9 +326,11 @@ Test::Result test_certstor_load_allcert() { std::vector key_id; result.confirm("Root cert found", store.find_cert(root_cert.subject_dn(), key_id) != std::nullopt); result.confirm("ValidCert found", store.find_cert(valid_cert.subject_dn(), key_id) != std::nullopt); + result.end_timer(); return result; } catch(std::exception& e) { result.test_failure(e.what()); + result.end_timer(); return result; } } diff --git a/src/tests/test_certstor_flatfile.cpp b/src/tests/test_certstor_flatfile.cpp index f5499834447..1a0986025cb 100644 --- a/src/tests/test_certstor_flatfile.cpp +++ b/src/tests/test_certstor_flatfile.cpp @@ -216,6 +216,7 @@ Test::Result no_certificate_matches() { Test::Result certstore_contains_user_certificate() { Test::Result result("Flatfile Certificate Store - rejects bundles with non-CA certs"); + result.start_timer(); try { result.start_timer(); @@ -225,6 +226,7 @@ Test::Result certstore_contains_user_certificate() { result.test_success(); } + result.end_timer(); return result; } diff --git a/src/tests/test_certstor_system.cpp b/src/tests/test_certstor_system.cpp index aa78cf82cc8..381002ff11a 100644 --- a/src/tests/test_certstor_system.cpp +++ b/src/tests/test_certstor_system.cpp @@ -22,6 +22,7 @@ namespace { Test::Result find_certificate_by_pubkey_sha1(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find Certificate by SHA1(pubkey)"); + result.start_timer(); try { result.start_timer(); @@ -39,11 +40,13 @@ Test::Result find_certificate_by_pubkey_sha1(Botan::Certificate_Store& certstore result.test_throws("on invalid SHA1 hash data", [&] { certstore.find_cert_by_pubkey_sha1({}); }); + result.end_timer(); return result; } Test::Result find_certificate_by_pubkey_sha1_with_unmatching_key_id(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find Certificate by SHA1(pubkey) - regression test for GH #2779"); + result.start_timer(); if(!certstore.find_cert(get_dn_of_cert_with_different_key_id(), {}).has_value()) { result.note_missing("OS does not trust the certificate used for this regression test, skipping"); @@ -63,12 +66,14 @@ Test::Result find_certificate_by_pubkey_sha1_with_unmatching_key_id(Botan::Certi } catch(std::exception& e) { result.test_failure(e.what()); } - + + result.end_timer(); return result; } Test::Result find_cert_by_subject_dn(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find Certificate by subject DN"); + result.start_timer(); try { auto dn = get_dn(); @@ -86,11 +91,13 @@ Test::Result find_cert_by_subject_dn(Botan::Certificate_Store& certstore) { result.test_failure(e.what()); } + result.end_timer(); return result; } Test::Result find_cert_by_utf8_subject_dn(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find Certificate by UTF8 subject DN"); + result.start_timer(); try { const auto DNs = get_utf8_dn_alternatives(); @@ -124,12 +131,14 @@ Test::Result find_cert_by_utf8_subject_dn(Botan::Certificate_Store& certstore) { result.test_failure(e.what()); } + result.end_timer(); return result; } Test::Result find_cert_by_subject_dn_and_key_id(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find Certificate by subject DN and key ID"); - + result.start_timer(); + try { auto dn = get_dn(); @@ -146,11 +155,13 @@ Test::Result find_cert_by_subject_dn_and_key_id(Botan::Certificate_Store& certst result.test_failure(e.what()); } + result.end_timer(); return result; } Test::Result find_certs_by_subject_dn_and_key_id(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find Certificates by subject DN and key ID"); + result.start_timer(); try { auto dn = get_dn(); @@ -169,11 +180,13 @@ Test::Result find_certs_by_subject_dn_and_key_id(Botan::Certificate_Store& certs result.test_failure(e.what()); } + result.end_timer(); return result; } Test::Result find_all_certs_by_subject_dn(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find all Certificates by subject DN"); + result.start_timer(); try { auto dn = get_dn(); @@ -199,11 +212,13 @@ Test::Result find_all_certs_by_subject_dn(Botan::Certificate_Store& certstore) { result.test_failure(e.what()); } + result.end_timer(); return result; } Test::Result find_all_subjects(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - Find all Certificate Subjects"); + result.start_timer(); try { result.start_timer(); @@ -223,11 +238,13 @@ Test::Result find_all_subjects(Botan::Certificate_Store& certstore) { result.test_failure(e.what()); } + result.end_timer(); return result; } Test::Result no_certificate_matches(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - can deal with no matches (regression test)"); + result.start_timer(); try { auto dn = get_unknown_dn(); @@ -246,6 +263,7 @@ Test::Result no_certificate_matches(Botan::Certificate_Store& certstore) { result.test_failure(e.what()); } + result.end_timer(); return result; } @@ -253,6 +271,7 @@ Test::Result no_certificate_matches(Botan::Certificate_Store& certstore) { Test::Result certificate_matching_with_dn_normalization(Botan::Certificate_Store& certstore) { Test::Result result("System Certificate Store - normalization of X.509 DN (regression test)"); + result.start_timer(); try { auto dn = get_skewed_dn(); @@ -272,6 +291,7 @@ Test::Result certificate_matching_with_dn_normalization(Botan::Certificate_Store result.test_failure(e.what()); } + result.end_timer(); return result; } @@ -281,6 +301,7 @@ class Certstor_System_Tests final : public Test { public: std::vector run() override { Test::Result open_result("System Certificate Store - Open Keychain"); + open_result.start_timer(); std::unique_ptr system; @@ -315,6 +336,7 @@ class Certstor_System_Tests final : public Test { results.push_back(certificate_matching_with_dn_normalization(*system)); #endif + open_result.end_timer(); return results; } }; diff --git a/src/tests/test_crystals.cpp b/src/tests/test_crystals.cpp index 7d38781a750..48e719f0ae5 100644 --- a/src/tests/test_crystals.cpp +++ b/src/tests/test_crystals.cpp @@ -38,6 +38,7 @@ consteval T u(T x, T y) { Test::Result test_extended_euclidean_algorithm() { Test::Result res("Extended Euclidean Algorithm"); + res.start_timer(); // The wrapper template functions gcd<>(), v<>() and u<>() are workarounds // for an assumed bug in MSVC 19.38.33134 that does not accept the invocation @@ -64,6 +65,7 @@ Test::Result test_extended_euclidean_algorithm() { res.test_is_eq("q^-1(3329) - Kyber::Q", Botan::modular_inverse(3329), -3327); res.test_is_eq("q^-1(8380417) - Dilithium::Q", Botan::modular_inverse(8380417), 58728449); + res.end_timer(); return res; } @@ -123,6 +125,7 @@ std::vector test_polynomial_basics() { return { CHECK("polynomial owning storage", [](Test::Result& res) { + res.start_timer(); Kyberish_Poly p; res.confirm("default constructed poly owns memory", p.owns_storage()); for(auto coeff : p) { @@ -134,10 +137,12 @@ std::vector test_polynomial_basics() { for(auto coeff : p) { res.test_is_eq("default constructed poly (NTT) has 0 coefficients", coeff, 0); } + res.end_timer(); }), CHECK("polynomial vector managing storage", [](Test::Result& res) { + res.start_timer(); Kyberish_PolyVec polys(4); res.test_is_eq("requested size", polys.size(), 4); @@ -151,10 +156,12 @@ std::vector test_polynomial_basics() { for(const auto& poly : polys_ntt) { res.confirm("poly (NTT) embedded in vector does not own memory", !poly.owns_storage()); } + res.end_timer(); }), CHECK("cloned polynomials always manage their storge", [](Test::Result& res) { + res.start_timer(); Kyberish_Poly p; auto p2 = p.clone(); res.confirm("cloned poly owns memory", p2.owns_storage()); @@ -186,10 +193,12 @@ std::vector test_polynomial_basics() { for(const auto& poly : pv2_ntt) { res.confirm("cloned vector polynomial (NTT) don't own memory", !poly.owns_storage()); } + res.end_timer(); }), CHECK("hamming weight of polynomials", [](Test::Result& res) { + res.start_timer(); Kyberish_Poly p; res.test_is_eq("hamming weight of 0", p.hamming_weight(), 0); @@ -216,10 +225,12 @@ std::vector test_polynomial_basics() { p[0] = 0; res.test_is_eq("hamming weight of 0", p.hamming_weight(), 0); + res.end_timer(); }), CHECK("hamming weight of polynomial vectors", [](Test::Result& res) { + res.start_timer(); Kyberish_PolyVec pv(3); res.test_is_eq("hamming weight of 0", pv.hamming_weight(), 0); @@ -240,10 +251,12 @@ std::vector test_polynomial_basics() { pv[0][0] = 0; res.test_is_eq("hamming weight of 0", pv.hamming_weight(), 0); + res.end_timer(); }), CHECK("value range validation", [](Test::Result& res) { + res.start_timer(); Kyberish_Poly p; res.confirm("value range validation (all zero)", p.ct_validate_value_range(0, 1)); @@ -257,10 +270,12 @@ std::vector test_polynomial_basics() { p[11] = -1; res.confirm("value range validation", !p.ct_validate_value_range(0, 1)); + res.end_timer(); }), CHECK("value range validation for polynomial vectors", [](Test::Result& res) { + res.start_timer(); Kyberish_PolyVec pv(3); res.confirm("value range validation (all zero)", pv.ct_validate_value_range(0, 1)); @@ -274,6 +289,7 @@ std::vector test_polynomial_basics() { pv[0][11] = -1; res.confirm("value range validation", !pv.ct_validate_value_range(0, 1)); + res.end_timer(); }), }; } @@ -310,6 +326,7 @@ class DeterministicXOF : public Botan::XOF { template void random_encoding_roundtrips(Test::Result& res, Botan::RandomNumberGenerator& rng, size_t expected_encoding_bits) { + res.start_timer(); using Poly = Botan::CRYSTALS::Polynomial; using T = typename Trait::T; @@ -336,6 +353,7 @@ void random_encoding_roundtrips(Test::Result& res, Botan::RandomNumberGenerator& p_unpacked -= p; res.test_eq("p = unpack(pack(p))", p_unpacked.hamming_weight(), 0); + res.end_timer(); } } // namespace @@ -370,6 +388,7 @@ std::vector test_encoding() { return { CHECK("encode polynomial coefficients into buffer", [&](Test::Result& res) { + res.start_timer(); // value range is about 3 bits Kyberish_Poly p1; for(size_t i = 0; i < p1.size(); ++i) { @@ -397,10 +416,12 @@ std::vector test_encoding() { Botan::BufferStuffer stuffer3(buffer3); Botan::CRYSTALS::pack<512>(p2, stuffer3, [](int16_t x) -> uint16_t { return x * 2; }); res.test_eq("10 bit encoding", buffer3, tenbitencoding); + res.end_timer(); }), CHECK("decode polynomial coefficients from buffer", [&](Test::Result& res) { + res.start_timer(); Kyberish_Poly p1; Botan::BufferSlicer slicer1(threebitencoding); Botan::CRYSTALS::unpack<6>(p1, slicer1); @@ -424,10 +445,12 @@ std::vector test_encoding() { for(size_t i = 0; i < p3.size(); ++i) { res.test_is_eq("decoded 10-bit coefficient with mapping", p3[i], i); } + res.end_timer(); }), CHECK("decode polynomial coefficients from XOF", [&](Test::Result& res) { + res.start_timer(); Kyberish_Poly p1; DeterministicXOF xof1(threebitencoding); Botan::CRYSTALS::unpack<6>(p1, xof1); @@ -448,10 +471,12 @@ std::vector test_encoding() { for(size_t i = 0; i < p3.size(); ++i) { res.test_is_eq("decoded 10-bit coefficient with mapping", p3[i], i); } + res.end_timer(); }), CHECK("random encoding roundtrips (0 to x)", [](Test::Result& res) { + res.start_timer(); auto rng = Test::new_rng("CRYSTALS encoding roundtrips"); random_encoding_roundtrips(res, *rng, 2); random_encoding_roundtrips(res, *rng, 3); @@ -461,10 +486,12 @@ std::vector test_encoding() { random_encoding_roundtrips(res, *rng, 6); random_encoding_roundtrips(res, *rng, 8); random_encoding_roundtrips(res, *rng, 11); + res.end_timer(); }), CHECK("random encoding roundtrips (Kyber ranges)", [](Test::Result& res) { + res.start_timer(); auto rng = Test::new_rng("CRYSTALS encoding roundtrips as used in kyber"); random_encoding_roundtrips(res, *rng, 1); random_encoding_roundtrips(res, *rng, 4); @@ -472,10 +499,12 @@ std::vector test_encoding() { random_encoding_roundtrips(res, *rng, 10); random_encoding_roundtrips(res, *rng, 11); random_encoding_roundtrips(res, *rng, 12); + res.end_timer(); }), CHECK("random encoding roundtrips (Dilithium ranges)", [](Test::Result& res) { + res.start_timer(); using Dilithiumish_Trait = Mock_Trait; auto rng = Test::new_rng("CRYSTALS encoding roundtrips as used in kyber"); @@ -495,6 +524,7 @@ std::vector test_encoding() { random_encoding_roundtrips(res, *rng, 3); random_encoding_roundtrips(res, *rng, 4); random_encoding_roundtrips(res, *rng, 13); + res.end_timer(); }), }; } @@ -523,21 +553,26 @@ std::vector test_bounded_xof() { return { CHECK("zero bound is reached immediately", [](Test::Result& result) { + result.start_timer(); Mocked_Bounded_XOF<0> xof; result.test_throws("output<1> throws", [&xof]() { xof.next_byte(); }); + result.end_timer(); }), CHECK("bounded XOF with small bound", [](Test::Result& result) { + result.start_timer(); Mocked_Bounded_XOF<3> xof; result.test_is_eq("next_byte() returns 0", xof.next_byte(), uint8_t(0)); result.test_is_eq("next_byte() returns 1", xof.next_byte(), uint8_t(1)); result.test_is_eq("next_byte() returns 2", xof.next_byte(), uint8_t(2)); result.test_throws("next_byte() throws", [&xof]() { xof.next_byte(); }); + result.end_timer(); }), CHECK("filter bytes", [](Test::Result& result) { + result.start_timer(); auto filter = [](uint8_t byte) { //test return byte % 2 == 1; @@ -547,10 +582,12 @@ std::vector test_bounded_xof() { result.test_is_eq("next_byte() returns 1", xof.next_byte(filter), uint8_t(1)); result.test_is_eq("next_byte() returns 3", xof.next_byte(filter), uint8_t(3)); result.test_throws("next_byte() throws", [&]() { xof.next_byte(filter); }); + result.end_timer(); }), CHECK("map bytes", [](Test::Result& result) { + result.start_timer(); auto map = [](auto bytes) { return Botan::load_be(bytes); }; Mocked_Bounded_XOF<17> xof; @@ -559,10 +596,12 @@ std::vector test_bounded_xof() { result.test_is_eq("next returns 0x08090A0B", xof.next<4>(map), uint32_t(0x08090A0B)); result.test_is_eq("next returns 0x0C0D0E0F", xof.next<4>(map), uint32_t(0x0C0D0E0F)); result.test_throws("next() throws", [&]() { xof.next<4>(map); }); + result.end_timer(); }), CHECK("map and filter bytes", [](Test::Result& result) { + result.start_timer(); auto map = [](std::array bytes) -> uint32_t { return bytes[0] + bytes[1] + bytes[2]; }; auto filter = [](uint32_t number) { return number < 50; }; @@ -573,6 +612,7 @@ std::vector test_bounded_xof() { result.test_is_eq("next returns 30", xof.next<3>(map, filter), uint32_t(30)); result.test_is_eq("next returns 39", xof.next<3>(map, filter), uint32_t(39)); result.test_throws("next() throws", [&]() { xof.next<3>(map, filter); }); + result.end_timer(); }), }; } diff --git a/src/tests/test_ct_utils.cpp b/src/tests/test_ct_utils.cpp index 65ae9bd8e97..d9f539c7371 100644 --- a/src/tests/test_ct_utils.cpp +++ b/src/tests/test_ct_utils.cpp @@ -14,6 +14,7 @@ class CT_Mask_Tests final : public Test { public: std::vector run() override { Test::Result result("CT::Mask"); + result.start_timer(); result.test_eq_sz("CT::is_zero8", Botan::CT::Mask::is_zero(0).value(), 0xFF); result.test_eq_sz("CT::is_zero8", Botan::CT::Mask::is_zero(1).value(), 0x00); @@ -71,6 +72,7 @@ class CT_Mask_Tests final : public Test { } } + result.end_timer(); return {result}; } }; @@ -81,6 +83,7 @@ class CT_Choice_Tests final : public Test { public: std::vector run() override { Test::Result result("CT::Choice"); + result.start_timer(); result.test_eq("CT::Choice::yes", Botan::CT::Choice::yes().as_bool(), true); result.test_eq("CT::Choice::no", Botan::CT::Choice::no().as_bool(), false); @@ -90,6 +93,7 @@ class CT_Choice_Tests final : public Test { test_choice_from_int("uint32_t", result); test_choice_from_int("uint64_t", result); + result.end_timer(); return {result}; } @@ -113,6 +117,7 @@ class CT_Option_Tests final : public Test { public: std::vector run() override { Test::Result result("CT::Option"); + result.start_timer(); class Val { public: @@ -142,6 +147,7 @@ class CT_Option_Tests final : public Test { test_ct_option(result, 42424242, 23232323); test_ct_option(result, 4242424242424242, 2323232323232323); + result.end_timer(); return {result}; } @@ -192,16 +198,19 @@ std::vector test_higher_level_ct_poison() { return { CHECK("custom poisonable object", [](Test::Result& result) { + result.start_timer(); Poisonable p; result.confirm("not poisoned", p.poisoned == false); Botan::CT::poison(p); result.confirm("poisoned", p.poisoned == true); Botan::CT::unpoison(p); result.confirm("unpoisoned", p.poisoned == false); + result.end_timer(); }), CHECK("poison multiple objects", [](Test::Result& result) { + result.start_timer(); // template is useless, but p1, p2, and p3 are different types and we // want to make sure that poison_all/unpoison_all can deal with that. Poisonable p1; @@ -213,10 +222,12 @@ std::vector test_higher_level_ct_poison() { result.confirm("all poisoned", p1.poisoned && p2.poisoned && p3.poisoned); Botan::CT::unpoison_all(p1, p2, p3); result.confirm("all unpoisoned", !p1.poisoned && !p2.poisoned && !p3.poisoned); + result.end_timer(); }), CHECK("scoped poison", [](Test::Result& result) { + result.start_timer(); // template is useless, but p1, p2, and p3 are different types and we // want to make sure that poison_all/unpoison_all can deal with that. Poisonable p1; @@ -231,10 +242,13 @@ std::vector test_higher_level_ct_poison() { } result.confirm("unpoisoned", !p1.poisoned && !p2.poisoned && !p3.poisoned); + result.end_timer(); }), CHECK("poison a range of poisonable objects", [](Test::Result& result) { + result.start_timer(); + auto is_poisoned = [](const auto& p) { return p.poisoned; }; std::vector> v(10); @@ -245,10 +259,14 @@ std::vector test_higher_level_ct_poison() { Botan::CT::unpoison_range(v); result.confirm("all unpoisoned", std::none_of(v.begin(), v.end(), is_poisoned)); + + result.end_timer(); }), CHECK("poison a poisonable objects with driveby_poison", [](Test::Result& result) { + result.start_timer(); + Poisonable p; result.confirm("not poisoned", p.poisoned == false); Poisonable p_poisoned = @@ -257,6 +275,8 @@ std::vector test_higher_level_ct_poison() { Poisonable p_unpoisoned = Botan::CT::driveby_unpoison( std::move(p_poisoned)); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) result.confirm("unpoisoned", p_unpoisoned.poisoned == false); + + result.end_timer(); }), }; } diff --git a/src/tests/test_dh.cpp b/src/tests/test_dh.cpp index 0060e361342..97939da5834 100644 --- a/src/tests/test_dh.cpp +++ b/src/tests/test_dh.cpp @@ -61,6 +61,7 @@ class Diffie_Hellman_KAT_Tests final : public PK_Key_Agreement_Test { std::vector run_final_tests() override { Test::Result result("DH negative tests"); + result.start_timer(); const BigInt g("2"); const BigInt p("58458002095536094658683755258523362961421200751439456159756164191494576279467"); @@ -81,6 +82,7 @@ class Diffie_Hellman_KAT_Tests final : public PK_Key_Agreement_Test { kas->derive_key(16, BigInt::encode(too_small)); }); + result.end_timer(); return {result}; } }; diff --git a/src/tests/test_dilithium.cpp b/src/tests/test_dilithium.cpp index 94e277f1f6d..efec84b59ba 100644 --- a/src/tests/test_dilithium.cpp +++ b/src/tests/test_dilithium.cpp @@ -33,6 +33,7 @@ class Dilithium_KAT_Tests : public Text_Based_Test { Test::Result run_one_test(const std::string& name, const VarMap& vars) override { Test::Result result(name); + result.start_timer(); // read input from test file const auto ref_seed = vars.get_req_bin("Seed"); @@ -75,6 +76,7 @@ class Dilithium_KAT_Tests : public Text_Based_Test { verifier.update(ref_msg.data(), ref_msg.size()); result.confirm("signature verifies", verifier.check_signature(signature.data(), signature.size())); + result.end_timer(); return result; } }; @@ -131,20 +133,23 @@ class DilithiumRoundtripTests final : public Test { static Test::Result run_roundtrip( const char* test_name, Botan::DilithiumMode mode, bool randomized, size_t strength, size_t psid) { Test::Result result(test_name); + result.start_timer(); + if(!mode.is_available()) { result.note_missing(mode.to_string()); + result.end_timer(); return result; } auto rng = Test::new_rng(test_name); - auto sign = [randomized, &rng](const auto& private_key, const auto& msg) { + auto sign = [randomized, &rng, &result](const auto& private_key, const auto& msg) { const std::string param = (randomized) ? "Randomized" : "Deterministic"; auto signer = Botan::PK_Signer(private_key, *rng, param); return signer.sign_message(msg, *rng); }; - auto verify = [](const auto& public_key, const auto& msg, const auto& signature) { + auto verify = [&result](const auto& public_key, const auto& msg, const auto& signature) { auto verifier = Botan::PK_Verifier(public_key, ""); verifier.update(msg); return verifier.check_signature(signature); @@ -206,6 +211,7 @@ class DilithiumRoundtripTests final : public Test { result.confirm("verification with generic private key", verify(*generic_privkey_decoded, msgvec, sig_before_codec)); + result.end_timer(); return result; } diff --git a/src/tests/test_dl_group.cpp b/src/tests/test_dl_group.cpp index 4a4da58a072..61a289bf734 100644 --- a/src/tests/test_dl_group.cpp +++ b/src/tests/test_dl_group.cpp @@ -31,6 +31,8 @@ class DL_Group_Tests final : public Test { private: static Test::Result test_dl_errors() { Test::Result result("DL_Group errors"); + result.start_timer(); + result.test_throws("Uninitialized", "DL_Group uninitialized", []() { Botan::DL_Group dl; dl.get_p(); @@ -45,11 +47,13 @@ class DL_Group_Tests final : public Test { }); #endif + result.end_timer(); return result; } static Test::Result test_dl_encoding() { Test::Result result("DL_Group encoding"); + result.start_timer(); const Botan::DL_Group orig("modp/ietf/1024"); @@ -75,6 +79,7 @@ class DL_Group_Tests final : public Test { // no q in PKCS #3 format result.test_eq("Same g in X9.57 decoding", group3.get_g(), orig.get_g()); + result.end_timer(); return result; } }; diff --git a/src/tests/test_dlies.cpp b/src/tests/test_dlies.cpp index 61ea1a0fa5f..df3e6a5208a 100644 --- a/src/tests/test_dlies.cpp +++ b/src/tests/test_dlies.cpp @@ -98,6 +98,7 @@ BOTAN_REGISTER_TEST("pubkey", "dlies", DLIES_KAT_Tests); Test::Result test_xor() { Test::Result result("DLIES XOR"); + result.start_timer(); std::vector kdfs = {"KDF2(SHA-512)", "KDF1-18033(SHA-512)"}; std::vector macs = {"HMAC(SHA-512)", "CMAC(AES-128)"}; @@ -150,6 +151,7 @@ Test::Result test_xor() { } } + result.end_timer(); return result; } diff --git a/src/tests/test_ec_group.cpp b/src/tests/test_ec_group.cpp index 170747205ae..a6c8084342b 100644 --- a/src/tests/test_ec_group.cpp +++ b/src/tests/test_ec_group.cpp @@ -353,6 +353,7 @@ BOTAN_REGISTER_TEST("pubkey", "ec_group", EC_Group_Tests); Test::Result test_decoding_with_seed() { Test::Result result("ECC Unit"); + result.start_timer(); const auto secp384r1_with_seed = Botan::EC_Group::from_PEM(Test::read_data_file("x509/ecc/secp384r1_seed.pem")); @@ -362,11 +363,13 @@ Test::Result test_decoding_with_seed() { result.test_eq("P-384 prime", secp384r1_with_seed.get_p(), secp384r1.get_p()); + result.end_timer(); return result; } Test::Result test_mixed_points() { Test::Result result("ECC Unit"); + result.start_timer(); const auto secp256r1 = Botan::EC_Group::from_name("secp256r1"); const auto secp384r1 = Botan::EC_Group::from_name("secp384r1"); @@ -375,11 +378,14 @@ Test::Result test_mixed_points() { const Botan::EC_Point& G384 = secp384r1.get_base_point(); result.test_throws("Mixing points from different groups", [&] { Botan::EC_Point p = G256 + G384; }); + + result.end_timer(); return result; } Test::Result test_basic_operations() { Test::Result result("ECC Unit"); + result.start_timer(); // precalculation const auto secp160r1 = Botan::EC_Group::from_name("secp160r1"); @@ -410,11 +416,13 @@ Test::Result test_basic_operations() { simpleMult.get_affine_y(), Botan::BigInt("56841378500012376527163928510402662349220202981")); + result.end_timer(); return result; } Test::Result test_enc_dec_compressed_160() { Test::Result result("ECC Unit"); + result.start_timer(); // Test for compressed conversion (02/03) 160bit const auto secp160r1 = Botan::EC_Group::from_name("secp160r1"); @@ -423,11 +431,14 @@ Test::Result test_enc_dec_compressed_160() { const std::vector sv_result = p.encode(Botan::EC_Point_Format::Compressed); result.test_eq("result", sv_result, G_comp); + + result.end_timer(); return result; } Test::Result test_enc_dec_compressed_256() { Test::Result result("ECC Unit"); + result.start_timer(); const auto group = Botan::EC_Group::from_name("secp256r1"); @@ -438,11 +449,14 @@ Test::Result test_enc_dec_compressed_256() { std::vector sv_result = p_G.encode(Botan::EC_Point_Format::Compressed); result.test_eq("compressed_256", sv_result, sv_G_secp_comp); + + result.end_timer(); return result; } Test::Result test_enc_dec_uncompressed_112() { Test::Result result("ECC Unit"); + result.start_timer(); // Test for uncompressed conversion (04) 112bit @@ -468,11 +482,14 @@ Test::Result test_enc_dec_uncompressed_112() { std::vector sv_result = p_G.encode(Botan::EC_Point_Format::Uncompressed); result.test_eq("uncompressed_112", sv_result, sv_G_secp_uncomp); + + result.end_timer(); return result; } Test::Result test_enc_dec_uncompressed_521() { Test::Result result("ECC Unit"); + result.start_timer(); // Test for uncompressed conversion(04) with big values(521 bit) @@ -488,11 +505,14 @@ Test::Result test_enc_dec_uncompressed_521() { std::vector sv_result = p_G.encode(Botan::EC_Point_Format::Uncompressed); result.test_eq("expected", sv_result, sv_G_secp_uncomp); + + result.end_timer(); return result; } Test::Result test_ecc_registration() { Test::Result result("ECC registration"); + result.start_timer(); // secp128r1 const Botan::BigInt p("0xfffffffdffffffffffffffffffffffff"); @@ -512,11 +532,13 @@ Test::Result test_ecc_registration() { result.test_eq("Group registration worked", group.get_p(), p); + result.end_timer(); return result; } Test::Result test_ec_group_from_params() { Test::Result result("EC_Group from params"); + result.start_timer(); Botan::EC_Group::clear_registered_curve_data(); @@ -535,12 +557,14 @@ Test::Result test_ec_group_from_params() { // This whole test can be removed once explicit curve support is removed Botan::EC_Group reg_group(p, a, b, g_x, g_y, order, 1); result.confirm("Group has correct OID", reg_group.get_curve_oid() == oid); - + + result.end_timer(); return result; } Test::Result test_ec_group_bad_registration() { Test::Result result("EC_Group registering non-match"); + result.start_timer(); Botan::EC_Group::clear_registered_curve_data(); @@ -562,11 +586,13 @@ Test::Result test_ec_group_bad_registration() { result.test_success("Got expected exception"); } + result.end_timer(); return result; } Test::Result test_ec_group_duplicate_orders() { Test::Result result("EC_Group with duplicate group order"); + result.start_timer(); Botan::EC_Group::clear_registered_curve_data(); @@ -594,6 +620,7 @@ Test::Result test_ec_group_duplicate_orders() { const auto other_group = Botan::EC_Group::from_OID(secp160r1); result.confirm("Group has correct OID", other_group.get_curve_oid() == secp160r1); + result.end_timer(); return result; } diff --git a/src/tests/test_ecies.cpp b/src/tests/test_ecies.cpp index 72c7d0fc1bd..52f8a286c27 100644 --- a/src/tests/test_ecies.cpp +++ b/src/tests/test_ecies.cpp @@ -243,6 +243,7 @@ BOTAN_REGISTER_TEST("pubkey", "ecies", ECIES_Tests); Test::Result test_other_key_not_set() { Test::Result result("ECIES other key not set"); + result.start_timer(); auto rng = Test::new_rng("ecies_other_key_not_set"); @@ -269,11 +270,13 @@ Test::Result test_other_key_not_set() { result.test_throws("encrypt not possible without setting other public key", [&ecies_enc, &rng]() { ecies_enc.encrypt(std::vector(8), *rng); }); + result.end_timer(); return result; } Test::Result test_kdf_not_found() { Test::Result result("ECIES kdf not found"); + result.start_timer(); auto rng = Test::new_rng("ecies_kdf_not_found"); @@ -300,11 +303,13 @@ Test::Result test_kdf_not_found() { ecies_enc.encrypt(std::vector(8), *rng); }); + result.end_timer(); return result; } Test::Result test_mac_not_found() { Test::Result result("ECIES mac not found"); + result.start_timer(); auto rng = Test::new_rng("ecies_mac_not_found"); @@ -331,11 +336,13 @@ Test::Result test_mac_not_found() { ecies_enc.encrypt(std::vector(8), *rng); }); + result.end_timer(); return result; } Test::Result test_cipher_not_found() { Test::Result result("ECIES cipher not found"); + result.start_timer(); auto rng = Test::new_rng("ecies_cipher_not_found"); @@ -362,11 +369,13 @@ Test::Result test_cipher_not_found() { ecies_enc.encrypt(std::vector(8), *rng); }); + result.end_timer(); return result; } Test::Result test_system_params_short_ctor() { Test::Result result("ECIES short system params ctor"); + result.start_timer(); auto rng = Test::new_rng("ecies_params_short_ctor"); @@ -405,11 +414,13 @@ Test::Result test_system_params_short_ctor() { check_encrypt_decrypt(result, private_key, other_private_key, ecies_params, iv, label, plaintext, ciphertext, *rng); + result.end_timer(); return result; } Test::Result test_ciphertext_too_short() { Test::Result result("ECIES ciphertext too short"); + result.start_timer(); const auto domain = Botan::EC_Group::from_name("secp521r1"); const Botan::BigInt private_key_value( @@ -435,6 +446,7 @@ Test::Result test_ciphertext_too_short() { result.test_throws("ciphertext too short", [&ecies_dec]() { ecies_dec.decrypt(Botan::hex_decode("0401519EAA0489FF9D51E98E4C22349A")); }); + result.end_timer(); return result; } diff --git a/src/tests/test_ed25519.cpp b/src/tests/test_ed25519.cpp index bc48d4eb68d..ccefd3b8ebb 100644 --- a/src/tests/test_ed25519.cpp +++ b/src/tests/test_ed25519.cpp @@ -81,6 +81,7 @@ class Ed25519_Curdle_Format_Tests final : public Test { "-----END PUBLIC KEY-----\n"; Test::Result result("Ed25519 CURDLE format"); + result.start_timer(); Botan::DataSource_Memory priv_data(priv_key_str); auto priv_key = Botan::PKCS8::load_key(priv_data); @@ -98,6 +99,7 @@ class Ed25519_Curdle_Format_Tests final : public Test { verifier.update("message"); result.confirm("Signature valid", verifier.check_signature(sig)); + result.end_timer(); return std::vector{result}; } }; diff --git a/src/tests/test_ed448.cpp b/src/tests/test_ed448.cpp index 799561f842f..40d5969667d 100644 --- a/src/tests/test_ed448.cpp +++ b/src/tests/test_ed448.cpp @@ -123,6 +123,8 @@ class Ed448_Utils_Test final : public Test { Test::Result test_reduce_mod_L() { Test::Result result("Reduce mod L test"); + result.start_timer(); + std::array full = {0}; std::memset(full.data(), 0xff, full.size()); @@ -136,6 +138,7 @@ class Ed448_Utils_Test final : public Test { result.test_is_eq("Reduce mod L result", res, ref); } + result.end_timer(); return result; } diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index 1cf4d91ebb2..713f922fe50 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -1384,6 +1384,7 @@ class FFI_AEAD_Test final : public FFI_Test { for(const std::string& aead : aeads) { Test::Result result(Botan::fmt("AEAD {}", aead)); + result.start_timer(); if(!TEST_FFI_INIT(botan_cipher_init, (&cipher_encrypt, aead.c_str(), BOTAN_CIPHER_INIT_FLAG_ENCRYPT))) { continue; @@ -1593,6 +1594,7 @@ class FFI_AEAD_Test final : public FFI_Test { TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt)); + result.end_timer(); merged_result.merge(result, true /* ignore names */); } } diff --git a/src/tests/test_filters.cpp b/src/tests/test_filters.cpp index edce80138ae..12d4b400b8d 100644 --- a/src/tests/test_filters.cpp +++ b/src/tests/test_filters.cpp @@ -60,6 +60,7 @@ class Filter_Tests final : public Test { private: static Test::Result test_secqueue() { Test::Result result("SecureQueue"); + result.start_timer(); try { Botan::SecureQueue queue_a; @@ -90,11 +91,13 @@ class Filter_Tests final : public Test { result.test_failure("SecureQueue", e.what()); } + result.end_timer(); return result; } static Test::Result test_data_src_sink() { Test::Result result("DataSink"); + result.start_timer(); #if defined(BOTAN_HAS_CODEC_FILTERS) std::ostringstream oss; @@ -117,11 +120,13 @@ class Filter_Tests final : public Test { result.test_eq("output string", oss.str(), "efghAAAACC"); #endif + result.end_timer(); return result; } static Test::Result test_data_src_sink_flush() { Test::Result result("DataSinkFlush"); + result.start_timer(); #if defined(BOTAN_HAS_CODEC_FILTERS) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) @@ -152,11 +157,13 @@ class Filter_Tests final : public Test { result.test_failure("Failed to remove temporary file at conclusion of test"); } #endif + result.end_timer(); return result; } static Test::Result test_pipe_io() { Test::Result result("Pipe I/O operators"); + result.start_timer(); #if defined(BOTAN_HAS_CODEC_FILTERS) Botan::Pipe pipe(new Botan::Hex_Encoder); @@ -177,11 +184,13 @@ class Filter_Tests final : public Test { result.test_eq("output string2", oss.str(), "4142434441414141"); #endif + result.end_timer(); return result; } static Test::Result test_pipe_errors() { Test::Result result("Pipe"); + result.start_timer(); Botan::Pipe pipe; @@ -248,11 +257,13 @@ class Filter_Tests final : public Test { pipe.prepend(nullptr); // ignored pipe.pop(); // empty pipe, so ignored + result.end_timer(); return result; } static Test::Result test_pipe_mac() { Test::Result result("Pipe"); + result.start_timer(); #if defined(BOTAN_HAS_CODEC_FILTERS) && defined(BOTAN_HAS_HMAC) && defined(BOTAN_HAS_SHA2_32) const Botan::SymmetricKey key("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); @@ -275,11 +286,14 @@ class Filter_Tests final : public Test { result.test_eq("MAC 2", pipe.read_all_as_string(1), "LhPnfEG+0rk+Ej6y"); result.test_eq("MAC 3", pipe.read_all_as_string(2), "e7NoVbtudgU0QiCZ"); #endif + + result.end_timer(); return result; } static Test::Result test_pipe_hash() { Test::Result result("Pipe"); + result.start_timer(); #if defined(BOTAN_HAS_SHA2_32) // unrelated test of popping a chain @@ -328,11 +342,13 @@ class Filter_Tests final : public Test { result.test_eq("Expected CRC32d", pipe.read_all(1), "99841F60"); #endif #endif + result.end_timer(); return result; } static Test::Result test_pipe_cfb() { Test::Result result("Pipe CFB"); + result.start_timer(); #if defined(BOTAN_HAS_BLOWFISH) && defined(BOTAN_HAS_MODE_CFB) && defined(BOTAN_HAS_CODEC_FILTERS) @@ -388,11 +404,13 @@ class Filter_Tests final : public Test { } #endif + result.end_timer(); return result; } static Test::Result test_pipe_cbc() { Test::Result result("Pipe CBC"); + result.start_timer(); #if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC) && defined(BOTAN_HAS_CIPHER_MODE_PADDING) Botan::Cipher_Mode_Filter* cipher = new Botan::Cipher_Mode_Filter( @@ -452,11 +470,14 @@ class Filter_Tests final : public Test { result.test_eq("Cipher roundtrip", zeros_in, zeros_out); #endif + + result.end_timer(); return result; } static Test::Result test_pipe_compress() { Test::Result result("Pipe compress zlib"); + result.start_timer(); #if defined(BOTAN_HAS_ZLIB) @@ -486,11 +507,13 @@ class Filter_Tests final : public Test { result.test_eq("Decompressed ok", decomp, input_str); #endif + result.end_timer(); return result; } static Test::Result test_pipe_compress_bzip2() { Test::Result result("Pipe compress bzip2"); + result.start_timer(); #if defined(BOTAN_HAS_BZIP2) @@ -519,11 +542,13 @@ class Filter_Tests final : public Test { result.test_eq("Decompressed ok", decomp, input_str); #endif + result.end_timer(); return result; } static Test::Result test_pipe_codec() { Test::Result result("Pipe"); + result.start_timer(); #if defined(BOTAN_HAS_CODEC_FILTERS) Botan::Pipe pipe(new Botan::Base64_Encoder); @@ -596,11 +621,13 @@ class Filter_Tests final : public Test { "68657820656e636f\n64696e6720746869\n7320737472696e67\n"); #endif + result.end_timer(); return result; } static Test::Result test_pipe_stream() { Test::Result result("Pipe CTR"); + result.start_timer(); #if defined(BOTAN_HAS_CTR_BE) && defined(BOTAN_HAS_AES) Botan::Keyed_Filter* aes = nullptr; @@ -620,11 +647,14 @@ class Filter_Tests final : public Test { pipe.process_msg("ABCDEF"); result.test_eq("Ciphertext", pipe.read_all(1), "8E72F1153514"); #endif + + result.end_timer(); return result; } static Test::Result test_fork() { Test::Result result("Filter Fork"); + result.start_timer(); #if defined(BOTAN_HAS_SHA2_32) && defined(BOTAN_HAS_SHA2_64) Botan::Pipe pipe(new Botan::Fork(new Botan::Hash_Filter("SHA-256"), new Botan::Hash_Filter("SHA-512-256"))); @@ -637,11 +667,14 @@ class Filter_Tests final : public Test { result.test_eq("Hash 2", pipe.read_all(1), "610480FFA82F24F6926544B976FE387878E3D973C03DFD591C2E9896EFB903E0"); result.test_eq("Hash 1", pipe.read_all(0), "C00862D1C6C1CF7C1B49388306E7B3C1BB79D8D6EC978B41035B556DBB3797DF"); #endif + + result.end_timer(); return result; } static Test::Result test_chain() { Test::Result result("Filter Chain"); + result.start_timer(); #if defined(BOTAN_HAS_CODEC_FILTERS) && defined(BOTAN_HAS_SHA2_32) && defined(BOTAN_HAS_SHA2_64) @@ -666,11 +699,13 @@ class Filter_Tests final : public Test { result.test_eq("Hash 2", pipe.read_all_as_string(1), "610480FFA82F24F6926544B976FE387878E3D9"); #endif + result.end_timer(); return result; } static Test::Result test_pipe_fd_io() { Test::Result result("Pipe file descriptor IO"); + result.start_timer(); #if defined(BOTAN_HAS_PIPE_UNIXFD_IO) && defined(BOTAN_HAS_CODEC_FILTERS) int fd[2]; @@ -695,11 +730,13 @@ class Filter_Tests final : public Test { result.test_eq("IO through Unix pipe works", dec, "hi chappy"); #endif + result.end_timer(); return result; } static Test::Result test_threaded_fork() { Test::Result result("Threaded_Fork"); + result.start_timer(); #if defined(BOTAN_HAS_THREAD_UTILS) && defined(BOTAN_HAS_CODEC_FILTERS) && defined(BOTAN_HAS_SHA2_32) Botan::Pipe pipe(new Botan::Threaded_Fork(new Botan::Hex_Encoder, new Botan::Base64_Encoder)); @@ -737,6 +774,7 @@ class Filter_Tests final : public Test { "Output", pipe.read_all(2 + i), "327AD8055223F5926693D8BEA40F7B35BDEEB535647DFB93F464E40EA01939A9"); } #endif + result.end_timer(); return result; } }; diff --git a/src/tests/test_frodokem.cpp b/src/tests/test_frodokem.cpp index 4968bfceaa8..16a71441479 100644 --- a/src/tests/test_frodokem.cpp +++ b/src/tests/test_frodokem.cpp @@ -96,6 +96,7 @@ std::vector test_frodo_roundtrips() { } Botan::FrodoKEMConstants consts(mode); Test::Result& result = results.emplace_back("FrodoKEM roundtrip: " + m.to_string()); + result.start_timer(); Botan::FrodoKEM_PrivateKey sk1(*rng, mode); Botan::FrodoKEM_PublicKey pk1(sk1.public_key_bits(), mode); @@ -136,6 +137,7 @@ std::vector test_frodo_roundtrips() { short_encaps_value.pop_back(); dec1.decrypt(short_encaps_value, 0); }); + result.end_timer(); } return results; diff --git a/src/tests/test_gf2m.cpp b/src/tests/test_gf2m.cpp index 4977e29ac09..8f7f4e34b66 100644 --- a/src/tests/test_gf2m.cpp +++ b/src/tests/test_gf2m.cpp @@ -29,6 +29,7 @@ class GF2m_Tests final : public Test { private: static Test::Result test_gf_overflow() { Test::Result result("GF2m"); + result.start_timer(); /* * This is testing one specific case where an overflow @@ -57,6 +58,7 @@ class GF2m_Tests final : public Test { } } } + result.end_timer(); return result; } }; diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp index 2bcf731fe37..77386d26965 100644 --- a/src/tests/test_hash.cpp +++ b/src/tests/test_hash.cpp @@ -21,6 +21,8 @@ class Invalid_Hash_Name_Tests final : public Test { public: std::vector run() override { Test::Result result("Invalid HashFunction names"); + result.start_timer(); + test_invalid_name(result, "NonExistentHash"); test_invalid_name(result, "Blake2b(9)", "Bad output bits size for BLAKE2b"); test_invalid_name(result, "Comb4P(MD5,MD5)", "Comb4P: Must use two distinct hashes"); @@ -28,6 +30,7 @@ class Invalid_Hash_Name_Tests final : public Test { test_invalid_name(result, "Keccak-1600(160)", "Keccak_1600: Invalid output length 160"); test_invalid_name(result, "SHA-3(160)", "SHA_3: Invalid output length 160"); + result.end_timer(); return {result}; } @@ -67,6 +70,7 @@ class Hash_Function_Tests final : public Text_Based_Test { const std::vector expected = vars.get_req_bin("Out"); Test::Result result(algo); + result.start_timer(); const std::vector providers = possible_providers(algo); @@ -152,6 +156,7 @@ class Hash_Function_Tests final : public Text_Based_Test { } } + result.end_timer(); return result; } }; @@ -172,6 +177,7 @@ class Hash_NIST_MonteCarlo_Tests final : public Text_Based_Test { const std::vector expected = vars.get_req_bin("Output"); Test::Result result("NIST Monte Carlo " + algo); + result.start_timer(); const std::vector providers = possible_providers(algo); @@ -215,6 +221,7 @@ class Hash_NIST_MonteCarlo_Tests final : public Text_Based_Test { result.test_eq("Output is expected", input[2], expected); } + result.end_timer(); return result; } }; @@ -247,6 +254,7 @@ class Hash_LongRepeat_Tests final : public Text_Based_Test { const std::vector expected = vars.get_req_bin("Digest"); Test::Result result("Long input " + algo); + result.start_timer(); const std::vector providers = possible_providers(algo); @@ -283,6 +291,7 @@ class Hash_LongRepeat_Tests final : public Text_Based_Test { result.test_eq("Output is expected", output, expected); } + result.end_timer(); return result; } }; @@ -294,12 +303,16 @@ BOTAN_REGISTER_TEST("hash", "hash_rep", Hash_LongRepeat_Tests); /// negative tests for Truncated_Hash, positive tests are implemented in hash/truncated.vec Test::Result hash_truncation_negative_tests() { Test::Result result("hash truncation parameter validation"); + result.start_timer(); + result.test_throws("truncation to zero", [] { Botan::HashFunction::create("Truncated(SHA-256,0)"); }); result.test_throws("cannot output more bits than the underlying hash", [] { Botan::HashFunction::create("Truncated(SHA-256,257)"); }); auto unobtainable = Botan::HashFunction::create("Truncated(NonExistentHash-256,128)"); result.confirm("non-existent hashes are not created", unobtainable == nullptr); + + result.end_timer(); return result; } diff --git a/src/tests/test_hash_id.cpp b/src/tests/test_hash_id.cpp index b1ef4b25695..49e0a3ee83c 100644 --- a/src/tests/test_hash_id.cpp +++ b/src/tests/test_hash_id.cpp @@ -42,6 +42,7 @@ class PKCS_HashID_Test final : public Test { const size_t hash_len = hash_info.second; Test::Result result("PKCS hash id for " + hash_fn); + result.start_timer(); try { const std::vector pkcs_id = Botan::pkcs_hash_id(hash_fn); @@ -71,6 +72,7 @@ class PKCS_HashID_Test final : public Test { result.test_failure(e.what()); } + result.end_timer(); results.push_back(result); } diff --git a/src/tests/test_hss_lms.cpp b/src/tests/test_hss_lms.cpp index 6c43c1d7a91..32638c7f14e 100644 --- a/src/tests/test_hss_lms.cpp +++ b/src/tests/test_hss_lms.cpp @@ -27,6 +27,7 @@ std::vector test_hss_lms_params_parsing() { return { CHECK("HSS Parameter Parsing", [&](Test::Result& result) { + result.start_timer(); result.test_no_throw("no throw", [&] { Botan::HSS_LMS_Params hss_params("SHA-256,HW(5,1),HW(25,8)"); @@ -48,6 +49,7 @@ std::vector test_hss_lms_params_parsing() { second_lms_params.lmots_params().algorithm_type(), Botan::LMOTS_Algorithm_Type::SHA256_N32_W8); }); + result.end_timer(); }), }; @@ -124,6 +126,7 @@ class HSS_LMS_Key_Generation_Test final : public PK_Key_Generation_Test { class HSS_LMS_Negative_Tests final : public Test { Test::Result test_flipped_signature_bits() { Test::Result result("HSS-LMS - flipped signature bits"); + result.start_timer(); auto sk = Botan::create_private_key("HSS-LMS", Test::rng(), "Truncated(SHA-256,192),HW(5,8)"); @@ -146,11 +149,13 @@ class HSS_LMS_Negative_Tests final : public Test { }); } + result.end_timer(); return result; } Test::Result test_too_short_signature() { Test::Result result("HSS-LMS"); + result.start_timer(); auto sk = Botan::create_private_key("HSS-LMS", Test::rng(), "Truncated(SHA-256,192),HW(5,8)"); @@ -171,11 +176,13 @@ class HSS_LMS_Negative_Tests final : public Test { }); } + result.end_timer(); return result; } Test::Result test_too_short_private_key() { Test::Result result("HSS-LMS"); + result.start_timer(); // HSS_LMS_PublicKey::key_length() auto sk = Botan::create_private_key("HSS-LMS", Test::rng(), "Truncated(SHA-256,192),HW(5,8)"); @@ -192,11 +199,14 @@ class HSS_LMS_Negative_Tests final : public Test { BOTAN_UNUSED(key); }); } + + result.end_timer(); return result; } Test::Result test_too_short_public_key() { Test::Result result("HSS-LMS"); + result.start_timer(); // HSS_LMS_PublicKey::key_length() auto sk = Botan::create_private_key("HSS-LMS", Test::rng(), "Truncated(SHA-256,192),HW(5,8)"); @@ -213,6 +223,8 @@ class HSS_LMS_Negative_Tests final : public Test { BOTAN_UNUSED(key); }); } + + result.end_timer(); return result; } @@ -238,6 +250,7 @@ class HSS_LMS_Statefulness_Test final : public Test { Test::Result test_sig_changes_state() { Test::Result result("HSS-LMS"); + result.start_timer(); auto sk = Botan::HSS_LMS_PrivateKey(Test::rng(), "Truncated(SHA-256,192),HW(5,8),HW(5,8)"); Botan::PK_Signer signer(sk, Test::rng(), ""); @@ -266,11 +279,13 @@ class HSS_LMS_Statefulness_Test final : public Test { "Next signature uses the new index.", Botan::HSS_Signature::from_bytes_or_throw(sig_1).bottom_sig().q() == Botan::LMS_Tree_Node_Idx(1)); + result.end_timer(); return result; } Test::Result test_max_sig_count() { Test::Result result("HSS-LMS"); + result.start_timer(); uint64_t total_sig_count = 32; auto sk = create_private_key_with_idx(total_sig_count - 1); @@ -285,6 +300,7 @@ class HSS_LMS_Statefulness_Test final : public Test { result.test_throws("Cannot sign with exhausted key.", [&]() { signer.sign_message(mes, Test::rng()); }); result.confirm("Still zero remaining signatures.", sk.remaining_operations() == uint64_t(0)); + result.end_timer(); return result; } @@ -297,6 +313,7 @@ class HSS_LMS_Statefulness_Test final : public Test { class HSS_LMS_Missing_API_Test final : public Test { std::vector run() final { Test::Result result("HSS-LMS"); + result.start_timer(); // HSS_LMS_PublicKey::key_length() auto sk = Botan::create_private_key("HSS-LMS", Test::rng(), "SHA-256,HW(10,4)"); @@ -319,6 +336,7 @@ class HSS_LMS_Missing_API_Test final : public Test { // HSS_LMS_Signature_Operation::hash_function() result.test_eq("PK_Signer should report the hash of the key", signer.hash_function(), "SHA-256"); + result.end_timer(); return {result}; } }; diff --git a/src/tests/test_keccak_helpers.cpp b/src/tests/test_keccak_helpers.cpp index 103aab96a73..d08e9dcddb8 100644 --- a/src/tests/test_keccak_helpers.cpp +++ b/src/tests/test_keccak_helpers.cpp @@ -58,6 +58,7 @@ std::vector keccak_helpers() { return { CHECK("keccak_int_encoding_size()", [](Test::Result& result) { + result.start_timer(); result.test_eq("keccak_int_encoding_size(0)", encode_size(0), 2); result.test_eq("keccak_int_encoding_size(255)", encode_size(0xFF), 2); result.test_eq("keccak_int_encoding_size(256)", encode_size(0xFF + 1), 3); @@ -65,10 +66,12 @@ std::vector keccak_helpers() { result.test_eq("keccak_int_encoding_size(65.536)", encode_size(0xFFFF + 1), 4); result.test_eq("keccak_int_encoding_size(16.777.215)", encode_size(0xFFFFFF), 4); result.test_eq("keccak_int_encoding_size(16.777.216)", encode_size(0xFFFFFF + 1), 5); + result.end_timer(); }), CHECK("keccak_int_left_encode()", [](Test::Result& result) { + result.start_timer(); result.test_is_eq("left_encode(0)", left_encode(result, 0), hex("0100")); result.test_is_eq("left_encode(1)", left_encode(result, 1), hex("0101")); result.test_is_eq("left_encode(255)", left_encode(result, 255), hex("01FF")); @@ -79,10 +82,12 @@ std::vector keccak_helpers() { result.test_is_eq("left_encode(16.777.215)", left_encode(result, 0xFFFFFF), hex("03FFFFFF")); result.test_is_eq("left_encode(16.777.216)", left_encode(result, 0xFFFFFF + 1), hex("0401000000")); result.test_is_eq("left_encode(287.454.020)", left_encode(result, 0x11223344), hex("0411223344")); + result.end_timer(); }), CHECK("keccak_int_right_encode()", [](Test::Result& result) { + result.start_timer(); result.test_is_eq("right_encode(0)", right_encode(result, 0), hex("0001")); result.test_is_eq("right_encode(1)", right_encode(result, 1), hex("0101")); result.test_is_eq("right_encode(255)", right_encode(result, 255), hex("FF01")); @@ -93,11 +98,14 @@ std::vector keccak_helpers() { result.test_is_eq("right_encode(16.777.215)", right_encode(result, 0xFFFFFF), hex("FFFFFF03")); result.test_is_eq("right_encode(16.777.216)", right_encode(result, 0xFFFFFF + 1), hex("0100000004")); result.test_is_eq("right_encode(287.454.020)", right_encode(result, 0x11223344), hex("1122334404")); + result.end_timer(); }), CHECK( "keccak_absorb_padded_strings_encoding() with one byte string (std::vector<>)", [](Test::Result& result) { + result.start_timer(); + std::vector out; const auto padmod = 136 /* SHAKE-256 byte rate */; @@ -112,11 +120,14 @@ std::vector keccak_helpers() { "0120" /* left_encode(n.size() * 8) */ "4B4D4143" /* "KMAC" */ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); + result.end_timer(); }), CHECK( "keccak_absorb_padded_strings_encoding() with two byte strings (std::vector<>)", [](Test::Result& result) { + result.start_timer(); + std::vector out; const auto padmod = 136 /* SHAKE-256 byte rate */; @@ -137,6 +148,7 @@ std::vector keccak_helpers() { "020420" /* left_encode(s.size() * 8) */ "546869732069732061206c6f6e672073616c742c2074686174206973206c6f6e676572207468616e2031323820627974657320696e206f7264657220746f2066696c6c2075702074686520666972737420726f756e64206f6620746865204b656363616b207065726d75746174696f6e2e20546861742073686f756c6420646f2069742e" "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); + result.end_timer(); }), #if defined(BOTAN_HAS_SHAKE_XOF) @@ -144,6 +156,8 @@ std::vector keccak_helpers() { CHECK( "keccak_absorb_padded_strings_encoding() with one byte string", [](Test::Result& result) { + result.start_timer(); + std::vector out(32); const auto xof = Botan::XOF::create_or_throw("SHAKE-256"); const auto padmod = xof->block_size(); @@ -159,9 +173,12 @@ std::vector keccak_helpers() { "0120" /* left_encode(n.size() * 8) */ "4B4D4143" /* "KMAC" */ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"))); + result.end_timer(); }), CHECK("keccak_absorb_padded_strings_encoding() with two byte strings", [](Test::Result& result) { + result.start_timer(); + std::vector out(32); const auto xof = Botan::XOF::create_or_throw("SHAKE-256"); const auto padmod = xof->block_size(); @@ -183,6 +200,7 @@ std::vector keccak_helpers() { "020420" /* left_encode(s.size() * 8) */ "546869732069732061206c6f6e672073616c742c2074686174206973206c6f6e676572207468616e2031323820627974657320696e206f7264657220746f2066696c6c2075702074686520666972737420726f756e64206f6620746865204b656363616b207065726d75746174696f6e2e20546861742073686f756c6420646f2069742e" "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"))); + result.end_timer(); }), #endif diff --git a/src/tests/test_kyber.cpp b/src/tests/test_kyber.cpp index 3ea8217cae6..e6768865b73 100644 --- a/src/tests/test_kyber.cpp +++ b/src/tests/test_kyber.cpp @@ -40,6 +40,7 @@ class KYBER_Tests final : public Test { public: static Test::Result run_kyber_test(const char* test_name, Botan::KyberMode mode, size_t strength, size_t psid) { Test::Result result(test_name); + result.start_timer(); if(!mode.is_available()) { result.note_missing(mode.to_string()); @@ -97,6 +98,7 @@ class KYBER_Tests final : public Test { const auto key_alice_try2 = dec.decrypt(kem_result.encapsulated_shared_key(), 0 /* no KDF */, empty_salt); result.test_eq("shared secrets are equal", key_alice_try2, kem_result.shared_key()); + result.end_timer(); return result; } @@ -229,6 +231,7 @@ class Kyber_Encoding_Test : public Text_Based_Test { Test::Result run_one_test(const std::string& algo_name, const VarMap& vars) override { Test::Result result("kyber_encodings"); + result.start_timer(); const auto mode = Botan::KyberMode(algo_name); const auto pk_raw = Botan::hex_decode(vars.get_req_str("PublicRaw")); @@ -257,6 +260,7 @@ class Kyber_Encoding_Test : public Text_Based_Test { result.test_eq("pk's encoding of pk", skr->public_key_bits(), pk_raw); } + result.end_timer(); return result; } }; diff --git a/src/tests/test_modes.cpp b/src/tests/test_modes.cpp index c61325af5e4..d3a4f12080d 100644 --- a/src/tests/test_modes.cpp +++ b/src/tests/test_modes.cpp @@ -249,6 +249,7 @@ class Cipher_Mode_IV_Carry_Tests final : public Test { private: static Test::Result test_cbc_iv_carry() { Test::Result result("CBC IV carry"); + result.start_timer(); #if defined(BOTAN_HAS_MODE_CBC) && defined(BOTAN_HAS_AES) std::unique_ptr enc( @@ -292,11 +293,14 @@ class Cipher_Mode_IV_Carry_Tests final : public Test { result.test_eq("Third plaintext", msg3, "49562063617272796F76657232"); #endif + result.end_timer(); return result; } static Test::Result test_cfb_iv_carry() { Test::Result result("CFB IV carry"); + result.start_timer(); + #if defined(BOTAN_HAS_MODE_CFB) && defined(BOTAN_HAS_AES) std::unique_ptr enc( Botan::Cipher_Mode::create("AES-128/CFB(8)", Botan::Cipher_Dir::Encryption)); @@ -339,11 +343,14 @@ class Cipher_Mode_IV_Carry_Tests final : public Test { dec->finish(msg3); result.test_eq("Third plaintext", msg3, "012345"); #endif + result.end_timer(); return result; } static Test::Result test_ctr_iv_carry() { Test::Result result("CTR IV carry"); + result.start_timer(); + #if defined(BOTAN_HAS_CTR_BE) && defined(BOTAN_HAS_AES) std::unique_ptr enc( @@ -391,6 +398,7 @@ class Cipher_Mode_IV_Carry_Tests final : public Test { } } #endif + result.end_timer(); return result; } }; diff --git a/src/tests/test_mp.cpp b/src/tests/test_mp.cpp index dd976c22c54..501f98ca3a1 100644 --- a/src/tests/test_mp.cpp +++ b/src/tests/test_mp.cpp @@ -32,6 +32,7 @@ class MP_Unit_Tests final : public Test { private: static Result test_cnd_add() { Result result("bigint_cnd_add"); + result.start_timer(); const Botan::word max = ~static_cast(0); @@ -47,12 +48,13 @@ class MP_Unit_Tests final : public Test { result.test_int_eq(c, 1, "Carry"); // TODO more tests - + result.end_timer(); return result; } static Result test_cnd_sub() { Result result("bigint_cnd_sub"); + result.start_timer(); Botan::word a = 2; Botan::word b = 3; @@ -66,11 +68,13 @@ class MP_Unit_Tests final : public Test { result.test_int_eq(a, ~static_cast(0), "Sub"); result.test_int_eq(c, 1, "Borrow"); + result.end_timer(); return result; } static Result test_cnd_abs() { Result result("bigint_cnd_abs"); + result.start_timer(); const Botan::word max = Botan::WordInfo::max; @@ -96,11 +100,13 @@ class MP_Unit_Tests final : public Test { result.test_int_eq(x2[0], 1, "Abs"); result.test_int_eq(x2[1], 0, "Abs"); + result.end_timer(); return result; } static Result test_cnd_swap() { Result result("bigint_cnd_swap"); + result.start_timer(); // null with zero length is ok Botan::bigint_cnd_swap(0, nullptr, nullptr, 0); @@ -129,6 +135,7 @@ class MP_Unit_Tests final : public Test { } result.test_int_eq(y5[4], 9, "Not touched"); + result.end_timer(); return result; } }; diff --git a/src/tests/test_name_constraint.cpp b/src/tests/test_name_constraint.cpp index cf529c9e8a2..2a7556bc397 100644 --- a/src/tests/test_name_constraint.cpp +++ b/src/tests/test_name_constraint.cpp @@ -52,6 +52,7 @@ class Name_Constraint_Tests final : public Test { Botan::X509_Certificate sub(Test::data_file("x509/name_constraint/" + std::get<1>(t))); Botan::Certificate_Store_In_Memory trusted; Test::Result result("X509v3 Name Constraints: " + std::get<1>(t)); + result.start_timer(); trusted.add_certificate(root); Botan::Path_Validation_Result path_result = Botan::x509_path_validate( @@ -62,6 +63,7 @@ class Name_Constraint_Tests final : public Test { } result.test_eq("validation result", path_result.result_string(), std::get<3>(t)); + result.end_timer(); results.emplace_back(result); } diff --git a/src/tests/test_ocsp.cpp b/src/tests/test_ocsp.cpp index 4d0612817b9..7973db7b4e3 100644 --- a/src/tests/test_ocsp.cpp +++ b/src/tests/test_ocsp.cpp @@ -32,6 +32,7 @@ class OCSP_Tests final : public Test { static Test::Result test_response_parsing() { Test::Result result("OCSP response parsing"); + result.start_timer(); // Simple parsing tests const std::vector ocsp_input_paths = { @@ -52,11 +53,13 @@ class OCSP_Tests final : public Test { result.confirm("parsing exposes correct status code", resp.status() == Botan::OCSP::Response_Status_Code::Try_Later); + result.end_timer(); return result; } static Test::Result test_response_certificate_access() { Test::Result result("OCSP response certificate access"); + result.start_timer(); try { Botan::OCSP::Response resp1(Test::read_binary_data_file("x509/ocsp/resp1.der")); @@ -76,11 +79,13 @@ class OCSP_Tests final : public Test { result.test_failure("Parsing failed", e.what()); } + result.end_timer(); return result; } static Test::Result test_request_encoding() { Test::Result result("OCSP request encoding"); + result.start_timer(); const Botan::X509_Certificate end_entity(Test::data_file("x509/ocsp/gmail.pem")); const Botan::X509_Certificate issuer(Test::data_file("x509/ocsp/google_g2.pem")); @@ -101,11 +106,13 @@ class OCSP_Tests final : public Test { const Botan::OCSP::Request req2(issuer, BigInt::from_bytes(end_entity.serial_number())); result.test_eq("Encoded OCSP request", req2.base64_encode(), expected_request); + result.end_timer(); return result; } static Test::Result test_response_find_signing_certificate() { Test::Result result("OCSP response finding signature certificates"); + result.start_timer(); const std::optional nullopt_cert; @@ -151,11 +158,13 @@ class OCSP_Tests final : public Test { randombit_alt_resp_ocsp.find_signing_certificate(randombit_ca, trusted_responders.get()), std::optional(randombit_alt_resp_cert)); + result.end_timer(); return result; } static Test::Result test_response_verification_with_next_update_without_max_age() { Test::Result result("OCSP request check with next_update w/o max_age"); + result.start_timer(); auto ee = load_test_X509_cert("x509/ocsp/randombit.pem"); auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem"); @@ -188,11 +197,13 @@ class OCSP_Tests final : public Test { check_ocsp(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED); + result.end_timer(); return result; } static Test::Result test_response_verification_with_next_update_with_max_age() { Test::Result result("OCSP request check with next_update with max_age"); + result.start_timer(); auto ee = load_test_X509_cert("x509/ocsp/randombit.pem"); auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem"); @@ -228,11 +239,13 @@ class OCSP_Tests final : public Test { check_ocsp(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED); + result.end_timer(); return result; } static Test::Result test_response_verification_without_next_update_with_max_age() { Test::Result result("OCSP request check w/o next_update with max_age"); + result.start_timer(); auto ee = load_test_X509_cert("x509/ocsp/patrickschmidt.pem"); auto ca = load_test_X509_cert("x509/ocsp/bdrive_encryption.pem"); @@ -266,11 +279,13 @@ class OCSP_Tests final : public Test { check_ocsp(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_IS_TOO_OLD); + result.end_timer(); return result; } static Test::Result test_response_verification_without_next_update_without_max_age() { Test::Result result("OCSP request check w/o next_update w/o max_age"); + result.start_timer(); auto ee = load_test_X509_cert("x509/ocsp/patrickschmidt.pem"); auto ca = load_test_X509_cert("x509/ocsp/bdrive_encryption.pem"); @@ -301,11 +316,13 @@ class OCSP_Tests final : public Test { check_ocsp(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD); + result.end_timer(); return result; } static Test::Result test_response_verification_softfail() { Test::Result result("OCSP request softfail check"); + result.start_timer(); auto ee = load_test_X509_cert("x509/ocsp/randombit.pem"); auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem"); @@ -330,12 +347,14 @@ class OCSP_Tests final : public Test { } } + result.end_timer(); return result; } #if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS) static Test::Result test_online_request() { Test::Result result("OCSP online check"); + result.start_timer(); auto cert = load_test_X509_cert("x509/ocsp/digicert-ecdsa-int.pem"); auto trust_root = load_test_X509_cert("x509/ocsp/digicert-root.pem"); @@ -359,12 +378,14 @@ class OCSP_Tests final : public Test { } } + result.end_timer(); return result; } #endif static Test::Result test_response_verification_with_additionally_trusted_responder() { Test::Result result("OCSP response with user-defined (additional) responder certificate"); + result.start_timer(); // OCSP response is signed by 3rd party responder certificate that is // not included in the OCSP response itself @@ -396,11 +417,13 @@ class OCSP_Tests final : public Test { ocsp.verify_signature(responder), Botan::Certificate_Status_Code::OCSP_SIGNATURE_OK); + result.end_timer(); return result; } static Test::Result test_responder_cert_with_nocheck_extension() { Test::Result result("BDr's OCSP response contains certificate featuring NoCheck extension"); + result.start_timer(); auto ocsp = load_test_OCSP_resp("x509/ocsp/bdr-ocsp-resp.der"); const bool contains_cert_with_nocheck = @@ -410,6 +433,7 @@ class OCSP_Tests final : public Test { result.confirm("Contains NoCheck extension", contains_cert_with_nocheck); + result.end_timer(); return result; } diff --git a/src/tests/test_octetstring.cpp b/src/tests/test_octetstring.cpp index 9462faa8b3b..c8f98b37aa9 100644 --- a/src/tests/test_octetstring.cpp +++ b/src/tests/test_octetstring.cpp @@ -16,37 +16,44 @@ namespace { Test::Result test_from_rng() { Test::Result result("OctetString"); + result.start_timer(); auto rng = Test::new_rng("octet_string_from_rng"); Botan::OctetString os(*rng, 32); result.test_eq("length is 32 bytes", os.size(), 32); + result.end_timer(); return result; } Test::Result test_from_hex() { Test::Result result("OctetString"); + result.start_timer(); Botan::OctetString os("0123456789ABCDEF"); result.test_eq("length is 8 bytes", os.size(), 8); + result.end_timer(); return result; } Test::Result test_from_byte() { Test::Result result("OctetString"); + result.start_timer(); auto rng = Test::new_rng("octet_string_from_byte"); auto rand_bytes = rng->random_vec(8); Botan::OctetString os(rand_bytes.data(), rand_bytes.size()); result.test_eq("length is 8 bytes", os.size(), 8); + result.end_timer(); return result; } Test::Result test_odd_parity() { Test::Result result("OctetString"); + result.start_timer(); Botan::OctetString os("FFFFFFFFFFFFFFFF"); os.set_odd_parity(); @@ -58,20 +65,24 @@ Test::Result test_odd_parity() { Botan::OctetString expected2("EFCBDA4FAB987F62"); result.test_eq("odd parity set correctly", os2, expected2); + result.end_timer(); return result; } Test::Result test_to_string() { Test::Result result("OctetString"); + result.start_timer(); Botan::OctetString os("0123456789ABCDEF"); result.test_eq("OctetString::to_string() returns correct string", os.to_string(), "0123456789ABCDEF"); + result.end_timer(); return result; } Test::Result test_xor() { Test::Result result("OctetString"); + result.start_timer(); Botan::OctetString os1("0000000000000000"); Botan::OctetString os2("FFFFFFFFFFFFFFFF"); @@ -91,11 +102,13 @@ Test::Result test_xor() { Botan::OctetString expected("FEDCBA9876543210"); result.test_eq("OctetString XOR operations works as expected", xor_result, expected); + result.end_timer(); return result; } Test::Result test_equality() { Test::Result result("OctetString"); + result.start_timer(); const Botan::OctetString os1("0000000000000000"); const Botan::OctetString& os1_copy = os1; @@ -106,11 +119,13 @@ Test::Result test_equality() { result.confirm("OctetString equality operations works as expected", os2 == os2_copy); result.confirm("OctetString equality operations works as expected", os1 != os2); + result.end_timer(); return result; } Test::Result test_append() { Test::Result result("OctetString"); + result.start_timer(); Botan::OctetString os1("0000"); Botan::OctetString os2("FFFF"); @@ -120,6 +135,7 @@ Test::Result test_append() { result.test_eq("OctetString append operations works as expected", append_result, expected); + result.end_timer(); return result; } diff --git a/src/tests/test_oid.cpp b/src/tests/test_oid.cpp index c0dae3279e4..2cc4cff7dc0 100644 --- a/src/tests/test_oid.cpp +++ b/src/tests/test_oid.cpp @@ -47,14 +47,17 @@ Test::Result test_OID_to_string() { Botan::OID oid{1, 2, 1000, 1001, 1002000}; Test::Result result("OID::to_string"); + result.start_timer(); result.test_eq("OID::to_string behaves as we expect", oid.to_string(), "1.2.1000.1001.1002000"); + result.end_timer(); return result; } Test::Result test_oid_registration() { Test::Result result("OID add"); + result.start_timer(); const std::string name = "botan-test-oid1"; const Botan::OID oid("1.3.6.1.4.1.25258.1000.1"); @@ -67,11 +70,13 @@ Test::Result test_oid_registration() { result.test_eq("name of OID matches expected", oid.to_formatted_string(), name); + result.end_timer(); return result; } Test::Result test_add_and_lookup() { Test::Result result("OID add with redundant entries"); + result.start_timer(); const std::string name = "botan-test-oid2"; const std::string name2 = "botan-test-oid2.2"; @@ -107,6 +112,7 @@ Test::Result test_add_and_lookup() { result.test_success("Registration of second name to the same OID fails"); } + result.end_timer(); return result; } @@ -144,6 +150,7 @@ class OID_Encoding_Tests : public Text_Based_Test { const auto expected_der = vars.get_req_bin("DER"); Test::Result result("OID DER encode/decode"); + result.start_timer(); const Botan::OID oid(oid_str); @@ -166,6 +173,7 @@ class OID_Encoding_Tests : public Text_Based_Test { result.test_failure("Decoding OID failed", e.what()); } + result.end_timer(); return result; } }; @@ -180,6 +188,7 @@ class OID_Invalid_Encoding_Tests : public Text_Based_Test { const auto test_der = vars.get_req_bin("DER"); Test::Result result("OID DER decode invalid"); + result.start_timer(); try { Botan::BER_Decoder dec(test_der); @@ -191,6 +200,7 @@ class OID_Invalid_Encoding_Tests : public Text_Based_Test { result.test_success("Rejected invalid OID with Decoding_Error"); } + result.end_timer(); return result; } }; diff --git a/src/tests/test_os_utils.cpp b/src/tests/test_os_utils.cpp index 9b44a409403..87a7c7ff25c 100644 --- a/src/tests/test_os_utils.cpp +++ b/src/tests/test_os_utils.cpp @@ -46,6 +46,7 @@ class OS_Utils_Tests final : public Test { private: static Test::Result test_get_process_id() { Test::Result result("OS::get_process_id"); + result.start_timer(); uint32_t pid1 = Botan::OS::get_process_id(); uint32_t pid2 = Botan::OS::get_process_id(); @@ -57,7 +58,7 @@ class OS_Utils_Tests final : public Test { #else result.test_ne("PID is non-zero on systems with processes", pid1, 0); #endif - + result.end_timer(); return result; } @@ -66,6 +67,7 @@ class OS_Utils_Tests final : public Test { const size_t max_repeats = 32; Test::Result result("OS::get_cpu_cycle_counter"); + result.start_timer(); const uint64_t proc_ts1 = Botan::OS::get_cpu_cycle_counter(); @@ -82,6 +84,7 @@ class OS_Utils_Tests final : public Test { result.test_lt("CPU cycle counter eventually changes value", counts, max_repeats); + result.end_timer(); return result; } @@ -90,6 +93,7 @@ class OS_Utils_Tests final : public Test { const size_t max_repeats = 128; Test::Result result("OS::get_high_resolution_clock"); + result.start_timer(); // TODO better tests const uint64_t hr_ts1 = Botan::OS::get_high_resolution_clock(); @@ -102,22 +106,26 @@ class OS_Utils_Tests final : public Test { result.test_lt("high resolution clock eventually changes value", counts, max_repeats); + result.end_timer(); return result; } static Test::Result test_get_cpu_numbers() { Test::Result result("OS::get_cpu_available"); + result.start_timer(); const size_t ta = Botan::OS::get_cpu_available(); result.test_gte("get_cpu_available is at least 1", ta, 1); + result.end_timer(); return result; } static Test::Result test_get_system_timestamp() { // TODO better tests Test::Result result("OS::get_system_timestamp_ns"); + result.start_timer(); uint64_t sys_ts1 = Botan::OS::get_system_timestamp_ns(); result.confirm("System timestamp value is never zero", sys_ts1 != 0); @@ -129,19 +137,23 @@ class OS_Utils_Tests final : public Test { result.confirm("System time moves forward", sys_ts1 <= sys_ts2); + result.end_timer(); return result; } static Test::Result test_memory_locking() { Test::Result result("OS memory locked pages"); + result.start_timer(); // TODO any tests... + result.end_timer(); return result; } static Test::Result test_cpu_instruction_probe() { Test::Result result("OS::run_cpu_instruction_probe"); + result.start_timer(); // OS::run_cpu_instruction_probe only implemented for Unix signals or Windows SEH @@ -194,6 +206,7 @@ class OS_Utils_Tests final : public Test { result.confirm("Result for function executing undefined opcode", crash_rc < 0); } + result.end_timer(); return result; } }; diff --git a/src/tests/test_otp.cpp b/src/tests/test_otp.cpp index 02ebfdfc304..c6f77f8cc3b 100644 --- a/src/tests/test_otp.cpp +++ b/src/tests/test_otp.cpp @@ -25,6 +25,7 @@ class HOTP_KAT_Tests final : public Text_Based_Test { Test::Result run_one_test(const std::string& hash_algo, const VarMap& vars) override { Test::Result result("HOTP " + hash_algo); + result.start_timer(); auto hash_test = Botan::HashFunction::create(hash_algo); if(!hash_test) { @@ -59,6 +60,7 @@ class HOTP_KAT_Tests final : public Text_Based_Test { result.test_eq("OTP verify result", otp_res.first, true); result.confirm("OTP verify next counter", otp_res.second == counter + 1); + result.end_timer(); return result; } }; @@ -73,6 +75,7 @@ class TOTP_KAT_Tests final : public Text_Based_Test { Test::Result run_one_test(const std::string& hash_algo, const VarMap& vars) override { Test::Result result("TOTP " + hash_algo); + result.start_timer(); auto hash_test = Botan::HashFunction::create(hash_algo); if(!hash_test) { @@ -99,6 +102,7 @@ class TOTP_KAT_Tests final : public Text_Based_Test { result.test_eq("TOTP verify time slip allowed", totp.verify_totp(otp, later_time, 1), true); result.test_eq("TOTP verify time slip out of range", totp.verify_totp(otp, too_late, 1), false); + result.end_timer(); return result; } diff --git a/src/tests/test_pbkdf.cpp b/src/tests/test_pbkdf.cpp index 77811dbdc8c..ab3fbcdfd16 100644 --- a/src/tests/test_pbkdf.cpp +++ b/src/tests/test_pbkdf.cpp @@ -253,6 +253,7 @@ class PGP_S2K_Iter_Test final : public Test { public: std::vector run() override { Test::Result result("PGP_S2K iteration encoding"); + result.start_timer(); // The maximum representable iteration count const size_t max_iter = 65011712; @@ -285,6 +286,7 @@ class PGP_S2K_Iter_Test final : public Test { last_enc = enc; } + result.end_timer(); return std::vector{result}; } }; diff --git a/src/tests/test_pem.cpp b/src/tests/test_pem.cpp index d8d3f2a855a..f59948d314c 100644 --- a/src/tests/test_pem.cpp +++ b/src/tests/test_pem.cpp @@ -16,6 +16,7 @@ class PEM_Tests : public Test { public: std::vector run() override { Test::Result result("PEM encoding"); + result.start_timer(); std::vector vec = {0, 1, 2, 3, 4}; @@ -42,6 +43,7 @@ class PEM_Tests : public Test { Botan::PEM_Code::decode_check_label(malformed_pem2, "BUNNY"); }); + result.end_timer(); return {result}; } }; diff --git a/src/tests/test_pk_pad.cpp b/src/tests/test_pk_pad.cpp index 3939ceb06dc..8d12f363f64 100644 --- a/src/tests/test_pk_pad.cpp +++ b/src/tests/test_pk_pad.cpp @@ -69,6 +69,7 @@ class EMSA_unit_tests final : public Test { public: std::vector run() override { Test::Result name_tests("EMSA_name_tests"); + name_tests.start_timer(); std::vector pads_need_hash = { #if BOTAN_HAS_EMSA_X931 @@ -135,6 +136,7 @@ class EMSA_unit_tests final : public Test { } } + name_tests.end_timer(); return {name_tests}; } }; diff --git a/src/tests/test_psk_db.cpp b/src/tests/test_psk_db.cpp index f97a0abb401..cf247ef7574 100644 --- a/src/tests/test_psk_db.cpp +++ b/src/tests/test_psk_db.cpp @@ -85,6 +85,7 @@ class PSK_DB_Tests final : public Test { private: static Test::Result test_psk_db() { Test::Result result("PSK_DB"); + result.start_timer(); const Botan::secure_vector zeros(32); Test_Map_PSK_Db db(zeros); @@ -135,6 +136,7 @@ class PSK_DB_Tests final : public Test { // test that redundant remove calls accepted db.remove("name2"); + result.end_timer(); return result; } @@ -157,6 +159,7 @@ class PSK_DB_Tests final : public Test { Test::Result test_psk_sql_db() { Test::Result result("PSK_DB SQL"); + result.start_timer(); const Botan::secure_vector zeros(32); const Botan::secure_vector not_zeros = this->rng().random_vec(32); @@ -226,6 +229,7 @@ class PSK_DB_Tests final : public Test { // test that redundant remove calls accepted db.remove("name2"); + result.end_timer(); return result; } #endif diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp index 455e3d22185..c82f702d591 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -275,6 +275,7 @@ std::vector PK_Sign_Verify_DER_Test::run() { auto privkey = key(); Test::Result result(algo_name() + "/" + padding + " signature sign/verify using DER format"); + result.start_timer(); for(const auto& provider : possible_providers(algo_name())) { std::unique_ptr signer; @@ -305,6 +306,7 @@ std::vector PK_Sign_Verify_DER_Test::run() { } } + result.end_timer(); return {result}; } diff --git a/src/tests/test_rng_behavior.cpp b/src/tests/test_rng_behavior.cpp index 2be03aed795..a452c1eb365 100644 --- a/src/tests/test_rng_behavior.cpp +++ b/src/tests/test_rng_behavior.cpp @@ -110,6 +110,7 @@ class Stateful_RNG_Tests : public Test { private: Test::Result test_reseed() { Test::Result result(rng_name() + " Reseed"); + result.start_timer(); // test reseed_interval is enforced Request_Counting_RNG counting_rng; @@ -140,11 +141,13 @@ class Stateful_RNG_Tests : public Test { result.test_eq("request exceeds output limit", counting_rng.randomize_count(), 9); } + result.end_timer(); return result; } Test::Result test_broken_entropy_input() { Test::Result result(rng_name() + " Broken Entropy Input"); + result.start_timer(); class Broken_Entropy_Source final : public Botan::Entropy_Source { public: @@ -210,11 +213,13 @@ class Stateful_RNG_Tests : public Test { rng_with_broken_rng_and_broken_es->random_vec(16); }); + result.end_timer(); return result; } Test::Result test_check_nonce() { Test::Result result(rng_name() + " Nonce Check"); + result.start_timer(); // make sure the nonce has at least security_strength bits auto rng = create_rng(nullptr, nullptr, 0); @@ -235,11 +240,13 @@ class Stateful_RNG_Tests : public Test { } } + result.end_timer(); return result; } Test::Result test_prediction_resistance() { Test::Result result(rng_name() + " Prediction Resistance"); + result.start_timer(); // set reseed_interval = 1, forcing a reseed for every RNG request Request_Counting_RNG counting_rng; @@ -254,11 +261,13 @@ class Stateful_RNG_Tests : public Test { rng->random_vec(16); result.test_eq("third request", counting_rng.randomize_count(), size_t(3)); + result.end_timer(); return result; } Test::Result test_fork_safety() { Test::Result result(rng_name() + " Fork Safety"); + result.start_timer(); #if defined(BOTAN_TARGET_OS_HAS_POSIX1) const size_t reseed_interval = 1024; @@ -339,11 +348,13 @@ class Stateful_RNG_Tests : public Test { ::_exit(0); // just in case /bin/true isn't available (sandbox?) } #endif + result.end_timer(); return result; } Test::Result test_randomize_with_ts_input() { Test::Result result(rng_name() + " Randomize With Timestamp Input"); + result.start_timer(); const size_t request_bytes = 64; const std::vector seed(128); @@ -369,11 +380,13 @@ class Stateful_RNG_Tests : public Test { result.test_ne("output differs due to different timestamp", output1, output2); + result.end_timer(); return result; } Test::Result test_input_output_edge_cases() { Test::Result result(rng_name() + " randomize"); + result.start_timer(); const std::vector seed(128); Fixed_Output_RNG fixed_output_rng(seed); @@ -388,6 +401,7 @@ class Stateful_RNG_Tests : public Test { result.test_success("RNG accepted input and output length"); } + result.end_timer(); return result; } }; @@ -421,6 +435,7 @@ class HMAC_DRBG_Unit_Tests final : public Stateful_RNG_Tests { Test::Result test_max_number_of_bytes_per_request() override { Test::Result result("HMAC_DRBG max_number_of_bytes_per_request"); + result.start_timer(); const std::string mac_string = "HMAC(SHA-256)"; @@ -464,11 +479,13 @@ class HMAC_DRBG_Unit_Tests final : public Stateful_RNG_Tests { rng.random_vec(1025); result.test_eq("17 requests", counting_rng.randomize_count(), 17); + result.end_timer(); return result; } Test::Result test_reseed_interval_limits() override { Test::Result result("HMAC_DRBG reseed_interval limits"); + result.start_timer(); const std::string mac_string = "HMAC(SHA-256)"; @@ -485,11 +502,13 @@ class HMAC_DRBG_Unit_Tests final : public Stateful_RNG_Tests { (static_cast(1) << 24) + 1); }); + result.end_timer(); return result; } Test::Result test_security_level() override { Test::Result result("HMAC_DRBG Security Level"); + result.start_timer(); std::vector approved_hash_fns{"SHA-1", "SHA-224", "SHA-256", "SHA-512/256", "SHA-384", "SHA-512"}; std::vector security_strengths{128, 192, 256, 256, 256, 256}; @@ -507,11 +526,13 @@ class HMAC_DRBG_Unit_Tests final : public Stateful_RNG_Tests { result.test_eq(hash_fn + " security level", rng.security_level(), security_strengths[i]); } + result.end_timer(); return result; } Test::Result test_reseed_kat() override { Test::Result result("HMAC_DRBG Reseed KAT"); + result.start_timer(); Request_Counting_RNG counting_rng; auto rng = make_rng(counting_rng, 2); @@ -535,6 +556,7 @@ class HMAC_DRBG_Unit_Tests final : public Stateful_RNG_Tests { result.test_eq("underlying RNG calls", counting_rng.randomize_count(), size_t(1)); result.test_eq("out after reseed", out, "2F8FCA696832C984781123FD64F4B20C7379A25C87AB29A21C9BF468B0081CE2"); + result.end_timer(); return result; } }; @@ -555,6 +577,8 @@ std::vector hmac_drbg_multiple_requests() { return {CHECK("bulk and split output without input", [&](auto& result) { + result.start_timer(); + auto rng1 = make_seeded_rng(2); auto rng2 = make_seeded_rng(2); @@ -569,10 +593,12 @@ std::vector hmac_drbg_multiple_requests() { result.test_eq("Output is equal, regardless bulk request", bulk, split1); + result.end_timer(); return result; }), CHECK("bulk and split output with input", [&](auto& result) { + result.start_timer(); auto rng1 = make_seeded_rng(3); auto rng2 = make_seeded_rng(3); @@ -590,6 +616,7 @@ std::vector hmac_drbg_multiple_requests() { result.test_eq("Output is equal, regardless bulk request", bulk, split); + result.end_timer(); return result; })}; } @@ -623,25 +650,32 @@ class ChaCha_RNG_Unit_Tests final : public Stateful_RNG_Tests { Test::Result test_security_level() override { Test::Result result("ChaCha_RNG Security Level"); + result.start_timer(); Botan::ChaCha_RNG rng; result.test_eq("Expected security level", rng.security_level(), size_t(256)); + result.end_timer(); return result; } Test::Result test_max_number_of_bytes_per_request() override { Test::Result result("ChaCha_RNG max_number_of_bytes_per_request"); + result.start_timer(); // ChaCha_RNG doesn't have this notion + result.end_timer(); return result; } Test::Result test_reseed_interval_limits() override { Test::Result result("ChaCha_RNG reseed_interval limits"); + result.start_timer(); // ChaCha_RNG doesn't apply any limits to reseed_interval + result.end_timer(); return result; } Test::Result test_reseed_kat() override { Test::Result result("ChaCha_RNG Reseed KAT"); + result.start_timer(); Request_Counting_RNG counting_rng; auto rng = make_rng(counting_rng, 2); @@ -663,6 +697,7 @@ class ChaCha_RNG_Unit_Tests final : public Stateful_RNG_Tests { result.test_eq("underlying RNG calls", counting_rng.randomize_count(), size_t(1)); result.test_eq("out after reseed", out, "F2CAE73F22684D5D773290B48FDCDA0E6C0661EBA0A854AFEC922832BDBB9C49"); + result.end_timer(); return result; } }; @@ -677,6 +712,7 @@ class AutoSeeded_RNG_Tests final : public Test { private: static Test::Result auto_rng_tests() { Test::Result result("AutoSeeded_RNG"); + result.start_timer(); Botan::Entropy_Sources no_entropy_for_you; Botan::Null_RNG null_rng; @@ -737,6 +773,7 @@ class AutoSeeded_RNG_Tests final : public Test { rng.clear(); + result.end_timer(); return result; } @@ -758,6 +795,7 @@ class System_RNG_Tests final : public Test { public: std::vector run() override { Test::Result result("System_RNG"); + result.start_timer(); Botan::System_RNG rng; @@ -790,6 +828,7 @@ class System_RNG_Tests final : public Test { std::memcmp(large_buf.data() + size32BitsMax, check_buf.data(), checkSize) != 0); } + result.end_timer(); return std::vector{result}; } }; @@ -804,6 +843,7 @@ class Processor_RNG_Tests final : public Test { public: std::vector run() override { Test::Result result("Processor_RNG"); + result.start_timer(); if(Botan::Processor_RNG::available()) { Botan::Processor_RNG rng; @@ -834,6 +874,7 @@ class Processor_RNG_Tests final : public Test { result.test_throws("Processor_RNG throws if instruction not available", []() { Botan::Processor_RNG rng; }); } + result.end_timer(); return std::vector{result}; } }; diff --git a/src/tests/test_roughtime.cpp b/src/tests/test_roughtime.cpp index ad25dbe61c5..67fa8f4bfd3 100644 --- a/src/tests/test_roughtime.cpp +++ b/src/tests/test_roughtime.cpp @@ -28,6 +28,7 @@ class Roughtime_Request_Tests final : public Text_Based_Test { Test::Result run_one_test(const std::string& type, const VarMap& vars) override { Test::Result result("Roughtime request"); + result.start_timer(); const auto nonce = vars.get_req_bin("Nonce"); const auto request_v = vars.get_req_bin("Request"); @@ -36,6 +37,7 @@ class Roughtime_Request_Tests final : public Text_Based_Test { result.test_eq( "encode", type == "Valid", request == Botan::typecast_copy>(request_v.data())); + result.end_timer(); return result; } }; @@ -51,6 +53,7 @@ class Roughtime_Response_Tests final : public Text_Based_Test { Test::Result run_one_test(const std::string& type, const VarMap& vars) override { Test::Result result("Roughtime response"); + result.start_timer(); const auto response_v = vars.get_req_bin("Response"); const auto nonce_bits = vars.has_key("Nonce") ? vars.get_opt_bin("Nonce") : std::vector(64); @@ -79,6 +82,7 @@ class Roughtime_Response_Tests final : public Text_Based_Test { result.confirm(e.what(), type == "Invalid"); } + result.end_timer(); return result; } }; @@ -92,6 +96,7 @@ class Roughtime_nonce_from_blind_Tests final : public Text_Based_Test { Test::Result run_one_test(const std::string& type, const VarMap& vars) override { Test::Result result("roughtime nonce_from_blind"); + result.start_timer(); const auto response = vars.get_req_bin("Response"); const auto blind = vars.get_req_bin("Blind"); @@ -100,6 +105,7 @@ class Roughtime_nonce_from_blind_Tests final : public Text_Based_Test { result.test_eq( "fail_validation", Botan::Roughtime::nonce_from_blind(response, blind) == nonce, type == "Valid"); + result.end_timer(); return result; } }; @@ -110,6 +116,7 @@ class Roughtime final : public Test { private: static Test::Result test_nonce(Botan::RandomNumberGenerator& rng) { Test::Result result("roughtime nonce"); + result.start_timer(); auto rand64 = Botan::unlock(rng.random_vec(64)); Botan::Roughtime::Nonce nonce_v(rand64); @@ -124,11 +131,13 @@ class Roughtime final : public Test { rand64.pop_back(); result.test_throws("vector undersize", [&rand64]() { Botan::Roughtime::Nonce nonce_v2(rand64); }); //size 63 + result.end_timer(); return result; } static Test::Result test_chain(Botan::RandomNumberGenerator& rng) { Test::Result result("roughtime chain"); + result.start_timer(); Botan::Roughtime::Chain c1; result.confirm("default constructed is empty", c1.links().empty() && c1.responses().empty()); @@ -177,11 +186,13 @@ class Roughtime final : public Test { "ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= eu9yhsJfVfguVSqGZdE8WKIxaBBM0ZG3Vmuc+IyZmG2UByDdwIFw6F4rZqmSFsBO85ljoVPz5bVPCOw== BQAAAEAAAABAAAAApAAAADwBAABTSUcAUEFUSFNSRVBDRVJUSU5EWBnGOEajOwPA6G7oL47seBP4C7eEpr57H43C2/fK/kMA0UGZVUdf4KNX8oxOK6JIcsbVk8qhghTwA70qtwpYmQkDAAAABAAAAAwAAABSQURJTUlEUFJPT1RAQg8AJrA8tEqPBQAqisiuAxgy2Pj7UJAiWbCdzGz1xcCnja3T+AqhC8fwpeIwW4GPy/vEb/awXW2DgSLKJfzWIAz+2lsR7t4UjNPvAgAAAEAAAABTSUcAREVMRes9Ch4X0HIw5KdOTB8xK4VDFSJBD/G9t7Et/CU7UW61OiTBXYYQTG2JekWZmGa0OHX1JPGG+APkpbsNw0BKUgYDAAAAIAAAACgAAABQVUJLTUlOVE1BWFR/9BWjpsWTQ1f6iUJea3EfZ1MkX3ftJiV3ABqNLpncFwAAAAAAAAAA//////////8AAAAA"); }); + result.end_timer(); return result; } static Test::Result test_server_information() { Test::Result result("roughtime server_information"); + result.start_timer(); const auto servers = Botan::Roughtime::servers_from_str( "Chainpoint-Roughtime ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= udp roughtime.chainpoint.org:2002\n" @@ -225,11 +236,13 @@ class Roughtime final : public Test { "A ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= tcp roughtime.chainpoint.org:2002"); }); + result.end_timer(); return result; } static Test::Result test_request_online(Botan::RandomNumberGenerator& rng) { Test::Result result("roughtime request online"); + result.start_timer(); Botan::Roughtime::Nonce nonce(rng); try { @@ -244,6 +257,8 @@ class Roughtime final : public Test { } catch(const std::exception& e) { result.test_failure(e.what()); } + + result.end_timer(); return result; } diff --git a/src/tests/test_rsa.cpp b/src/tests/test_rsa.cpp index ad5b3fb298b..f5f03398a6e 100644 --- a/src/tests/test_rsa.cpp +++ b/src/tests/test_rsa.cpp @@ -157,6 +157,7 @@ class RSA_Keygen_Bad_RNG_Test final : public Test { public: std::vector run() override { Test::Result result("RSA keygen with bad RNG"); + result.start_timer(); /* We don't need to count requests here; actually this test @@ -173,6 +174,7 @@ class RSA_Keygen_Bad_RNG_Test final : public Test { result.test_eq("Expected message", e.what(), "Internal error: RNG failure during RSA key generation"); } + result.end_timer(); return {result}; } }; @@ -181,6 +183,7 @@ class RSA_Blinding_Tests final : public Test { public: std::vector run() override { Test::Result result("RSA blinding"); + result.start_timer(); /* This test makes only sense with the base provider, else skip it. */ if(provider_filter({"base"}).empty()) { @@ -269,6 +272,7 @@ class RSA_Blinding_Tests final : public Test { #endif + result.end_timer(); return std::vector{result}; } }; diff --git a/src/tests/test_simd.cpp b/src/tests/test_simd.cpp index 14a3533f14a..d93862bd911 100644 --- a/src/tests/test_simd.cpp +++ b/src/tests/test_simd.cpp @@ -23,6 +23,7 @@ class SIMD_32_Tests final : public Test { public: std::vector run() override { Test::Result result("SIMD_4x32"); + result.start_timer(); if(Botan::CPUID::has_simd_32() == false) { result.test_note("Skipping SIMD_4x32 tests due to missing CPU support at runtime"); @@ -168,6 +169,7 @@ class SIMD_32_Tests final : public Test { result.test_is_eq( "roundtrip SIMD strong big-endian", Botan::store_be>(simd_be_strong), simd_be_in); + result.end_timer(); return {result}; } diff --git a/src/tests/test_sodium.cpp b/src/tests/test_sodium.cpp index 30da3523fd6..446d953a14c 100644 --- a/src/tests/test_sodium.cpp +++ b/src/tests/test_sodium.cpp @@ -48,6 +48,7 @@ class Sodium_API_Tests : public Test { private: static Test::Result sodium_malloc() { Test::Result result("sodium_malloc"); + result.start_timer(); void* p = Botan::Sodium::sodium_malloc(50); std::memset(p, 0xFF, 50); @@ -57,11 +58,13 @@ class Sodium_API_Tests : public Test { result.test_success("Didn't crash"); + result.end_timer(); return result; } static Test::Result sodium_utils() { Test::Result result("sodium math utils"); + result.start_timer(); result.confirm("sodium_is_zero", Botan::Sodium::sodium_is_zero(nullptr, 0) == 1); @@ -95,11 +98,13 @@ class Sodium_API_Tests : public Test { Botan::Sodium::sodium_add(b.data(), a.data(), a.size()); result.test_eq("sodium_add", b, "5350505050"); + result.end_timer(); return result; } static Test::Result randombytes_buf_deterministic() { Test::Result result("randombytes_buf_deterministic"); + result.start_timer(); const uint8_t seed[32] = {1, 0}; std::vector output(18); @@ -108,11 +113,13 @@ class Sodium_API_Tests : public Test { result.test_eq("output", output, "04069B5F37E82F91DC37FD5EB99F1A4124B1"); + result.end_timer(); return result; } static Test::Result hash_sha512() { Test::Result result("crypto_hash_sha512"); + result.start_timer(); std::vector output(64); Botan::Sodium::crypto_hash_sha512(output.data(), nullptr, 0); @@ -122,22 +129,26 @@ class Sodium_API_Tests : public Test { output, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + result.end_timer(); return result; } static Test::Result hash_sha256() { Test::Result result("crypto_hash_sha256"); + result.start_timer(); std::vector output(32); Botan::Sodium::crypto_hash_sha256(output.data(), nullptr, 0); result.test_eq("expected output", output, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + result.end_timer(); return result; } static Test::Result box_curve25519xsalsa20poly1305() { Test::Result result("crypto_box_curve25519xsalsa20poly1305"); + result.start_timer(); const std::vector seed(32); @@ -182,11 +193,13 @@ class Sodium_API_Tests : public Test { result.test_eq("recover1", recovered, ptext); + result.end_timer(); return result; } static Test::Result aead_chacha20poly1305() { Test::Result result("crypto_aead_chacha20poly1305"); + result.start_timer(); const std::vector key = Botan::hex_decode("0000000000000000000000000000000000000000000000000000000000000000"); @@ -272,11 +285,13 @@ class Sodium_API_Tests : public Test { result.test_eq("recovered", recovered, in); + result.end_timer(); return result; } static Test::Result aead_chacha20poly1305_ietf() { Test::Result result("crypto_aead_chacha20poly1305_ietf"); + result.start_timer(); const std::vector key = Botan::hex_decode("0000000000000000000000000000000000000000000000000000000000000000"); @@ -362,11 +377,13 @@ class Sodium_API_Tests : public Test { result.test_eq("recovered", recovered, in); + result.end_timer(); return result; } static Test::Result aead_xchacha20poly1305() { Test::Result result("crypto_aead_xchacha20poly1305"); + result.start_timer(); const std::vector key = Botan::hex_decode("0000000000000000000000000000000000000000000000000000000000000000"); @@ -452,11 +469,13 @@ class Sodium_API_Tests : public Test { result.test_eq("recovered", recovered, in); + result.end_timer(); return result; } static Test::Result auth_hmacsha512() { Test::Result result("crypto_auth_hmacsha512"); + result.start_timer(); const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); @@ -481,11 +500,13 @@ class Sodium_API_Tests : public Test { "invalid mac", Botan::Sodium::crypto_auth_hmacsha512_verify(mac.data(), in.data(), in.size(), key.data())); + result.end_timer(); return result; } static Test::Result auth_hmacsha512256() { Test::Result result("crypto_auth_hmacsha512256"); + result.start_timer(); const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); @@ -505,11 +526,13 @@ class Sodium_API_Tests : public Test { "invalid mac", Botan::Sodium::crypto_auth_hmacsha512256_verify(mac.data(), in.data(), in.size(), key.data())); + result.end_timer(); return result; } static Test::Result auth_hmacsha256() { Test::Result result("crypto_auth_hmacsha256"); + result.start_timer(); const std::vector key = Botan::hex_decode("0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20"); @@ -529,11 +552,13 @@ class Sodium_API_Tests : public Test { "invalid mac", Botan::Sodium::crypto_auth_hmacsha256_verify(mac.data(), in.data(), in.size(), key.data())); + result.end_timer(); return result; } static Test::Result auth_poly1305() { Test::Result result("crypto_onetimeauth_poly1305"); + result.start_timer(); const std::vector key(Botan::Sodium::crypto_onetimeauth_keybytes(), 0x42); const std::vector in(15); @@ -555,11 +580,13 @@ class Sodium_API_Tests : public Test { "invalid mac", Botan::Sodium::crypto_onetimeauth_poly1305_verify(mac.data(), in.data(), in.size(), key.data())); + result.end_timer(); return result; } static Test::Result shorthash_siphash24() { Test::Result result("crypto_shorthash_siphash24"); + result.start_timer(); const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F"); const std::vector in = Botan::hex_decode("000102030405060708090A0B0C0D0E"); @@ -569,11 +596,13 @@ class Sodium_API_Tests : public Test { result.test_eq("expected mac", mac, "E545BE4961CA29A1"); + result.end_timer(); return result; } static Test::Result secretbox_xsalsa20poly1305() { Test::Result result("secretbox_xsalsa20poly1305"); + result.start_timer(); const std::vector ptext(33); std::vector ctext(33); @@ -593,11 +622,13 @@ class Sodium_API_Tests : public Test { result.test_eq("decrypted", recovered, ptext); + result.end_timer(); return result; } static Test::Result secretbox_xsalsa20poly1305_detached() { Test::Result result("secretbox_xsalsa20poly1305"); + result.start_timer(); const std::vector ptext(33); const std::vector nonce(Botan::Sodium::crypto_secretbox_xsalsa20poly1305_noncebytes()); @@ -620,11 +651,13 @@ class Sodium_API_Tests : public Test { result.test_eq("recovered", recovered, ptext); + result.end_timer(); return result; } static Test::Result sign_ed25519() { Test::Result result("crypto_sign_ed25519"); + result.start_timer(); const std::vector seed(32); std::vector pk(32), sk(64); @@ -661,11 +694,13 @@ class Sodium_API_Tests : public Test { "reject invalid", Botan::Sodium::crypto_sign_ed25519_verify_detached(sig.data(), msg.data(), msg.size(), pk.data())); + result.end_timer(); return result; } static Test::Result stream_salsa20() { Test::Result result("crypto_stream_salsa20"); + result.start_timer(); const std::vector key = Botan::hex_decode("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"); @@ -682,11 +717,13 @@ class Sodium_API_Tests : public Test { xor_output.data(), output.data(), output.size(), nonce.data(), key.data()); result.test_eq("stream", xor_output, std::vector(32)); // all zeros + result.end_timer(); return result; } static Test::Result stream_xsalsa20() { Test::Result result("crypto_stream_xsalsa20"); + result.start_timer(); const std::vector key = Botan::hex_decode("1B27556473E985D462CD51197A9A46C76009549EAC6474F206C4EE0844F68389"); @@ -703,11 +740,13 @@ class Sodium_API_Tests : public Test { xor_output.data(), output.data(), output.size(), nonce.data(), key.data()); result.test_eq("stream", xor_output, std::vector(32)); // all zeros + result.end_timer(); return result; } static Test::Result stream_chacha20() { Test::Result result("crypto_stream_chacha20"); + result.start_timer(); const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); @@ -724,11 +763,13 @@ class Sodium_API_Tests : public Test { xor_output.data(), output.data(), output.size(), nonce.data(), key.data()); result.test_eq("stream", xor_output, std::vector(32)); // all zeros + result.end_timer(); return result; } static Test::Result stream_chacha20_ietf() { Test::Result result("crypto_stream_chacha20"); + result.start_timer(); const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); @@ -745,11 +786,13 @@ class Sodium_API_Tests : public Test { xor_output.data(), output.data(), output.size(), nonce.data(), key.data()); result.test_eq("stream", xor_output, std::vector(32)); // all zeros + result.end_timer(); return result; } static Test::Result stream_xchacha20() { Test::Result result("crypto_stream_xchacha20"); + result.start_timer(); const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); @@ -766,6 +809,7 @@ class Sodium_API_Tests : public Test { xor_output.data(), output.data(), output.size(), nonce.data(), key.data()); result.test_eq("stream", xor_output, std::vector(32)); // all zeros + result.end_timer(); return result; } }; diff --git a/src/tests/test_sphincsplus_utils.cpp b/src/tests/test_sphincsplus_utils.cpp index 03a07c0a18d..58f7ee71c2b 100644 --- a/src/tests/test_sphincsplus_utils.cpp +++ b/src/tests/test_sphincsplus_utils.cpp @@ -26,14 +26,17 @@ std::vector test_sphincsplus_address() { return { CHECK("default address", [&](Test::Result& result) { + result.start_timer(); Botan::Sphincs_Address a({0, 0, 0, 0, 0, 0, 0, 0}); result.test_is_eq("SHA-256(32*0x00)", sha256(a), Botan::hex_decode("66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925")); + result.end_timer(); }), CHECK("set up an address", [&](Test::Result& result) { + result.start_timer(); Botan::Sphincs_Address a(Botan::Sphincs_Address::ForsTree); a.set_layer_address(Botan::HypertreeLayerIndex(1337)) .set_tree_address(Botan::XmssTreeIndexInLayer(4294967338) /* longer than 32bits */) @@ -44,10 +47,12 @@ std::vector test_sphincsplus_address() { result.test_is_eq("SHA-256(a1)", sha256(a), Botan::hex_decode("aecc0696fee5c4aa601779343d01090aae0d0a3b6cf118d3c7245d48dc0f3af9")); + result.end_timer(); }), CHECK("set up another address", [&](Test::Result& result) { + result.start_timer(); Botan::Sphincs_Address a(Botan::Sphincs_Address::ForsTree); a.set_layer_address(Botan::HypertreeLayerIndex(1337)) .set_tree_address(Botan::XmssTreeIndexInLayer(4294967338) /* longer than 32bits */) @@ -57,10 +62,12 @@ std::vector test_sphincsplus_address() { result.test_is_eq("SHA-256(a2)", sha256(a), Botan::hex_decode("607fdc9d063168fbea64e4da2a255693314712d859062abb80cf7c78116ded2a")); + result.end_timer(); }), CHECK("copy subtree", [&](Test::Result& result) { + result.start_timer(); Botan::Sphincs_Address a(Botan::Sphincs_Address::ForsTree); a.set_layer_address(Botan::HypertreeLayerIndex(1337)) .set_tree_address(Botan::XmssTreeIndexInLayer(4294967338) /* longer than 32bits */) @@ -78,10 +85,12 @@ std::vector test_sphincsplus_address() { result.test_is_eq("SHA-256(subtree2)", sha256(subtree2), Botan::hex_decode("f192c8f8e946aa16d16eafe88bd4eabcc88a305b69bb7c0bb49e65bd122bb973")); + result.end_timer(); }), CHECK("copy keypair", [&](Test::Result& result) { + result.start_timer(); Botan::Sphincs_Address a(Botan::Sphincs_Address::ForsTree); a.set_layer_address(Botan::HypertreeLayerIndex(1337)) .set_tree_address(Botan::XmssTreeIndexInLayer(4294967338) /* longer than 32bits */) @@ -99,6 +108,7 @@ std::vector test_sphincsplus_address() { result.test_is_eq("SHA-256(keypair2)", sha256(keypair2), Botan::hex_decode("1cdd4835a6057306678e7d8cb903c140aba1d4805a8a1f75b11f1129bb22d08c")); + result.end_timer(); }), }; } diff --git a/src/tests/test_strong_type.cpp b/src/tests/test_strong_type.cpp index c9690784e9a..6bbc147f4d0 100644 --- a/src/tests/test_strong_type.cpp +++ b/src/tests/test_strong_type.cpp @@ -53,37 +53,45 @@ std::vector test_strong_type() { CHECK("value retrieval", [](auto& result) { + result.start_timer(); Test_Size a(42); const Test_Size b(42); result.test_is_eq("get()", a.get(), size_t(42)); result.test_is_eq("const get()", b.get(), size_t(42)); + result.end_timer(); }), CHECK("comparisons", [](auto& result) { + result.start_timer(); const Test_Size a(42); const Test_Size b(42); result.confirm("equal", a == b); result.confirm("lower than", a < Test_Size(1337)); result.confirm("greater than", Test_Size(1337) > b); + result.end_timer(); }), CHECK("function overloading", [](auto& result) { + result.start_timer(); result.test_eq("overloading size", foo(Test_Size(42)), "some size"); result.test_eq("overloading size", foo(Test_Length(42)), "some length"); + result.end_timer(); }), CHECK("is_strong_type", [](auto& result) { + result.start_timer(); result.confirm("strong type (int)", Botan::is_strong_type_v); result.confirm("no strong type (int)", !Botan::is_strong_type_v); result.confirm("strong type (vector)", Botan::is_strong_type_v); result.confirm("no strong type (vector)", !Botan::is_strong_type_v>); result.confirm("strong type (const vector)", Botan::is_strong_type_v); result.confirm("no strong type (const vector)", !Botan::is_strong_type_v>); + result.end_timer(); }), }; } @@ -98,6 +106,7 @@ std::vector test_container_strong_type() { CHECK("behaves like a standard container", [](auto& result) { + result.start_timer(); auto base_nonce = Botan::hex_decode("DEADBEEF"); auto dataptr = base_nonce.data(); auto nonce = Test_Nonce(std::move(base_nonce)); @@ -109,11 +118,13 @@ std::vector test_container_strong_type() { for(auto& c : nonce) { result.confirm("iteration", c > 0); } + result.end_timer(); }), CHECK( "container concepts are satisfied", [](auto& result) { + result.start_timer(); using Test_Map = Botan::Strong, struct Test_Map_>; using Test_Array = Botan::Strong, struct Test_Array_>; @@ -131,28 +142,34 @@ std::vector test_container_strong_type() { result.confirm("Test_Array is not resizable_container", !Botan::concepts::resizable_container); result.confirm("Test_Map is not resizable_container", !Botan::concepts::resizable_container); result.confirm("Test_Size is not resizable_container", !Botan::concepts::resizable_container); + result.end_timer(); }), CHECK("binds to a std::span<>", [](auto& result) { + result.start_timer(); auto get_size = [](std::span data) { return data.size(); }; const auto nonce = Test_Nonce(Botan::hex_decode("DEADBEEF")); result.test_is_eq("can bind to std::span<>", get_size(nonce), nonce.size()); + result.end_timer(); }), CHECK("std::string container", [](auto& result) { + result.start_timer(); Test_Hash_Name thn("SHA-1"); std::stringstream stream; stream << thn; result.test_eq("strong types are streamable", stream.str(), std::string("SHA-1")); + result.end_timer(); }), CHECK("strong types are sortable", [](auto& result) { + result.start_timer(); using Test_Length_List = Botan::Strong, struct Test_Length_List_>; Test_Length_List hashes({Test_Length(3), Test_Length(1), Test_Length(4), Test_Length(2)}); @@ -164,10 +181,12 @@ std::vector test_container_strong_type() { result.test_eq("2", hashes.get().at(1).get(), size_t(2)); result.test_eq("3", hashes.get().at(2).get(), size_t(3)); result.test_eq("4", hashes.get().at(3).get(), size_t(4)); + result.end_timer(); }), CHECK("byte-container strong types can be randomly generated", [](auto& result) { + result.start_timer(); using Test_Buffer = Botan::Strong, struct Test_Buffer_>; using Test_Secure_Buffer = Botan::Strong, struct Test_Secure_Buffer_>; using Test_Fixed_Array = Botan::Strong, struct Test_Fixed_Array_>; @@ -190,6 +209,7 @@ std::vector test_container_strong_type() { result.test_eq("generated expected fixed output", std::vector(tfa.begin(), tfa.end()), Botan::hex_decode("baadf00d")); + result.end_timer(); }), }; } @@ -201,6 +221,7 @@ std::vector test_integer_strong_type() { return { CHECK("comparison operators with POD are always allowed", [](auto& result) { + result.start_timer(); StrongInt i(42); result.confirm("i ==", i == 42); @@ -220,10 +241,12 @@ std::vector test_integer_strong_type() { result.confirm("< i", 41 < i); result.confirm("<= 1 i", 41 <= i); result.confirm("<= 2 i", 42 <= i); + result.end_timer(); }), CHECK("increment/decrement are always allowed", [](auto& result) { + result.start_timer(); StrongInt i(42); result.confirm("i++", i++ == 42); @@ -235,10 +258,12 @@ std::vector test_integer_strong_type() { result.confirm("i post-decremented", i == 43); result.confirm("--i", --i == 42); result.confirm("i pre-decremented", i == 42); + result.end_timer(); }), CHECK("comparison operators with Strong<>", [](auto& result) { + result.start_timer(); StrongInt i(42); StrongInt i42(42); StrongInt i41(41); @@ -253,10 +278,12 @@ std::vector test_integer_strong_type() { result.confirm("<", i < i43); result.confirm("<= 1", i <= i43); result.confirm("<= 2", i <= i42); + result.end_timer(); }), CHECK("arithmetics with Strong<>", [](auto& result) { + result.start_timer(); StrongInt i(42); StrongInt i2(2); StrongInt i4(4); @@ -281,10 +308,12 @@ std::vector test_integer_strong_type() { result.confirm("|=", (i |= i2) == 10); result.confirm("<<=", (i <<= i2) == 40); result.confirm(">>=", (i >>= i4) == 2); + result.end_timer(); }), CHECK("arithmetics with POD", [](auto& result) { + result.start_timer(); StrongIntWithPodArithmetics i(42); StrongIntWithPodArithmetics i2(2); @@ -317,10 +346,12 @@ std::vector test_integer_strong_type() { result.confirm("i |=", (i |= 2) == 10); result.confirm("i <<=", (i <<= 2) == 40); result.confirm("i >>=", (i >>= 4) == 2); + result.end_timer(); }), CHECK("arithmetics with POD is still Strong<>", [](auto& result) { + result.start_timer(); StrongIntWithPodArithmetics i(42); StrongIntWithPodArithmetics i2(2); @@ -353,6 +384,7 @@ std::vector test_integer_strong_type() { result.confirm("i |=", Botan::is_strong_type_v); result.confirm("i <<=", Botan::is_strong_type_v); result.confirm("i >>=", Botan::is_strong_type_v>= 4)>); + result.end_timer(); }), }; } @@ -374,6 +406,7 @@ using Test_Bar = Botan::Strong, struct Test_Bar_>; Test::Result test_strong_span() { Test::Result result("StrongSpan<>"); + result.start_timer(); const Test_Foo foo(Botan::hex_decode("DEADBEEF")); result.test_is_eq("binds to StrongSpan", test_strong_helper(foo), 1); @@ -391,6 +424,7 @@ Test::Result test_strong_span() { result.confirm("strong span is not a contiguous strong type buffer", !Botan::concepts::contiguous_strong_type); + result.end_timer(); return result; } @@ -403,6 +437,7 @@ std::vector test_wrapping_unwrapping() { return { CHECK("generically wrapping an object into a strong type", [&](Test::Result& result) { + result.start_timer(); const std::string expl("explicit creation"s); std::string rval("rvalue-ref creation"s); auto stt_copy = Botan::wrap_strong_type(expl); @@ -424,10 +459,12 @@ std::vector test_wrapping_unwrapping() { result.test_eq("stt_implicit_ptr", *stt_implicit_ptr.get(), "implicit creation from ptr"); result.test_eq("stt_rvalue_ptr", *stt_rvalue_ptr.get(), "rvalue creation from ptr"); + result.end_timer(); }), CHECK("generically wrapping a strong type from itself", [&](Test::Result& result) { + result.start_timer(); const Strong_String stt("wrapped"); Strong_String stt_rval("wrapped and moved"); @@ -444,10 +481,12 @@ std::vector test_wrapping_unwrapping() { auto stt_ptr_move = Botan::wrap_strong_type(std::move(stt_ptr)); result.test_eq("stt_ptr_move", *stt_ptr_move.get(), "wrapped ptr"); + result.end_timer(); }), CHECK("unwrapping a strong type wisely chooses return reference type", [&](Test::Result& result) { + result.start_timer(); Strong_String stt("wrapped"); const Strong_String stt_const("const wrapped"); @@ -483,11 +522,13 @@ std::vector test_wrapping_unwrapping() { result.confirm("wrapped_type on rvalue strong type", std::same_as, std::remove_cvref_t>); + result.end_timer(); }), CHECK( "unwrapping a non-strong type does not alter return reference type", [](Test::Result& result) { + result.start_timer(); std::string stt("wrapped"); const std::string stt_const("const wrapped"); @@ -522,10 +563,12 @@ std::vector test_wrapping_unwrapping() { result.confirm("wrapped_type on rvalue non-strong type", std::same_as, std::remove_cvref_t>); + result.end_timer(); }), CHECK("generically unwrapping an object from a strong type", [&](Test::Result& result) { + result.start_timer(); Strong_String stt("wrapped lvalue"); Strong_String stt_move("wrapped lvalue to be moved"); const Strong_String const_stt("wrapped const lvalue"); @@ -551,10 +594,12 @@ std::vector test_wrapping_unwrapping() { result.test_eq("unwrapped_ptr", *unwrapped_ptr, "wrapped ptr"); result.test_eq("unwrapped_ptr_move", *unwrapped_ptr_move, "wrapped ptr to be moved"); result.test_eq("unwrapped_ptr_rvalue", *unwrapped_ptr_rvalue, "wrapped ptr rvalue"); + result.end_timer(); }), CHECK("generically unwrapping an object that isn't a strong type", [&](Test::Result& result) { + result.start_timer(); std::string stt("wrapped lvalue"); std::string stt_move("wrapped lvalue to be moved"); const std::string const_stt("wrapped const lvalue"); @@ -580,6 +625,7 @@ std::vector test_wrapping_unwrapping() { result.test_eq("unwrapped_ptr", *unwrapped_ptr, "wrapped ptr"); result.test_eq("unwrapped_ptr_move", *unwrapped_ptr_move, "wrapped ptr to be moved"); result.test_eq("unwrapped_ptr_rvalue", *unwrapped_ptr_rvalue, "wrapped ptr rvalue"); + result.end_timer(); }), }; } diff --git a/src/tests/test_tests.cpp b/src/tests/test_tests.cpp index ce73758c1c9..17afe6a9dc3 100644 --- a/src/tests/test_tests.cpp +++ b/src/tests/test_tests.cpp @@ -26,6 +26,7 @@ class Test_Tests final : public Test { */ Test::Result result("Test Framework"); + result.start_timer(); // Test a few success corner cases first const std::string testcase_name = "Failing Test"; @@ -197,12 +198,14 @@ class Test_Tests final : public Test { } #endif + result.end_timer(); return {result, test_testsuite_rng()}; } private: static Test::Result test_testsuite_rng() { Test::Result result("Testsuite_RNG"); + result.start_timer(); size_t histogram[256] = {0}; @@ -222,6 +225,7 @@ class Test_Tests final : public Test { } } + result.end_timer(); return result; } diff --git a/src/tests/test_thread_utils.cpp b/src/tests/test_thread_utils.cpp index d244d4765d2..88c4be9e520 100644 --- a/src/tests/test_thread_utils.cpp +++ b/src/tests/test_thread_utils.cpp @@ -20,6 +20,7 @@ namespace { Test::Result thread_pool() { Test::Result result("Thread_Pool"); + result.start_timer(); // Using lots of threads since here the works spend most of the time sleeping Botan::Thread_Pool pool(16); @@ -54,6 +55,7 @@ Test::Result thread_pool() { pool.shutdown(); + result.end_timer(); return result; } diff --git a/src/tests/test_tls.cpp b/src/tests/test_tls.cpp index 6f8c5a41b2d..1c3d2e7ed80 100644 --- a/src/tests/test_tls.cpp +++ b/src/tests/test_tls.cpp @@ -30,6 +30,7 @@ class TLS_Session_Tests final : public Test { public: std::vector run() override { Test::Result result("TLS::Session"); + result.start_timer(); Botan::TLS::Session session(Botan::secure_vector{0xCC, 0xDD}, Botan::TLS::Protocol_Version::TLS_V12, @@ -87,6 +88,7 @@ class TLS_Session_Tests final : public Test { "Serialized TLS session contains unknown cipher suite (47789)", [&] { Botan::TLS::Session{pem_with_unknown_ciphersuite}; }); + result.end_timer(); return {result}; } }; @@ -106,7 +108,9 @@ class TLS_CBC_Padding_Tests final : public Text_Based_Test { uint16_t res = Botan::TLS::check_tls_cbc_padding(record.data(), record.size()); Test::Result result("TLS CBC padding check"); + result.start_timer(); result.test_eq("Expected", res, output); + result.end_timer(); return result; } }; @@ -187,6 +191,7 @@ class TLS_CBC_Tests final : public Text_Based_Test { Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { Test::Result result("TLS CBC"); + result.start_timer(); const size_t block_size = vars.get_req_sz("Blocksize"); const size_t mac_len = vars.get_req_sz("MACsize"); @@ -224,6 +229,7 @@ class TLS_CBC_Tests final : public Text_Based_Test { } } + result.end_timer(); return result; } }; @@ -236,6 +242,7 @@ class Test_TLS_Alert_Strings : public Test { public: std::vector run() override { Test::Result result("TLS::Alert::type_string"); + result.start_timer(); const std::vector alert_types = { Botan::TLS::Alert::CloseNotify, @@ -285,6 +292,7 @@ class Test_TLS_Alert_Strings : public Test { result.test_eq("Unknown alert str", unknown_alert.type_string(), "unrecognized_alert_66"); + result.end_timer(); return {result}; } }; @@ -295,6 +303,7 @@ class Test_TLS_Policy_Text : public Test { public: std::vector run() override { Test::Result result("TLS Policy"); + result.start_timer(); const std::vector policies = {"default", "suiteb_128", "suiteb_192", "strict", "datagram", "bsi"}; @@ -310,6 +319,7 @@ class Test_TLS_Policy_Text : public Test { result.test_eq("Values for TLS " + policy + " policy", from_file, from_policy_obj); } + result.end_timer(); return {result}; } @@ -354,6 +364,7 @@ class Test_TLS_Ciphersuites : public Test { public: std::vector run() override { Test::Result result("TLS::Ciphersuite"); + result.start_timer(); for(size_t csuite_id = 0; csuite_id <= 0xFFFF; ++csuite_id) { const uint16_t csuite_id16 = static_cast(csuite_id); @@ -375,6 +386,7 @@ class Test_TLS_Ciphersuites : public Test { } } + result.end_timer(); return {result}; } }; @@ -396,6 +408,7 @@ class Test_TLS_Algo_Strings : public Test { private: static Test::Result test_tls_sig_method_strings() { Test::Result result("TLS::Signature_Scheme"); + result.start_timer(); std::vector schemes = Botan::TLS::Signature_Scheme::all_available_schemes(); @@ -408,11 +421,13 @@ class Test_TLS_Algo_Strings : public Test { scheme_strs.insert(scheme_str); } + result.end_timer(); return result; } static Test::Result test_auth_method_strings() { Test::Result result("TLS::Auth_Method"); + result.start_timer(); const std::vector auth_methods({ Botan::TLS::Auth_Method::RSA, @@ -427,11 +442,13 @@ class Test_TLS_Algo_Strings : public Test { result.confirm("Decoded method matches", meth == meth2); } + result.end_timer(); return result; } static Test::Result test_kex_algo_strings() { Test::Result result("TLS::Kex_Algo"); + result.start_timer(); const std::vector kex_algos({Botan::TLS::Kex_Algo::STATIC_RSA, Botan::TLS::Kex_Algo::DH, @@ -446,6 +463,7 @@ class Test_TLS_Algo_Strings : public Test { result.confirm("Decoded method matches", meth == meth2); } + result.end_timer(); return result; } }; diff --git a/src/tests/test_tls_cipher_state.cpp b/src/tests/test_tls_cipher_state.cpp index 20b3c459d6b..61d1a159641 100644 --- a/src/tests/test_tls_cipher_state.cpp +++ b/src/tests/test_tls_cipher_state.cpp @@ -314,6 +314,7 @@ std::vector test_secret_derivation_rfc8448_rtt1() { {CHECK_both( "secret logging during initialization", [&](Cipher_State*, Journaling_Secret_Logger* sl, Connection_Side, Test::Result& result) { + result.start_timer(); result.test_eq("logged expected secrets", sl->secrets.size(), 2); result.require("has client traffic secret", sl->secrets.contains("CLIENT_HANDSHAKE_TRAFFIC_SECRET")); result.require("has server traffic secret", sl->secrets.contains("SERVER_HANDSHAKE_TRAFFIC_SECRET")); @@ -324,10 +325,12 @@ std::vector test_secret_derivation_rfc8448_rtt1() { result.test_is_eq("server traffic secret", sl->secrets.at("SERVER_HANDSHAKE_TRAFFIC_SECRET"), server_handshake_traffic_secret); + result.end_timer(); }), CHECK_both("ciphersuite compatibility", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side side, Test::Result& result) { + result.start_timer(); result.confirm("self-compatibility", cs->is_compatible_with(cipher)); result.confirm( "fully defined state is not compatible to other suites", @@ -341,16 +344,20 @@ std::vector test_secret_derivation_rfc8448_rtt1() { result.confirm("Servers must expect unprotected alerts in response to their server hello", cs->must_expect_unprotected_alert_traffic()); } + result.end_timer(); }), CHECK_both("ticket nonce counter is not yet available", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) { + result.start_timer(); result.test_throws("nonce counter is disabled", [&] { cs->next_ticket_nonce(); }); + result.end_timer(); }), CHECK_both("handshake traffic without PSK", [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) { + result.start_timer(); result.confirm("can not yet write application data", !cs->can_encrypt_application_traffic()); result.confirm("can not yet export key material", !cs->can_export_keys()); @@ -443,10 +450,12 @@ std::vector test_secret_derivation_rfc8448_rtt1() { result.test_eq("key export result did not change", cs->export_key(export_label, export_context, 16), expected_key_export); + result.end_timer(); }), CHECK_both("ticket nonce counter counts", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) { + result.start_timer(); result.test_is_eq("nonce is 0x00, 0x00", cs->next_ticket_nonce(), Botan::TLS::Ticket_Nonce(std::vector{0x00, 0x00})); @@ -463,18 +472,22 @@ std::vector test_secret_derivation_rfc8448_rtt1() { // Cannot generate more than 2^16 ticket nonces result.test_throws("nonces are depleted", [&] { cs->next_ticket_nonce(); }); + result.end_timer(); }), CHECK_both("PSK", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) { + result.start_timer(); // derive PSK for resumption const auto psk = cs->psk(Botan::TLS::Ticket_Nonce( std::vector{0x00, 0x00}) /* ticket_nonce as defined in RFC 8448 */); result.test_eq("PSK matches", psk, expected_psk); + result.end_timer(); }), CHECK_both("key update", [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) { + result.start_timer(); const auto read_label = side == Connection_Side::Client ? "SERVER_TRAFFIC_SECRET_1" : "CLIENT_TRAFFIC_SECRET_1"; const auto write_label = @@ -496,9 +509,11 @@ std::vector test_secret_derivation_rfc8448_rtt1() { updated_server_traffic_secret); result.confirm("can encrypt application traffic", cs->can_encrypt_application_traffic()); + result.end_timer(); }), CHECK_both("cleanup", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) { + result.start_timer(); // cleanup cs->clear_write_keys(); result.confirm("can no longer write application data", !cs->can_encrypt_application_traffic()); @@ -507,6 +522,7 @@ std::vector test_secret_derivation_rfc8448_rtt1() { cs->clear_read_keys(); result.confirm("can no longer write application data", !cs->can_encrypt_application_traffic()); result.confirm("can no longer read application data", !cs->can_decrypt_application_traffic()); + result.end_timer(); })}); } @@ -673,18 +689,23 @@ std::vector test_secret_derivation_rfc8448_rtt0() { return Test::flatten_result_lists( {CHECK_both("no secrets logged for PSK initialization", [&](Cipher_State*, Journaling_Secret_Logger* sl, Connection_Side, Test::Result& result) { + result.start_timer(); result.test_eq("no secrets logged", sl->secrets.size(), 0); + result.end_timer(); }), CHECK_both("calculating PSK binder", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) { + result.start_timer(); const auto mac = cs->psk_binder_mac(th_client_hello_prefix); result.test_eq("PSK binder is as expected", mac, expected_psk_binder); + result.end_timer(); }), CHECK_both( "ciphersuite compatibility", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) { + result.start_timer(); result.confirm("self-compatibility", cs->is_compatible_with(cipher)); result.confirm("partially defined state is compatible with suites using the same hash", cs->is_compatible_with(Ciphersuite::from_name("CHACHA20_POLY1305_SHA256").value()) && @@ -694,10 +715,12 @@ std::vector test_secret_derivation_rfc8448_rtt0() { result.confirm("partially defined state is not compatible with other hashes or protocol versions", !cs->is_compatible_with(Ciphersuite::from_name("PSK_WITH_AES_128_GCM_SHA256").value()) && !cs->is_compatible_with(Ciphersuite::from_name("AES_256_GCM_SHA384").value())); + result.end_timer(); }), CHECK_both("calculate the early traffic secrets", [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) { + result.start_timer(); cs->advance_with_client_hello(th_client_hello, *sl); result.require("early key export is possible", cs->can_export_keys()); result.test_eq("early key export produces expected result", @@ -722,11 +745,13 @@ std::vector test_secret_derivation_rfc8448_rtt0() { // application traffic in this state. result.confirm("can not yet write application data", !cs->can_encrypt_application_traffic()); result.confirm("can not yet read application data", !cs->can_decrypt_application_traffic()); + result.end_timer(); }), CHECK_both( "handshake traffic after PSK", [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) { + result.start_timer(); cs->advance_with_server_hello(cipher, secure_vector(shared_secret), th_server_hello, *sl); // decrypt encrypted extensions from server @@ -809,10 +834,12 @@ std::vector test_secret_derivation_rfc8448_rtt0() { // encrypt client Finished message by client // (under the client handshake traffic secret) encrypted_client_finished_message.xxcrypt(result, cs, side); + result.end_timer(); }), CHECK_both("application traffic after PSK", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side side, Test::Result& result) { + result.start_timer(); // advance Cipher_State with client_hello...client_Finished // (allows generation of resumption PSKs) result.test_no_throw("state advancement is legal", @@ -833,6 +860,7 @@ std::vector test_secret_derivation_rfc8448_rtt0() { // decrypt application data from server // (encrypted under the application traffic secret -- and a new sequence number) encrypted_application_data_server.xxcrypt(result, cs, side); + result.end_timer(); })}); } diff --git a/src/tests/test_tls_handshake_layer_13.cpp b/src/tests/test_tls_handshake_layer_13.cpp index f2d40532fc1..002dee2a3c6 100644 --- a/src/tests/test_tls_handshake_layer_13.cpp +++ b/src/tests/test_tls_handshake_layer_13.cpp @@ -152,51 +152,62 @@ std::vector read_handshake_messages() { return { CHECK("empty read", [&](auto& result) { + result.start_timer(); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); result.confirm("needs header bytes", !hl.next_message(Policy(), th)); check_transcript_hash_empty(result, th); + result.end_timer(); }), CHECK("read incomplete header", [&](auto& result) { + result.start_timer(); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); hl.copy_data(std::vector{0x00, 0x01, 0x02}); result.confirm("needs more bytes", !hl.next_message(Policy(), th)); check_transcript_hash_empty(result, th); + result.end_timer(); }), CHECK("read client hello", [&](auto& result) { + result.start_timer(); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); hl.copy_data(client_hello_message); result.confirm("is a client hello", has_message(result, hl.next_message(Policy(), th))); check_transcript_hash_filled(result, th); + result.end_timer(); }), CHECK("read server hello", [&](auto& result) { + result.start_timer(); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); hl.copy_data(server_hello_message); result.confirm("is a server hello", has_message(result, hl.next_message(Policy(), th))); check_transcript_hash_filled(result, th); + result.end_timer(); }), CHECK("read legacy server hello", [&](auto& result) { + result.start_timer(); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); hl.copy_data(server_hello_12_message); result.confirm("is a legacy server hello", has_message(result, hl.next_message(Policy(), th))); check_transcript_hash_filled(result, th); + result.end_timer(); }), CHECK("read client hello in two steps", [&](auto& result) { + result.start_timer(); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); @@ -212,10 +223,12 @@ std::vector read_handshake_messages() { result.confirm("is a client hello", has_message(result, hl.next_message(Policy(), th))); check_transcript_hash_filled(result, th); + result.end_timer(); }), CHECK("read multiple messages", [&](auto& result) { + result.start_timer(); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); hl.copy_data(Botan::concat(server_hello_message, encrypted_extensions)); @@ -223,10 +236,12 @@ std::vector read_handshake_messages() { result.confirm("is encrypted extensions", has_message(result, hl.next_message(Policy(), th))); check_transcript_hash_filled(result, th); + result.end_timer(); }), CHECK("reject TLS 1.2 messages", [&](auto& result) { + result.start_timer(); for(const auto& msg : tls_12_only_messages) { Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); @@ -238,6 +253,7 @@ std::vector read_handshake_messages() { check_transcript_hash_empty(result, th); } + result.end_timer(); }), CHECK("reject incomplete messages with invalid type", @@ -247,6 +263,7 @@ std::vector read_handshake_messages() { // to "random data" with an insensible type tag and a long (insensible) length field. // This caused a deadlock as we waited to receive the complete message, rather than validating the type // tag to exit early. + result.start_timer(); const auto data = Botan::hex_decode_locked("D4B028717D0FA310FF8664127B9448D7952E06A4F9EA23"); // data from the bogo test -- ~~~~~~ <- length // ~~ <- bogus message type @@ -255,6 +272,7 @@ std::vector read_handshake_messages() { hl.copy_data(data); result.template test_throws( "message is rejected", "Unknown handshake message received", [&] { hl.next_message(Policy(), th); }); + result.end_timer(); }), }; } @@ -263,22 +281,26 @@ std::vector prepare_message() { return { CHECK("prepare client hello", [&](auto& result) { + result.start_timer(); auto hello = std::get( Client_Hello_13::parse({client_hello_message.cbegin() + 4, client_hello_message.cend()})); Handshake_Layer hl(Connection_Side::Client); Transcript_Hash_State th("SHA-256"); result.test_eq("produces the same message", hl.prepare_message(hello, th), client_hello_message); check_transcript_hash_filled(result, th); + result.end_timer(); }), CHECK("prepare server hello", [&](auto& result) { + result.start_timer(); auto hello = std::get( Server_Hello_13::parse({server_hello_message.cbegin() + 4, server_hello_message.cend()})); Handshake_Layer hl(Connection_Side::Server); Transcript_Hash_State th("SHA-256"); result.test_eq("produces the same message", hl.prepare_message(hello, th), server_hello_message); check_transcript_hash_filled(result, th); + result.end_timer(); }), }; } @@ -292,14 +314,17 @@ std::vector full_client_handshake() { return { CHECK("client hello", [&](auto& result) { + result.start_timer(); auto hello = std::get( Client_Hello_13::parse({client_hello_message.cbegin() + 4, client_hello_message.cend()})); hl.prepare_message(hello, th); check_transcript_hash_empty(result, th); + result.end_timer(); }), CHECK("server hello", [&](auto& result) { + result.start_timer(); hl.copy_data(server_hello_message); const auto server_hello = hl.next_message(policy, th); @@ -315,10 +340,12 @@ std::vector full_client_handshake() { result.test_eq( "correct transcript hash produced after server hello", th.current(), expected_after_server_hello); + result.end_timer(); }), CHECK("server handshake messages", [&](auto& result) { + result.start_timer(); hl.copy_data(server_handshake_messages); const auto enc_exts = hl.next_message(policy, th); @@ -340,16 +367,19 @@ std::vector full_client_handshake() { const auto server_finished = hl.next_message(policy, th); result.confirm("is Finished", has_message(result, server_finished)); result.test_eq("hash is updated after server Finished", th.current(), expected_after_server_finished); + result.end_timer(); }), CHECK("client finished", [&](auto& result) { + result.start_timer(); const auto expected_after_client_finished = Botan::hex_decode( "20 91 45 a9 6e e8 e2 a1 22 ff 81 00 47 cc 95 26 84 65 8d 60 49 e8 64 29 42 6d b8 7c 54 ad 14 3d"); Finished_13 client_finished({client_finished_message.cbegin() + 4, client_finished_message.cend()}); hl.prepare_message(client_finished, th); result.test_eq("hash is updated after client Finished", th.current(), expected_after_client_finished); + result.end_timer(); }), }; } @@ -363,15 +393,18 @@ std::vector hello_retry_request_handshake() { return { CHECK("client hello 1", [&](auto& result) { + result.start_timer(); auto hello = std::get( Client_Hello_13::parse({hrr_client_hello_msg.cbegin() + 4, hrr_client_hello_msg.cend()})); auto msg = hl.prepare_message(hello, th); result.test_eq("parsing and re-marshalling produces same message", msg, hrr_client_hello_msg); check_transcript_hash_empty(result, th); + result.end_timer(); }), CHECK("hello retry request", [&](auto& result) { + result.start_timer(); hl.copy_data(hrr_hello_retry_request_msg); const auto hrr = hl.next_message(policy, th); @@ -389,6 +422,7 @@ std::vector hello_retry_request_handshake() { result.test_eq("correct transcript hash produced after hello retry request", th.current(), expected_after_hello_retry_request); + result.end_timer(); }), // ... the rest of the handshake will work just like in full_client_handshake diff --git a/src/tests/test_tls_handshake_state_13.cpp b/src/tests/test_tls_handshake_state_13.cpp index 2c772c28ffd..b7276a19263 100644 --- a/src/tests/test_tls_handshake_state_13.cpp +++ b/src/tests/test_tls_handshake_state_13.cpp @@ -50,6 +50,8 @@ std::vector finished_message_handling() { return { CHECK("Client sends and receives Finished messages", [&](auto& result) { + result.start_timer(); + Botan::TLS::Client_Handshake_State_13 state; Botan::TLS::Finished_13 client_finished(client_finished_message); @@ -70,6 +72,8 @@ std::vector finished_message_handling() { "correct client Finished stored", state.client_finished().serialize(), client_finished_message); result.test_eq( "correct server Finished stored", state.server_finished().serialize(), server_finished_message); + + result.end_timer(); }), }; } @@ -78,6 +82,8 @@ std::vector handshake_message_filtering() { return { CHECK("Client with client hello", [&](auto& result) { + result.start_timer(); + Botan::TLS::Client_Handshake_State_13 state; auto client_hello = @@ -94,9 +100,12 @@ std::vector handshake_message_filtering() { std::get(Botan::TLS::Client_Hello_13::parse(client_hello_message)); state.received(std::move(ch)); }); + + result.end_timer(); }), CHECK("Client with server hello", [&](auto& result) { + result.start_timer(); Botan::TLS::Client_Handshake_State_13 state; auto server_hello = @@ -107,6 +116,7 @@ std::vector handshake_message_filtering() { std::holds_alternative>(filtered)); result.test_eq("correct server hello stored", state.server_hello().serialize(), server_hello_message); + result.end_timer(); }), }; } diff --git a/src/tests/test_tls_handshake_transitions.cpp b/src/tests/test_tls_handshake_transitions.cpp index 6f25f631e62..229bf3db956 100644 --- a/src/tests/test_tls_handshake_transitions.cpp +++ b/src/tests/test_tls_handshake_transitions.cpp @@ -19,6 +19,7 @@ std::vector test_handshake_state_transitions() { return { CHECK("uninitialized expects nothing", [](Test::Result& result) { + result.start_timer(); Botan::TLS::Handshake_Transitions ht; result.confirm("CCS is not expected by default", !ht.change_cipher_spec_expected()); @@ -26,10 +27,12 @@ std::vector test_handshake_state_transitions() { !ht.received_handshake_msg(Botan::TLS::Handshake_Type::ClientHello)); result.test_throws("no expectations set, always throws", [&] { ht.confirm_transition_to(Botan::TLS::Handshake_Type::ClientHello); }); + result.end_timer(); }), CHECK("expect exactly one message", [](Test::Result& result) { + result.start_timer(); Botan::TLS::Handshake_Transitions ht; ht.set_expected_next(Botan::TLS::Handshake_Type::ClientHello); @@ -41,19 +44,23 @@ std::vector test_handshake_state_transitions() { result.test_throws("confirmation resets expectations", [&] { ht.confirm_transition_to(Botan::TLS::Handshake_Type::ClientHello); }); + result.end_timer(); }), CHECK("expect exactly one message but don't satisfy it", [](Test::Result& result) { + result.start_timer(); Botan::TLS::Handshake_Transitions ht; ht.set_expected_next(Botan::TLS::Handshake_Type::ClientHello); result.test_throws("server hello does not meet expectation", [&] { ht.confirm_transition_to(Botan::TLS::Handshake_Type::ServerHello); }); + result.end_timer(); }), CHECK("two expectations can be fulfilled", [](Test::Result& result) { + result.start_timer(); Botan::TLS::Handshake_Transitions ht; ht.set_expected_next( {Botan::TLS::Handshake_Type::CertificateRequest, Botan::TLS::Handshake_Type::Certificate}); @@ -69,13 +76,16 @@ std::vector test_handshake_state_transitions() { [&] { ht2.confirm_transition_to(Botan::TLS::Handshake_Type::CertificateRequest); }); result.confirm("received CERTIFICATE_REQUEST", ht2.received_handshake_msg(Botan::TLS::Handshake_Type::CertificateRequest)); + result.end_timer(); }), CHECK("expect CCS", [](Test::Result& result) { + result.start_timer(); Botan::TLS::Handshake_Transitions ht; ht.set_expected_next(Botan::TLS::Handshake_Type::HandshakeCCS); result.confirm("CCS expected", ht.change_cipher_spec_expected()); + result.end_timer(); }), }; } diff --git a/src/tests/test_tls_hybrid_kem_key.cpp b/src/tests/test_tls_hybrid_kem_key.cpp index 8170900cb56..6502f237da5 100644 --- a/src/tests/test_tls_hybrid_kem_key.cpp +++ b/src/tests/test_tls_hybrid_kem_key.cpp @@ -161,55 +161,92 @@ std::vector hybrid_kem_keypair() { return { CHECK("public handles empty list", [](auto& result) { + result.start_timer(); result.test_throws("hybrid KEM key does not accept an empty list of keys", [] { Botan::TLS::Hybrid_KEM_PublicKey({}); }); + result.end_timer(); }), CHECK("private handles empty list", [](auto& result) { + result.start_timer(); result.test_throws("hybrid KEM key does not accept an empty list of keys", [] { Botan::TLS::Hybrid_KEM_PrivateKey({}); }); + result.end_timer(); }), CHECK("public key handles nullptr", [&](auto& result) { + result.start_timer(); result.test_throws("hybrid KEM key does not accept nullptr keys", [] { Botan::TLS::Hybrid_KEM_PublicKey(pubkeys(nullptr)); }); result.test_throws("hybrid KEM key does not accept nullptr keys along with KEM", [&] { Botan::TLS::Hybrid_KEM_PublicKey(pubkeys(nullptr, kem())); }); result.test_throws("hybrid KEM key does not accept nullptr keys along with KEX", [&] { Botan::TLS::Hybrid_KEM_PublicKey(pubkeys(nullptr, kex_dh())); }); + result.end_timer(); }), CHECK("private key handles nullptr", [&](auto& result) { + result.start_timer(); result.test_throws("hybrid KEM key does not accept nullptr keys", [] { Botan::TLS::Hybrid_KEM_PrivateKey(keys(nullptr)); }); result.test_throws("hybrid KEM key does not accept nullptr keys along with KEM", [&] { Botan::TLS::Hybrid_KEM_PrivateKey(keys(nullptr, kem())); }); result.test_throws("hybrid KEM key does not accept nullptr keys along with KEX", [&] { Botan::TLS::Hybrid_KEM_PrivateKey(keys(nullptr, kex_dh())); }); + result.end_timer(); }), CHECK("handles incompatible keys (non-KEM, non-KEX)", [&](auto& result) { + result.start_timer(); result.test_throws("hybrid KEM key does not accept signature keys", [&] { Botan::TLS::Hybrid_KEM_PrivateKey(keys(sig())); }); result.test_throws("signature keys aren't allowed along with KEM keys", [&] { Botan::TLS::Hybrid_KEM_PrivateKey(keys(sig(), kem())); }); result.test_throws("signature keys aren't allowed along with KEX keys", [&] { Botan::TLS::Hybrid_KEM_PrivateKey(keys(sig(), kex_dh())); }); + result.end_timer(); }), CHECK("single KEM key", - [&](auto& result) { result.test_throws("need at least two keys", [&] { roundtrip_test(result, kem); }); }), - CHECK("dual KEM key", [&](auto& result) { roundtrip_test(result, kem, kem); }), - CHECK( - "single KEX key", - [&](auto& result) { result.test_throws("need at least two keys", [&] { roundtrip_test(result, kex_dh); }); }), - CHECK("dual KEX key", [&](auto& result) { roundtrip_test(result, kex_dh, kex_ecdh); }), - CHECK("hybrid KEX/KEM key", [&](auto& result) { roundtrip_test(result, kex_dh, kem); }), - CHECK("hybrid triple key", [&](auto& result) { roundtrip_test(result, kex_dh, kem, kex_ecdh); }), + [&](auto& result) { + result.start_timer(); + result.test_throws("need at least two keys", [&] { roundtrip_test(result, kem); }); + result.end_timer(); + }), + CHECK("dual KEM key", + [&](auto& result) { + result.start_timer(); + roundtrip_test(result, kem, kem); + result.end_timer(); + }), + CHECK("single KEX key", + [&](auto& result) { + result.start_timer(); + result.test_throws("need at least two keys", [&] { roundtrip_test(result, kex_dh); }); + result.end_timer(); + }), + CHECK("dual KEX key", + [&](auto& result) { + result.start_timer(); + roundtrip_test(result, kex_dh, kex_ecdh); + result.end_timer(); + }), + CHECK("hybrid KEX/KEM key", + [&](auto& result) { + result.start_timer(); + roundtrip_test(result, kex_dh, kem); + result.end_timer(); + }), + CHECK("hybrid triple key", + [&](auto& result) { + result.start_timer(); + roundtrip_test(result, kex_dh, kem, kex_ecdh); + result.end_timer(); + }), }; } @@ -246,20 +283,34 @@ std::vector kex_to_kem_adapter() { return { CHECK("handles nullptr", [](auto& result) { + result.start_timer(); result.test_throws("private KEM adapter handles nullptr", [] { Botan::TLS::KEX_to_KEM_Adapter_PrivateKey(nullptr); }); result.test_throws("public KEM adapter handles nullptr", [] { Botan::TLS::KEX_to_KEM_Adapter_PublicKey(nullptr); }); + result.end_timer(); }), CHECK("handles non-KEX keys", [](auto& result) { + result.start_timer(); result.test_throws("public KEM adapter does not work with KEM keys", [] { Botan::TLS::KEX_to_KEM_Adapter_PublicKey{kem()}; }); + result.end_timer(); }), - CHECK("Diffie-Hellman roundtrip", [](auto& result) { kex_to_kem_roundtrip(result, kex_dh); }), - CHECK("ECDH roundtrip", [](auto& result) { kex_to_kem_roundtrip(result, kex_ecdh); }), + CHECK("Diffie-Hellman roundtrip", + [](auto& result) { + result.start_timer(); + kex_to_kem_roundtrip(result, kex_dh); + result.end_timer(); + }), + CHECK("ECDH roundtrip", + [](auto& result) { + result.start_timer(); + kex_to_kem_roundtrip(result, kex_ecdh); + result.end_timer(); + }), }; } diff --git a/src/tests/test_tls_messages.cpp b/src/tests/test_tls_messages.cpp index 0667b1b30f7..a818a1245c8 100644 --- a/src/tests/test_tls_messages.cpp +++ b/src/tests/test_tls_messages.cpp @@ -35,6 +35,7 @@ namespace { #if defined(BOTAN_HAS_TLS) Test::Result test_hello_verify_request() { Test::Result result("hello_verify_request construction"); + result.start_timer(); std::vector test_data; std::vector key_data(32); @@ -51,6 +52,7 @@ Test::Result test_hello_verify_request() { std::vector test = unlock(hmac->final()); result.test_eq("Cookie comparison", hfr.cookie(), test); + result.end_timer(); return result; } @@ -91,6 +93,7 @@ class TLS_Message_Parsing_Test final : public Text_Based_Test { const bool is_positive_test = exception.empty(); Test::Result result(algo + " parsing"); + result.start_timer(); if(is_positive_test) { try { @@ -191,6 +194,7 @@ class TLS_Message_Parsing_Test final : public Text_Based_Test { } } + result.end_timer(); return result; } diff --git a/src/tests/test_tls_record_layer_13.cpp b/src/tests/test_tls_record_layer_13.cpp index bad585c9a48..ffc6f1f7ce9 100644 --- a/src/tests/test_tls_record_layer_13.cpp +++ b/src/tests/test_tls_record_layer_13.cpp @@ -85,6 +85,7 @@ std::vector read_full_records() { return {CHECK("change cipher spec", [&](auto& result) { + result.start_timer(); auto rl = record_layer_server(); rl.copy_data(ccs_record); @@ -96,10 +97,12 @@ std::vector read_full_records() { result.test_eq("CCS byte is 0x01", record.fragment, Botan::hex_decode("01")); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); }), CHECK("two CCS messages", [&](auto& result) { + result.start_timer(); const auto two_ccs_records = Botan::concat(ccs_record, ccs_record); auto rl = record_layer_server(); @@ -121,10 +124,12 @@ std::vector read_full_records() { result.test_eq("CCS byte is 0x01", record.fragment, Botan::hex_decode("01")); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); }), CHECK("read full handshake message", [&](auto& result) { + result.start_timer(); auto rl = record_layer_server(); rl.copy_data(client_hello_record); @@ -139,9 +144,11 @@ std::vector read_full_records() { rec.fragment); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); }), CHECK("read full handshake message followed by CCS", [&](auto& result) { + result.start_timer(); const auto payload = Botan::concat(client_hello_record, ccs_record); auto rl = record_layer_server(); @@ -165,6 +172,7 @@ std::vector read_full_records() { result.test_eq("CCS byte is 0x01", rec.fragment, Botan::hex_decode("01")); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); })}; } @@ -177,14 +185,17 @@ std::vector basic_sanitization_parse_records(TLS::Connection_Side return {CHECK("'receive' empty data", [&](auto& result) { + result.start_timer(); auto read = parse_records({}); result.require("needs bytes", std::holds_alternative(read)); result.test_eq( "need all the header bytes", std::get(read), Botan::TLS::TLS_HEADER_SIZE); + result.end_timer(); }), CHECK("incomplete header asks for more data", [&](auto& result) { + result.start_timer(); std::vector partial_header{'\x23', '\x03', '\x03'}; auto read = parse_records(partial_header); result.require("returned 'bytes needed'", std::holds_alternative(read)); @@ -192,42 +203,52 @@ std::vector basic_sanitization_parse_records(TLS::Connection_Side result.test_eq("asks for some more bytes", std::get(read), Botan::TLS::TLS_HEADER_SIZE - partial_header.size()); + result.end_timer(); }), CHECK("complete header asks for enough data to finish processing the record", [&](auto& result) { + result.start_timer(); std::vector full_header{'\x17', '\x03', '\x03', '\x00', '\x42'}; auto read = parse_records(full_header); result.require("returned 'bytes needed'", std::holds_alternative(read)); result.test_eq("asks for many more bytes", std::get(read), 0x42); + result.end_timer(); }), CHECK("received an empty record (that is not application data)", [&](auto& result) { + result.start_timer(); std::vector empty_record{'\x16', '\x03', '\x03', '\x00', '\x00'}; result.test_throws("record empty", "empty record received", [&] { parse_records(empty_record); }); + result.end_timer(); }), CHECK("received the maximum size of an unprotected record", [&](auto& result) { + result.start_timer(); std::vector full_record{'\x16', '\x03', '\x03', '\x40', '\x00'}; full_record.resize(TLS::MAX_PLAINTEXT_SIZE + TLS::TLS_HEADER_SIZE); auto read = parse_records(full_record); result.confirm("returned 'record'", !std::holds_alternative(read)); + result.end_timer(); }), CHECK("received too many bytes in one protected record", [&](auto& result) { + result.start_timer(); std::vector huge_record{'\x17', '\x03', '\x03', '\x41', '\x01'}; huge_record.resize(TLS::MAX_CIPHERTEXT_SIZE_TLS13 + TLS::TLS_HEADER_SIZE + 1); result.test_throws("record too big", "Received an encrypted record that exceeds maximum size", [&] { parse_records(huge_record); }); + result.end_timer(); }), CHECK("decryption would result in too large plaintext", [&](auto& result) { + result.start_timer(); // In this case the ciphertext is within the allowed bounds, but the // decrypted plaintext would be too large. std::vector huge_record{'\x17', '\x03', '\x03', '\x40', '\x12'}; @@ -239,35 +260,43 @@ std::vector basic_sanitization_parse_records(TLS::Connection_Side result.test_throws("record too big", "Received an encrypted record that exceeds maximum plaintext size", [&] { parse_records(huge_record, cs.get()); }); + result.end_timer(); }), CHECK("received too many bytes in one unprotected record", [&](auto& result) { + result.start_timer(); std::vector huge_record{'\x16', '\x03', '\x03', '\x40', '\x01'}; huge_record.resize(TLS::MAX_PLAINTEXT_SIZE + TLS::TLS_HEADER_SIZE + 1); result.test_throws("record too big", "Received a record that exceeds maximum size", [&] { parse_records(huge_record); }); + result.end_timer(); }), CHECK("invalid record type", [&](auto& result) { + result.start_timer(); std::vector invalid_record_type{'\x42', '\x03', '\x03', '\x41', '\x01'}; result.test_throws("invalid record type", "TLS record type had unexpected value", [&] { parse_records(invalid_record_type); }); + result.end_timer(); }), CHECK("invalid record version", [&](auto& result) { + result.start_timer(); std::vector invalid_record_version{'\x17', '\x13', '\x37', '\x00', '\x01', '\x42'}; result.test_throws("invalid record version", "Received unexpected record version", [&] { parse_records(invalid_record_version); }); + result.end_timer(); }), CHECK("initial received record versions might be 0x03XX ", [&](auto& result) { + result.start_timer(); auto rl = record_layer_client(); rl.copy_data(std::vector{0x16, 0x03, 0x00, 0x00, 0x01, 0x42}); result.test_no_throw("0x03 0x00 should be fine for first records", [&] { rl.next_record(); }); @@ -288,14 +317,17 @@ std::vector basic_sanitization_parse_records(TLS::Connection_Side rl.copy_data(std::vector{0x16, 0x03, 0x01, 0x00, 0x01, 0x42}); result.test_throws("0x03 0x01 not okay once client hello was received", [&] { rl.next_record(); }); + result.end_timer(); }), CHECK("malformed change cipher spec", [&](auto& result) { + result.start_timer(); std::vector invalid_ccs_record{'\x14', '\x03', '\x03', '\x00', '\x01', '\x02'}; result.test_throws("invalid CCS record", "malformed change cipher spec record received", [&] { parse_records(invalid_ccs_record); }); + result.end_timer(); }) }; @@ -323,6 +355,7 @@ std::vector read_fragmented_records() { return {CHECK("change cipher spec in many small pieces", [&](auto& result) { + result.start_timer(); std::vector ccs_record{'\x14', '\x03', '\x03', '\x00', '\x01', '\x01'}; wait_for_more_bytes(4, rl, {'\x14'}, result); @@ -340,9 +373,11 @@ std::vector read_fragmented_records() { result.test_eq("CCS byte is 0x01", rec1.fragment, Botan::hex_decode("01")); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); }), CHECK("two change cipher specs in several pieces", [&](auto& result) { + result.start_timer(); wait_for_more_bytes(1, rl, {'\x14', '\x03', '\x03', '\x00'}, result); rl.copy_data(std::vector{'\x01', '\x01', /* second CCS starts here */ '\x14', '\x03'}); @@ -364,6 +399,7 @@ std::vector read_fragmented_records() { result.confirm("received CCS", rec3.type == TLS::Record_Type::ChangeCipherSpec); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); })}; } @@ -372,14 +408,17 @@ std::vector write_records() { return { CHECK("prepare an zero-length application data fragment", [&](auto& result) { + result.start_timer(); auto record = record_layer_client().prepare_records(Botan::TLS::Record_Type::ApplicationData, {}, cs.get()); result.require("record header was added", record.size() > Botan::TLS::TLS_HEADER_SIZE + 1 /* encrypted content type */); + result.end_timer(); }), CHECK("prepare a client hello", [&](auto& result) { + result.start_timer(); const auto client_hello_msg = Botan::hex_decode( // from RFC 8448 "01 00 00 c0 03 03 cb" "34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12" @@ -399,30 +438,37 @@ std::vector write_records() { const auto header = std::vector(record.cbegin(), record.cbegin() + Botan::TLS::TLS_HEADER_SIZE); result.test_eq("record header is well-formed", header, Botan::hex_decode("16030100c4")); + result.end_timer(); }), CHECK("prepare a dummy CCS", [&](auto& result) { + result.start_timer(); std::array ccs_content = {0x01}; auto record = record_layer_client(true).prepare_records(Botan::TLS::Record_Type::ChangeCipherSpec, ccs_content); result.require("record was created", record.size() == Botan::TLS::TLS_HEADER_SIZE + 1); result.test_eq("CCS record is well-formed", record, Botan::hex_decode("140303000101")); + result.end_timer(); }), CHECK("cannot prepare non-dummy CCS", [&](auto& result) { + result.start_timer(); result.test_throws("cannot create non-dummy CCS", "TLS 1.3 deprecated CHANGE_CIPHER_SPEC", [] { const auto ccs_content = Botan::hex_decode("de ad be ef"); record_layer_client().prepare_records(Botan::TLS::Record_Type::ChangeCipherSpec, ccs_content); }); + result.end_timer(); }), CHECK("large messages are sharded", [&](auto& result) { + result.start_timer(); const std::vector large_client_hello(Botan::TLS::MAX_PLAINTEXT_SIZE + 4096); auto record = record_layer_client().prepare_records(Botan::TLS::Record_Type::Handshake, large_client_hello); result.test_gte("produces at least two record headers", record.size(), large_client_hello.size() + 2 * Botan::TLS::TLS_HEADER_SIZE); + result.end_timer(); })}; } @@ -514,6 +560,7 @@ std::vector read_encrypted_records() { return { CHECK("read encrypted server hello extensions", [&](Test::Result& result) { + result.start_timer(); auto cs = rfc8448_rtt1_handshake_traffic(); auto rl = parse_records(encrypted_record); @@ -525,10 +572,12 @@ std::vector read_encrypted_records() { result.test_eq("decrypted payload length", record.fragment.size(), 657 /* taken from RFC 8448 */); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); }), CHECK("premature application data", [&](Test::Result& result) { + result.start_timer(); auto rl = record_layer_client(true); rl.copy_data(encrypted_record); @@ -536,10 +585,12 @@ std::vector read_encrypted_records() { "cannot process encrypted data with uninitialized cipher state", "premature Application Data received", [&] { auto res = rl.next_record(nullptr); }); + result.end_timer(); }), CHECK("decryption fails due to bad MAC", [&](Test::Result& result) { + result.start_timer(); auto tampered_encrypted_record = encrypted_record; tampered_encrypted_record.back() = '\x42'; // changing one payload byte causes the MAC check to fails @@ -548,10 +599,12 @@ std::vector read_encrypted_records() { auto rl = parse_records(tampered_encrypted_record); rl.next_record(cs.get()); }); + result.end_timer(); }), CHECK("decryption fails due to too short record", [&](Test::Result& result) { + result.start_timer(); const auto short_record = Botan::hex_decode("17 03 03 00 08 de ad be ef ba ad f0 0d"); result.test_throws("too short to decrypt", [&] { @@ -559,10 +612,12 @@ std::vector read_encrypted_records() { auto rl = parse_records(short_record); rl.next_record(cs.get()); }); + result.end_timer(); }), CHECK("protected Change Cipher Spec message is illegal", [&](Test::Result& result) { + result.start_timer(); // factored message, encrypted under the same key as `encrypted_record` const auto protected_ccs = Botan::hex_decode("1703030012D8EBBBE055C8167D5690EC67DEA9A525B036"); @@ -572,10 +627,12 @@ std::vector read_encrypted_records() { auto rl = parse_records(protected_ccs); rl.next_record(cs.get()); }); + result.end_timer(); }), CHECK("unprotected CCS is legal when encrypted traffic is expected", [&](Test::Result& result) { + result.start_timer(); const auto ccs_record = Botan::hex_decode("14 03 03 00 01 01"); result.test_no_throw("CCS is acceptable", [&] { @@ -583,10 +640,12 @@ std::vector read_encrypted_records() { auto rl = parse_records(ccs_record); rl.next_record(cs.get()); }); + result.end_timer(); }), CHECK("unprotected Alert message might be legal", [&](Test::Result& result) { + result.start_timer(); const auto alert = Botan::hex_decode("15030300020232"); // decode error const auto hsmsg = Botan::hex_decode( // factored 'certificate_request' message "160303002a0d000027000024000d0020001e040305030603" @@ -624,19 +683,23 @@ std::vector read_encrypted_records() { auto rl = parse_records(hsmsg); rl.next_record(cs.get()); }); + result.end_timer(); }), CHECK("unprotected traffic is illegal when encrypted traffic is expected", [&](Test::Result& result) { + result.start_timer(); result.test_throws("unprotected record is unacceptable", [&] { auto cs = rfc8448_rtt1_handshake_traffic(); // expect encrypted traffic auto rl = parse_records(server_hello); rl.next_record(cs.get()); }); + result.end_timer(); }), CHECK("read fragmented application data", [&](Test::Result& result) { + result.start_timer(); const auto encrypted = Botan::hex_decode( "17 03 03 00 1A 90 78 6D 7E 6F A8 F7 67 1F 6D 05 F7 24 18 F5 DB 43 F7 0B 9E 48 A6 96 B6 5B EC" "17 03 03 00 28 6C 21 B5 B8 D8 1B 85 5C 17 0E C7 9B 2C 28 85 85 51 29 2F 71 14 F3 D7 BD D5 D1" @@ -673,11 +736,13 @@ std::vector read_encrypted_records() { result.test_eq("third record", records.fragment, plaintext_records.at(2)); result.confirm("no more records", std::holds_alternative(rl.next_record())); + result.end_timer(); }), CHECK( "read coalesced server hello and encrypted extensions", [&](Test::Result& result) { + result.start_timer(); // contains the plaintext server hello and the encrypted extensions in one go auto coalesced = server_hello; coalesced.insert(coalesced.end(), encrypted_record.cbegin(), encrypted_record.cend()); @@ -693,25 +758,30 @@ std::vector read_encrypted_records() { const auto enc_exts = client.next_record(cs.get()); result.confirm("read a record", std::holds_alternative(enc_exts)); result.confirm("is handshake record", std::get(enc_exts).type == TLS::Record_Type::Handshake); + result.end_timer(); }), CHECK("read a padded record", [&](Test::Result& result) { + result.start_timer(); auto client = record_layer_client(true); client.copy_data(encrypted_record_with_padding); auto cs = rfc8448_rtt1_handshake_traffic(); const auto record = client.next_record(cs.get()); result.confirm("read a record with padding", std::holds_alternative(record)); + result.end_timer(); }), CHECK("read an empty encrypted record", [&](Test::Result& result) { + result.start_timer(); auto client = record_layer_client(true); client.copy_data(Botan::hex_decode("1703030011CE43CA0D2F28336715E770071B2D5EE0FE")); auto cs = rfc8448_rtt1_handshake_traffic(); const auto record = client.next_record(cs.get()); result.confirm("read an empty record", std::holds_alternative(record)); + result.end_timer(); })}; } @@ -724,6 +794,7 @@ std::vector write_encrypted_records() { return { CHECK("write encrypted client handshake finished", [&](Test::Result& result) { + result.start_timer(); auto ct = record_layer_client(true).prepare_records(TLS::Record_Type::Handshake, plaintext_msg, cs.get()); auto expected_ct = Botan::hex_decode( @@ -731,19 +802,23 @@ std::vector write_encrypted_records() { "0b 29 80 44 a7 1e 21 9c 56 cc 77 b0 51 7f e9 b9 3c 7a 4b fc 44 d8 7f" "38 f8 03 38 ac 98 fc 46 de b3 84 bd 1c ae ac ab 68 67 d7 26 c4 05 46"); result.test_eq("produced the expected ciphertext", ct, expected_ct); + result.end_timer(); }), CHECK("write a dummy CCS (that must not be encrypted)", [&](auto& result) { + result.start_timer(); std::array ccs_content = {0x01}; auto record = record_layer_client(true).prepare_records( Botan::TLS::Record_Type::ChangeCipherSpec, ccs_content, cs.get()); result.require("record was created and not encrypted", record.size() == Botan::TLS::TLS_HEADER_SIZE + 1); result.test_eq("CCS record is well-formed", record, Botan::hex_decode("140303000101")); + result.end_timer(); }), CHECK("write a lot of data producing two protected records", [&](Test::Result& result) { + result.start_timer(); std::vector big_data(TLS::MAX_PLAINTEXT_SIZE + TLS::MAX_PLAINTEXT_SIZE / 2); auto ct = record_layer_client(true).prepare_records(TLS::Record_Type::ApplicationData, big_data, cs.get()); result.require("encryption added some MAC and record headers", @@ -768,6 +843,7 @@ std::vector write_encrypted_records() { reader.discard_next(fragment_length2); result.confirm("consumed all bytes", !reader.has_remaining()); + result.end_timer(); })}; } @@ -801,6 +877,7 @@ std::vector legacy_version_handling() { return {CHECK("client side starts with version 0x0301", [&](Test::Result& result) { + result.start_timer(); auto rl = record_layer_client(); auto rec = rl.prepare_records(TLS::Record_Type::Handshake, std::vector(5)); result.confirm("first record has version 0x0301", has_version(rec, 0x0301)); @@ -809,10 +886,12 @@ std::vector legacy_version_handling() { rec = rl.prepare_records(TLS::Record_Type::Handshake, std::vector(5)); result.confirm("next record has version 0x0303", has_version(rec, 0x0303)); + result.end_timer(); }), CHECK("client side starts with version 0x0301 (even if multiple reconds are required)", [&](Test::Result& result) { + result.start_timer(); auto rl = record_layer_client(); auto rec = rl.prepare_records(TLS::Record_Type::Handshake, std::vector(5 * Botan::TLS::MAX_PLAINTEXT_SIZE)); @@ -823,51 +902,63 @@ std::vector legacy_version_handling() { rec = rl.prepare_records(TLS::Record_Type::Handshake, std::vector(5 * Botan::TLS::MAX_PLAINTEXT_SIZE)); result.confirm("next record has version 0x0303", has_version(rec, 0x0303)); + result.end_timer(); }), CHECK("server side starts with version 0x0303", [&](Test::Result& result) { + result.start_timer(); auto rl = record_layer_server(true); auto rec = rl.prepare_records(TLS::Record_Type::Handshake, std::vector(5)); result.confirm("first record has version 0x0303", has_version(rec, 0x0303)); + result.end_timer(); }), CHECK("server side accepts version 0x0301 for the first record", [&](Test::Result& result) { + result.start_timer(); const auto first_record = Botan::hex_decode("16 03 01 00 05 00 00 00 00 00"); const auto second_record = Botan::hex_decode("16 03 03 00 05 00 00 00 00 00"); auto rl = record_layer_server(); result.test_no_throw("parsing initial record", [&] { parse_record(rl, first_record); }); result.test_no_throw("parsing second record", [&] { parse_record(rl, second_record); }); + result.end_timer(); }), CHECK("server side accepts version 0x0301 for the first record for partial records", [&](Test::Result& result) { + result.start_timer(); const auto first_part = Botan::hex_decode("16 03 01"); const auto second_part = Botan::hex_decode("00 05 00 00 00 00 00"); auto rl = record_layer_server(); result.test_no_throw("parsing initial part", [&] { parse_record(rl, first_part); }); result.test_no_throw("parsing second part", [&] { parse_record(rl, second_part); }); + result.end_timer(); }), CHECK("server side accepts version 0x0303 for the first record", [&](Test::Result& result) { + result.start_timer(); const auto first_record = Botan::hex_decode("16 03 03 00 05 00 00 00 00 00"); auto rl = record_layer_server(); result.test_no_throw("parsing initial record", [&] { parse_record(rl, first_record); }); + result.end_timer(); }), CHECK("server side does not accept version 0x0301 after receiving client hello", [&](Test::Result& result) { + result.start_timer(); const auto record = Botan::hex_decode("16 03 01 00 05 00 00 00 00 00"); auto rl = record_layer_server(); result.test_no_throw("parsing initial record", [&] { parse_record(rl, record); }); rl.disable_receiving_compat_mode(); result.test_throws("parsing second record", [&] { parse_record(rl, record); }); + result.end_timer(); }), CHECK("server side does not accept other versions (after receiving client hello)", [&](Test::Result& result) { + result.start_timer(); auto rl = record_layer_server(true); result.test_throws("does not accept 0x0300", [&] { parse_record(rl, Botan::hex_decode("16 03 00 00 05 00 00 00 00 00")); }); @@ -877,6 +968,7 @@ std::vector legacy_version_handling() { [&] { parse_record(rl, Botan::hex_decode("16 03 04 00 05 00 00 00 00 00")); }); result.test_throws("does not accept 0x0305", [&] { parse_record(rl, Botan::hex_decode("16 03 05 00 05 00 00 00 00 00")); }); + result.end_timer(); }) }; @@ -905,6 +997,7 @@ std::vector record_size_limits() { return { CHECK("no specified limits means protocol defaults", [&](Test::Result& result) { + result.start_timer(); auto csc = rfc8448_rtt1_handshake_traffic(Botan::TLS::Connection_Side::Client); auto rlc = record_layer_client(true); @@ -924,10 +1017,12 @@ std::vector record_size_limits() { result.test_eq("correct length record", record_length(result, rls.next_record(css.get())), Botan::TLS::MAX_PLAINTEXT_SIZE); + result.end_timer(); }), CHECK("outgoing record size limit", [&](Test::Result& result) { + result.start_timer(); auto cs = rfc8448_rtt1_handshake_traffic(); auto rl = record_layer_client(true); @@ -940,11 +1035,13 @@ std::vector record_size_limits() { const auto r2 = rl.prepare_records(TLS::Record_Type::ApplicationData, std::vector(128), cs.get()); result.test_eq("two records generated", count_records(r2), 2); + result.end_timer(); }), CHECK( "outgoing record size limit can be changed", [&](Test::Result& result) { + result.start_timer(); auto cs = rfc8448_rtt1_handshake_traffic(); auto rl = record_layer_client(true); @@ -963,10 +1060,12 @@ std::vector record_size_limits() { const auto r4 = rl.prepare_records(TLS::Record_Type::ApplicationData, std::vector(128), cs.get()); result.test_eq("two records generated", count_records(r4), 2); + result.end_timer(); }), CHECK("outgoing record limit does not affect unencrypted records", [&](Test::Result& result) { + result.start_timer(); auto rl = record_layer_client(true); rl.set_record_size_limits(127 + 1 /* content type byte */, Botan::TLS::MAX_PLAINTEXT_SIZE + 1); @@ -978,20 +1077,24 @@ std::vector record_size_limits() { const auto r2 = rl.prepare_records(TLS::Record_Type::Handshake, std::vector(Botan::TLS::MAX_PLAINTEXT_SIZE + 1)); result.test_eq("two records generated", count_records(r2), 2); + result.end_timer(); }), CHECK("incoming limit is not checked on unprotected records", [&](Test::Result& result) { + result.start_timer(); auto rlc = record_layer_client(true); rlc.set_record_size_limits(Botan::TLS::MAX_PLAINTEXT_SIZE + 1, 95 + 1); rlc.copy_data(Botan::concat(Botan::hex_decode("16 03 03 00 80"), std::vector(128))); result.test_eq("correct length record", record_length(result, rlc.next_record()), 128); + result.end_timer(); }), CHECK("incoming limit is checked on protected records", [&](Test::Result& result) { + result.start_timer(); auto css = rfc8448_rtt1_handshake_traffic(Botan::TLS::Connection_Side::Server); auto rls = record_layer_server(true); @@ -1015,6 +1118,7 @@ std::vector record_size_limits() { result.test_throws("overflow detected", "Received an encrypted record that exceeds maximum plaintext size", [&] { rls.next_record(css.get()); }); + result.end_timer(); }), }; } diff --git a/src/tests/test_tls_rfc8448.cpp b/src/tests/test_tls_rfc8448.cpp index 39070bd138f..889a70f66cf 100644 --- a/src/tests/test_tls_rfc8448.cpp +++ b/src/tests/test_tls_rfc8448.cpp @@ -1000,6 +1000,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { return { CHECK("Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique(rng, std::make_shared("rfc8448_1rtt"), vars.get_req_u64("CurrentTimestamp"), @@ -1018,10 +1019,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq( "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1")); + result.end_timer(); }), CHECK("Server Hello", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto server_hello = vars.get_req_bin("Record_ServerHello"); // splitting the input data to test partial reads @@ -1040,10 +1043,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.confirm("client is not yet active", !ctx->client.is_active()); result.confirm("handshake is not yet complete", !ctx->client.is_handshake_complete()); + result.end_timer(); }), CHECK("Server HS messages .. Client Finished", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages")); @@ -1069,10 +1074,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq("correct handshake finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished")); + result.end_timer(); }), CHECK("Post-Handshake: NewSessionTicket", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); result.require("no sessions so far", ctx->stored_sessions().empty()); ctx->client.received_data(vars.get_req_bin("Record_NewSessionTicket")); @@ -1089,10 +1096,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { Botan::unlock(stored_session.DER_encode()), vars.get_req_bin("Client_SessionData")); } + result.end_timer(); }), CHECK("Send Application Data", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->send(vars.get_req_bin("Client_AppData")); @@ -1101,10 +1110,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq("correct client application data", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_AppData")); + result.end_timer(); }), CHECK("Receive Application Data", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_Server_AppData")); @@ -1113,10 +1124,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { const auto rcvd = ctx->pull_receive_buffer(); result.test_eq("decrypted application traffic", rcvd, vars.get_req_bin("Server_AppData")); result.test_is_eq("sequence number", ctx->last_received_seq_no(), uint64_t(1)); + result.end_timer(); }), CHECK("Close Connection", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.close(); @@ -1129,6 +1142,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result, "CLOSE_NOTIFY received", {"tls_alert", "tls_peer_closed_connection"}); result.confirm("connection is closed", ctx->client.is_closed()); + result.end_timer(); }), }; } @@ -1162,6 +1176,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { return { CHECK("Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique( std::move(rng), std::make_shared("rfc8448_1rtt"), @@ -1183,6 +1198,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq( "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1")); + result.end_timer(); }) // TODO: The rest of this test vector requires 0-RTT which is not @@ -1226,6 +1242,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { return { CHECK("Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique(std::move(rng), std::make_shared("rfc8448_hrr_client"), vars.get_req_u64("CurrentTimestamp"), @@ -1244,10 +1261,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq( "TLS client hello (1)", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1")); + result.end_timer(); }), CHECK("Hello Retry Request .. second Client Hello", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_HelloRetryRequest")); @@ -1264,10 +1283,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq( "TLS client hello (2)", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_2")); + result.end_timer(); }), CHECK("Server Hello", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHello")); @@ -1278,10 +1299,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { "tls_examine_extensions_server_hello", "tls_ephemeral_key_agreement", }); + result.end_timer(); }), CHECK("Server HS Messages .. Client Finished", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages")); @@ -1302,10 +1325,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq( "client finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished")); + result.end_timer(); }), CHECK("Close Connection", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.close(); ctx->check_callback_invocations( @@ -1318,6 +1343,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result, "encrypted handshake messages received", {"tls_alert", "tls_peer_closed_connection"}); result.confirm("connection is closed", ctx->client.is_closed()); + result.end_timer(); }), }; } @@ -1343,6 +1369,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { return { CHECK("Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique(std::move(rng), std::make_shared("rfc8448_1rtt"), vars.get_req_u64("CurrentTimestamp"), @@ -1362,10 +1389,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { }); result.test_eq("Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1")); + result.end_timer(); }), CHECK("Server Hello", [&](auto& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHello")); @@ -1376,10 +1405,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_server_hello", "tls_ephemeral_key_agreement", }); + result.end_timer(); }), CHECK("other handshake messages and client auth", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages")); @@ -1408,10 +1439,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { // Messages: Certificate, CertificateVerify, Finished result.test_eq( "Client Auth and Finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished")); + result.end_timer(); }), CHECK("Close Connection", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.close(); result.test_eq( @@ -1428,6 +1461,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { ctx->check_callback_invocations( result, "after receiving close notify", {"tls_alert", "tls_peer_closed_connection"}); + result.end_timer(); }), }; } @@ -1454,6 +1488,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { return { CHECK("Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique(std::move(rng), std::make_shared("rfc8448_compat_client"), @@ -1471,10 +1506,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { "tls_generate_ephemeral_key", "tls_current_timestamp", }); + result.end_timer(); }), CHECK("Server Hello + other handshake messages", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data( Botan::concat(vars.get_req_bin("Record_ServerHello"), @@ -1508,10 +1545,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.confirm("client is ready to send application traffic", ctx->client.is_active()); result.confirm("handshake is complete", ctx->client.is_handshake_complete()); + result.end_timer(); }), CHECK("Close connection", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.close(); @@ -1525,6 +1564,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify")); result.confirm("client connection was terminated", ctx->client.is_closed()); + result.end_timer(); }), }; } @@ -1560,6 +1600,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { return { CHECK("Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique( std::move(rng), std::make_shared("rfc8448_psk_dhe", false /* no rfc8448 */), @@ -1583,10 +1624,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq( "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1")); + result.end_timer(); }), CHECK("Server Hello", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto server_hello = vars.get_req_bin("Record_ServerHello"); ctx->client.received_data(server_hello); @@ -1598,11 +1641,13 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.confirm("client is not yet active", !ctx->client.is_active()); result.confirm("handshake is not yet complete", !ctx->client.is_handshake_complete()); + result.end_timer(); }), CHECK( "Server HS messages .. Client Finished", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages")); @@ -1621,10 +1666,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq( "correct handshake finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished")); + result.end_timer(); }), CHECK("Send Application Data", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->send(vars.get_req_bin("Client_AppData")); @@ -1633,10 +1680,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result.test_eq("correct client application data", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_AppData")); + result.end_timer(); }), CHECK("Receive Application Data", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_Server_AppData")); @@ -1645,10 +1694,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { const auto rcvd = ctx->pull_receive_buffer(); result.test_eq("decrypted application traffic", rcvd, vars.get_req_bin("Server_AppData")); result.test_is_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0)); + result.end_timer(); }), CHECK("Close Connection", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.close(); @@ -1661,6 +1712,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { result, "CLOSE_NOTIFY received", {"tls_alert", "tls_peer_closed_connection"}); result.confirm("connection is closed", ctx->client.is_closed()); + result.end_timer(); }), }; } @@ -1698,6 +1750,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { return { CHECK("Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique(std::move(rng), std::make_shared("rfc8448_rawpubkey"), vars.get_req_u64("CurrentTimestamp"), @@ -1717,10 +1770,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { }); result.test_eq("Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1")); + result.end_timer(); }), CHECK("Server Hello", [&](auto& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHello")); @@ -1731,10 +1786,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_server_hello", "tls_ephemeral_key_agreement", }); + result.end_timer(); }), CHECK("other handshake messages and client auth", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages")); @@ -1768,10 +1825,12 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { // Messages: Certificate, CertificateVerify, Finished result.test_eq( "Client Auth and Finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished")); + result.end_timer(); }), CHECK("Close Connection", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->client.close(); result.test_eq( @@ -1788,6 +1847,7 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 { ctx->check_callback_invocations( result, "after receiving close notify", {"tls_alert", "tls_peer_closed_connection"}); + result.end_timer(); }), }; } @@ -1810,6 +1870,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { return { CHECK("Send Client Hello", [&](Test::Result& result) { + result.start_timer(); auto add_early_data_and_sort = [&](Botan::TLS::Extensions& exts, Botan::TLS::Connection_Side side, Botan::TLS::Handshake_Type type) { @@ -1848,10 +1909,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_certificate", "tls_inspect_handshake_msg_certificate_verify", "tls_inspect_handshake_msg_finished"}); + result.end_timer(); }), CHECK("Verify generated messages in server's first flight", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto& msgs = ctx->observed_handshake_messages(); @@ -1880,10 +1943,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { // the handshake is not yet finished. result.confirm("Server can now send application data", ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Send Client Finished", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_ClientFinished")); @@ -1893,10 +1958,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_current_timestamp", "tls_session_established", "tls_session_activated"}); + result.end_timer(); }), CHECK("Send Session Ticket", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto new_tickets = ctx->server.send_new_session_tickets(1); @@ -1909,17 +1976,21 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_emit_data", "tls_modify_extensions_new_session_ticket", "tls_should_persist_resumption_information"}); + result.end_timer(); }), CHECK("Verify generated new session ticket message", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); result.test_eq( "New Session Ticket", ctx->pull_send_buffer(), vars.get_req_bin("Record_NewSessionTicket")); + result.end_timer(); }), CHECK("Receive Application Data", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_AppData")); ctx->check_callback_invocations(result, "application data received", {"tls_record_received"}); @@ -1927,10 +1998,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { const auto rcvd = ctx->pull_receive_buffer(); result.test_eq("decrypted application traffic", rcvd, vars.get_req_bin("Client_AppData")); result.test_is_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0)); + result.end_timer(); }), CHECK("Send Application Data", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->send(vars.get_req_bin("Server_AppData")); @@ -1939,10 +2012,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("correct server application data", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_AppData")); + result.end_timer(); }), CHECK("Receive Client's close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify")); @@ -1952,10 +2027,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("connection is not yet closed", !ctx->server.is_closed()); result.confirm("connection is still active", ctx->server.is_active()); result.confirm("handshake is still finished", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Expect Server close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.close(); @@ -1965,6 +2042,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("Server's close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_CloseNotify")); + result.end_timer(); }), }; } @@ -1981,6 +2059,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { return { CHECK("Receive Client Hello", [&](Test::Result& result) { + result.start_timer(); auto add_cookie_and_sort = [&](Botan::TLS::Extensions& exts, Botan::TLS::Connection_Side side, Botan::TLS::Handshake_Type type) { @@ -2018,10 +2097,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_encrypted_extensions", "tls_inspect_handshake_msg_finished", }); + result.end_timer(); }), CHECK("Verify generated messages in server's first flight", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto& msgs = ctx->observed_handshake_messages(); @@ -2044,6 +2125,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { // the handshake is not yet finished. result.confirm("Server can now send application data", ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); + result.end_timer(); }), // TODO: The rest of this test vector requires 0-RTT which is not @@ -2066,6 +2148,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { return { CHECK("Receive Client Hello", [&](Test::Result& result) { + result.start_timer(); auto add_cookie_and_sort = [&](Botan::TLS::Extensions& exts, Botan::TLS::Connection_Side side, Botan::TLS::Handshake_Type type) { @@ -2092,20 +2175,24 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_modify_extensions_hello_retry_request", "tls_inspect_handshake_msg_client_hello", "tls_inspect_handshake_msg_hello_retry_request"}); + result.end_timer(); }), CHECK("Verify generated Hello Retry Request message", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); result.test_eq("Server's Hello Retry Request record", ctx->pull_send_buffer(), vars.get_req_bin("Record_HelloRetryRequest")); result.confirm("TLS handshake not yet finished", !ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Receive updated Client Hello message", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_ClientHello_2")); @@ -2125,10 +2212,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_certificate", "tls_inspect_handshake_msg_certificate_verify", "tls_inspect_handshake_msg_finished"}); + result.end_timer(); }), CHECK("Verify generated messages in server's second flight", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto& msgs = ctx->observed_handshake_messages(); @@ -2155,10 +2244,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("Server could now send application data", ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); // See RFC 8446 4.4.4 + result.end_timer(); }), CHECK("Receive Client Finished", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_ClientFinished")); @@ -2171,10 +2262,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("TLS handshake finished", ctx->server.is_active()); result.confirm("handshake is complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Receive Client close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify")); @@ -2184,10 +2277,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("connection is not yet closed", !ctx->server.is_closed()); result.confirm("connection is still active", ctx->server.is_active()); result.confirm("handshake is still complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Expect Server close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.close(); @@ -2197,6 +2292,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("Server's close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_CloseNotify")); + result.end_timer(); }), }; @@ -2214,6 +2310,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { return { CHECK("Receive Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique( std::move(rng), std::make_shared("rfc8448_client_auth_server"), @@ -2243,10 +2340,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_certificate", "tls_inspect_handshake_msg_certificate_verify", "tls_inspect_handshake_msg_finished"}); + result.end_timer(); }), CHECK("Verify server's generated handshake messages", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto& msgs = ctx->observed_handshake_messages(); @@ -2278,10 +2377,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("Server could now send application data", ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); // See RFC 8446 4.4.4 + result.end_timer(); }), CHECK("Receive Client's second flight", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); // This encrypted message contains the following messages: // * client's Certificate message @@ -2307,10 +2408,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("TLS handshake finished", ctx->server.is_active()); result.confirm("handshake is complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Receive Client close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify")); @@ -2320,10 +2423,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("connection is not yet closed", !ctx->server.is_closed()); result.confirm("connection is still active", ctx->server.is_active()); result.confirm("handshake is still complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Expect Server close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.close(); @@ -2333,6 +2438,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("Server's close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_CloseNotify")); + result.end_timer(); }), }; @@ -2350,6 +2456,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { return { CHECK("Receive Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique(std::move(rng), std::make_shared("rfc8448_compat_server"), @@ -2376,10 +2483,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_certificate", "tls_inspect_handshake_msg_certificate_verify", "tls_inspect_handshake_msg_finished"}); + result.end_timer(); }), CHECK("Verify server's generated handshake messages", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto& msgs = ctx->observed_handshake_messages(); @@ -2408,10 +2517,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("Server could now send application data", ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); // See RFC 8446 4.4.4 + result.end_timer(); }), CHECK("Receive Client Finished", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_ClientFinished")); @@ -2424,10 +2535,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("TLS handshake fully finished", ctx->server.is_active()); result.confirm("handshake is complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Receive Client close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify")); @@ -2437,10 +2550,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("connection is not yet closed", !ctx->server.is_closed()); result.confirm("connection is still active", ctx->server.is_active()); result.confirm("handshake is still complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Expect Server close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.close(); @@ -2450,6 +2565,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("Server's close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_CloseNotify")); + result.end_timer(); }), }; @@ -2467,6 +2583,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { return { CHECK("Send Client Hello", [&](Test::Result& result) { + result.start_timer(); auto sort_our_extensions = [&](Botan::TLS::Extensions& exts, Botan::TLS::Connection_Side /* side */, Botan::TLS::Handshake_Type type) { @@ -2517,10 +2634,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_server_hello", "tls_inspect_handshake_msg_encrypted_extensions", "tls_inspect_handshake_msg_finished"}); + result.end_timer(); }), CHECK("Verify generated messages in server's first flight", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto& msgs = ctx->observed_handshake_messages(); @@ -2542,10 +2661,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("Server can now send application data", ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); // See RFC 8446 4.4.4 + result.end_timer(); }), CHECK("Send Client Finished", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_ClientFinished")); result.require("PSK negotiated", @@ -2557,10 +2678,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_current_timestamp", "tls_session_established", "tls_session_activated"}); + result.end_timer(); }), CHECK("Exchange Application Data", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_AppData")); ctx->check_callback_invocations(result, "application data received", {"tls_record_received"}); @@ -2574,10 +2697,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("correct server application data", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_AppData")); + result.end_timer(); }), CHECK("Terminate Connection", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify")); @@ -2596,6 +2721,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("Server's close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_CloseNotify")); + result.end_timer(); }), }; } @@ -2636,6 +2762,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { return { CHECK("Receive Client Hello", [&](Test::Result& result) { + result.start_timer(); ctx = std::make_unique(std::move(rng), std::make_shared("rfc8448_rawpubkey"), vars.get_req_u64("CurrentTimestamp"), @@ -2663,10 +2790,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { "tls_inspect_handshake_msg_certificate", "tls_inspect_handshake_msg_certificate_verify", "tls_inspect_handshake_msg_finished"}); + result.end_timer(); }), CHECK("Verify server's generated handshake messages", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); const auto& msgs = ctx->observed_handshake_messages(); @@ -2698,10 +2827,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("Server could now send application data", ctx->server.is_active()); result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete()); // See RFC 8446 4.4.4 + result.end_timer(); }), CHECK("Receive Client's second flight", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); // This encrypted message contains the following messages: // * client's Certificate message @@ -2728,10 +2859,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("TLS handshake finished", ctx->server.is_active()); result.confirm("handshake is complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Receive Client close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify")); @@ -2741,10 +2874,12 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.confirm("connection is not yet closed", !ctx->server.is_closed()); result.confirm("connection is still active", ctx->server.is_active()); result.confirm("handshake is still complete", ctx->server.is_handshake_complete()); + result.end_timer(); }), CHECK("Expect Server close_notify", [&](Test::Result& result) { + result.start_timer(); result.require("ctx is available", ctx != nullptr); ctx->server.close(); @@ -2754,6 +2889,7 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 { result.test_eq("Server's close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Server_CloseNotify")); + result.end_timer(); }), }; } diff --git a/src/tests/test_tls_session_manager.cpp b/src/tests/test_tls_session_manager.cpp index a9fd20e59fe..e3fb6834c5d 100644 --- a/src/tests/test_tls_session_manager.cpp +++ b/src/tests/test_tls_session_manager.cpp @@ -152,6 +152,7 @@ std::vector test_session_manager_in_memory() { CHECK("empty cache does not obtain anything", [&](auto& result) { + result.start_timer(); result.confirm("no session found via server info", mgr->find(server_info, cbs, plcy).empty()); Botan::TLS::Session_ID mock_id = random_id(*rng); @@ -159,23 +160,31 @@ std::vector test_session_manager_in_memory() { result.confirm("no session found via ID", !mgr->retrieve(mock_id, cbs, plcy)); result.confirm("no session found via ID", !mgr->retrieve(mock_ticket, cbs, plcy)); + result.end_timer(); }), CHECK("clearing empty cache", - [&](auto& result) { result.test_eq("does not delete anything", mgr->remove_all(), 0); }), + [&](auto& result) { + result.start_timer(); + result.test_eq("does not delete anything", mgr->remove_all(), 0); + result.end_timer(); + }), CHECK("establish new session", [&](auto& result) { + result.start_timer(); auto handle = mgr->establish(default_session(Botan::TLS::Connection_Side::Server, cbs), default_id); if(result.confirm("establishment was successful", handle.has_value())) { result.require("session id was set", handle->id().has_value()); result.confirm("session ticket was empty", !handle->ticket().has_value()); result.test_is_eq("session id is correct", handle->id().value(), default_id); } + result.end_timer(); }), CHECK("obtain session from server info", [&](auto& result) { + result.start_timer(); auto sessions = mgr->find(server_info, cbs, plcy); if(result.confirm("session was found successfully", sessions.size() == 1)) { result.test_is_eq("protocol version was echoed", @@ -185,10 +194,12 @@ std::vector test_session_manager_in_memory() { result.test_is_eq("ID was echoed", sessions[0].handle.id().value(), default_id); result.confirm("not a ticket", !sessions[0].handle.ticket().has_value()); } + result.end_timer(); }), CHECK("obtain session from ID", [&](auto& result) { + result.start_timer(); auto session = mgr->retrieve(default_id, cbs, plcy); if(result.confirm("session was found successfully", session.has_value())) { result.test_is_eq("protocol version was echoed", @@ -196,10 +207,12 @@ std::vector test_session_manager_in_memory() { Botan::TLS::Protocol_Version(Botan::TLS::Version_Code::TLS_V12)); result.test_is_eq("ciphersuite was echoed", session->ciphersuite_code(), uint16_t(0x009C)); } + result.end_timer(); }), CHECK("obtain session from ID disguised as opaque handle", [&](auto& result) { + result.start_timer(); auto session = mgr->retrieve(Botan::TLS::Opaque_Session_Handle(default_id), cbs, plcy); if(result.confirm("session was found successfully", session.has_value())) { result.test_is_eq("protocol version was echoed", @@ -207,34 +220,44 @@ std::vector test_session_manager_in_memory() { Botan::TLS::Protocol_Version(Botan::TLS::Version_Code::TLS_V12)); result.test_is_eq("ciphersuite was echoed", session->ciphersuite_code(), uint16_t(0x009C)); } + result.end_timer(); }), CHECK("obtain session from ticket == id does not work", [&](auto& result) { + result.start_timer(); auto session = mgr->retrieve(Botan::TLS::Session_Ticket(default_id), cbs, plcy); result.confirm("session was not found", !session.has_value()); + result.end_timer(); }), CHECK("invalid ticket causes std::nullopt", [&](auto& result) { + result.start_timer(); auto no_session = mgr->retrieve(random_ticket(*rng), cbs, plcy); result.confirm("std::nullopt on bogus ticket", !no_session.has_value()); + result.end_timer(); }), CHECK("invalid ID causes std::nullopt", [&](auto& result) { + result.start_timer(); auto no_session = mgr->retrieve(random_id(*rng), cbs, plcy); result.confirm("std::nullopt on bogus ID", !no_session.has_value()); + result.end_timer(); }), CHECK("remove_all", [&](auto& result) { + result.start_timer(); result.test_eq("removed one element", mgr->remove_all(), 1); result.test_eq("should be empty now", mgr->remove_all(), 0); + result.end_timer(); }), CHECK("add session with ID", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_ID new_id = random_id(*rng); mgr->store(default_session(Botan::TLS::Connection_Side::Client, cbs), new_id); @@ -251,10 +274,12 @@ std::vector test_session_manager_in_memory() { } mgr->remove_all(); + result.end_timer(); }), CHECK("add session with ticket", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Ticket new_ticket = random_ticket(*rng); mgr->store(default_session(Botan::TLS::Connection_Side::Client, cbs), new_ticket); @@ -271,10 +296,12 @@ std::vector test_session_manager_in_memory() { } mgr->remove_all(); + result.end_timer(); }), CHECK("removing by ID or opaque handle", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_In_Memory local_mgr(rng); const auto new_session1 = @@ -301,10 +328,12 @@ std::vector test_session_manager_in_memory() { result.confirm("cannot obtain via ID anymore", !local_mgr.retrieve(new_session2->id().value(), cbs, plcy).has_value()); result.confirm("cannot find via server info", local_mgr.find(server_info, cbs, plcy).empty()); + result.end_timer(); }), CHECK("removing by ticket or opaque handle", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_In_Memory local_mgr(rng); Botan::TLS::Session_Ticket ticket1 = random_ticket(*rng); @@ -326,11 +355,13 @@ std::vector test_session_manager_in_memory() { size_t(1)); result.test_is_eq( "can find only one via server info", local_mgr.find(server_info, cbs, plcy).size(), size_t(1)); + result.end_timer(); }), CHECK( "session purging", [&](auto& result) { + result.start_timer(); result.require("max sessions is 5", mgr->capacity() == 5); // fill the Session_Manager up fully @@ -377,6 +408,7 @@ std::vector test_session_manager_in_memory() { // clear it all out result.test_eq("rest of the sessions removed", mgr->remove_all(), size_t(5)); + result.end_timer(); }), }; } @@ -422,6 +454,7 @@ std::vector test_session_manager_choose_ticket() { return { CHECK("empty manager has nothing to choose from", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_In_Memory mgr(rng); Botan::TLS::Session_Ticket random_session_ticket = random_ticket(*rng); @@ -432,10 +465,12 @@ std::vector test_session_manager_choose_ticket() { "empty session manager, no session", !mgr.choose_from_offered_tickets(std::vector{ticket(random_session_ticket)}, "SHA-256", cbs, plcy) .has_value()); + result.end_timer(); }), CHECK("choose ticket by ID", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_In_Memory mgr(rng); std::vector handles; @@ -459,10 +494,12 @@ std::vector test_session_manager_choose_ticket() { std::vector{ticket(random_ticket(*rng)), ticket(handles[1].id().value())}, "SHA-256", cbs, plcy); result.require("ticket was chosen and produced a session (3)", session3.has_value()); result.test_is_eq("chosen second offset", session3->second, uint16_t(1)); + result.end_timer(); }), CHECK("choose ticket by ticket", [&](auto& result) { + result.start_timer(); auto creds = std::make_shared(); Botan::TLS::Session_Manager_Stateless mgr(creds, rng); std::vector handles; @@ -487,10 +524,12 @@ std::vector test_session_manager_choose_ticket() { std::vector{ticket(random_ticket(*rng)), ticket(handles[1].ticket().value())}, "SHA-256", cbs, plcy); result.require("ticket was chosen and produced a session (3)", session3.has_value()); result.test_is_eq("chosen second offset", session3->second, uint16_t(1)); + result.end_timer(); }), CHECK("choose ticket based on requested hash function", [&](auto& result) { + result.start_timer(); auto creds = std::make_shared(); Botan::TLS::Session_Manager_Stateless mgr(creds, rng); std::vector handles; @@ -506,10 +545,12 @@ std::vector test_session_manager_choose_ticket() { plcy); result.require("ticket was chosen and produced a session", session.has_value()); result.test_is_eq("chosen second offset", session->second, uint16_t(2)); + result.end_timer(); }), CHECK("choose ticket based on protocol version", [&](auto& result) { + result.start_timer(); auto creds = std::make_shared(); Botan::TLS::Session_Manager_Stateless mgr(creds, rng); std::vector handles; @@ -527,6 +568,7 @@ std::vector test_session_manager_choose_ticket() { plcy); result.require("ticket was chosen and produced a session", session.has_value()); result.test_is_eq("chosen second offset (TLS 1.3 ticket)", session->second, uint16_t(2)); + result.end_timer(); }), }; #else @@ -547,30 +589,37 @@ std::vector test_session_manager_stateless() { return { CHECK("establish with default parameters", [&](auto& result) { + result.start_timer(); result.confirm("will emit tickets", mgr.emits_session_tickets()); auto ticket = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.confirm("returned ticket", ticket.has_value() && ticket->is_ticket()); + result.end_timer(); }), CHECK("establish with disabled tickets", [&](auto& result) { + result.start_timer(); result.confirm("will emit tickets", mgr.emits_session_tickets()); auto ticket = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs), std::nullopt, true); result.confirm("returned std::nullopt", !ticket.has_value()); + result.end_timer(); }), CHECK("establish without ticket key in credentials manager", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_Stateless local_mgr(std::make_shared(), rng); result.confirm("won't emit tickets", !local_mgr.emits_session_tickets()); auto ticket = local_mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.confirm("returned std::nullopt", !ticket.has_value()); + result.end_timer(); }), CHECK("retrieve via ticket", [&](auto& result) { + result.start_timer(); auto ticket1 = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); auto ticket2 = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.require("tickets created successfully", ticket1.has_value() && ticket2.has_value()); @@ -579,27 +628,33 @@ std::vector test_session_manager_stateless() { result.confirm("can retrieve ticket 1", mgr.retrieve(ticket1.value(), cbs, plcy).has_value()); result.confirm("can retrieve ticket 2 from different manager but sam credentials", local_mgr.retrieve(ticket2.value(), cbs, plcy).has_value()); + result.end_timer(); }), CHECK("retrieve via ID does not work", [&](auto& result) { + result.start_timer(); auto ticket1 = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.require("tickets created successfully", ticket1.has_value() && ticket1.has_value()); result.confirm("retrieval by ID does not work", !mgr.retrieve(random_id(*rng), cbs, plcy).has_value()); + result.end_timer(); }), CHECK("retrieve via opaque handle does work", [&](auto& result) { + result.start_timer(); auto ticket1 = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.require("tickets created successfully", ticket1.has_value() && ticket1.has_value()); result.confirm("retrieval by opaque handle", mgr.retrieve(ticket1->opaque_handle(), cbs, plcy).has_value()); + result.end_timer(); }), CHECK("no retrieve without or with wrong ticket key", [&](auto& result) { + result.start_timer(); auto ticket1 = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.require("tickets created successfully", ticket1.has_value() && ticket1.has_value()); @@ -613,10 +668,12 @@ std::vector test_session_manager_stateless() { result.confirm("no successful retrieval (with wrong key)", !local_mgr2.retrieve(ticket1.value(), cbs, plcy).has_value()); result.confirm("successful retrieval", mgr.retrieve(ticket1.value(), cbs, plcy).has_value()); + result.end_timer(); }), CHECK("Clients cannot be stateless", [&](auto& result) { + result.start_timer(); result.test_throws("::store() does not work with ID", [&] { mgr.store(default_session(Botan::TLS::Connection_Side::Client, cbs), random_id(*rng)); }); @@ -630,10 +687,12 @@ std::vector test_session_manager_stateless() { auto ticket1 = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.require("tickets created successfully", ticket1.has_value() && ticket1.has_value()); result.confirm("finding tickets does not work", mgr.find(server_info, cbs, plcy).empty()); + result.end_timer(); }), CHECK("remove is a NOOP", [&](auto& result) { + result.start_timer(); auto ticket1 = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.require("tickets created successfully", ticket1.has_value() && ticket1.has_value()); @@ -642,11 +701,13 @@ std::vector test_session_manager_stateless() { result.test_is_eq("remove the ticket", mgr.remove_all(), size_t(0)); result.confirm("successful retrieval 1", mgr.retrieve(ticket1.value(), cbs, plcy).has_value()); + result.end_timer(); }), CHECK( "retrieval via ticket reconstructs the start_time stamp", [&](auto& result) { + result.start_timer(); auto session_before = default_session(Botan::TLS::Connection_Side::Server, cbs); auto ticket = mgr.establish(session_before); result.require("got a ticket", ticket.has_value() && ticket->is_ticket()); @@ -658,6 +719,7 @@ std::vector test_session_manager_stateless() { std::chrono::duration_cast(session_before.start_time().time_since_epoch()).count(), std::chrono::duration_cast(session_after->start_time().time_since_epoch()) .count()); + result.end_timer(); }), }; } @@ -708,6 +770,7 @@ std::vector test_session_manager_hybrid() { return Test::flatten_result_lists({ CHECK_all("ticket vs ID preference in establishment", [&](auto make_manager, auto& result) { + result.start_timer(); auto mgr_prefers_tickets = make_manager(true); auto ticket1 = mgr_prefers_tickets.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); @@ -726,10 +789,12 @@ std::vector test_session_manager_hybrid() { std::nullopt, true /* TLS 1.2 no ticket support */); result.confirm("emits an ID", ticket4.has_value() && ticket4->is_id()); + result.end_timer(); }), CHECK_all("ticket vs ID preference in retrieval", [&](auto make_manager, auto& result) { + result.start_timer(); auto mgr_prefers_tickets = make_manager(true); auto mgr_prefers_ids = make_manager(false); @@ -748,10 +813,12 @@ std::vector test_session_manager_hybrid() { result.confirm("mgr2 + ID2", mgr_prefers_ids.retrieve(id2.value(), cbs, plcy).has_value()); result.confirm("mgr1 + ticket", mgr_prefers_tickets.retrieve(ticket.value(), cbs, plcy).has_value()); result.confirm("mgr2 + ticket", mgr_prefers_ids.retrieve(ticket.value(), cbs, plcy).has_value()); + result.end_timer(); }), CHECK_all("no session tickets if hybrid manager cannot create them", [&](auto make_manager, auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_Hybrid empty_mgr( std::make_unique(rng, 10), std::make_shared(), @@ -762,6 +829,7 @@ std::vector test_session_manager_hybrid() { result.confirm("does not emit tickets", !empty_mgr.emits_session_tickets()); result.confirm("does emit tickets 1", mgr_prefers_tickets.emits_session_tickets()); result.confirm("does emit tickets 2", mgr_prefers_ids.emits_session_tickets()); + result.end_timer(); }), }); } @@ -806,6 +874,7 @@ std::vector test_session_manager_sqlite() { return { CHECK("migrate session database scheme (purges database)", [&](auto& result) { + result.start_timer(); Temporary_Database_File dbfile("tls-sessions/botan-2.19.3.sqlite"); // legacy database (encrypted with 'thetruthisoutthere') containing: @@ -834,16 +903,20 @@ std::vector test_session_manager_sqlite() { legacy_db.find(Botan::TLS::Server_Information("cloudflare.com", 443), cbs, plcy).empty()); result.test_is_eq("empty database won't get more empty", legacy_db.remove_all(), size_t(0)); + result.end_timer(); }), CHECK("clearing empty database", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr("thetruthisoutthere", rng, Test::temp_file_name("empty.sqlite")); result.test_eq("does not delete anything", mgr.remove_all(), 0); + result.end_timer(); }), CHECK("establish new session", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr( "thetruthisoutthere", rng, Test::temp_file_name("new_session.sqlite")); auto some_random_id = random_id(*rng); @@ -856,10 +929,12 @@ std::vector test_session_manager_sqlite() { auto some_virtual_handle = mgr.establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); result.require("establishment was successful", some_virtual_handle.has_value()); result.require("session id was set", some_virtual_handle->id().has_value()); + result.end_timer(); }), CHECK("retrieve session by ID", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr( "thetruthisoutthere", rng, Test::temp_file_name("retrieve_by_id.sqlite")); auto some_random_id = random_id(*rng); @@ -888,10 +963,12 @@ std::vector test_session_manager_sqlite() { auto session3 = mgr.retrieve(random_id(*rng), cbs, plcy); result.confirm("random ID creates empty result", !session3.has_value()); + result.end_timer(); }), CHECK("retrieval via ticket creates empty result", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr( "thetruthisoutthere", rng, Test::temp_file_name("retrieve_by_ticket.sqlite")); auto some_random_handle = @@ -900,10 +977,12 @@ std::vector test_session_manager_sqlite() { result.confirm("std::nullopt on random ticket", !mgr.retrieve(random_ticket(*rng), cbs, plcy).has_value()); + result.end_timer(); }), CHECK("storing sessions and finding them by server info", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr( "thetruthisoutthere", rng, Test::temp_file_name("store_and_find.sqlite")); auto id = random_id(*rng); @@ -918,10 +997,12 @@ std::vector test_session_manager_sqlite() { result.confirm("ticket matches", !handle.is_ticket() || handle.ticket().value() == ticket); } } + result.end_timer(); }), CHECK("removing sessions", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr("thetruthisoutthere", rng, Test::temp_file_name("remove.sqlite")); auto id = random_id(*rng); auto ticket = random_ticket(*rng); @@ -942,10 +1023,12 @@ std::vector test_session_manager_sqlite() { } result.test_is_eq("removing the rest of the sessions", mgr.remove_all(), size_t(2)); + result.end_timer(); }), CHECK("old sessions are purged when needed", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr( "thetruthisoutthere", rng, Test::temp_file_name("purging.sqlite"), 1); @@ -968,10 +1051,12 @@ std::vector test_session_manager_sqlite() { result.require("new ID exists", mgr.retrieve(ids[2], cbs, plcy).has_value()); result.test_is_eq("only one entry exists", mgr.remove_all(), size_t(1)); + result.end_timer(); }), CHECK("session purging can be disabled", [&](auto& result) { + result.start_timer(); Botan::TLS::Session_Manager_SQLite mgr( "thetruthisoutthere", rng, Test::temp_file_name("purging.sqlite"), 0 /* no pruning! */); @@ -980,6 +1065,7 @@ std::vector test_session_manager_sqlite() { } result.test_is_eq("no entries were purged along the way", mgr.remove_all(), size_t(25)); + result.end_timer(); }), }; #else @@ -1027,6 +1113,7 @@ std::vector tls_session_manager_expiry() { return Test::flatten_result_lists({ CHECK_all("sessions expire", [&](auto, auto factory, auto& result) { + result.start_timer(); auto mgr = factory(); auto handle = mgr->establish(default_session(Botan::TLS::Connection_Side::Server, cbs)); @@ -1035,10 +1122,12 @@ std::vector tls_session_manager_expiry() { cbs.tick(); result.confirm("session has expired", !mgr->retrieve(handle.value(), cbs, plcy).has_value()); result.test_is_eq("session was deleted when it expired", mgr->remove_all(), size_t(0)); + result.end_timer(); }), CHECK_all("expired sessions are not found", [&](const std::string& type, auto factory, auto& result) { + result.start_timer(); if(type == "Stateless") { return; // this manager can neither store nor find anything } @@ -1061,11 +1150,13 @@ std::vector tls_session_manager_expiry() { "the new session is found", sessions_and_handles.front().handle.id().value(), handle_new); result.test_is_eq("old session was deleted when it expired", mgr->remove_all(), size_t(1)); + result.end_timer(); }), CHECK_all( "session tickets are not reused", [&](const std::string& type, auto factory, auto& result) { + result.start_timer(); if(type == "Stateless") { return; // this manager can neither store nor find anything } @@ -1100,10 +1191,12 @@ std::vector tls_session_manager_expiry() { "found session is the Session_ID", sessions_and_handles2.front().handle.id().value(), handle_1); result.confirm("found session is TLS 1.2", sessions_and_handles2.front().session.version().is_pre_tls_13()); + result.end_timer(); }), CHECK_all("number of found tickets is capped", [&](const std::string& type, auto factory, auto& result) { + result.start_timer(); if(type == "Stateless") { return; // this manager can neither store nor find anything } @@ -1130,10 +1223,12 @@ std::vector tls_session_manager_expiry() { plcy.set_session_limit(10); result.test_is_eq("find all five", mgr->find(server_info, cbs, plcy).size(), size_t(5)); + result.end_timer(); }), #if defined(BOTAN_HAS_TLS_13) CHECK_all("expired tickets are not selected for PSK resumption", [&](auto, auto factory, auto& result) { + result.start_timer(); auto ticket = [&](const Botan::TLS::Session_Handle& handle) { return Botan::TLS::PskIdentity(handle.opaque_handle().get(), 0); }; @@ -1157,6 +1252,7 @@ std::vector tls_session_manager_expiry() { auto nothing = mgr->choose_from_offered_tickets( std::vector{ticket(new_handle.value()), ticket(old_handle.value())}, "SHA-256", cbs, plcy); result.require("all tickets are expired", !nothing.has_value()); + result.end_timer(); }), #endif }); diff --git a/src/tests/test_tls_signature_scheme.cpp b/src/tests/test_tls_signature_scheme.cpp index 89c0015cba7..1a3744fb4d8 100644 --- a/src/tests/test_tls_signature_scheme.cpp +++ b/src/tests/test_tls_signature_scheme.cpp @@ -24,6 +24,7 @@ std::vector test_signature_scheme() { for(const auto& s : Botan::TLS::Signature_Scheme::all_available_schemes()) { results.push_back(CHECK(s.to_string().c_str(), [&](auto& result) { + result.start_timer(); result.confirm("is_set handles all cases", s.is_set()); result.confirm("is_available handles all cases", s.is_available()); @@ -35,11 +36,13 @@ std::vector test_signature_scheme() { result.confirm("format handles all cases", s.format().has_value()); result.confirm("algorithm_identifier handles all cases", Botan::AlgorithmIdentifier() != s.key_algorithm_identifier()); + result.end_timer(); })); } Botan::TLS::Signature_Scheme bogus(0x1337); results.push_back(CHECK("bogus scheme", [&](auto& result) { + result.start_timer(); result.confirm("is_set still works", bogus.is_set()); result.confirm("is not available", !bogus.is_available()); @@ -51,6 +54,7 @@ std::vector test_signature_scheme() { result.confirm("format deals with bogus schemes", !bogus.format().has_value()); result.confirm("algorithm_identifier deals with bogus schemes", Botan::AlgorithmIdentifier() == bogus.key_algorithm_identifier()); + result.end_timer(); })); return results; diff --git a/src/tests/test_tls_transcript_hash_13.cpp b/src/tests/test_tls_transcript_hash_13.cpp index 5905ccf4664..f7c765f84e5 100644 --- a/src/tests/test_tls_transcript_hash_13.cpp +++ b/src/tests/test_tls_transcript_hash_13.cpp @@ -60,24 +60,29 @@ std::vector transcript_hash() { return { CHECK("trying to get 'previous' or 'current' with invalid state", [](Test::Result& result) { + result.start_timer(); result.test_throws("previous throws invalid state exception", [] { Transcript_Hash_State().previous(); }); result.test_throws("current throws invalid state exception", [] { Transcript_Hash_State().current(); }); + result.end_timer(); }), CHECK("update without an algorithm", [](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h; result.test_no_throw("update is successful", [&] { h.update(Botan::hex_decode("baadbeef")); }); result.test_throws("previous throws invalid state exception", [&] { h.previous(); }); result.test_throws("current throws invalid state exception", [&] { h.current(); }); + result.end_timer(); }), CHECK("cannot change algorithm", [](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h; result.test_no_throw("initial set is successful", [&] { h.set_algorithm("SHA-256"); }); result.test_no_throw("resetting is successful (NOOP)", [&] { h.set_algorithm("SHA-256"); }); @@ -88,10 +93,12 @@ std::vector transcript_hash() { result.test_no_throw("resetting is successful (NOOP)", [&] { h2.set_algorithm("SHA-256"); }); result.test_throws("set_algorithm throws invalid state exception", [&] { h2.set_algorithm("SHA-384"); }); + result.end_timer(); }), CHECK("update and result retrieval (algorithm is set)", [&](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h("SHA-256"); h.update(Botan::hex_decode("baadbeef")); @@ -102,10 +109,12 @@ std::vector transcript_hash() { h.update(Botan::hex_decode("600df00d")); result.test_eq("p = SHA-256(baadbeef)", h.previous(), sha256("baadbeef")); result.test_eq("c = SHA-256(deadbeef | goodfood)", h.current(), sha256("baadbeef600df00d")); + result.end_timer(); }), CHECK("update and result retrieval (deferred algorithm specification)", [&](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h; h.update(Botan::hex_decode("baadbeef")); @@ -114,10 +123,12 @@ std::vector transcript_hash() { result.test_throws("previous throws invalid state exception", [&] { h.previous(); }); result.test_eq("c = SHA-256(baadbeef)", h.current(), sha256("baadbeef")); + result.end_timer(); }), CHECK("update and result retrieval (deferred algorithm specification multiple updates)", [&](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h; h.update(Botan::hex_decode("baadbeef")); @@ -125,10 +136,12 @@ std::vector transcript_hash() { h.set_algorithm("SHA-256"); result.test_eq("c = SHA-256(baadbeef | goodfood)", h.current(), sha256("baadbeef600df00d")); + result.end_timer(); }), CHECK("C-style update interface", [&](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h; std::array baad{0xba, 0xad}; @@ -142,10 +155,12 @@ std::vector transcript_hash() { h.update(food); result.test_eq("c = SHA-256(baadbeef | goodfood)", h.current(), sha256("baadbeef600df00d")); + result.end_timer(); }), CHECK("cloning creates independent transcript_hash instances", [&](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h1("SHA-256"); h1.update(std::array{0xba, 0xad, 0xbe, 0xef}); @@ -159,10 +174,12 @@ std::vector transcript_hash() { result.test_eq( "c1 = SHA-256(baadbeef | goodfood | cafedude)", h1.current(), sha256("baadbeef600df00dcafed00d")); result.test_eq("c2 = SHA-256(baadbeef | goodfood)", h2.current(), sha256("baadbeef600df00d")); + result.end_timer(); }), CHECK("recreation after hello retry request", [&](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h1; h1.update(std::array{0xc0, 0xca, 0xc0, 0x1a} /* client hello 1 */); @@ -174,10 +191,12 @@ std::vector transcript_hash() { const std::string hash_of_client_hello = Botan::hex_encode(sha256("c0cac01a")); const std::string transcript = "fe000020" + hash_of_client_hello + "c001f00d"; result.test_eq("transcript hash of hello retry request", h2.current(), sha256(transcript)); + result.end_timer(); }), CHECK("truncated transcript hash in client hellos with PSK", [&](Test::Result& result) { + result.start_timer(); Transcript_Hash_State h1; const size_t truncation_mark = 477; @@ -193,6 +212,7 @@ std::vector transcript_hash() { // truncated hash is cleared as soon as new messages are read h1.update(std::array{0xc0, 0xca, 0xc0, 0x1a} /* server hello */); result.test_throws("truncated hash is cleared", [&] { h1.truncated(); }); + result.end_timer(); }), }; } diff --git a/src/tests/test_uri.cpp b/src/tests/test_uri.cpp index afa4664a088..68897bb17fe 100644 --- a/src/tests/test_uri.cpp +++ b/src/tests/test_uri.cpp @@ -17,26 +17,31 @@ class URI_Tests final : public Test { private: static Test::Result test_uri_ctor() { Test::Result result("URI constructors"); + result.start_timer(); Botan::URI uri(Botan::URI::Type::Domain, "localhost", 9000); result.confirm("type", uri.type() == Botan::URI::Type::Domain); result.test_eq("host", uri.host(), "localhost"); result.test_eq("post", size_t(uri.port()), 9000); + result.end_timer(); return result; } static Test::Result test_uri_tostring() { Test::Result result("URI to_string"); + result.start_timer(); result.test_eq("domain", Botan::URI(Botan::URI::Type::Domain, "localhost", 23).to_string(), "localhost:23"); result.test_eq("IPv4", Botan::URI(Botan::URI::Type::IPv4, "192.168.1.1", 25).to_string(), "192.168.1.1:25"); result.test_eq("IPv6", Botan::URI(Botan::URI::Type::IPv6, "::1", 65535).to_string(), "[::1]:65535"); result.test_eq("IPv6 no port", Botan::URI(Botan::URI::Type::IPv6, "::1", 0).to_string(), "::1"); + result.end_timer(); return result; } static Test::Result test_uri_parsing() { Test::Result result("URI parsing"); + result.start_timer(); struct { std::string uri; @@ -84,11 +89,13 @@ class URI_Tests final : public Test { result.test_throws("invalid IPv6", []() { Botan::URI::from_ipv6("]"); }); result.test_throws("invalid IPv6", []() { Botan::URI::from_ipv6("[::1]1"); }); + result.end_timer(); return result; } static Test::Result test_uri_parsing_invalid() { Test::Result result("URI parsing invalid"); + result.start_timer(); const std::vector invalid_uris = { "localhost::80", @@ -108,6 +115,7 @@ class URI_Tests final : public Test { result.test_success("Rejected invalid URI"); } } + result.end_timer(); return result; } diff --git a/src/tests/test_utils.cpp b/src/tests/test_utils.cpp index 558fa8a476f..d116befb183 100644 --- a/src/tests/test_utils.cpp +++ b/src/tests/test_utils.cpp @@ -53,6 +53,8 @@ class Utility_Function_Tests final : public Test { Test::Result test_checked_add() { Test::Result result("checked_add"); + result.start_timer(); + const size_t large = static_cast(-5); const size_t zero = 0; @@ -85,12 +87,15 @@ class Utility_Function_Tests final : public Test { } } + result.end_timer(); return result; } Test::Result test_checked_mul() { Test::Result result("checked_mul"); + result.start_timer(); + auto& rng = Test::rng(); for(size_t i = 0; i != 100; ++i) { @@ -106,11 +111,13 @@ class Utility_Function_Tests final : public Test { } } + result.end_timer(); return result; } Test::Result test_checked_cast() { Test::Result result("checked_cast"); + result.start_timer(); const uint32_t large = static_cast(-1); const uint32_t is_16_bits = 0x8123; @@ -123,11 +130,13 @@ class Utility_Function_Tests final : public Test { result.test_int_eq("checked_cast converts", Botan::checked_cast_to(is_16_bits), 0x8123); result.test_int_eq("checked_cast converts", Botan::checked_cast_to(is_8_bits), 0x89); + result.end_timer(); return result; } Test::Result test_round_up() { Test::Result result("Util round_up"); + result.start_timer(); // clang-format off const std::vector inputs = { @@ -157,6 +166,7 @@ class Utility_Function_Tests final : public Test { result.test_throws("Integer overflow is detected", []() { Botan::round_up(static_cast(-1), 1024); }); + result.end_timer(); return result; } @@ -176,6 +186,7 @@ class Utility_Function_Tests final : public Test { static Test::Result test_loadstore() { Test::Result result("Util load/store"); + result.start_timer(); const std::vector membuf = Botan::hex_decode("00112233445566778899AABBCCDDEEFF"); const uint8_t* mem = membuf.data(); @@ -465,6 +476,7 @@ class Utility_Function_Tests final : public Test { result.test_is_eq(Botan::store_le>(TestEnum32::_1), Botan::hex_decode("78563412")); result.test_is_eq>(Botan::store_be(TestEnum32::_2), {0x78, 0x56, 0x34, 0x12}); + result.end_timer(); return result; } @@ -508,6 +520,8 @@ class Utility_Function_Tests final : public Test { const size_t inszt = 0x87654321; Test::Result result("Util load/store ambiguity"); + result.start_timer(); + const auto out_be_32 = Botan::store_be(in32); const auto out_le_32 = Botan::store_le(in32); const auto out_be_64 = Botan::store_be(in64); @@ -522,6 +536,7 @@ class Utility_Function_Tests final : public Test { result.test_is_eq("be szt", Botan::load_be(out_be_szt), inszt); result.test_is_eq("le szt", Botan::load_le(out_le_szt), inszt); + result.end_timer(); return result; } @@ -531,6 +546,7 @@ class Utility_Function_Tests final : public Test { // fallback implementation is correct. On all typical platforms it // won't be called in production. Test::Result result("Util load/store fallback"); + result.start_timer(); result.test_is_eq("lLE 16", fb_load_le({1, 2}), 0x0201); result.test_is_eq("lLE 32", fb_load_le({1, 2, 3, 4}), 0x04030201); @@ -548,11 +564,13 @@ class Utility_Function_Tests final : public Test { result.test_is_eq>("sBE 32", fb_store_be(0x01020304), {1, 2, 3, 4}); result.test_is_eq>("sBE 64", fb_store_be(0x0102030405060708), {1, 2, 3, 4, 5, 6, 7, 8}); + result.end_timer(); return result; } static Test::Result test_loadstore_constexpr() { Test::Result result("Util load/store constexpr"); + result.start_timer(); constexpr uint16_t in16 = 0x1234; constexpr uint32_t in32 = 0xA0B0C0D0; @@ -694,6 +712,7 @@ class Utility_Function_Tests final : public Test { constexpr auto cex_load_be64s = Botan::load_be>(cex_mem); result.test_is_eq(cex_load_be64s, {0x0011223344556677, 0x8899AABBCCDDEEFF}); + result.end_timer(); return result; } @@ -701,66 +720,82 @@ class Utility_Function_Tests final : public Test { return { CHECK("copy_out_be with 16bit input (word aligned)", [&](auto& result) { + result.start_timer(); std::vector out_vector(4); const std::array in_array = {0x0A0B, 0x0C0D}; Botan::copy_out_be(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C0D")); + result.end_timer(); }), CHECK("copy_out_be with 16bit input (partial words)", [&](auto& result) { + result.start_timer(); std::vector out_vector(3); const std::array in_array = {0x0A0B, 0x0C0D}; Botan::copy_out_be(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C")); + result.end_timer(); }), CHECK("copy_out_le with 16bit input (word aligned)", [&](auto& result) { + result.start_timer(); std::vector out_vector(4); const std::array in_array = {0x0A0B, 0x0C0D}; Botan::copy_out_le(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("0B0A0D0C")); + result.end_timer(); }), CHECK("copy_out_le with 16bit input (partial words)", [&](auto& result) { + result.start_timer(); std::vector out_vector(3); const std::array in_array = {0x0A0B, 0x0C0D}; Botan::copy_out_le(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("0B0A0D")); + result.end_timer(); }), CHECK("copy_out_be with 64bit input (word aligned)", [&](auto& result) { + result.start_timer(); std::vector out_vector(16); const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; Botan::copy_out_be(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C0D0E0F10111213141516171819")); + result.end_timer(); }), CHECK("copy_out_le with 64bit input (word aligned)", [&](auto& result) { + result.start_timer(); std::vector out_vector(16); const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; Botan::copy_out_le(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("11100F0E0D0C0B0A1918171615141312")); + result.end_timer(); }), CHECK("copy_out_be with 64bit input (partial words)", [&](auto& result) { + result.start_timer(); std::vector out_vector(15); const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; Botan::copy_out_be(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C0D0E0F101112131415161718")); + result.end_timer(); }), CHECK("copy_out_le with 64bit input (partial words)", [&](auto& result) { + result.start_timer(); std::vector out_vector(15); const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; Botan::copy_out_le(out_vector, in_array); result.test_is_eq(out_vector, Botan::hex_decode("11100F0E0D0C0B0A19181716151413")); + result.end_timer(); }), }; } @@ -788,6 +823,8 @@ class BitOps_Tests final : public Test { Test::Result test_ctz() { Test::Result result("ctz"); + result.start_timer(); + test_ctz(result, 0, 32); test_ctz(result, 1, 0); test_ctz(result, 0x80, 7); @@ -795,6 +832,7 @@ class BitOps_Tests final : public Test { test_ctz(result, 0x8100000, 20); test_ctz(result, 0x80000000, 31); + result.end_timer(); return result; } @@ -805,6 +843,8 @@ class BitOps_Tests final : public Test { Test::Result test_sig_bytes() { Test::Result result("significant_bytes"); + result.start_timer(); + test_sig_bytes(result, 0, 0); test_sig_bytes(result, 1, 1); test_sig_bytes(result, 0x80, 1); @@ -821,6 +861,7 @@ class BitOps_Tests final : public Test { test_sig_bytes(result, 0x80000000, 4); test_sig_bytes(result, 0x100000000, 5); + result.end_timer(); return result; } @@ -831,6 +872,7 @@ class BitOps_Tests final : public Test { Test::Result test_power_of_2() { Test::Result result("is_power_of_2"); + result.start_timer(); test_power_of_2(result, 0, false); test_power_of_2(result, 1, false); @@ -849,6 +891,7 @@ class BitOps_Tests final : public Test { test_power_of_2(result, 0x8000000, true); test_power_of_2(result, 0x100000000000, true); + result.end_timer(); return result; } }; @@ -882,6 +925,7 @@ class Version_Tests final : public Test { public: std::vector run() override { Test::Result result("Versions"); + result.start_timer(); result.confirm("Version datestamp matches macro", Botan::version_datestamp() == BOTAN_VERSION_DATESTAMP); @@ -915,6 +959,7 @@ class Version_Tests final : public Test { result.test_eq("Expected warning text", version_check_bad, expected_error); + result.end_timer(); return {result}; } }; @@ -977,9 +1022,11 @@ class Date_Format_Tests final : public Text_Based_Test { std::vector run_final_tests() override { Test::Result result("calendar_point::to_string"); + result.start_timer(); Botan::calendar_point d(2008, 5, 15, 9, 30, 33); // desired format: --
T:: result.test_eq("calendar_point::to_string", d.to_string(), "2008-05-15T09:30:33"); + result.end_timer(); return {result}; } }; @@ -1131,6 +1178,7 @@ class CPUID_Tests final : public Test { public: std::vector run() override { Test::Result result("CPUID"); + result.start_timer(); result.confirm("Endian is either little or big", Botan::CPUID::is_big_endian() || Botan::CPUID::is_little_endian()); @@ -1157,7 +1205,7 @@ class CPUID_Tests final : public Test { result.test_eq("After reinitializing, has_sse2 returns true", Botan::CPUID::has_sse2(), true); } #endif - + result.end_timer(); return {result}; } }; @@ -1170,6 +1218,7 @@ class UUID_Tests : public Test { public: std::vector run() override { Test::Result result("UUID"); + result.start_timer(); const Botan::UUID empty_uuid; const Botan::UUID random_uuid1(this->rng()); @@ -1225,6 +1274,7 @@ class UUID_Tests : public Test { const Botan::UUID ones_uuid(ones); result.test_eq("Ones UUID matches expected", ones_uuid.to_string(), "FFFFFFFF-FFFF-4FFF-BFFF-FFFFFFFFFFFF"); + result.end_timer(); return {result}; } }; @@ -1237,6 +1287,7 @@ class Formatter_Tests : public Test { public: std::vector run() override { Test::Result result("Format utility"); + result.start_timer(); /* In a number of these tests, we are not strictly depending on the @@ -1251,6 +1302,7 @@ class Formatter_Tests : public Test { result.test_eq("test 4", Botan::fmt("{}"), "{}"); result.test_eq("test 5", Botan::fmt("{} == '{}'", 5, "five"), "5 == 'five'"); + result.end_timer(); return {result}; } }; @@ -1263,15 +1315,18 @@ class ScopedCleanup_Tests : public Test { return { CHECK("leaving a scope results in cleanup", [](Test::Result& result) { + result.start_timer(); bool ran = false; { auto clean = Botan::scoped_cleanup([&] { ran = true; }); } result.confirm("cleanup ran", ran); + result.end_timer(); }), CHECK("leaving a function, results in cleanup", [](Test::Result& result) { + result.start_timer(); bool ran = false; bool fn_called = false; auto fn = [&] { @@ -1283,10 +1338,12 @@ class ScopedCleanup_Tests : public Test { fn(); result.confirm("fn called", fn_called); result.confirm("cleanup ran", ran); + result.end_timer(); }), CHECK("stack unwinding results in cleanup", [](Test::Result& result) { + result.start_timer(); bool ran = false; bool fn_called = false; bool exception_caught = false; @@ -1306,16 +1363,19 @@ class ScopedCleanup_Tests : public Test { result.confirm("fn called", fn_called); result.confirm("cleanup ran", ran); result.confirm("exception caught", exception_caught); + result.end_timer(); }), CHECK("cleanup isn't called after disengaging", [](Test::Result& result) { + result.start_timer(); bool ran = false; { auto clean = Botan::scoped_cleanup([&] { ran = true; }); clean.disengage(); } result.confirm("cleanup not ran", !ran); + result.end_timer(); }), }; diff --git a/src/tests/test_utils_buffer.cpp b/src/tests/test_utils_buffer.cpp index c8a23e19a93..236fc3d81d7 100644 --- a/src/tests/test_utils_buffer.cpp +++ b/src/tests/test_utils_buffer.cpp @@ -29,6 +29,7 @@ std::vector test_buffer_slicer() { return { CHECK("Empty BufferSlicer", [](auto& result) { + result.start_timer(); const std::vector buffer(0); Botan::BufferSlicer s(buffer); result.confirm("empty slicer has no remaining bytes", s.remaining() == 0); @@ -38,10 +39,12 @@ std::vector test_buffer_slicer() { result.test_throws("empty slicer cannot emit bytes", [&]() { s.take(1); }); result.test_throws("empty slicer cannot skip bytes", [&]() { s.skip(1); }); result.test_throws("empty slicer cannot copy bytes", [&]() { s.copy_as_vector(1); }); + result.end_timer(); }), CHECK("Read from BufferSlicer", [](auto& result) { + result.start_timer(); const std::vector buffer{'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', ' ', '!'}; Botan::BufferSlicer s(buffer); @@ -88,10 +91,12 @@ std::vector test_buffer_slicer() { result.test_throws("empty slicer cannot emit bytes", [&]() { s.take(1); }); result.test_throws("empty slicer cannot skip bytes", [&]() { s.skip(1); }); result.test_throws("empty slicer cannot copy bytes", [&]() { s.copy_as_vector(1); }); + result.end_timer(); }), CHECK("Strong type support", [](auto& result) { + result.start_timer(); const Botan::secure_vector secure_buffer{'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'}; Botan::BufferSlicer s(secure_buffer); @@ -105,6 +110,7 @@ std::vector test_buffer_slicer() { const auto reproduce = Botan::concat>(span1, span2, vec1, vec2, vec3, vec4); result.test_eq("sliced into various types", reproduce, secure_buffer); + result.end_timer(); }), }; } @@ -113,6 +119,7 @@ std::vector test_buffer_stuffer() { return { CHECK("Empty BufferStuffer", [](auto& result) { + result.start_timer(); std::vector empty_buffer; Botan::BufferStuffer s(empty_buffer); @@ -125,10 +132,12 @@ std::vector test_buffer_stuffer() { std::vector some_bytes(42); s.append(some_bytes); }); + result.end_timer(); }), CHECK("Fill BufferStuffer", [](auto& result) { + result.start_timer(); std::vector sink(13); Botan::BufferStuffer s(sink); @@ -175,6 +184,7 @@ std::vector test_buffer_stuffer() { std::string final_string(Botan::cast_uint8_ptr_to_char(sink.data()), sink.size()); result.test_eq("final buffer is as expected", final_string, "hello world !"); + result.end_timer(); }), }; } @@ -188,16 +198,19 @@ std::vector test_alignment_buffer() { return { CHECK("Fresh Alignment Buffer", [](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; result.test_eq("size()", b.size(), 32); result.test_eq("elements_in_buffer()", b.elements_in_buffer(), 0); result.test_eq("elements_until_alignment()", b.elements_until_alignment(), 32); result.confirm("in_alignment()", b.in_alignment()); result.confirm("!ready_to_consume()", !b.ready_to_consume()); + result.end_timer(); }), CHECK("Fill Alignment Buffer", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; b.append(first_half_data); @@ -215,10 +228,12 @@ std::vector test_alignment_buffer() { result.test_eq("elements_until_alignment()", b.elements_until_alignment(), 0); result.confirm("!in_alignment()", !b.in_alignment()); result.confirm("ready_to_consume()", b.ready_to_consume()); + result.end_timer(); }), CHECK("Consume Alignment Buffer", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; b.append(data); @@ -233,10 +248,12 @@ std::vector test_alignment_buffer() { result.confirm("!ready_to_consume()", !b.ready_to_consume()); result.test_is_eq("in == out", v(data), v(out)); + result.end_timer(); }), CHECK("Consume partially filled Alignment Buffer", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; result.require("!ready_to_consume()", !b.ready_to_consume()); @@ -255,10 +272,12 @@ std::vector test_alignment_buffer() { const auto out_full = b.consume_partial(); result.test_eq("consumed full-data resets buffer", b.elements_in_buffer(), 0); result.test_is_eq("full-in == full-out", v(out_full), v(data)); + result.end_timer(); }), CHECK("Clear Alignment Buffer", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; b.append(first_half_data); @@ -271,10 +290,12 @@ std::vector test_alignment_buffer() { result.test_eq("elements_until_alignment()", b.elements_until_alignment(), 32); result.confirm("in_alignment()", b.in_alignment()); result.confirm("!ready_to_consume()", !b.ready_to_consume()); + result.end_timer(); }), CHECK("Add Zero-Padding to Alignment Buffer", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; b.append(first_half_data); @@ -303,10 +324,12 @@ std::vector test_alignment_buffer() { const auto out_without_padding = b.consume(); result.test_is_eq("no padding", v(out_without_padding), v(data)); + result.end_timer(); }), CHECK("Handle unaligned data in Alignment Buffer (no block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; Botan::BufferSlicer first_half(first_half_data); @@ -331,10 +354,12 @@ std::vector test_alignment_buffer() { result.confirm("!ready_to_consume()", !b.ready_to_consume()); result.test_is_eq("collected block is correct", v(r2.value()), v(data)); + result.end_timer(); }), CHECK("Aligned data is not buffered unneccesarily (no block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; Botan::BufferSlicer full_block_1(data); @@ -357,10 +382,12 @@ std::vector test_alignment_buffer() { result.confirm("in_alignment()", b.in_alignment()); result.confirm("!ready_to_consume()", !b.ready_to_consume()); result.test_eq("input is consumed until alignment", full_block_2.remaining(), 16); + result.end_timer(); }), CHECK("Handle unaligned data in Alignment Buffer (with block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; Botan::BufferSlicer first_half(first_half_data); @@ -395,10 +422,12 @@ std::vector test_alignment_buffer() { result.confirm("!ready_to_consume()", !b.ready_to_consume()); result.test_is_eq("collected block is correct", v(r3.value()), v(data)); + result.end_timer(); }), CHECK("Aligned data is not buffered unneccesarily (with block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; Botan::BufferSlicer full_block_1(data); @@ -423,10 +452,12 @@ std::vector test_alignment_buffer() { result.test_eq("no input data is consumed", one_extra_byte.remaining(), 1); result.test_is_eq("collected block is correct", v(r3.value()), v(data)); + result.end_timer(); }), CHECK("Aligned data passthrough (no block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; result.require("buffer is in alignment", b.in_alignment()); @@ -451,10 +482,12 @@ std::vector test_alignment_buffer() { result.test_eq("two blocks for processing", r3, 2); result.test_is_eq(v(s3), two_blocks_data); result.test_eq("aligned data is fully consumed", two_blocks.remaining(), 0); + result.end_timer(); }), CHECK("Aligned data blockwise (no block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; result.require("buffer is in alignment", b.in_alignment()); @@ -484,10 +517,12 @@ std::vector test_alignment_buffer() { result.test_eq("data of second block for processing", s3_2->size(), 32); result.test_is_eq(v(s3_2.value()), v(data)); result.test_eq("second block is consumed", two_blocks.remaining(), 0); + result.end_timer(); }), CHECK("Aligned data passthrough (with block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; result.require("buffer is in alignment", b.in_alignment()); @@ -512,10 +547,12 @@ std::vector test_alignment_buffer() { result.test_eq("one block for processing", r3, 1); result.test_is_eq(v(s3), v(data)); result.test_eq("aligned data is partially consumed", two_blocks.remaining(), 32); + result.end_timer(); }), CHECK("Aligned data blockwise (with block-defer)", [=](auto& result) { + result.start_timer(); Botan::AlignmentBuffer b; result.require("buffer is in alignment", b.in_alignment()); @@ -543,6 +580,7 @@ std::vector test_alignment_buffer() { const auto s3_2 = b.next_aligned_block_to_process(two_blocks); result.confirm("second block is not passed through", !s3_2.has_value()); result.test_eq("second block is not consumed", two_blocks.remaining(), 32); + result.end_timer(); }), }; } @@ -551,6 +589,7 @@ std::vector test_concat() { return { CHECK("empty concat", [](Test::Result& result) { + result.start_timer(); // only define a dynamic output type, but no input to be concat'ed const auto empty1 = Botan::concat>(); result.confirm("empty concat 1", empty1.empty()); @@ -567,11 +606,13 @@ std::vector test_concat() { const auto empty4 = Botan::concat>( std::vector(), std::array(), Botan::secure_vector()); result.confirm("empty concat 4", empty4.empty()); + result.end_timer(); }), CHECK( "auto-detected output type", [](Test::Result& result) { + result.start_timer(); // define a static output type without any input parameters const auto t0 = Botan::concat>(); result.confirm("type 0", std::is_same_v, std::remove_cvref_t>); @@ -597,10 +638,12 @@ std::vector test_concat() { const std::array some_buffer{}; const auto t5 = Botan::concat(std::array(), std::array(), std::span{some_buffer}); result.confirm("type 5", std::is_same_v, std::remove_cvref_t>); + result.end_timer(); }), CHECK("concatenate", [](Test::Result& result) { + result.start_timer(); constexpr std::array a1 = {1, 2, 3, 4, 5}; const std::vector v1{6, 7, 8, 9, 10}; @@ -627,10 +670,12 @@ std::vector test_concat() { result.test_is_eq("concat 4", concat4, {1, 2, 3, 4, 5, 1, 2, 3, 4, 5}); result.confirm("correct type 4", std::is_same_v, std::remove_cvref_t>); + result.end_timer(); }), CHECK("dynamic length-check", [](Test::Result& result) { + result.start_timer(); std::vector v1{1, 2, 3, 4, 5}; std::vector v2{6, 7, 8, 9, 10}; @@ -638,10 +683,12 @@ std::vector test_concat() { [&]() { Botan::concat>(v1, v2); }); result.test_throws("concatenate into a statically sized type with too much space", [&]() { Botan::concat>(v1, v2); }); + result.end_timer(); }), CHECK("concatenate strong types", [](Test::Result& result) { + result.start_timer(); using StrongV = Botan::Strong, struct StrongV_>; using StrongA = Botan::Strong, struct StrongA_>; @@ -659,6 +706,7 @@ std::vector test_concat() { // concat strong types into a dynamically allocated strong type auto concat2 = Botan::concat(a2, v1); result.test_is_eq("concat 2", concat2.get(), {6, 7, 8, 9, 1, 2, 3, 4, 5}); + result.end_timer(); }), }; } diff --git a/src/tests/test_x25519.cpp b/src/tests/test_x25519.cpp index 8542f4ca069..d0cdd778828 100644 --- a/src/tests/test_x25519.cpp +++ b/src/tests/test_x25519.cpp @@ -54,6 +54,7 @@ class X25519_Roundtrip_Test final : public Test { for(size_t i = 0; i < 10; ++i) { Test::Result result("X25519 roundtrip"); + result.start_timer(); Botan::X25519_PrivateKey a_priv_gen(this->rng()); Botan::X25519_PrivateKey b_priv_gen(this->rng()); @@ -114,6 +115,7 @@ class X25519_Roundtrip_Test final : public Test { result.test_failure("Cast back to X25519 failed"); } + result.end_timer(); results.push_back(result); } diff --git a/src/tests/test_x509_path.cpp b/src/tests/test_x509_path.cpp index 0a5e44c40c6..7a7fec472b8 100644 --- a/src/tests/test_x509_path.cpp +++ b/src/tests/test_x509_path.cpp @@ -387,6 +387,9 @@ class Validate_V1Cert_Test final : public Test { }; std::vector Validate_V1Cert_Test::run() { + Test::Result result("Verifying using v1 certificate"); + result.start_timer(); + if(Botan::has_filesystem_impl() == false) { return {Test::Result::Note("BSI path validation", "Skipping due to missing filesystem access")}; } @@ -412,7 +415,7 @@ std::vector Validate_V1Cert_Test::run() { Botan::Path_Validation_Result validation_result = Botan::x509_path_validate(chain, restrictions, trusted, "", Botan::Usage_Type::UNSPECIFIED, validation_time); - Test::Result result("Verifying using v1 certificate"); + result.test_eq("Path validation result", validation_result.result_string(), "Verified"); Botan::Certificate_Store_In_Memory empty; @@ -424,6 +427,7 @@ std::vector Validate_V1Cert_Test::run() { result.test_eq("Path validation result", validation_result2.result_string(), "Cannot establish trust"); + result.end_timer(); return {result}; } @@ -435,6 +439,9 @@ class Validate_V2Uid_in_V1_Test final : public Test { }; std::vector Validate_V2Uid_in_V1_Test::run() { + Test::Result result("Verifying v1 certificate using v2 uid fields"); + result.start_timer(); + if(Botan::has_filesystem_impl() == false) { return {Test::Result::Note("Path validation", "Skipping due to missing filesystem access")}; } @@ -460,11 +467,12 @@ std::vector Validate_V2Uid_in_V1_Test::run() { Botan::Path_Validation_Result validation_result = Botan::x509_path_validate(chain, restrictions, trusted, "", Botan::Usage_Type::UNSPECIFIED, validation_time); - Test::Result result("Verifying v1 certificate using v2 uid fields"); + result.test_eq("Path validation failed", validation_result.successful_validation(), false); result.test_eq( "Path validation result", validation_result.result_string(), "Encountered v2 identifiers in v1 certificate"); + result.end_timer(); return {result}; } @@ -476,6 +484,9 @@ class Validate_Name_Constraint_SAN_Test final : public Test { }; std::vector Validate_Name_Constraint_SAN_Test::run() { + Test::Result result("Verifying certificate with alternative SAN violating name constraint"); + result.start_timer(); + if(Botan::has_filesystem_impl() == false) { return {Test::Result::Note("Path validation", "Skipping due to missing filesystem access")}; } @@ -501,11 +512,12 @@ std::vector Validate_Name_Constraint_SAN_Test::run() { Botan::Path_Validation_Result validation_result = Botan::x509_path_validate(chain, restrictions, trusted, "", Botan::Usage_Type::UNSPECIFIED, validation_time); - Test::Result result("Verifying certificate with alternative SAN violating name constraint"); + result.test_eq("Path validation failed", validation_result.successful_validation(), false); result.test_eq( "Path validation result", validation_result.result_string(), "Certificate does not pass name constraint"); - + + result.end_timer(); return {result}; } @@ -517,6 +529,9 @@ class Validate_Name_Constraint_CaseInsensitive final : public Test { }; std::vector Validate_Name_Constraint_CaseInsensitive::run() { + Test::Result result("DNS name constraints are case insensitive"); + result.start_timer(); + if(Botan::has_filesystem_impl() == false) { return {Test::Result::Note("Path validation", "Skipping due to missing filesystem access")}; } @@ -542,9 +557,8 @@ std::vector Validate_Name_Constraint_CaseInsensitive::run() { Botan::Path_Validation_Result validation_result = Botan::x509_path_validate(chain, restrictions, trusted, "", Botan::Usage_Type::UNSPECIFIED, validation_time); - Test::Result result("DNS name constraints are case insensitive"); result.test_eq("Path validation succeeded", validation_result.successful_validation(), true); - + result.end_timer(); return {result}; } @@ -556,6 +570,9 @@ class Validate_Name_Constraint_NoCheckSelf final : public Test { }; std::vector Validate_Name_Constraint_NoCheckSelf::run() { + Test::Result result("Name constraints do not apply to the certificate which includes them"); + result.start_timer(); + if(Botan::has_filesystem_impl() == false) { return {Test::Result::Note("Path validation", "Skipping due to missing filesystem access")}; } @@ -581,9 +598,9 @@ std::vector Validate_Name_Constraint_NoCheckSelf::run() { Botan::Path_Validation_Result validation_result = Botan::x509_path_validate(chain, restrictions, trusted, "", Botan::Usage_Type::UNSPECIFIED, validation_time); - Test::Result result("Name constraints do not apply to the certificate which includes them"); + result.test_eq("Path validation succeeded", validation_result.successful_validation(), true); - + result.end_timer(); return {result}; } @@ -608,6 +625,7 @@ class Root_Cert_Time_Check_Test final : public Test { const std::vector chain = {leaf_cert}; Test::Result result("Root cert time check"); + result.start_timer(); auto assert_path_validation_result = [&](std::string_view descr, bool ignore_trusted_root_time_range, @@ -685,6 +703,7 @@ class Root_Cert_Time_Check_Test final : public Test { Botan::Certificate_Status_Code::OK, Botan::Certificate_Status_Code::TRUSTED_CERT_NOT_YET_VALID); + result.end_timer(); return {result}; } }; @@ -844,6 +863,8 @@ class Path_Validation_With_OCSP_Tests final : public Test { static Test::Result validate_with_ocsp_with_next_update_without_max_age() { Test::Result result("path check with ocsp with next_update w/o max_age"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(false, 110, false); @@ -882,11 +903,14 @@ class Path_Validation_With_OCSP_Tests final : public Test { check_path(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED); + result.end_timer(); return result; } static Test::Result validate_with_ocsp_with_next_update_with_max_age() { Test::Result result("path check with ocsp with next_update with max_age"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(false, 110, false, std::chrono::minutes(59)); @@ -925,11 +949,14 @@ class Path_Validation_With_OCSP_Tests final : public Test { check_path(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED); + result.end_timer(); return result; } static Test::Result validate_with_ocsp_without_next_update_without_max_age() { Test::Result result("path check with ocsp w/o next_update w/o max_age"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(false, 110, false); @@ -966,11 +993,14 @@ class Path_Validation_With_OCSP_Tests final : public Test { Botan::Certificate_Status_Code::OK); check_path(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OK); + result.end_timer(); return result; } static Test::Result validate_with_ocsp_without_next_update_with_max_age() { Test::Result result("path check with ocsp w/o next_update with max_age"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(false, 110, false, std::chrono::minutes(59)); @@ -1008,11 +1038,14 @@ class Path_Validation_With_OCSP_Tests final : public Test { check_path(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_IS_TOO_OLD); + result.end_timer(); return result; } static Test::Result validate_with_ocsp_with_authorized_responder() { Test::Result result("path check with ocsp response from authorized responder certificate"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(true, // require revocation info @@ -1056,12 +1089,15 @@ class Path_Validation_With_OCSP_Tests final : public Test { check_path(Botan::calendar_point(2022, 9, 20, 16, 30, 0).to_std_timepoint(), Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED); + result.end_timer(); return result; } static Test::Result validate_with_ocsp_with_authorized_responder_without_keyusage() { Test::Result result( "path check with ocsp response from authorized responder certificate (without sufficient key usage)"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(true, // require revocation info @@ -1114,11 +1150,14 @@ class Path_Validation_With_OCSP_Tests final : public Test { Botan::Certificate_Status_Code::OCSP_RESPONSE_MISSING_KEYUSAGE, Botan::Certificate_Status_Code::OCSP_ISSUER_NOT_TRUSTED); + result.end_timer(); return result; } static Test::Result validate_with_forged_ocsp_using_self_signed_cert() { Test::Result result("path check with forged ocsp using self-signed certificate"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(true, // require revocation info @@ -1163,12 +1202,15 @@ class Path_Validation_With_OCSP_Tests final : public Test { Botan::Certificate_Status_Code::CERT_ISSUER_NOT_FOUND, Botan::Certificate_Status_Code::OCSP_ISSUER_NOT_TRUSTED); + result.end_timer(); return result; } static Test::Result validate_with_ocsp_self_signed_by_intermediate_cert() { Test::Result result( "path check with ocsp response for intermediate that is (maliciously) self-signed by the intermediate"); + result.start_timer(); + Botan::Certificate_Store_In_Memory trusted; auto restrictions = Botan::Path_Validation_Restrictions(true, // require revocation info @@ -1202,6 +1244,7 @@ class Path_Validation_With_OCSP_Tests final : public Test { path_result.result() == Botan::Certificate_Status_Code::OCSP_ISSUER_NOT_FOUND); result.test_note(std::string("Failed with: ") + Botan::to_string(path_result.result())); + result.end_timer(); return result; } @@ -1227,6 +1270,8 @@ class CVE_2020_0601_Tests final : public Test { public: std::vector run() override { Test::Result result("CVE-2020-0601"); + result.start_timer(); + auto ca_crt = Botan::X509_Certificate(Test::data_file("x509/cve-2020-0601/ca.pem")); auto fake_ca_crt = Botan::X509_Certificate(Test::data_file("x509/cve-2020-0601/fake_ca.pem")); auto ee_crt = Botan::X509_Certificate(Test::data_file("x509/cve-2020-0601/ee.pem")); @@ -1281,6 +1326,7 @@ class CVE_2020_0601_Tests final : public Test { result.confirm("Validation succeeded", path_result3.successful_validation()); + result.end_timer(); return {result}; } }; @@ -1295,6 +1341,7 @@ class XMSS_Path_Validation_Tests final : public Test { public: static Test::Result validate_self_signed(const std::string& name, const std::string& file) { Test::Result result(name); + result.start_timer(); Botan::Path_Validation_Restrictions restrictions; auto self_signed = Botan::X509_Certificate(Test::data_file("x509/xmss/" + file)); @@ -1305,6 +1352,7 @@ class XMSS_Path_Validation_Tests final : public Test { auto status = Botan::PKIX::overall_status( Botan::PKIX::check_chain(cert_path, valid_time, "", Botan::Usage_Type::UNSPECIFIED, restrictions)); result.test_eq("Cert validation status", Botan::to_string(status), "Verified"); + result.end_timer(); return result; } diff --git a/src/tests/test_xmss.cpp b/src/tests/test_xmss.cpp index 7ff0d7afa9c..1fb16f0a758 100644 --- a/src/tests/test_xmss.cpp +++ b/src/tests/test_xmss.cpp @@ -163,15 +163,18 @@ std::vector xmss_statefulness() { return {CHECK("signing alters state", [&](auto& result) { + result.start_timer(); Botan::XMSS_PrivateKey sk(Botan::XMSS_Parameters::XMSS_SHA2_10_256, *rng); result.require("allows 1024 signatures", sk.remaining_operations() == 1024); sign_something(sk); result.require("allows 1023 signatures", sk.remaining_operations() == 1023); + result.end_timer(); }), CHECK("state can become exhausted", [&](auto& result) { + result.start_timer(); const auto skbytes = Botan::hex_decode( "000000011BBB81273E8057724A2A894593A1A688B3271410B3BEAB9F5587337BCDCBBF5C4E43AB" "0AB2F88258E5AC54BB252E39335AE9B0D4AF0C0347EA45B8AA0AA3804C000003FFAC0C29C1ACD3" @@ -185,6 +188,7 @@ std::vector xmss_statefulness() { result.require("allow no more signatures", sk.remaining_operations() == 0); result.test_throws("no more signing", [&] { sign_something(sk); }); + result.end_timer(); })}; } @@ -286,29 +290,35 @@ std::vector xmss_legacy_private_key() { return { CHECK("Use a legacy private key to create a signature", [&](auto& result) { + result.start_timer(); Botan::PK_Signer signer(legacy_secret_key, *rng, algo_name); auto signature = signer.sign_message(message, *rng); Botan::PK_Verifier verifier(public_key_from_secret_key, algo_name); result.confirm("legacy private key generates signatures that are still verifiable", verifier.verify_message(message, signature)); + result.end_timer(); }), CHECK("Verify a legacy signature", [&](auto& result) { + result.start_timer(); Botan::PK_Verifier verifier(public_key_from_secret_key, algo_name); result.confirm("legacy private key generates signatures that are still verifiable", verifier.verify_message(message, legacy_signature)); + result.end_timer(); }), CHECK("Verify a new signature by a legacy private key with a legacy public key", [&](auto& result) { + result.start_timer(); Botan::PK_Signer signer(legacy_secret_key, *rng, algo_name); auto signature = signer.sign_message(message, *rng); Botan::PK_Verifier verifier(legacy_public_key, algo_name); result.confirm("legacy private key generates signatures that are still verifiable", verifier.verify_message(message, legacy_signature)); + result.end_timer(); }), }; } diff --git a/src/tests/test_xof.cpp b/src/tests/test_xof.cpp index b830565034d..ceddba360a9 100644 --- a/src/tests/test_xof.cpp +++ b/src/tests/test_xof.cpp @@ -184,6 +184,8 @@ class XOF_Tests final : public Text_Based_Test { #if defined(BOTAN_HAS_CSHAKE_XOF) CHECK("cSHAKE without a name", [](Test::Result& result) { + result.start_timer(); + std::vector> cshakes; cshakes.push_back(std::make_unique("")); cshakes.push_back(std::make_unique("")); @@ -194,16 +196,20 @@ class XOF_Tests final : public Text_Based_Test { cshake->valid_salt_length(1)); result.test_throws("cSHAKE without a name throws without salt", [&]() { cshake->start({}); }); } + result.end_timer(); }), #endif #if defined(BOTAN_HAS_AES_CRYSTALS_XOF) CHECK("AES-256/CTR XOF failure modes", [](Test::Result& result) { + result.start_timer(); + Botan::AES_256_CTR_XOF aes_xof; result.test_throws("AES-256/CTR XOF throws for empty key", [&]() { aes_xof.start({}, {}); }); result.test_throws("AES-256/CTR XOF throws for too long key", [&]() { aes_xof.start({}, std::vector(33)); }); result.test_throws("AES-256/CTR XOF throws for too long IV", [&]() { aes_xof.start(std::vector(17), std::vector(32)); }); + result.end_timer(); }), #endif }; diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp index 9add78614c1..1b8a1ef9371 100644 --- a/src/tests/tests.cpp +++ b/src/tests/tests.cpp @@ -408,14 +408,9 @@ std::vector Test::possible_providers(const std::string& /*unused*/) //static std::string Test::format_time(uint64_t ns) { + // Use a stringstream to convert nanoseconds to seconds. ns in a second is 1'000'000'000 std::ostringstream o; - - if(ns > 1000000000) { - o << std::setprecision(2) << std::fixed << ns / 1000000000.0 << " sec"; - } else { - o << std::setprecision(2) << std::fixed << ns / 1000000.0 << " msec"; - } - + o << std::fixed << std::setprecision(6) << static_cast(ns) / 1'000'000'000 << " sec"; return o.str(); } diff --git a/src/tests/unit_ecdsa.cpp b/src/tests/unit_ecdsa.cpp index 8abfd20ca2a..42bcee3f508 100644 --- a/src/tests/unit_ecdsa.cpp +++ b/src/tests/unit_ecdsa.cpp @@ -32,6 +32,8 @@ namespace { #if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) Test::Result test_decode_ecdsa_X509() { Test::Result result("ECDSA Unit"); + result.start_timer(); + Botan::X509_Certificate cert(Test::data_file("x509/ecc/CSCA.CSCA.csca-germany.1.crt")); result.test_eq("correct signature oid", cert.signature_algorithm().oid().to_formatted_string(), "ECDSA/SHA-224"); @@ -45,16 +47,21 @@ Test::Result test_decode_ecdsa_X509() { auto pubkey = cert.subject_public_key(); result.test_eq("verify self-signed signature", cert.check_signature(*pubkey), true); + result.end_timer(); return result; } Test::Result test_decode_ver_link_SHA256() { Test::Result result("ECDSA Unit"); + result.start_timer(); + Botan::X509_Certificate root_cert(Test::data_file("x509/ecc/root2_SHA256.cer")); Botan::X509_Certificate link_cert(Test::data_file("x509/ecc/link_SHA256.cer")); auto pubkey = root_cert.subject_public_key(); result.confirm("verified self-signed signature", link_cert.check_signature(*pubkey)); + + result.end_timer(); return result; } @@ -63,6 +70,8 @@ Test::Result test_decode_ver_link_SHA1() { Botan::X509_Certificate link_cert(Test::data_file("x509/ecc/link_SHA1.166.crt")); Test::Result result("ECDSA Unit"); + result.start_timer(); + auto pubkey = root_cert.subject_public_key(); auto sha1 = Botan::HashFunction::create("SHA-1"); @@ -73,12 +82,15 @@ Test::Result test_decode_ver_link_SHA1() { return result; } result.confirm("verified self-signed signature", link_cert.check_signature(*pubkey)); + + result.end_timer(); return result; } #endif Test::Result test_encoding_options() { Test::Result result("ECDSA Unit"); + result.start_timer(); auto rng = Test::new_rng("ecdsa_encoding_options"); @@ -118,6 +130,7 @@ Test::Result test_encoding_options() { }); #endif + result.end_timer(); return result; } @@ -125,6 +138,7 @@ Test::Result test_encoding_options() { Test::Result test_read_pkcs8() { Test::Result result("ECDSA Unit"); + result.start_timer(); auto rng = Test::new_rng("ecdsa_read_pkcs8"); @@ -159,11 +173,13 @@ Test::Result test_read_pkcs8() { result.test_failure("read_pkcs8", e.what()); } + result.end_timer(); return result; } Test::Result test_ecc_key_with_rfc5915_extensions() { Test::Result result("ECDSA Unit"); + result.start_timer(); try { Botan::DataSource_Stream key_stream(Test::data_file("x509/ecc/ecc_private_with_rfc5915_ext.pem")); @@ -176,11 +192,13 @@ Test::Result test_ecc_key_with_rfc5915_extensions() { result.test_failure("load_rfc5915_ext", e.what()); } + result.end_timer(); return result; } Test::Result test_ecc_key_with_rfc5915_parameters() { Test::Result result("ECDSA Unit"); + result.start_timer(); try { Botan::DataSource_Stream key_stream(Test::data_file("x509/ecc/ecc_private_with_rfc5915_parameters.pem")); @@ -193,6 +211,7 @@ Test::Result test_ecc_key_with_rfc5915_parameters() { result.test_failure("load_rfc5915_params", e.what()); } + result.end_timer(); return result; } diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp index 5ba137c672f..7c59f23330d 100644 --- a/src/tests/unit_tls.cpp +++ b/src/tests/unit_tls.cpp @@ -1199,6 +1199,7 @@ class DTLS_Reconnection_Test : public Test { }; Test::Result result("DTLS reconnection"); + result.start_timer(); auto rng = Test::new_shared_rng(this->test_name()); @@ -1330,6 +1331,7 @@ class DTLS_Reconnection_Test : public Test { } } + result.end_timer(); return {result}; } }; diff --git a/src/tests/unit_tls_policy.cpp b/src/tests/unit_tls_policy.cpp index 2262ebcdffa..708d22c5797 100644 --- a/src/tests/unit_tls_policy.cpp +++ b/src/tests/unit_tls_policy.cpp @@ -52,6 +52,8 @@ class TLS_Policy_Unit_Tests final : public Test { private: static Test::Result test_peer_key_acceptable_rsa(Botan::RandomNumberGenerator& rng) { Test::Result result("TLS Policy RSA key verification"); + result.start_timer(); + #if defined(BOTAN_HAS_RSA) auto rsa_key_1024 = std::make_unique(rng, 1024); Botan::TLS::Policy policy; @@ -67,11 +69,15 @@ class TLS_Policy_Unit_Tests final : public Test { policy.check_peer_key_acceptable(*rsa_key_2048); result.test_success("Correctly accepting 2048 bit RSA keys"); #endif + + result.end_timer(); return result; } static Test::Result test_peer_key_acceptable_ecdh(Botan::RandomNumberGenerator& rng) { Test::Result result("TLS Policy ECDH key verification"); + result.start_timer(); + #if defined(BOTAN_HAS_ECDH) const auto group_192 = Botan::EC_Group::from_name("secp192r1"); auto ecdh_192 = std::make_unique(rng, group_192); @@ -89,11 +95,15 @@ class TLS_Policy_Unit_Tests final : public Test { policy.check_peer_key_acceptable(*ecdh_256); result.test_success("Correctly accepting 256 bit EC keys"); #endif + + result.end_timer(); return result; } static Test::Result test_peer_key_acceptable_ecdsa(Botan::RandomNumberGenerator& rng) { Test::Result result("TLS Policy ECDSA key verification"); + result.start_timer(); + #if defined(BOTAN_HAS_ECDSA) const auto group_192 = Botan::EC_Group::from_name("secp192r1"); auto ecdsa_192 = std::make_unique(rng, group_192); @@ -111,11 +121,15 @@ class TLS_Policy_Unit_Tests final : public Test { policy.check_peer_key_acceptable(*ecdsa_256); result.test_success("Correctly accepting 256 bit EC keys"); #endif + + result.end_timer(); return result; } static Test::Result test_peer_key_acceptable_dh() { Test::Result result("TLS Policy DH key verification"); + result.start_timer(); + #if defined(BOTAN_HAS_DIFFIE_HELLMAN) const BigInt g("2"); const BigInt p("58458002095536094658683755258523362961421200751439456159756164191494576279467"); @@ -131,11 +145,14 @@ class TLS_Policy_Unit_Tests final : public Test { result.test_success("Correctly rejecting short bit DH keys"); } #endif + + result.end_timer(); return result; } static Test::Result test_key_exchange_groups_to_offer() { Test::Result result("TLS Policy key share offering"); + result.start_timer(); Botan::TLS::Policy default_policy; result.test_eq( @@ -160,6 +177,7 @@ class TLS_Policy_Unit_Tests final : public Test { result.confirm("list of offerings (1)", TP(two_groups).key_exchange_groups_to_offer()[1] == Botan::TLS::Group_Params::FFDHE_4096); + result.end_timer(); return result; } }; diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp index 7520453af89..f22ccccb6ea 100644 --- a/src/tests/unit_x509.cpp +++ b/src/tests/unit_x509.cpp @@ -123,6 +123,7 @@ std::unique_ptr make_a_private_key(const std::string& algo, Test::Result test_cert_status_strings() { Test::Result result("Certificate_Status_Code to_string"); + result.start_timer(); std::set seen; @@ -186,11 +187,13 @@ Test::Result test_cert_status_strings() { seen.insert(s); } + result.end_timer(); return result; } Test::Result test_x509_extension() { Test::Result result("X509 Extensions API"); + result.start_timer(); Botan::Extensions extn; @@ -227,11 +230,13 @@ Test::Result test_x509_extension() { result.confirm("Basic constraints is not set", !extn.extension_set(oid_bc)); result.confirm("Basic constraints is not critical", !extn.critical_extension_set(oid_bc)); + result.end_timer(); return result; } Test::Result test_x509_dates() { Test::Result result("X509 Time"); + result.start_timer(); Botan::X509_Time time; result.confirm("unset time not set", !time.time_is_set()); @@ -402,6 +407,7 @@ Test::Result test_x509_dates() { result.test_throws("invalid", [v]() { Botan::X509_Time t(v, Botan::ASN1_Type::GeneralizedTime); }); } + result.end_timer(); return result; } @@ -409,6 +415,7 @@ Test::Result test_x509_dates() { Test::Result test_crl_dn_name() { Test::Result result("CRL DN name"); + result.start_timer(); // See GH #1252 @@ -430,11 +437,13 @@ Test::Result test_crl_dn_name() { result.confirm("contains DC component", crl.issuer_dn().get_attributes().count(dc_oid) == 1); #endif + result.end_timer(); return result; } Test::Result test_rdn_multielement_set_name() { Test::Result result("DN with multiple elements in RDN"); + result.start_timer(); // GH #2611 @@ -442,12 +451,14 @@ Test::Result test_rdn_multielement_set_name() { result.confirm("issuer DN contains expected name components", cert.issuer_dn().get_attributes().size() == 4); result.confirm("subject DN contains expected name components", cert.subject_dn().get_attributes().size() == 4); - + + result.end_timer(); return result; } Test::Result test_rsa_oaep() { Test::Result result("RSA OAEP decoding"); + result.start_timer(); #if defined(BOTAN_HAS_RSA) Botan::X509_Certificate cert(Test::data_file("x509/misc/rsa_oaep.pem")); @@ -459,11 +470,13 @@ Test::Result test_rsa_oaep() { result.test_eq("RSA-OAEP OID", pk_info.oid().to_string(), Botan::OID::from_string("RSA/OAEP").to_string()); #endif + result.end_timer(); return result; } Test::Result test_x509_decode_list() { Test::Result result("X509_Certificate list decode"); + result.start_timer(); Botan::DataSource_Stream input(Test::data_file("x509/misc/cert_seq.der"), true); @@ -476,11 +489,13 @@ Test::Result test_x509_decode_list() { result.test_eq("Expected cert 1 CN", certs[0].subject_dn().get_first_attribute("CN"), "CA1-PP.01.02"); result.test_eq("Expected cert 2 CN", certs[1].subject_dn().get_first_attribute("CN"), "User1-PP.01.02"); + result.end_timer(); return result; } Test::Result test_x509_utf8() { Test::Result result("X509 with UTF-8 encoded fields"); + result.start_timer(); try { Botan::X509_Certificate utf8_cert(Test::data_file("x509/misc/contains_utf8string.pem")); @@ -507,11 +522,13 @@ Test::Result test_x509_utf8() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_x509_bmpstring() { Test::Result result("X509 with UCS-2 (BMPString) encoded fields"); + result.start_timer(); try { Botan::X509_Certificate ucs2_cert(Test::data_file("x509/misc/contains_bmpstring.pem")); @@ -533,11 +550,13 @@ Test::Result test_x509_bmpstring() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_x509_teletex() { Test::Result result("X509 with TeletexString encoded fields"); + result.start_timer(); try { Botan::X509_Certificate teletex_cert(Test::data_file("x509/misc/teletex_dn.der")); @@ -552,11 +571,13 @@ Test::Result test_x509_teletex() { result.test_failure(ex.what()); } + result.end_timer(); return result; } Test::Result test_x509_authority_info_access_extension() { Test::Result result("X509 with PKIX.AuthorityInformationAccess extension"); + result.start_timer(); // contains no AIA extension Botan::X509_Certificate no_aia_cert(Test::data_file("x509/misc/contains_utf8string.pem")); @@ -571,6 +592,7 @@ Test::Result test_x509_authority_info_access_extension() { result.test_eq("number of ca_issuers URLs", ca_issuers.size(), 1); if(result.tests_failed()) { + result.end_timer(); return result; } @@ -585,6 +607,7 @@ Test::Result test_x509_authority_info_access_extension() { result.test_eq("number of ca_issuers URLs", ca_issuers2.size(), 2); if(result.tests_failed()) { + result.end_timer(); return result; } @@ -596,11 +619,13 @@ Test::Result test_x509_authority_info_access_extension() { "ldap://directory.d-trust.net/CN=Bdrive%20Test%20CA%201-2%202017,O=Bundesdruckerei%20GmbH,C=DE?cACertificate?base?"); result.test_eq("OCSP responder URL matches", aia_cert_2ca.ocsp_responder(), "http://staging.ocsp.d-trust.net"); + result.end_timer(); return result; } Test::Result test_x509_encode_authority_info_access_extension() { Test::Result result("X509 with encoded PKIX.AuthorityInformationAccess extension"); + result.start_timer(); #if defined(BOTAN_HAS_RSA) auto rng = Test::new_rng(__func__); @@ -634,6 +659,7 @@ Test::Result test_x509_encode_authority_info_access_extension() { Botan::X509_Certificate cert = ca.sign_request(req, *rng, from_date(-1, 01, 01), from_date(2, 01, 01)); if(!result.test_eq("number of ca_issuers URIs", cert.ca_issuers().size(), 2)) { + result.end_timer(); return result; } @@ -668,11 +694,13 @@ Test::Result test_x509_encode_authority_info_access_extension() { result.confirm("CA Issuer URI available", !cert.ca_issuers().empty()); #endif + result.end_timer(); return result; } Test::Result test_parse_rsa_pss_cert() { Test::Result result("X509 RSA-PSS certificate"); + result.start_timer(); // See https://github.com/randombit/botan/issues/3019 for background @@ -683,11 +711,13 @@ Test::Result test_parse_rsa_pss_cert() { result.test_failure("Parsing failed", e.what()); } + result.end_timer(); return result; } Test::Result test_verify_gost2012_cert() { Test::Result result("X509 GOST-2012 certificates"); + result.start_timer(); #if defined(BOTAN_HAS_GOST_34_10_2012) && defined(BOTAN_HAS_STREEBOG) try { @@ -707,6 +737,7 @@ Test::Result test_verify_gost2012_cert() { } #endif + result.end_timer(); return result; } @@ -719,6 +750,7 @@ Test::Result test_verify_gost2012_cert() { Test::Result test_padding_config() { // Throughout the test, some synonyms for EMSA4 are used, e.g. PSSR, EMSA-PSS Test::Result test_result("X509 Padding Config"); + test_result.start_timer(); auto rng = Test::new_rng(__func__); @@ -813,6 +845,7 @@ Test::Result test_padding_config() { Botan::x509_path_validate(end_cert_emsa4, restrictions, trusted); test_result.confirm("EMSA4-signed certificate validates", validation_result.successful_validation()); + test_result.end_timer(); return test_result; } #endif @@ -824,6 +857,7 @@ Test::Result test_pkcs10_ext(const Botan::Private_Key& key, const std::string& hash_fn, Botan::RandomNumberGenerator& rng) { Test::Result result("PKCS10 extensions"); + result.start_timer(); Botan::X509_Cert_Options opts; @@ -859,6 +893,7 @@ Test::Result test_pkcs10_ext(const Botan::Private_Key& key, result.test_eq("Expected number of alt DNs", req.subject_alt_name().directory_names().size(), 1); result.confirm("Alt DN is correct", *req.subject_alt_name().directory_names().begin() == alt_dn); + result.end_timer(); return result; } @@ -868,6 +903,7 @@ Test::Result test_x509_cert(const Botan::Private_Key& ca_key, const std::string& hash_fn, Botan::RandomNumberGenerator& rng) { Test::Result result("X509 Unit"); + result.start_timer(); /* Create the self-signed cert */ const auto ca_cert = Botan::X509::create_self_signed_cert(ca_opts(sig_padding), ca_key, hash_fn, rng); @@ -1019,6 +1055,7 @@ Test::Result test_x509_cert(const Botan::Private_Key& ca_key, result_u2 = Botan::x509_path_validate(user2_cert, restrictions, store); result.test_eq("user 2 still revoked", result_u2.result_string(), revoked_str); + result.end_timer(); return result; } @@ -1030,6 +1067,7 @@ Test::Result test_usage(const Botan::Private_Key& ca_key, using Botan::Usage_Type; Test::Result result("X509 Usage"); + result.start_timer(); /* Create the self-signed cert */ const Botan::X509_Certificate ca_cert = Botan::X509::create_self_signed_cert(ca_opts(), ca_key, hash_fn, rng); @@ -1098,6 +1136,7 @@ Test::Result test_usage(const Botan::Private_Key& ca_key, result.confirm("cert does not allow TLS client auth", !enc_cert.allowed_usage(Usage_Type::TLS_CLIENT_AUTH)); } + result.end_timer(); return result; } @@ -1109,6 +1148,7 @@ Test::Result test_self_issued(const Botan::Private_Key& ca_key, using Botan::Key_Constraints; Test::Result result("X509 Self Issued"); + result.start_timer(); // create the self-signed cert const Botan::X509_Certificate ca_cert = @@ -1140,11 +1180,13 @@ Test::Result test_self_issued(const Botan::Private_Key& ca_key, result.confirm("chain with self-issued cert validates", validation_result.successful_validation()); + result.end_timer(); return result; } Test::Result test_x509_uninit() { Test::Result result("X509 object uninitialized access"); + result.start_timer(); Botan::X509_Certificate cert; result.test_throws("uninitialized cert access causes exception", "X509_Certificate uninitialized", [&cert]() { @@ -1155,6 +1197,7 @@ Test::Result test_x509_uninit() { result.test_throws( "uninitialized crl access causes exception", "X509_CRL uninitialized", [&crl]() { crl.crl_number(); }); + result.end_timer(); return result; } @@ -1162,6 +1205,7 @@ Test::Result test_valid_constraints(const Botan::Private_Key& key, const std::st using Botan::Key_Constraints; Test::Result result("X509 Valid Constraints " + pk_algo); + result.start_timer(); result.confirm("empty constraints always acceptable", Key_Constraints().compatible_with(key)); @@ -1254,6 +1298,7 @@ Test::Result test_valid_constraints(const Botan::Private_Key& key, const std::st result.test_eq("sign allowed", sign_everything.compatible_with(key), true); } + result.end_timer(); return result; } @@ -1300,7 +1345,8 @@ Test::Result test_custom_dn_attr(const Botan::Private_Key& ca_key, const std::string& hash_fn, Botan::RandomNumberGenerator& rng) { Test::Result result("X509 Custom DN"); - + result.start_timer(); + /* Create the self-signed cert */ Botan::X509_Certificate ca_cert = Botan::X509::create_self_signed_cert(ca_opts(sig_padding), ca_key, hash_fn, rng); @@ -1351,6 +1397,7 @@ Test::Result test_custom_dn_attr(const Botan::Private_Key& ca_key, result.confirm("Attr1 tag matches encoded", cert_val1.tagging() == val1.tagging()); result.confirm("Attr2 tag matches encoded", cert_val2.tagging() == val2.tagging()); + result.end_timer(); return result; } @@ -1362,6 +1409,7 @@ Test::Result test_x509_extensions(const Botan::Private_Key& ca_key, using Botan::Key_Constraints; Test::Result result("X509 Extensions"); + result.start_timer(); /* Create the self-signed cert */ Botan::X509_Certificate ca_cert = Botan::X509::create_self_signed_cert(ca_opts(sig_padding), ca_key, hash_fn, rng); @@ -1467,11 +1515,13 @@ Test::Result test_x509_extensions(const Botan::Private_Key& ca_key, } } + result.end_timer(); return result; } Test::Result test_hashes(const Botan::Private_Key& key, const std::string& hash_fn, Botan::RandomNumberGenerator& rng) { Test::Result result("X509 Hashes"); + result.start_timer(); struct TestData { const std::string issuer, subject, issuer_hash, subject_hash; @@ -1518,6 +1568,7 @@ Test::Result test_hashes(const Botan::Private_Key& key, const std::string& hash_ result.test_eq(a.subject, Botan::hex_encode(subject_cert.raw_issuer_dn_sha256()), a.issuer_hash); result.test_eq(a.subject, Botan::hex_encode(subject_cert.raw_subject_dn_sha256()), a.subject_hash); } + result.end_timer(); return result; }