add portability tests (#871)

* added portability tests only on Ubuntu, documentation added

* using Westmere as test CPU type; disable avx2 for common code other than sha3x4 on portable builds

* removed extraneous PORTABLE_BUILD guards
This commit is contained in:
Michael Baentsch 2020-12-17 16:10:27 +01:00 committed by GitHub
parent 1fb8a3d382
commit b08d581acb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 78 additions and 13 deletions

View File

@ -249,6 +249,7 @@ workflows:
context: openquantumsafe
CONTAINER: openquantumsafe/ci-ubuntu-bionic-x86_64:latest
CMAKE_ARGS: -DCMAKE_C_COMPILER=clang-9 -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=Address
PYTEST_ARGS: --ignore=tests/test_portability.py --numprocesses=auto
# Disabling for now due to https://github.com/open-quantum-safe/liboqs/issues/791
#- linux_x64:
# name: undefined-sanitizer

View File

@ -112,6 +112,8 @@ The following instructions assume we are in `build`.
- `test_kem`: Simple test harness for key encapsulation mechanisms
- `test_sig`: Simple test harness for key signature schemes
- `test_kem_mem`: Simple test harness for checking memory consumption of key encapsulation mechanisms
- `test_sig_mem`: Simple test harness for checking memory consumption of key signature schemes
- `kat_kem`: Program that generates known answer test (KAT) values for key encapsulation mechanisms using the same procedure as the NIST submission requirements, for checking against submitted KAT values using `tests/test_kat.py`
- `kat_sig`: Program that generates known answer test (KAT) values for signature schemes using the same procedure as the NIST submission requirements, for checking against submitted KAT values using `tests/test_kat.py`
- `speed_kem`: Benchmarking program for key encapsulation mechanisms; see `./speed_kem --help` for usage instructions
@ -119,6 +121,7 @@ The following instructions assume we are in `build`.
- `example_kem`: Minimal runnable example showing the usage of the KEM API
- `example_sig`: Minimal runnable example showing the usage of the signature API
- `test_aes`, `test_sha3`: Simple test harnesses for crypto sub-components
- `test_portability`: Simple test harnesses for checking cross-CPU code portability; requires presence of `qemu`; proper operation validated only on Ubuntu
The test suite can be run using

View File

@ -65,7 +65,8 @@ add_library(oqs kem/kem.c
${KEM_OBJS}
sig/sig.c
${SIG_OBJS}
$<TARGET_OBJECTS:common>)
${COMMON_OBJS})
set(COMMON_OBJS ${COMMON_OBJS} PARENT_SCOPE)
if(DEFINED SANITIZER_LD_FLAGS)
target_link_libraries(oqs PUBLIC ${SANITIZER_LD_FLAGS})
endif()

View File

@ -49,10 +49,18 @@ endif()
# That being said, code that requires these functions must take care to ensure
# that they fall-back appropriately.
# What must be ensured, though, is that only sha3x4 is compiled with avx2;
# all other code must be compiled without this extension if portability is requested
if(OQS_USE_AVX2_INSTRUCTIONS)
if(OQS_PORTABLE_BUILD)
add_library(sha3x4_avx2 OBJECT sha3/sha3x4.c)
target_compile_options(sha3x4_avx2 PRIVATE -mavx2)
set(_COMMON_OBJS $<TARGET_OBJECTS:sha3x4_avx2>)
else()
set(SHA3_IMPL ${SHA3_IMPL} sha3/sha3x4.c)
add_compile_options(-mavx2)
endif()
endif()
add_library(common OBJECT ${AES_IMPL}
${SHA2_IMPL}
@ -64,3 +72,6 @@ add_library(common OBJECT ${AES_IMPL}
if(OQS_USE_OPENSSL)
target_include_directories(common PRIVATE ${OPENSSL_INCLUDE_DIR})
endif()
set(_COMMON_OBJS ${_COMMON_OBJS} $<TARGET_OBJECTS:common>)
set(COMMON_OBJS ${_COMMON_OBJS} PARENT_SCOPE)

View File

@ -10,7 +10,7 @@
#include <windows.h>
#endif
#if (defined(OQS_USE_CPU_EXTENSIONS) && defined(OQS_PORTABLE_BUILD))
#if defined(OQS_USE_CPU_EXTENSIONS)
static OQS_CPU_EXTENSIONS available_cpu_extensions = { 0 };
static unsigned int available_cpu_extensions_set = 0;
@ -148,10 +148,10 @@ OQS_API OQS_CPU_EXTENSIONS OQS_get_available_CPU_extensions(void) {
}
return available_cpu_extensions;
}
#endif /* OQS_USE_CPU_EXTENSIONS && OQS_PORTABLE_BUILD */
#endif /* OQS_USE_CPU_EXTENSIONS */
OQS_API void OQS_init(void) {
#if (defined(OQS_USE_CPU_EXTENSIONS) && defined(OQS_PORTABLE_BUILD))
#if defined(OQS_USE_CPU_EXTENSIONS)
if (!available_cpu_extensions_set) {
#if defined(ARCH_X86_64)
set_available_cpu_extensions_x86_64();
@ -160,7 +160,7 @@ OQS_API void OQS_init(void) {
#endif /* ARCH_X86_64 or ARCH_ARM_ANY */
available_cpu_extensions_set = 1;
}
#endif /* OQS_USE_CPU_EXTENSIONS && OQS_PORTABLE_BUILD */
#endif /* OQS_USE_CPU_EXTENSIONS */
}
OQS_API void OQS_MEM_cleanse(void *ptr, size_t len) {

View File

@ -98,7 +98,7 @@ typedef enum {
OQS_EXTERNAL_LIB_ERROR_OPENSSL = 50,
} OQS_STATUS;
#if (defined(OQS_USE_CPU_EXTENSIONS) && defined(OQS_PORTABLE_BUILD))
#if defined(OQS_USE_CPU_EXTENSIONS)
/**
* Architecture macros.
@ -147,7 +147,7 @@ OQS_API OQS_CPU_EXTENSIONS OQS_get_available_CPU_extensions(void);
*/
OQS_API const char *OQS_get_cpu_extension_name(unsigned int i);
#endif /* OQS_USE_CPU_EXTENSIONS && OQS_PORTABLE_BUILD */
#endif /* OQS_USE_CPU_EXTENSIONS */
/**
* This currently only sets the values in the OQS_CPU_EXTENSIONS,

View File

@ -34,13 +34,13 @@ if(NOT WIN32)
execute_process(COMMAND ${PROJECT_SOURCE_DIR}/scripts/git_commit.sh OUTPUT_VARIABLE GIT_COMMIT)
add_definitions(-DOQS_COMPILE_GIT_COMMIT="${GIT_COMMIT}")
add_executable(test_aes test_aes.c $<TARGET_OBJECTS:common>)
add_executable(test_aes test_aes.c ${COMMON_OBJS})
target_link_libraries(test_aes PRIVATE ${INTERNAL_TEST_DEPS})
add_executable(test_hash test_hash.c $<TARGET_OBJECTS:common>)
add_executable(test_hash test_hash.c ${COMMON_OBJS})
target_link_libraries(test_hash PRIVATE ${INTERNAL_TEST_DEPS})
add_executable(test_sha3 test_sha3.c $<TARGET_OBJECTS:common>)
add_executable(test_sha3 test_sha3.c ${COMMON_OBJS})
target_link_libraries(test_sha3 PRIVATE ${INTERNAL_TEST_DEPS})
set(UNIX_TESTS test_aes test_hash test_sha3)

View File

@ -60,7 +60,7 @@ static void print_platform_info(void) {
/* Display all active CPU extensions: */
static void print_cpu_extensions(void) {
#if defined(OQS_USE_CPU_EXTENSIONS) && defined(OQS_PORTABLE_BUILD)
#if defined(OQS_USE_CPU_EXTENSIONS)
/* Make CPU features struct iterable */
typedef union ext_u {
OQS_CPU_EXTENSIONS ext_x;
@ -81,10 +81,15 @@ static void print_cpu_extensions(void) {
}
}
}
printf("\n");
#else /* no extensions active */
printf("CPU exts active: None\n");
printf("CPU exts active: None");
#endif
#if defined(OQS_PORTABLE_BUILD)
printf(" (portable build)\n");
#else
printf("\n");
#endif
}
static void print_oqs_configuration(void) {

44
tests/test_portability.py Normal file
View File

@ -0,0 +1,44 @@
# SPDX-License-Identifier: MIT
import helpers
import pytest
import platform
from pathlib import Path
MIN_CPUS = {}
# set other CPU types for other architectures; Westmere supports cpuid but not avx2
MIN_CPUS["x86_64"] = "Westmere"
@helpers.filtered_test
@pytest.mark.parametrize('kem_name', helpers.available_kems_by_name())
@pytest.mark.skipif(not "Ubuntu" in platform.platform(), reason="Only supported on Ubuntu")
def test_kem(kem_name):
if not(helpers.is_build_portable()):
pytest.skip("Portability not enabled")
if not(helpers.is_kem_enabled_by_name(kem_name)):
pytest.skip('Not enabled')
helpers.run_subprocess(["qemu-"+platform.machine(), "-cpu", MIN_CPUS[platform.machine()],
helpers.path_to_executable('test_kem'), kem_name])
@helpers.filtered_test
@pytest.mark.parametrize('sig_name', helpers.available_sigs_by_name())
@pytest.mark.skipif(not "Ubuntu" in platform.platform(), reason="Only supported on Ubuntu")
def test_sig(sig_name):
if not(helpers.is_build_portable()):
pytest.skip("Portability not enabled")
if not(helpers.is_sig_enabled_by_name(sig_name)):
pytest.skip('Not enabled')
if (sig_name.startswith("picnic")):
pytest.skip("Picnic portability known to not be given.")
helpers.run_subprocess(["qemu-"+platform.machine(), "-cpu", MIN_CPUS[platform.machine()],
helpers.path_to_executable('test_sig'), sig_name])
if __name__ == "__main__":
import sys
pytest.main(sys.argv)