Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions src/cli/perf_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,34 +277,22 @@ 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); });
}
}

config.record_result(*genprime_timer);
config.record_result(*gensafe_timer);
config.record_result(*is_prime_timer);
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/scripts/ci_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
47 changes: 37 additions & 10 deletions src/scripts/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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')

Expand Down Expand Up @@ -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')

Expand Down Expand Up @@ -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,
]

Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down
Loading