Skip to content

Commit

Permalink
Add full-cycle speed test (#1391)
Browse files Browse the repository at this point in the history
* adding true repetitive full-cycle testing

* fix mem leak in speed testing
  • Loading branch information
baentsch authored Feb 17, 2023
1 parent f96d9c2 commit 20fadb8
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 33 additions & 6 deletions tests/speed_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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");
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand All @@ -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, "<alg> Only run the specified KEM method; must be one of the algorithms output by --algs\n");
return EXIT_FAILURE;
Expand All @@ -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;
}
Expand Down
40 changes: 34 additions & 6 deletions tests/speed_sig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand All @@ -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, "<alg> Only run the specified SIG method; must be one of the algorithms output by --algs\n");
return EXIT_FAILURE;
Expand All @@ -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;
}
Expand Down
25 changes: 25 additions & 0 deletions tests/test_speed.py
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 20fadb8

Please sign in to comment.