diff --git a/src/cli/perf_math.cpp b/src/cli/perf_math.cpp index 758f75b213..c61b34814c 100644 --- a/src/cli/perf_math.cpp +++ b/src/cli/perf_math.cpp @@ -277,26 +277,15 @@ class PerfTest_RandomPrime final : public PerfTest { for(size_t bits : {256, 384, 512, 768, 1024, 1536}) { auto genprime_timer = config.make_timer("random_prime " + std::to_string(bits)); - auto gensafe_timer = config.make_timer("random_safe_prime " + std::to_string(bits)); auto is_prime_timer = config.make_timer("is_prime " + std::to_string(bits)); - while(gensafe_timer->under(runtime)) { + while(genprime_timer->under(runtime) && is_prime_timer->under(runtime)) { const Botan::BigInt p = genprime_timer->run([&] { return Botan::random_prime(rng, bits, coprime); }); if(!is_prime_timer->run([&] { return Botan::is_prime(p, rng, 64, true); })) { config.error_output() << "Generated prime " << p << " which failed a primality test"; } - const Botan::BigInt sg = gensafe_timer->run([&] { return Botan::random_safe_prime(rng, bits); }); - - if(!is_prime_timer->run([&] { return Botan::is_prime(sg, rng, 64, true); })) { - config.error_output() << "Generated safe prime " << sg << " which failed a primality test"; - } - - if(!is_prime_timer->run([&] { return Botan::is_prime(sg / 2, rng, 64, true); })) { - config.error_output() << "Generated prime " << sg / 2 << " which failed a primality test"; - } - // Now test p+2, p+4, ... which may or may not be prime for(size_t i = 2; i <= 64; i += 2) { is_prime_timer->run([&]() { Botan::is_prime(p + i, rng, 64, true); }); @@ -304,7 +293,6 @@ class PerfTest_RandomPrime final : public PerfTest { } config.record_result(*genprime_timer); - config.record_result(*gensafe_timer); config.record_result(*is_prime_timer); } } diff --git a/src/scripts/ci_build.py b/src/scripts/ci_build.py index 695bd25019..68cc94c1fd 100755 --- a/src/scripts/ci_build.py +++ b/src/scripts/ci_build.py @@ -939,7 +939,9 @@ def main(args=None): botan_exe = os.path.join(build_dir, 'botan-cli.exe' if options.os == 'windows' else 'botan') args = ['--threads=%d' % (options.build_jobs)] - if target in ['coverage']: + if target in ['shared']: + # Ideally we'd run these in the coverage build but with coverage some + # of them run incredibly slowly, eg cli_xmss_sign_tests takes 10+ minutes args.append('--run-slow-tests') if root_dir != '.': args.append('--test-data-dir=%s' % root_dir) diff --git a/src/scripts/test_cli.py b/src/scripts/test_cli.py index 60b0b890bd..937b23ee44 100755 --- a/src/scripts/test_cli.py +++ b/src/scripts/test_cli.py @@ -262,6 +262,8 @@ def test_cli(cmd, cmd_options, if "\r\n" in stdout: stdout = stdout.replace("\r\n", "\n") + if "\r\n" in stderr: + stderr = stderr.replace("\r\n", "\n") if stderr: if expected_stderr is None: @@ -565,6 +567,11 @@ def cli_key_tests(tmp_dir): "Certificate did not validate - Certificate issuer not found") def cli_xmss_sign_tests(tmp_dir): + if os.linesep != '\n': + # This test is hashing the PEM encoding of the XMSS private key which + # will have a different value due to line endings + return + priv_key = os.path.join(tmp_dir, 'priv.pem') pub_key = os.path.join(tmp_dir, 'pub.pem') pub_key2 = os.path.join(tmp_dir, 'pub2.pem') @@ -1617,12 +1624,25 @@ def cli_tls_client_hello_tests(_tmp_dir): output = test_cli("tls_client_hello", ["--hex", "-"], None, chello) test_cli("hash", ["--no-fsname", "--algo=SHA-256", "-"], output_hash, output) -def cli_speed_pk_tests(_tmp_dir): +def cli_speed_pk_fast_tests(_tmp_dir): msec = 1 pk_algos = ["ECDSA", "ECDH", "SM2", "ECKCDSA", "ECGDSA", "GOST-34.10", - "DH", "DSA", "ElGamal", "Ed25519", "Ed448", "X25519", "X448", - "RSA", "RSA_keygen", "XMSS", "Kyber", "Dilithium", "SLH-DSA"] + "ML-KEM", "ML-DSA", "Ed25519", "Ed448", "X25519", "X448", + "DH", "DSA", "ElGamal"] + + output = test_cli("speed", ["--msec=%d" % (msec)] + pk_algos, None).split('\n') + + # ECDSA-secp256r1 106 keygen/sec; 9.35 ms/op 37489733 cycles/op (1 op in 9 ms) + format_re = re.compile(r'^.* [0-9]+ ([A-Za-z0-9 ]+)/sec; [0-9]+\.[0-9]+ ms/op .*\([0-9]+ (op|ops) in [0-9\.]+ ms\)') + for line in output: + if format_re.match(line) is None: + logging.error("Unexpected line %s", line) + +def cli_speed_pk_slow_tests(_tmp_dir): + msec = 1 + + pk_algos = ["RSA", "RSA_keygen", "XMSS", "SLH-DSA"] output = test_cli("speed", ["--msec=%d" % (msec)] + pk_algos, None).split('\n') @@ -1654,6 +1674,12 @@ def cli_speed_table_tests(_tmp_dir): output = test_cli("speed", ["--format=table", "--msec=%d" % (msec), "AES-128"], None).split('\n') + # Mac is somewhat unusual in that there is (at least for now) a parallel provider + # that is distinct from but does not replace the usual algorithm implementations. + # Just zap out lines referencing this provider from the output so that the remainder + # has the same format as other platforms + output = [line for line in output if "commoncrypto" not in line] + if len(output) != 11: logging.error('Unexpected number of lines from table output') @@ -1836,12 +1862,9 @@ def main(args=None): return 1 slow_test_fns = [ - cli_speed_tests, - cli_speed_pk_tests, + cli_speed_pk_slow_tests, cli_speed_math_tests, cli_speed_pbkdf_tests, - cli_speed_table_tests, - cli_speed_invalid_option_tests, cli_xmss_sign_tests, ] @@ -1880,6 +1903,10 @@ def main(args=None): cli_rng_tests, cli_roughtime_check_tests, cli_roughtime_tests, + cli_speed_tests, + cli_speed_pk_fast_tests, + cli_speed_invalid_option_tests, + cli_speed_table_tests, cli_timing_test_tests, cli_tls_ciphersuite_tests, cli_tls_client_hello_tests, @@ -1896,9 +1923,9 @@ def main(args=None): test_fns = [] if options.run_slow_tests: - test_fns = slow_test_fns + fast_test_fns - else: - test_fns = fast_test_fns + test_fns += slow_test_fns + + test_fns += fast_test_fns if not options.skip_tls_proxy_test: test_fns.append(cli_tls_proxy_tests)