diff --git a/.circleci/config.yml b/.circleci/config.yml index 119cdcb4c4..3c6cc786c0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -117,7 +117,7 @@ jobs: - run: name: Run tests no_output_timeout: 1h - command: mkdir -p tmp && python3 -m pytest --verbose --ignore=tests/test_code_conventions.py --junitxml=build/test-results/pytest/test-results.xml << parameters.PYTEST_ARGS >> + command: mkdir -p tmp && python3 -m pytest --verbose --ignore=tests/test_speed.py --ignore=tests/test_code_conventions.py --junitxml=build/test-results/pytest/test-results.xml << parameters.PYTEST_ARGS >> environment: SKIP_ALGS: << parameters.SKIP_ALGS >> - store_test_results: # Note that this command will fail when running CircleCI locally, that is expected behaviour diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index aba1c79d3d..a0c1bbe9e3 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -101,7 +101,7 @@ jobs: - name: armhf ARCH: armhf CMAKE_ARGS: -DOQS_ENABLE_SIG_SPHINCS=OFF -DOQS_USE_OPENSSL=OFF -DOQS_OPT_TARGET=generic - PYTEST_ARGS: --ignore=tests/test_alg_info.py + PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_speed.py # no longer supporting armel # - name: armel # ARCH: armel diff --git a/tests/speed_kem.c b/tests/speed_kem.c index 1f984c6bf9..883a09bf49 100644 --- a/tests/speed_kem.c +++ b/tests/speed_kem.c @@ -17,7 +17,23 @@ #include "ds_benchmark.h" #include "system_info.c" -static OQS_STATUS kem_speed_wrapper(const char *method_name, uint64_t duration, bool printInfo) { +static void fullcycletest(OQS_KEM *kem, uint8_t *public_key, uint8_t *secret_key, uint8_t *ciphertext, uint8_t *shared_secret_e, uint8_t *shared_secret_d) { + if (OQS_KEM_keypair(kem, public_key, secret_key) != OQS_SUCCESS) { + printf("Error creating KEM key. Exiting.\n"); + exit(-1); + } + if (OQS_KEM_encaps(kem, ciphertext, shared_secret_e, public_key) != OQS_SUCCESS) { + printf("Error during KEM encaps. Exiting.\n"); + exit(-1); + } + if (OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key) != OQS_SUCCESS) { + printf("Error during KEM decaps. Exiting.\n"); + exit(-1); + } + +} + +static OQS_STATUS kem_speed_wrapper(const char *method_name, uint64_t duration, bool printInfo, bool doFullCycle) { OQS_KEM *kem = NULL; uint8_t *public_key = NULL; @@ -44,9 +60,13 @@ static OQS_STATUS kem_speed_wrapper(const char *method_name, uint64_t duration, } printf("%-36s | %10s | %14s | %15s | %10s | %25s | %10s\n", kem->method_name, "", "", "", "", "", ""); - TIME_OPERATION_SECONDS(OQS_KEM_keypair(kem, public_key, secret_key), "keygen", duration) - TIME_OPERATION_SECONDS(OQS_KEM_encaps(kem, ciphertext, shared_secret_e, public_key), "encaps", duration) - TIME_OPERATION_SECONDS(OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key), "decaps", duration) + if (!doFullCycle) { + TIME_OPERATION_SECONDS(OQS_KEM_keypair(kem, public_key, secret_key), "keygen", duration) + TIME_OPERATION_SECONDS(OQS_KEM_encaps(kem, ciphertext, shared_secret_e, public_key), "encaps", duration) + TIME_OPERATION_SECONDS(OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key), "decaps", duration) + } else { + TIME_OPERATION_SECONDS(fullcycletest(kem, public_key, secret_key, ciphertext, shared_secret_e, shared_secret_d), "fullcycletest", duration) + } if (printInfo) { printf("public key bytes: %zu, ciphertext bytes: %zu, secret key bytes: %zu, shared secret key bytes: %zu, NIST level: %d, IND-CCA: %s\n", kem->length_public_key, kem->length_ciphertext, kem->length_secret_key, kem->length_shared_secret, kem->claimed_nist_level, kem->ind_cca ? "Y" : "N"); @@ -92,6 +112,7 @@ int main(int argc, char **argv) { bool printUsage = false; uint64_t duration = 3; bool printKemInfo = false; + bool doFullCycle = false; OQS_KEM *single_kem = NULL; @@ -119,6 +140,9 @@ int main(int argc, char **argv) { } else if ((strcmp(argv[i], "--info") == 0) || (strcmp(argv[i], "-i") == 0)) { printKemInfo = true; continue; + } else if ((strcmp(argv[i], "--fullcycle") == 0) || (strcmp(argv[i], "-f") == 0)) { + doFullCycle = true; + continue; } else { single_kem = OQS_KEM_new(argv[i]); if (single_kem == NULL) { @@ -139,6 +163,8 @@ int main(int argc, char **argv) { fprintf(stderr, " -h Print usage\n"); fprintf(stderr, "--info\n"); fprintf(stderr, " -i Print info (sizes, security level) about each KEM\n"); + fprintf(stderr, "--fullcycle\n"); + fprintf(stderr, " -f Do full keygen-encaps-decaps cycle for each KEM\n"); fprintf(stderr, "\n"); fprintf(stderr, " Only run the specified KEM method; must be one of the algorithms output by --algs\n"); return EXIT_FAILURE; @@ -151,13 +177,14 @@ int main(int argc, char **argv) { PRINT_TIMER_HEADER if (single_kem != NULL) { - rc = kem_speed_wrapper(single_kem->method_name, duration, printKemInfo); + rc = kem_speed_wrapper(single_kem->method_name, duration, printKemInfo, doFullCycle); if (rc != OQS_SUCCESS) { ret = EXIT_FAILURE; } + OQS_KEM_free(single_kem); } else { for (size_t i = 0; i < OQS_KEM_algs_length; i++) { - rc = kem_speed_wrapper(OQS_KEM_alg_identifier(i), duration, printKemInfo); + rc = kem_speed_wrapper(OQS_KEM_alg_identifier(i), duration, printKemInfo, doFullCycle); if (rc != OQS_SUCCESS) { ret = EXIT_FAILURE; } diff --git a/tests/speed_sig.c b/tests/speed_sig.c index 25831e6c90..2876420e00 100644 --- a/tests/speed_sig.c +++ b/tests/speed_sig.c @@ -17,7 +17,22 @@ #include "ds_benchmark.h" #include "system_info.c" -static OQS_STATUS sig_speed_wrapper(const char *method_name, uint64_t duration, bool printInfo) { +static void fullcycle(OQS_SIG *sig, uint8_t *public_key, uint8_t *secret_key, uint8_t *signature, size_t signature_len, uint8_t *message, size_t message_len) { + if (OQS_SIG_keypair(sig, public_key, secret_key) != OQS_SUCCESS) { + printf("keygen error. Exiting.\n"); + exit(-1); + } + if (OQS_SIG_sign(sig, signature, &signature_len, message, message_len, secret_key) != OQS_SUCCESS) { + printf("sign error. Exiting.\n"); + exit(-1); + } + if (OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key) != OQS_SUCCESS) { + printf("verify error. Exiting.\n"); + exit(-1); + } +} + +static OQS_STATUS sig_speed_wrapper(const char *method_name, uint64_t duration, bool printInfo, bool doFullCycle) { OQS_SIG *sig = NULL; uint8_t *public_key = NULL; @@ -46,9 +61,14 @@ static OQS_STATUS sig_speed_wrapper(const char *method_name, uint64_t duration, OQS_randombytes(message, message_len); printf("%-36s | %10s | %14s | %15s | %10s | %25s | %10s\n", sig->method_name, "", "", "", "", "", ""); - TIME_OPERATION_SECONDS(OQS_SIG_keypair(sig, public_key, secret_key), "keypair", duration) - TIME_OPERATION_SECONDS(OQS_SIG_sign(sig, signature, &signature_len, message, message_len, secret_key), "sign", duration) - TIME_OPERATION_SECONDS(OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key), "verify", duration) + if (!doFullCycle) { + TIME_OPERATION_SECONDS(OQS_SIG_keypair(sig, public_key, secret_key), "keypair", duration) + TIME_OPERATION_SECONDS(OQS_SIG_sign(sig, signature, &signature_len, message, message_len, secret_key), "sign", duration) + TIME_OPERATION_SECONDS(OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key), "verify", duration) + } else { + TIME_OPERATION_SECONDS(fullcycle(sig, public_key, secret_key, signature, signature_len, message, message_len), "fullcycle", duration) + } + if (printInfo) { printf("public key bytes: %zu, secret key bytes: %zu, signature bytes: %zu\n", sig->length_public_key, sig->length_secret_key, sig->length_signature); @@ -96,6 +116,7 @@ int main(int argc, char **argv) { bool printUsage = false; uint64_t duration = 3; bool printSigInfo = false; + bool doFullCycle = false; OQS_SIG *single_sig = NULL; @@ -123,6 +144,9 @@ int main(int argc, char **argv) { } else if ((strcmp(argv[i], "--info") == 0) || (strcmp(argv[i], "-i") == 0)) { printSigInfo = true; continue; + } else if ((strcmp(argv[i], "--fullcycle") == 0) || (strcmp(argv[i], "-f") == 0)) { + doFullCycle = true; + continue; } else { single_sig = OQS_SIG_new(argv[i]); if (single_sig == NULL) { @@ -143,6 +167,8 @@ int main(int argc, char **argv) { fprintf(stderr, " -h Print usage\n"); fprintf(stderr, "--info\n"); fprintf(stderr, " -i Print info (sizes, security level) about each SIG\n"); + fprintf(stderr, "--fullcycle\n"); + fprintf(stderr, " -f Test full keygen-sign-verify cycle of each SIG\n"); fprintf(stderr, "\n"); fprintf(stderr, " Only run the specified SIG method; must be one of the algorithms output by --algs\n"); return EXIT_FAILURE; @@ -155,13 +181,15 @@ int main(int argc, char **argv) { PRINT_TIMER_HEADER if (single_sig != NULL) { - rc = sig_speed_wrapper(single_sig->method_name, duration, printSigInfo); + rc = sig_speed_wrapper(single_sig->method_name, duration, printSigInfo, doFullCycle); if (rc != OQS_SUCCESS) { ret = EXIT_FAILURE; } + OQS_SIG_free(single_sig); + } else { for (size_t i = 0; i < OQS_SIG_algs_length; i++) { - rc = sig_speed_wrapper(OQS_SIG_alg_identifier(i), duration, printSigInfo); + rc = sig_speed_wrapper(OQS_SIG_alg_identifier(i), duration, printSigInfo, doFullCycle); if (rc != OQS_SUCCESS) { ret = EXIT_FAILURE; } diff --git a/tests/test_speed.py b/tests/test_speed.py new file mode 100644 index 0000000000..a99bbc9499 --- /dev/null +++ b/tests/test_speed.py @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: MIT + +import helpers +import os +import os.path +import pytest +import platform + +@helpers.filtered_test +@pytest.mark.parametrize('kem_name', helpers.available_kems_by_name()) +def test_kem(kem_name): + kats = helpers.get_kats("kem") + if not(helpers.is_kem_enabled_by_name(kem_name)): pytest.skip('Not enabled') + helpers.run_subprocess( [helpers.path_to_executable('speed_kem'), kem_name, "-f"] ) + +@helpers.filtered_test +@pytest.mark.parametrize('sig_name', helpers.available_sigs_by_name()) +def test_sig(sig_name): + kats = helpers.get_kats("sig") + if not(helpers.is_sig_enabled_by_name(sig_name)): pytest.skip('Not enabled') + helpers.run_subprocess( [helpers.path_to_executable('speed_sig'), sig_name, "-f"]) + +if __name__ == "__main__": + import sys + pytest.main(sys.argv)