diff --git a/liboqs-0.10.0-dlopen-openssl.patch b/liboqs-0.10.0-dlopen-openssl.patch new file mode 100644 index 0000000..14ba12d --- /dev/null +++ b/liboqs-0.10.0-dlopen-openssl.patch @@ -0,0 +1,4189 @@ +From 32afec8fccd77a264e6104764986ce46d120f5ff Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Fri, 5 Apr 2024 23:20:17 +0900 +Subject: [PATCH] Add option to dynamically load libcrypto.so.* (#1603) + +* sha2: Use EVP_MD_CTX_free instead of EVP_MD_CTX_destroy + +According to the manual page, EVP_MD_CTX_destroy has been renamed to +EVP_MD_CTX_free in OpenSSL 1.1.0 and only provided as a compatibility +macro in later OpenSSL releases: +https://www.openssl.org/docs/man1.1.1/man3/EVP_MD_CTX_free.html + +Signed-off-by: Daiki Ueno + +* ossl_helpers: Use pthread_once instead of CRYPTO_THREAD_run_once + +Throughout the code base, liboqs uses pthread_once for one-shot +initialization and falls back to thread-unsafe code if it is not +supported nor enabled on the system. For consistency and to remove +additional dependency on OpenSSL, this switches the use of +CRYPTO_THREAD_run_once with that. + +Signed-off-by: Daiki Ueno + +* Make common algorithms pluggable + +This allows applications to replace the implementation of common +cryptographic algorithms at runtime, by setting callback functions for +each operations with OQS_AES_set_callbacks, OQS_SHA2_set_callbacks, +OQS_SHA3_set_callbacks, and OQS_SHA3_x4_callbacks. Those functions +may be called once before OQS_init; otherwise the default +implementation will be used. + +Signed-off-by: Daiki Ueno + +* Add option to dynamically load libcrypto.so.* + +This adds OQS_DLOPEN_OPENSSL build option to use OpenSSL through +dynamically loaded libcrypto.so.* with dlopen, instead of linking to +the library at build time. + +That way the applications could use their favorite implementation of +common cryptographic primitives without pulling in the OpenSSL as a +hard dependency. + +Signed-off-by: Daiki Ueno + +* Add tests for OQS_*_set_callbacks + +This adds tests that exercise OQS_*_set_callbacks by overriding one of +the function of each and ensuring the wrapper function is called. + +Signed-off-by: Daiki Ueno + +--------- + +Signed-off-by: Daiki Ueno +--- + .CMake/alg_support.cmake | 2 + + .github/workflows/unix.yml | 4 + + CMakeLists.txt | 14 ++ + CONFIGURE.md | 10 +- + src/CMakeLists.txt | 5 + + src/common/CMakeLists.txt | 16 +- + src/common/aes/aes.c | 117 +++---------- + src/common/aes/aes.h | 82 +++++++++ + src/common/aes/aes_impl.c | 160 ++++++++++++++++++ + src/common/aes/aes_local.h | 2 + + src/common/aes/aes_ossl.c | 79 +++++---- + src/common/common.c | 6 +- + src/common/ossl_functions.h | 51 ++++++ + src/common/ossl_helpers.c | 304 +++++++++++++++++++++++++--------- + src/common/ossl_helpers.h | 24 ++- + src/common/rand/rand.c | 8 +- + src/common/rand/rand_nist.c | 13 +- + src/common/sha2/sha2.c | 90 +++------- + src/common/sha2/sha2.h | 113 ++++++++++++- + src/common/sha2/sha2_impl.c | 123 ++++++++++++++ + src/common/sha2/sha2_local.h | 2 + + src/common/sha2/sha2_ossl.c | 127 ++++++++------ + src/common/sha3/ossl_sha3.c | 237 +++++++++++++++----------- + src/common/sha3/ossl_sha3x4.c | 245 ++++++++++++++------------- + src/common/sha3/sha3.c | 161 ++++++++++++++++++ + src/common/sha3/sha3.h | 201 ++++++++++++++++++++++ + src/common/sha3/sha3x4.c | 77 +++++++++ + src/common/sha3/sha3x4.h | 145 ++++++++++++++++ + src/common/sha3/xkcp_sha3.c | 116 ++++++++----- + src/common/sha3/xkcp_sha3x4.c | 53 ++++-- + src/oqsconfig.h.cmake | 2 + + tests/test_aes.c | 19 +++ + tests/test_hash.c | 44 +++-- + tests/test_sha3.c | 38 +++++ + 34 files changed, 2060 insertions(+), 630 deletions(-) + create mode 100644 src/common/aes/aes_impl.c + create mode 100644 src/common/ossl_functions.h + create mode 100644 src/common/sha2/sha2_impl.c + create mode 100644 src/common/sha3/sha3.c + create mode 100644 src/common/sha3/sha3x4.c + +diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake +index 66449097..3bdb103a 100644 +--- a/.CMake/alg_support.cmake ++++ b/.CMake/alg_support.cmake +@@ -69,6 +69,8 @@ cmake_dependent_option(OQS_USE_SHA3_OPENSSL "" OFF "OQS_USE_OPENSSL" OFF) + # sanity check: Disable OpenSSL if not a single OpenSSL component define is on + cmake_dependent_option(OQS_USE_OPENSSL "" ON "OQS_USE_AES_OPENSSL OR OQS_USE_SHA2_OPENSSL OR OQS_USE_SHA3_OPENSSL" OFF) + ++option(OQS_DLOPEN_OPENSSL "Enable OpenSSL through dlopen" OFF) ++ + if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") + if(OQS_DIST_X86_64_BUILD OR OQS_USE_AVX2_INSTRUCTIONS) + cmake_dependent_option(OQS_ENABLE_SHA3_xkcp_low_avx2 "" ON "NOT OQS_USE_SHA3_OPENSSL" OFF) +diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml +index b4effa7a..b3dd56b7 100644 +--- a/.github/workflows/unix.yml ++++ b/.github/workflows/unix.yml +@@ -92,6 +92,10 @@ jobs: + container: openquantumsafe/ci-ubuntu-jammy:latest + CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_ALGS_ENABLED=STD -DBUILD_SHARED_LIBS=ON + PYTEST_ARGS: --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py ++ - name: jammy-std-openssl3-dlopen ++ container: openquantumsafe/ci-ubuntu-jammy:latest ++ CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_ALGS_ENABLED=STD -DBUILD_SHARED_LIBS=ON -DOQS_DLOPEN_OPENSSL=ON ++ PYTEST_ARGS: --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py + - name: address-sanitizer + container: openquantumsafe/ci-ubuntu-focal-x86_64:latest + CMAKE_ARGS: -DCMAKE_C_COMPILER=clang-9 -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=Address +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 60cdfc66..77da3023 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -133,6 +133,20 @@ if(${OQS_USE_OPENSSL}) + endif() + endif() + find_package(OpenSSL 1.1.1 REQUIRED) ++ ++ if(OQS_DLOPEN_OPENSSL) ++ find_program(OBJDUMP objdump) ++ if(NOT OBJDUMP) ++ message(FATAL_ERROR "objdump not found. Please install it from binutils.") ++ endif() ++ execute_process( ++ COMMAND ${OBJDUMP} -p ${OPENSSL_CRYPTO_LIBRARY} ++ COMMAND sed -n "s/[ ]\\{1,\\}SONAME[ ]\\{1,\\}//p" ++ OUTPUT_VARIABLE OQS_OPENSSL_CRYPTO_SONAME ++ OUTPUT_STRIP_TRAILING_WHITESPACE ++ COMMAND_ERROR_IS_FATAL ANY) ++ message(STATUS "OpenSSL dlopen SONAME: " ${OQS_OPENSSL_CRYPTO_SONAME}) ++ endif() + endif() + + set(PUBLIC_HEADERS ${PROJECT_SOURCE_DIR}/src/oqs.h +diff --git a/CONFIGURE.md b/CONFIGURE.md +index 397aa2cd..8adcbb2d 100644 +--- a/CONFIGURE.md ++++ b/CONFIGURE.md +@@ -96,7 +96,7 @@ These can be set to `ON` or `OFF` and take an effect if liboqs is built for use + + ## OQS_USE_OPENSSL + +-In order to save size and limit the mount of different cryptographic code bases, it is possible to use OpenSSL as a crypto code provider by setting this configuration option. ++In order to save size and limit the amount of different cryptographic code bases, it is possible to use OpenSSL as a crypto code provider by setting this configuration option. + + This can be set to `ON` or `OFF`. When `ON`, the additional options `OQS_USE_AES_OPENSSL`, `OQS_USE_SHA2_OPENSSL`, and `OQS_USE_SHA3_OPENSSL` are made available to control whether liboqs uses OpenSSL's AES, SHA-2, and SHA-3 implementations. + +@@ -111,6 +111,14 @@ When `OQS_USE_OPENSSL` is `ON`, CMake also scans the filesystem to find the mini + + **Default**: `ON`. + ++### OQS_DLOPEN_OPENSSL ++ ++Dynamically load OpenSSL through `dlopen`. When using liboqs from other cryptographic libraries, hard dependency on OpenSSL is sometimes undesirable. If this option is `ON`, loading of OpenSSL will be deferred until any of the OpenSSL functions is used. ++ ++Only has an effect if the system supports `dlopen` and ELF binary format, such as Linux or BSD family. ++ ++**Default**: `OFF`. ++ + ## OQS_OPT_TARGET + + An optimization target. Only has an effect if the compiler is GCC or Clang and `OQS_DIST_BUILD=OFF`. Can take any valid input to the `-march` (on x86-64) or `-mcpu` (on ARM32v7 or ARM64v8) option for `CMAKE_C_COMPILER`. Can also be set to one of the following special values. +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 51e887fe..d0dfb6f0 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -70,8 +70,13 @@ if(DEFINED SANITIZER_LD_FLAGS) + target_link_libraries(oqs-internal PUBLIC ${SANITIZER_LD_FLAGS}) + endif() + if(${OQS_USE_OPENSSL}) ++ if(${OQS_DLOPEN_OPENSSL}) ++ target_link_libraries(oqs PRIVATE ${CMAKE_DL_LIBS}) ++ target_link_libraries(oqs-internal PRIVATE ${CMAKE_DL_LIBS}) ++ else() + target_link_libraries(oqs PRIVATE ${OPENSSL_CRYPTO_LIBRARY}) + target_link_libraries(oqs-internal PRIVATE ${OPENSSL_CRYPTO_LIBRARY}) ++ endif() + endif() + + target_include_directories(oqs +diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt +index 79172404..73b917e0 100644 +--- a/src/common/CMakeLists.txt ++++ b/src/common/CMakeLists.txt +@@ -22,7 +22,7 @@ if(${OQS_USE_AES_OPENSSL}) + set(AES_IMPL aes/aes_ossl.c) + set(OSSL_HELPERS ossl_helpers.c) + else() +- set(AES_IMPL aes/aes.c aes/aes_c.c) ++ set(AES_IMPL aes/aes_impl.c aes/aes_c.c) + if (OQS_DIST_X86_64_BUILD OR OQS_USE_AES_INSTRUCTIONS) + set(AES_IMPL ${AES_IMPL} aes/aes128_ni.c) + set(AES_IMPL ${AES_IMPL} aes/aes256_ni.c) +@@ -47,7 +47,7 @@ if(${OQS_USE_SHA2_OPENSSL}) + set(SHA2_IMPL sha2/sha2_ossl.c) + set(OSSL_HELPERS ossl_helpers.c) + else() +- set(SHA2_IMPL sha2/sha2.c sha2/sha2_c.c) ++ set(SHA2_IMPL sha2/sha2_impl.c sha2/sha2_c.c) + if (OQS_DIST_ARM64_V8_BUILD) + set(SHA2_IMPL ${SHA2_IMPL} sha2/sha2_armv8.c) + set_source_files_properties(sha2/sha2_armv8.c PROPERTIES COMPILE_FLAGS -mcpu=cortex-a53+crypto) +@@ -71,9 +71,9 @@ else() # using XKCP + set(SHA3_IMPL sha3/xkcp_sha3.c sha3/xkcp_sha3x4.c) + endif() + +-add_library(common OBJECT ${AES_IMPL} +- ${SHA2_IMPL} +- ${SHA3_IMPL} ++add_library(common OBJECT ${AES_IMPL} aes/aes.c ++ ${SHA2_IMPL} sha2/sha2.c ++ ${SHA3_IMPL} sha3/sha3.c sha3/sha3x4.c + ${OSSL_HELPERS} + common.c + pqclean_shims/fips202.c +@@ -81,9 +81,9 @@ add_library(common OBJECT ${AES_IMPL} + rand/rand.c) + + # Implementations of the internal API to be exposed to test programs +-add_library(internal OBJECT ${AES_IMPL} +- ${SHA2_IMPL} +- ${SHA3_IMPL} ++add_library(internal OBJECT ${AES_IMPL} aes/aes.c ++ ${SHA2_IMPL} sha2/sha2.c ++ ${SHA3_IMPL} sha3/sha3.c sha3/sha3x4.c + ${OSSL_HELPERS} + common.c + rand/rand_nist.c) +diff --git a/src/common/aes/aes.c b/src/common/aes/aes.c +index 1fef083a..3ac87949 100644 +--- a/src/common/aes/aes.c ++++ b/src/common/aes/aes.c +@@ -9,129 +9,60 @@ + #include "aes.h" + #include "aes_local.h" + +-#if defined(OQS_DIST_X86_64_BUILD) +-#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ +- do { \ +- if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { \ +- stmt_ni; \ +- } else { \ +- stmt_c; \ +- } \ +- } while(0) +-#elif defined(OQS_DIST_ARM64_V8_BUILD) +-#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ +- do { \ +- if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_AES)) { \ +- stmt_arm; \ +- } else { \ +- stmt_c; \ +- } \ +- } while(0) +-#elif defined(OQS_USE_AES_INSTRUCTIONS) +-#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ +- stmt_ni +-#elif defined(OQS_USE_ARM_AES_INSTRUCTIONS) +-#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ +- stmt_arm +-#else +-#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ +- stmt_c +-#endif +- +-void OQS_AES128_ECB_load_schedule(const uint8_t *key, void **_schedule) { +- C_OR_NI_OR_ARM( +- oqs_aes128_load_schedule_c(key, _schedule), +- oqs_aes128_load_schedule_ni(key, _schedule), +- oqs_aes128_load_schedule_no_bitslice(key, _schedule) +- ); ++static struct OQS_AES_callbacks *callbacks = &aes_default_callbacks; ++ ++OQS_API void OQS_AES_set_callbacks(struct OQS_AES_callbacks *new_callbacks) { ++ callbacks = new_callbacks; ++} ++ ++void OQS_AES128_ECB_load_schedule(const uint8_t *key, void **schedule) { ++ callbacks->AES128_ECB_load_schedule(key, schedule); + } + + void OQS_AES128_free_schedule(void *schedule) { +- C_OR_NI_OR_ARM( +- oqs_aes128_free_schedule_c(schedule), +- oqs_aes128_free_schedule_ni(schedule), +- oqs_aes128_free_schedule_no_bitslice(schedule) +- ); ++ callbacks->AES128_free_schedule(schedule); + } + +-void OQS_AES256_ECB_load_schedule(const uint8_t *key, void **_schedule) { +- C_OR_NI_OR_ARM( +- oqs_aes256_load_schedule_c(key, _schedule), +- oqs_aes256_load_schedule_ni(key, _schedule), +- oqs_aes256_load_schedule_no_bitslice(key, _schedule) +- ); ++void OQS_AES256_ECB_load_schedule(const uint8_t *key, void **schedule) { ++ callbacks->AES256_ECB_load_schedule(key, schedule); + } + +-void OQS_AES256_CTR_inc_init(const uint8_t *key, void **_schedule) { +- OQS_AES256_ECB_load_schedule(key, _schedule); ++void OQS_AES256_CTR_inc_init(const uint8_t *key, void **schedule) { ++ callbacks->AES256_CTR_inc_init(key, schedule); + } + +-void OQS_AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *_schedule) { +- C_OR_NI_OR_ARM( +- oqs_aes256_load_iv_c(iv, iv_len, _schedule), +- oqs_aes256_load_iv_ni(iv, iv_len, _schedule), +- oqs_aes256_load_iv_armv8(iv, iv_len, _schedule) +- ); ++void OQS_AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *schedule) { ++ callbacks->AES256_CTR_inc_iv(iv, iv_len, schedule); + } + +-void OQS_AES256_CTR_inc_ivu64(uint64_t iv, void *_schedule) { +- C_OR_NI_OR_ARM( +- oqs_aes256_load_iv_u64_c(iv, _schedule), +- oqs_aes256_load_iv_u64_ni(iv, _schedule), +- (void) iv; (void) _schedule +- ); ++void OQS_AES256_CTR_inc_ivu64(uint64_t iv, void *schedule) { ++ callbacks->AES256_CTR_inc_ivu64(iv, schedule); + } + + void OQS_AES256_free_schedule(void *schedule) { +- C_OR_NI_OR_ARM( +- oqs_aes256_free_schedule_c(schedule), +- oqs_aes256_free_schedule_ni(schedule), +- oqs_aes256_free_schedule_no_bitslice(schedule) +- ); ++ callbacks->AES256_free_schedule(schedule); + } + + void OQS_AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { +- void *schedule = NULL; +- OQS_AES128_ECB_load_schedule(key, &schedule); +- OQS_AES128_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); +- OQS_AES128_free_schedule(schedule); ++ callbacks->AES128_ECB_enc(plaintext, plaintext_len, key, ciphertext); + } + + void OQS_AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { +- C_OR_NI_OR_ARM( +- oqs_aes128_ecb_enc_sch_c(plaintext, plaintext_len, schedule, ciphertext), +- oqs_aes128_ecb_enc_sch_ni(plaintext, plaintext_len, schedule, ciphertext), +- oqs_aes128_ecb_enc_sch_armv8(plaintext, plaintext_len, schedule, ciphertext) +- ); ++ callbacks->AES128_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); + } + + void OQS_AES256_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { +- void *schedule = NULL; +- OQS_AES256_ECB_load_schedule(key, &schedule); +- OQS_AES256_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); +- OQS_AES256_free_schedule(schedule); ++ callbacks->AES256_ECB_enc(plaintext, plaintext_len, key, ciphertext); + } + + void OQS_AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { +- C_OR_NI_OR_ARM( +- oqs_aes256_ecb_enc_sch_c(plaintext, plaintext_len, schedule, ciphertext), +- oqs_aes256_ecb_enc_sch_ni(plaintext, plaintext_len, schedule, ciphertext), +- oqs_aes256_ecb_enc_sch_armv8(plaintext, plaintext_len, schedule, ciphertext) +- ); ++ callbacks->AES256_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); + } + + void OQS_AES256_CTR_inc_stream_iv(const uint8_t *iv, const size_t iv_len, const void *schedule, uint8_t *out, size_t out_len) { +- C_OR_NI_OR_ARM( +- oqs_aes256_ctr_enc_sch_c(iv, iv_len, schedule, out, out_len), +- oqs_aes256_ctr_enc_sch_ni(iv, iv_len, schedule, out, out_len), +- oqs_aes256_ctr_enc_sch_armv8(iv, iv_len, schedule, out, out_len) +- ); ++ callbacks->AES256_CTR_inc_stream_iv(iv, iv_len, schedule, out, out_len); + } + + void OQS_AES256_CTR_inc_stream_blks(void *schedule, uint8_t *out, size_t out_blks) { +- C_OR_NI_OR_ARM( +- oqs_aes256_ctr_enc_sch_upd_blks_c(schedule, out, out_blks), +- oqs_aes256_ctr_enc_sch_upd_blks_ni(schedule, out, out_blks), +- oqs_aes256_ctr_enc_sch_upd_blks_armv8(schedule, out, out_blks) +- ); ++ callbacks->AES256_CTR_inc_stream_blks(schedule, out, out_blks); + } +diff --git a/src/common/aes/aes.h b/src/common/aes/aes.h +index 83649dbe..0194b907 100644 +--- a/src/common/aes/aes.h ++++ b/src/common/aes/aes.h +@@ -14,6 +14,8 @@ + #include + #include + ++#include ++ + #if defined(__cplusplus) + extern "C" { + #endif +@@ -147,6 +149,86 @@ void OQS_AES256_CTR_inc_stream_iv(const uint8_t *iv, size_t iv_len, const void * + */ + void OQS_AES256_CTR_inc_stream_blks(void *ctx, uint8_t *out, size_t out_blks); + ++/** Data structure implemented by cryptographic provider for AES operations. ++ */ ++struct OQS_AES_callbacks { ++ /** ++ * Implementation of function OQS_AES128_ECB_load_schedule. ++ */ ++ void (*AES128_ECB_load_schedule)(const uint8_t *key, void **ctx); ++ ++ /** ++ * Implementation of function OQS_AES128_free_schedule. ++ */ ++ void (*AES128_free_schedule)(void *ctx); ++ ++ /** ++ * Implementation of function OQS_AES128_ECB_enc. ++ */ ++ void (*AES128_ECB_enc)(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext); ++ ++ /** ++ * Implementation of function OQS_AES128_ECB_enc_sch. ++ */ ++ void (*AES128_ECB_enc_sch)(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext); ++ ++ /** ++ * Implementation of function OQS_AES256_ECB_load_schedule. ++ */ ++ void (*AES256_ECB_load_schedule)(const uint8_t *key, void **ctx); ++ ++ /** ++ * Implementation of function OQS_AES256_CTR_inc_init. ++ */ ++ void (*AES256_CTR_inc_init)(const uint8_t *key, void **ctx); ++ ++ /** ++ * Implementation of function OQS_AES256_CTR_inc_iv. ++ */ ++ void (*AES256_CTR_inc_iv)(const uint8_t *iv, size_t iv_len, void *ctx); ++ ++ /** ++ * Implementation of function OQS_AES256_CTR_inc_ivu64. ++ */ ++ void (*AES256_CTR_inc_ivu64)(uint64_t iv, void *ctx); ++ ++ /** ++ * Implementation of function OQS_AES256_free_schedule. ++ */ ++ void (*AES256_free_schedule)(void *ctx); ++ ++ /** ++ * Implementation of function OQS_AES256_ECB_enc. ++ */ ++ void (*AES256_ECB_enc)(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext); ++ ++ /** ++ * Implementation of function OQS_AES256_ECB_enc_sch. ++ */ ++ void (*AES256_ECB_enc_sch)(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext); ++ ++ /** ++ * Implementation of function OQS_AES256_CTR_inc_stream_iv. ++ */ ++ void (*AES256_CTR_inc_stream_iv)(const uint8_t *iv, size_t iv_len, const void *ctx, uint8_t *out, size_t out_len); ++ ++ /** ++ * Implementation of function OQS_AES256_CTR_inc_stream_blks. ++ */ ++ void (*AES256_CTR_inc_stream_blks)(void *ctx, uint8_t *out, size_t out_blks); ++}; ++ ++/** ++ * Set callback functions for AES operations. ++ * ++ * This function may be called before OQS_init to switch the ++ * cryptographic provider for AES operations. If it is not called, the ++ * default provider determined at build time will be used. ++ * ++ * @param[in] new_callbacks Callback functions defined in OQS_AES_callbacks ++ */ ++OQS_API void OQS_AES_set_callbacks(struct OQS_AES_callbacks *new_callbacks); ++ + #if defined(__cplusplus) + } // extern "C" + #endif +diff --git a/src/common/aes/aes_impl.c b/src/common/aes/aes_impl.c +new file mode 100644 +index 00000000..ae9be662 +--- /dev/null ++++ b/src/common/aes/aes_impl.c +@@ -0,0 +1,160 @@ ++// SPDX-License-Identifier: MIT ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "aes.h" ++#include "aes_local.h" ++ ++#if defined(OQS_DIST_X86_64_BUILD) ++#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ ++ do { \ ++ if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { \ ++ stmt_ni; \ ++ } else { \ ++ stmt_c; \ ++ } \ ++ } while(0) ++#elif defined(OQS_DIST_ARM64_V8_BUILD) ++#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ ++ do { \ ++ if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_AES)) { \ ++ stmt_arm; \ ++ } else { \ ++ stmt_c; \ ++ } \ ++ } while(0) ++#elif defined(OQS_USE_AES_INSTRUCTIONS) ++#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ ++ stmt_ni ++#elif defined(OQS_USE_ARM_AES_INSTRUCTIONS) ++#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ ++ stmt_arm ++#else ++#define C_OR_NI_OR_ARM(stmt_c, stmt_ni, stmt_arm) \ ++ stmt_c ++#endif ++ ++static void AES128_ECB_load_schedule(const uint8_t *key, void **_schedule) { ++ C_OR_NI_OR_ARM( ++ oqs_aes128_load_schedule_c(key, _schedule), ++ oqs_aes128_load_schedule_ni(key, _schedule), ++ oqs_aes128_load_schedule_no_bitslice(key, _schedule) ++ ); ++} ++ ++static void AES128_free_schedule(void *schedule) { ++ C_OR_NI_OR_ARM( ++ oqs_aes128_free_schedule_c(schedule), ++ oqs_aes128_free_schedule_ni(schedule), ++ oqs_aes128_free_schedule_no_bitslice(schedule) ++ ); ++} ++ ++static void AES256_ECB_load_schedule(const uint8_t *key, void **_schedule) { ++ C_OR_NI_OR_ARM( ++ oqs_aes256_load_schedule_c(key, _schedule), ++ oqs_aes256_load_schedule_ni(key, _schedule), ++ oqs_aes256_load_schedule_no_bitslice(key, _schedule) ++ ); ++} ++ ++static void AES256_CTR_inc_init(const uint8_t *key, void **_schedule) { ++ AES256_ECB_load_schedule(key, _schedule); ++} ++ ++static void AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *_schedule) { ++ C_OR_NI_OR_ARM( ++ oqs_aes256_load_iv_c(iv, iv_len, _schedule), ++ oqs_aes256_load_iv_ni(iv, iv_len, _schedule), ++ oqs_aes256_load_iv_armv8(iv, iv_len, _schedule) ++ ); ++} ++ ++static void AES256_CTR_inc_ivu64(uint64_t iv, void *_schedule) { ++ C_OR_NI_OR_ARM( ++ oqs_aes256_load_iv_u64_c(iv, _schedule), ++ oqs_aes256_load_iv_u64_ni(iv, _schedule), ++ (void) iv; (void) _schedule ++ ); ++} ++ ++static void AES256_free_schedule(void *schedule) { ++ C_OR_NI_OR_ARM( ++ oqs_aes256_free_schedule_c(schedule), ++ oqs_aes256_free_schedule_ni(schedule), ++ oqs_aes256_free_schedule_no_bitslice(schedule) ++ ); ++} ++ ++static void AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext); ++ ++static void AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { ++ void *schedule = NULL; ++ AES128_ECB_load_schedule(key, &schedule); ++ AES128_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); ++ AES128_free_schedule(schedule); ++} ++ ++static void AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { ++ C_OR_NI_OR_ARM( ++ oqs_aes128_ecb_enc_sch_c(plaintext, plaintext_len, schedule, ciphertext), ++ oqs_aes128_ecb_enc_sch_ni(plaintext, plaintext_len, schedule, ciphertext), ++ oqs_aes128_ecb_enc_sch_armv8(plaintext, plaintext_len, schedule, ciphertext) ++ ); ++} ++ ++static void AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext); ++ ++static void AES256_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { ++ void *schedule = NULL; ++ AES256_ECB_load_schedule(key, &schedule); ++ AES256_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); ++ AES256_free_schedule(schedule); ++} ++ ++static void AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { ++ C_OR_NI_OR_ARM( ++ oqs_aes256_ecb_enc_sch_c(plaintext, plaintext_len, schedule, ciphertext), ++ oqs_aes256_ecb_enc_sch_ni(plaintext, plaintext_len, schedule, ciphertext), ++ oqs_aes256_ecb_enc_sch_armv8(plaintext, plaintext_len, schedule, ciphertext) ++ ); ++} ++ ++static void AES256_CTR_inc_stream_iv(const uint8_t *iv, const size_t iv_len, const void *schedule, uint8_t *out, size_t out_len) { ++ C_OR_NI_OR_ARM( ++ oqs_aes256_ctr_enc_sch_c(iv, iv_len, schedule, out, out_len), ++ oqs_aes256_ctr_enc_sch_ni(iv, iv_len, schedule, out, out_len), ++ oqs_aes256_ctr_enc_sch_armv8(iv, iv_len, schedule, out, out_len) ++ ); ++} ++ ++static void AES256_CTR_inc_stream_blks(void *schedule, uint8_t *out, size_t out_blks) { ++ C_OR_NI_OR_ARM( ++ oqs_aes256_ctr_enc_sch_upd_blks_c(schedule, out, out_blks), ++ oqs_aes256_ctr_enc_sch_upd_blks_ni(schedule, out, out_blks), ++ oqs_aes256_ctr_enc_sch_upd_blks_armv8(schedule, out, out_blks) ++ ); ++} ++ ++struct OQS_AES_callbacks aes_default_callbacks = { ++ AES128_ECB_load_schedule, ++ AES128_free_schedule, ++ AES128_ECB_enc, ++ AES128_ECB_enc_sch, ++ AES256_ECB_load_schedule, ++ AES256_CTR_inc_init, ++ AES256_CTR_inc_iv, ++ AES256_CTR_inc_ivu64, ++ AES256_free_schedule, ++ AES256_ECB_enc, ++ AES256_ECB_enc_sch, ++ AES256_CTR_inc_stream_iv, ++ AES256_CTR_inc_stream_blks, ++}; ++ ++void OQS_AES_init(void) { ++} +diff --git a/src/common/aes/aes_local.h b/src/common/aes/aes_local.h +index eac87935..4c9942a0 100644 +--- a/src/common/aes/aes_local.h ++++ b/src/common/aes/aes_local.h +@@ -40,3 +40,5 @@ void oqs_aes256_enc_sch_block_armv8(const uint8_t *plaintext, const void *_sched + void oqs_aes256_ecb_enc_sch_armv8(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext); + void oqs_aes256_ctr_enc_sch_armv8(const uint8_t *iv, const size_t iv_len, const void *schedule, uint8_t *out, size_t out_len); + void oqs_aes256_ctr_enc_sch_upd_blks_armv8(void *schedule, uint8_t *out, size_t out_blks); ++ ++extern struct OQS_AES_callbacks aes_default_callbacks; +diff --git a/src/common/aes/aes_ossl.c b/src/common/aes/aes_ossl.c +index 67193292..feaff395 100644 +--- a/src/common/aes/aes_ossl.c ++++ b/src/common/aes/aes_ossl.c +@@ -7,7 +7,6 @@ + + #include "aes.h" + +-#include + #include "../ossl_helpers.h" + + struct key_schedule { +@@ -28,60 +27,60 @@ static inline void br_enc64be(unsigned char *dst, uint64_t x) { + dst[0] = (unsigned char)x; + } + +-void OQS_AES128_ECB_load_schedule(const uint8_t *key, void **schedule) { ++static void AES128_ECB_load_schedule(const uint8_t *key, void **schedule) { + *schedule = malloc(sizeof(struct key_schedule)); + OQS_EXIT_IF_NULLPTR(*schedule, "OpenSSL"); + struct key_schedule *ks = (struct key_schedule *) *schedule; + ks->for_ECB = 1; +- ks->ctx = EVP_CIPHER_CTX_new(); ++ ks->ctx = OSSL_FUNC(EVP_CIPHER_CTX_new)(); + OQS_EXIT_IF_NULLPTR(ks->ctx, "OpenSSL"); +- OQS_OPENSSL_GUARD(EVP_EncryptInit_ex(ks->ctx, oqs_aes_128_ecb(), NULL, key, NULL)); +- EVP_CIPHER_CTX_set_padding(ks->ctx, 0); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptInit_ex)(ks->ctx, oqs_aes_128_ecb(), NULL, key, NULL)); ++ OSSL_FUNC(EVP_CIPHER_CTX_set_padding)(ks->ctx, 0); + } + +-void OQS_AES128_free_schedule(void *schedule) { ++static void AES128_free_schedule(void *schedule) { + if (schedule != NULL) { + struct key_schedule *ks = (struct key_schedule *) schedule; + if (ks->ctx != NULL) { +- EVP_CIPHER_CTX_free(ks->ctx); ++ OSSL_FUNC(EVP_CIPHER_CTX_free)(ks->ctx); + } + OQS_MEM_cleanse(ks->key, 32); + OQS_MEM_secure_free(schedule, sizeof(struct key_schedule)); + } + } + +-void OQS_AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { ++static void AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { + void *schedule = NULL; + OQS_AES128_ECB_load_schedule(key, &schedule); + OQS_AES128_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); + OQS_AES128_free_schedule(schedule); + } + +-void OQS_AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { ++static void AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { + assert(plaintext_len % 16 == 0); + int outlen; + const struct key_schedule *ks = (const struct key_schedule *) schedule; + SIZE_T_TO_INT_OR_EXIT(plaintext_len, plaintext_len_int) +- OQS_OPENSSL_GUARD(EVP_EncryptUpdate(ks->ctx, ciphertext, &outlen, plaintext, plaintext_len_int)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptUpdate)(ks->ctx, ciphertext, &outlen, plaintext, plaintext_len_int)); + assert(outlen == plaintext_len_int); +- OQS_OPENSSL_GUARD(EVP_EncryptFinal_ex(ks->ctx, ciphertext, &outlen)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptFinal_ex)(ks->ctx, ciphertext, &outlen)); + } + +-void OQS_AES256_ECB_load_schedule(const uint8_t *key, void **schedule) { ++static void AES256_ECB_load_schedule(const uint8_t *key, void **schedule) { + *schedule = malloc(sizeof(struct key_schedule)); + OQS_EXIT_IF_NULLPTR(*schedule, "OpenSSL"); + struct key_schedule *ks = (struct key_schedule *) *schedule; + ks->for_ECB = 1; +- ks->ctx = EVP_CIPHER_CTX_new(); ++ ks->ctx = OSSL_FUNC(EVP_CIPHER_CTX_new)(); + OQS_EXIT_IF_NULLPTR(ks->ctx, "OpenSSL"); +- OQS_OPENSSL_GUARD(EVP_EncryptInit_ex(ks->ctx, oqs_aes_256_ecb(), NULL, key, NULL)); +- EVP_CIPHER_CTX_set_padding(ks->ctx, 0); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptInit_ex)(ks->ctx, oqs_aes_256_ecb(), NULL, key, NULL)); ++ OSSL_FUNC(EVP_CIPHER_CTX_set_padding)(ks->ctx, 0); + } + +-void OQS_AES256_CTR_inc_init(const uint8_t *key, void **schedule) { ++static void AES256_CTR_inc_init(const uint8_t *key, void **schedule) { + *schedule = malloc(sizeof(struct key_schedule)); + struct key_schedule *ks = (struct key_schedule *) *schedule; +- EVP_CIPHER_CTX *ctr_ctx = EVP_CIPHER_CTX_new(); ++ EVP_CIPHER_CTX *ctr_ctx = OSSL_FUNC(EVP_CIPHER_CTX_new)(); + assert(ctr_ctx != NULL); + + OQS_EXIT_IF_NULLPTR(*schedule, "OpenSSL"); +@@ -90,7 +89,7 @@ void OQS_AES256_CTR_inc_init(const uint8_t *key, void **schedule) { + memcpy(ks->key, key, 32); + } + +-void OQS_AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *schedule) { ++static void AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *schedule) { + OQS_EXIT_IF_NULLPTR(schedule, "OpenSSL"); + struct key_schedule *ks = (struct key_schedule *) schedule; + if (iv_len == 12) { +@@ -101,36 +100,36 @@ void OQS_AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *schedule) { + } else { + exit(EXIT_FAILURE); + } +- OQS_OPENSSL_GUARD(EVP_EncryptInit_ex(ks->ctx, oqs_aes_256_ctr(), NULL, ks->key, ks->iv)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptInit_ex)(ks->ctx, oqs_aes_256_ctr(), NULL, ks->key, ks->iv)); + } + +-void OQS_AES256_CTR_inc_ivu64(uint64_t iv, void *schedule) { ++static void AES256_CTR_inc_ivu64(uint64_t iv, void *schedule) { + OQS_EXIT_IF_NULLPTR(schedule, "OpenSSL"); + struct key_schedule *ks = (struct key_schedule *) schedule; + br_enc64be(ks->iv, iv); + memset(&ks->iv[8], 0, 8); +- OQS_OPENSSL_GUARD(EVP_EncryptInit_ex(ks->ctx, oqs_aes_256_ctr(), NULL, ks->key, ks->iv)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptInit_ex)(ks->ctx, oqs_aes_256_ctr(), NULL, ks->key, ks->iv)); + } + +-void OQS_AES256_free_schedule(void *schedule) { ++static void AES256_free_schedule(void *schedule) { + // actually same code as AES 128 + OQS_AES128_free_schedule(schedule); + } + +-void OQS_AES256_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { ++static void AES256_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) { + void *schedule = NULL; + OQS_AES256_ECB_load_schedule(key, &schedule); + OQS_AES256_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); + OQS_AES256_free_schedule(schedule); + } + +-void OQS_AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { ++static void AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) { + // actually same code as AES 128 + OQS_AES128_ECB_enc_sch(plaintext, plaintext_len, schedule, ciphertext); + } + +-void OQS_AES256_CTR_inc_stream_iv(const uint8_t *iv, size_t iv_len, const void *schedule, uint8_t *out, size_t out_len) { +- EVP_CIPHER_CTX *ctr_ctx = EVP_CIPHER_CTX_new(); ++static void AES256_CTR_inc_stream_iv(const uint8_t *iv, size_t iv_len, const void *schedule, uint8_t *out, size_t out_len) { ++ EVP_CIPHER_CTX *ctr_ctx = OSSL_FUNC(EVP_CIPHER_CTX_new)(); + assert(ctr_ctx != NULL); + uint8_t iv_ctr[16]; + if (iv_len == 12) { +@@ -145,21 +144,37 @@ void OQS_AES256_CTR_inc_stream_iv(const uint8_t *iv, size_t iv_len, const void * + exit(EXIT_FAILURE); + } + const struct key_schedule *ks = (const struct key_schedule *) schedule; +- OQS_OPENSSL_GUARD(EVP_EncryptInit_ex(ctr_ctx, oqs_aes_256_ctr(), NULL, ks->key, iv_ctr)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptInit_ex)(ctr_ctx, oqs_aes_256_ctr(), NULL, ks->key, iv_ctr)); + + SIZE_T_TO_INT_OR_EXIT(out_len, out_len_input_int) + memset(out, 0, (size_t)out_len_input_int); + int out_len_output; +- OQS_OPENSSL_GUARD(EVP_EncryptUpdate(ctr_ctx, out, &out_len_output, out, out_len_input_int)); +- OQS_OPENSSL_GUARD(EVP_EncryptFinal_ex(ctr_ctx, out + out_len_output, &out_len_output)); +- EVP_CIPHER_CTX_free(ctr_ctx); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptUpdate)(ctr_ctx, out, &out_len_output, out, out_len_input_int)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptFinal_ex)(ctr_ctx, out + out_len_output, &out_len_output)); ++ OSSL_FUNC(EVP_CIPHER_CTX_free)(ctr_ctx); + } + +-void OQS_AES256_CTR_inc_stream_blks(void *schedule, uint8_t *out, size_t out_blks) { ++static void AES256_CTR_inc_stream_blks(void *schedule, uint8_t *out, size_t out_blks) { + size_t out_len = out_blks * 16; + struct key_schedule *ks = (struct key_schedule *) schedule; + int out_len_output; + SIZE_T_TO_INT_OR_EXIT(out_len, out_len_input_int); + memset(out, 0, (size_t)out_len_input_int); +- OQS_OPENSSL_GUARD(EVP_EncryptUpdate(ks->ctx, out, &out_len_output, out, (int) out_len)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_EncryptUpdate)(ks->ctx, out, &out_len_output, out, (int) out_len)); + } ++ ++struct OQS_AES_callbacks aes_default_callbacks = { ++ AES128_ECB_load_schedule, ++ AES128_free_schedule, ++ AES128_ECB_enc, ++ AES128_ECB_enc_sch, ++ AES256_ECB_load_schedule, ++ AES256_CTR_inc_init, ++ AES256_CTR_inc_iv, ++ AES256_CTR_inc_ivu64, ++ AES256_free_schedule, ++ AES256_ECB_enc, ++ AES256_ECB_enc_sch, ++ AES256_CTR_inc_stream_iv, ++ AES256_CTR_inc_stream_blks, ++}; +diff --git a/src/common/common.c b/src/common/common.c +index 9d6fc9f0..7de1e658 100644 +--- a/src/common/common.c ++++ b/src/common/common.c +@@ -26,9 +26,7 @@ + #endif + + #if defined(OQS_USE_OPENSSL) +-#include + #include "ossl_helpers.h" +-CRYPTO_ONCE OQS_ONCE_STATIC_FREE; + #endif + + /* Identifying the CPU is expensive so we cache the results in cpu_ext_data */ +@@ -233,7 +231,6 @@ OQS_API void OQS_init(void) { + #if defined(OQS_DIST_BUILD) + OQS_CPU_has_extension(OQS_CPU_EXT_INIT); + #endif +- return; + } + + OQS_API const char *OQS_version(void) { +@@ -242,9 +239,8 @@ OQS_API const char *OQS_version(void) { + + OQS_API void OQS_destroy(void) { + #if defined(OQS_USE_OPENSSL) +- CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_FREE, oqs_free_ossl_objects); ++ oqs_ossl_destroy(); + #endif +- return; + } + + OQS_API int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len) { +diff --git a/src/common/ossl_functions.h b/src/common/ossl_functions.h +new file mode 100644 +index 00000000..cece5c95 +--- /dev/null ++++ b/src/common/ossl_functions.h +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: MIT ++ ++// This file lists all OpenSSL functions used throughout the liboqs source code. ++// ++// Note that this file is included multiple times to generate custom ++// code by definining the FUNC macro, so no header guard should be ++// added here. ++ ++VOID_FUNC(void, ERR_print_errors_fp, (FILE *fp), (fp)) ++VOID_FUNC(void, EVP_CIPHER_CTX_free, (EVP_CIPHER_CTX *c), (c)) ++FUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, (void), ()) ++FUNC(int, EVP_CIPHER_CTX_set_padding, (EVP_CIPHER_CTX *c, int pad), (c, pad)) ++FUNC(int, EVP_DigestFinalXOF, (EVP_MD_CTX *ctx, unsigned char *md, size_t len), (ctx, md, len)) ++FUNC(int, EVP_DigestFinal_ex, (EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s), (ctx, md, s)) ++FUNC(int, EVP_DigestInit_ex, (EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl), (ctx, type, impl)) ++FUNC(int, EVP_DigestUpdate, (EVP_MD_CTX *ctx, const void *d, size_t cnt), (ctx, d, cnt)) ++FUNC(int, EVP_EncryptFinal_ex, (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl), (ctx, out, outl)) ++FUNC(int, EVP_EncryptInit_ex, (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv), ++ (ctx, cipher, impl, key, iv)) ++FUNC(int, EVP_EncryptUpdate, (EVP_CIPHER_CTX *ctx, unsigned char *out, ++ int *outl, const unsigned char *in, int inl), ++ (ctx, out, outl, in, inl)) ++FUNC(int, EVP_MD_CTX_copy_ex, (EVP_MD_CTX *out, const EVP_MD_CTX *in), (out, in)) ++VOID_FUNC(void, EVP_MD_CTX_free, (EVP_MD_CTX *ctx), (ctx)) ++FUNC(EVP_MD_CTX *, EVP_MD_CTX_new, (void), ()) ++FUNC(int, EVP_MD_CTX_reset, (EVP_MD_CTX *ctx), (ctx)) ++FUNC(const EVP_CIPHER *, EVP_aes_128_ecb, (void), ()) ++FUNC(const EVP_CIPHER *, EVP_aes_256_ecb, (void), ()) ++FUNC(const EVP_CIPHER *, EVP_aes_256_ctr, (void), ()) ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L ++FUNC(EVP_CIPHER *, EVP_CIPHER_fetch, (OSSL_LIB_CTX *ctx, const char *algorithm, ++ const char *properties), ++ (ctx, algorithm, properties)) ++VOID_FUNC(void, EVP_CIPHER_free, (EVP_CIPHER *cipher), (cipher)) ++FUNC(EVP_MD *, EVP_MD_fetch, (OSSL_LIB_CTX *ctx, const char *algorithm, ++ const char *properties), ++ (ctx, algorithm, properties)) ++VOID_FUNC(void, EVP_MD_free, (EVP_MD *md), (md)) ++#else ++FUNC(const EVP_MD *, EVP_sha256, (void), ()) ++FUNC(const EVP_MD *, EVP_sha384, (void), ()) ++FUNC(const EVP_MD *, EVP_sha3_256, (void), ()) ++FUNC(const EVP_MD *, EVP_sha3_384, (void), ()) ++FUNC(const EVP_MD *, EVP_sha3_512, (void), ()) ++FUNC(const EVP_MD *, EVP_sha512, (void), ()) ++FUNC(const EVP_MD *, EVP_shake128, (void), ()) ++FUNC(const EVP_MD *, EVP_shake256, (void), ()) ++#endif ++FUNC(int, RAND_bytes, (unsigned char *buf, int num), (buf, num)) ++FUNC(int, RAND_poll, (void), ()) ++FUNC(int, RAND_status, (void), ()) +diff --git a/src/common/ossl_helpers.c b/src/common/ossl_helpers.c +index f52ceaef..1c73d8b9 100644 +--- a/src/common/ossl_helpers.c ++++ b/src/common/ossl_helpers.c +@@ -1,33 +1,39 @@ + // SPDX-License-Identifier: MIT + #include + #if defined(OQS_USE_OPENSSL) +-#include ++#define OQS_OSSL_NO_EXTERN 1 + #include "ossl_helpers.h" ++#include ++#include ++ + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++#include ++ ++static pthread_once_t init_once_control = PTHREAD_ONCE_INIT; ++static pthread_once_t free_once_control = PTHREAD_ONCE_INIT; ++#endif ++ + static EVP_MD *sha256_ptr, *sha384_ptr, *sha512_ptr, + *sha3_256_ptr, *sha3_384_ptr, *sha3_512_ptr, + *shake128_ptr, *shake256_ptr; + + static EVP_CIPHER *aes128_ecb_ptr, *aes256_ecb_ptr, *aes256_ctr_ptr; +-#endif + +-CRYPTO_ONCE OQS_ONCE_STATIC_INIT; ++static void fetch_ossl_objects(void) { ++ sha256_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHA256", NULL); ++ sha384_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHA384", NULL); ++ sha512_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHA512", NULL); + +-#if OPENSSL_VERSION_NUMBER >= 0x30000000L +-static void oqs_fetch_ossl_objects(void) { +- sha256_ptr = EVP_MD_fetch(NULL, "SHA256", NULL); +- sha384_ptr = EVP_MD_fetch(NULL, "SHA384", NULL); +- sha512_ptr = EVP_MD_fetch(NULL, "SHA512", NULL); +- +- sha3_256_ptr = EVP_MD_fetch(NULL, "SHA3-256", NULL); +- sha3_384_ptr = EVP_MD_fetch(NULL, "SHA3-384", NULL); +- sha3_512_ptr = EVP_MD_fetch(NULL, "SHA3-512", NULL); +- shake128_ptr = EVP_MD_fetch(NULL, "SHAKE128", NULL); +- shake256_ptr = EVP_MD_fetch(NULL, "SHAKE256", NULL); ++ sha3_256_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHA3-256", NULL); ++ sha3_384_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHA3-384", NULL); ++ sha3_512_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHA3-512", NULL); ++ shake128_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHAKE128", NULL); ++ shake256_ptr = OSSL_FUNC(EVP_MD_fetch)(NULL, "SHAKE256", NULL); + +- aes128_ecb_ptr = EVP_CIPHER_fetch(NULL, "AES-128-ECB", NULL); +- aes256_ecb_ptr = EVP_CIPHER_fetch(NULL, "AES-256-ECB", NULL); +- aes256_ctr_ptr = EVP_CIPHER_fetch(NULL, "AES-256-CTR", NULL); ++ aes128_ecb_ptr = OSSL_FUNC(EVP_CIPHER_fetch)(NULL, "AES-128-ECB", NULL); ++ aes256_ecb_ptr = OSSL_FUNC(EVP_CIPHER_fetch)(NULL, "AES-256-ECB", NULL); ++ aes256_ctr_ptr = OSSL_FUNC(EVP_CIPHER_fetch)(NULL, "AES-256-CTR", NULL); + + if (!sha256_ptr || !sha384_ptr || !sha512_ptr || !sha3_256_ptr || + !sha3_384_ptr || !sha3_512_ptr || !shake128_ptr || !shake256_ptr || +@@ -35,164 +41,314 @@ static void oqs_fetch_ossl_objects(void) { + fprintf(stderr, "liboqs warning: OpenSSL initialization failure. Is provider for SHA, SHAKE, AES enabled?\n"); + } + } +-#endif + +-void oqs_free_ossl_objects(void) { ++static void free_ossl_objects(void) { ++ OSSL_FUNC(EVP_MD_free)(sha256_ptr); ++ sha256_ptr = NULL; ++ OSSL_FUNC(EVP_MD_free)(sha384_ptr); ++ sha384_ptr = NULL; ++ OSSL_FUNC(EVP_MD_free)(sha512_ptr); ++ sha512_ptr = NULL; ++ OSSL_FUNC(EVP_MD_free)(sha3_256_ptr); ++ sha3_256_ptr = NULL; ++ OSSL_FUNC(EVP_MD_free)(sha3_384_ptr); ++ sha3_384_ptr = NULL; ++ OSSL_FUNC(EVP_MD_free)(sha3_512_ptr); ++ sha3_512_ptr = NULL; ++ OSSL_FUNC(EVP_MD_free)(shake128_ptr); ++ shake128_ptr = NULL; ++ OSSL_FUNC(EVP_MD_free)(shake256_ptr); ++ shake256_ptr = NULL; ++ OSSL_FUNC(EVP_CIPHER_free)(aes128_ecb_ptr); ++ aes128_ecb_ptr = NULL; ++ OSSL_FUNC(EVP_CIPHER_free)(aes256_ecb_ptr); ++ aes256_ecb_ptr = NULL; ++ OSSL_FUNC(EVP_CIPHER_free)(aes256_ctr_ptr); ++ aes256_ctr_ptr = NULL; ++} ++#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L ++ ++void oqs_ossl_destroy(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L +- EVP_MD_free(sha256_ptr); +- EVP_MD_free(sha384_ptr); +- EVP_MD_free(sha512_ptr); +- EVP_MD_free(sha3_256_ptr); +- EVP_MD_free(sha3_384_ptr); +- EVP_MD_free(sha3_512_ptr); +- EVP_MD_free(shake128_ptr); +- EVP_MD_free(shake256_ptr); +- EVP_CIPHER_free(aes128_ecb_ptr); +- EVP_CIPHER_free(aes256_ecb_ptr); +- EVP_CIPHER_free(aes256_ctr_ptr); ++#if defined(OQS_USE_PTHREADS) ++ pthread_once(&free_once_control, free_ossl_objects); ++#else ++ if (sha256_ptr || sha384_ptr || sha512_ptr || sha3_256_ptr || ++ sha3_384_ptr || sha3_512_ptr || shake128_ptr || shake256_ptr || ++ aes128_ecb_ptr || aes256_ecb_ptr || aes256_ctr_ptr) { ++ free_ossl_objects(); ++ } ++#endif + #endif + } + + const EVP_MD *oqs_sha256(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!sha256_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return sha256_ptr; + #else +- return EVP_sha256(); ++ return OSSL_FUNC(EVP_sha256)(); + #endif + } + + const EVP_MD *oqs_sha384(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!sha384_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return sha384_ptr; + #else +- return EVP_sha384(); ++ return OSSL_FUNC(EVP_sha384)(); + #endif + } + + const EVP_MD *oqs_sha512(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!sha512_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return sha512_ptr; + #else +- return EVP_sha512(); ++ return OSSL_FUNC(EVP_sha512)(); + #endif + } + + const EVP_MD *oqs_shake128(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!shake128_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return shake128_ptr; + #else +- return EVP_shake128(); ++ return OSSL_FUNC(EVP_shake128)(); + #endif + } + + const EVP_MD *oqs_shake256(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!shake256_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return shake256_ptr; + #else +- return EVP_shake256(); ++ return OSSL_FUNC(EVP_shake256)(); + #endif + } + + const EVP_MD *oqs_sha3_256(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!sha3_256_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return sha3_256_ptr; + #else +- return EVP_sha3_256(); ++ return OSSL_FUNC(EVP_sha3_256)(); + #endif + } + + const EVP_MD *oqs_sha3_384(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!sha3_384_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return sha3_384_ptr; + #else +- return EVP_sha3_384(); ++ return OSSL_FUNC(EVP_sha3_384)(); + #endif + } + + const EVP_MD *oqs_sha3_512(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!sha3_512_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return sha3_512_ptr; + #else +- return EVP_sha3_512(); ++ return OSSL_FUNC(EVP_sha3_512)(); + #endif + } + + const EVP_CIPHER *oqs_aes_128_ecb(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!aes128_ecb_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return aes128_ecb_ptr; + #else +- return EVP_aes_128_ecb(); ++ return OSSL_FUNC(EVP_aes_128_ecb)(); + #endif + } + + const EVP_CIPHER *oqs_aes_256_ecb(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!aes256_ecb_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return aes256_ecb_ptr; + #else +- return EVP_aes_256_ecb(); ++ return OSSL_FUNC(EVP_aes_256_ecb)(); + #endif + } + + const EVP_CIPHER *oqs_aes_256_ctr(void) { + #if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#if defined(OQS_USE_PTHREADS) ++ if (pthread_once(&init_once_control, fetch_ossl_objects)) { ++ return NULL; ++ } ++#else + if (!aes256_ctr_ptr) { +- if (!CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_INIT, oqs_fetch_ossl_objects)) { +- return NULL; +- } ++ fetch_ossl_objects(); + } ++#endif + return aes256_ctr_ptr; + #else +- return EVP_aes_256_ctr(); ++ return OSSL_FUNC(EVP_aes_256_ctr)(); ++#endif ++} ++ ++#if defined(OQS_DLOPEN_OPENSSL) ++ ++static void *libcrypto_dlhandle; ++ ++static void ensure_library(void); ++ ++#if defined(OQS_USE_PTHREADS) ++static pthread_once_t dlopen_once_control = PTHREAD_ONCE_INIT; ++ ++#define ENSURE_LIBRARY pthread_once(&dlopen_once_control, ensure_library) ++#else ++#define ENSURE_LIBRARY do { \ ++ if (!libcrypto_dlhandle) { \ ++ ensure_library(); \ ++ } \ ++ } while (0) ++#endif // OQS_USE_PTHREADS ++ ++/* Define redirection symbols */ ++#if (2 <= __GNUC__ || (4 <= __clang_major__)) ++#define FUNC(ret, name, args, cargs) \ ++ static __typeof__(name)(*_oqs_ossl_sym_##name); ++#else ++#define FUNC(ret, name, args, cargs) \ ++ static ret(*_oqs_ossl_sym_##name)args; + #endif ++#define VOID_FUNC FUNC ++#include "ossl_functions.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++/* Define redirection wrapper functions */ ++#define FUNC(ret, name, args, cargs) \ ++ret _oqs_ossl_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert(_oqs_ossl_sym_##name); \ ++ return _oqs_ossl_sym_##name cargs; \ ++} ++#define VOID_FUNC(ret, name, args, cargs) \ ++ret _oqs_ossl_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert(_oqs_ossl_sym_##name); \ ++ _oqs_ossl_sym_##name cargs; \ ++} ++#include "ossl_functions.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++static void ensure_symbol(const char *name, void **symp) { ++ if (!*symp) { ++ void *sym = dlsym(libcrypto_dlhandle, name); ++ if (!sym) { ++ exit(EXIT_FAILURE); ++ } ++ *symp = sym; ++ } ++} ++ ++static void ensure_library(void) { ++ if (!libcrypto_dlhandle) { ++ libcrypto_dlhandle = dlopen(OQS_OPENSSL_CRYPTO_SONAME, ++ RTLD_LAZY | RTLD_LOCAL); ++ if (!libcrypto_dlhandle) { ++ exit(EXIT_FAILURE); ++ } ++ } ++ ++#define ENSURE_SYMBOL(name) \ ++ ensure_symbol(#name, (void **)&_oqs_ossl_sym_##name) ++#define FUNC(ret, name, args, cargs) \ ++ ENSURE_SYMBOL(name); ++#define VOID_FUNC FUNC ++#include "ossl_functions.h" ++#undef VOID_FUNC ++#undef FUNC ++#undef ENSURE_SYMBOL + } ++ ++#endif // OQS_DLOPEN_OPENSSL ++ + #endif +diff --git a/src/common/ossl_helpers.h b/src/common/ossl_helpers.h +index fd7b0dde..fe6d3468 100644 +--- a/src/common/ossl_helpers.h ++++ b/src/common/ossl_helpers.h +@@ -6,8 +6,12 @@ + extern "C" { + #endif + ++#include ++#include ++#include ++ + #if defined(OQS_USE_OPENSSL) +-void oqs_free_ossl_objects(void); ++void oqs_ossl_destroy(void); + + const EVP_MD *oqs_sha256(void); + +@@ -30,6 +34,24 @@ const EVP_CIPHER *oqs_aes_128_ecb(void); + const EVP_CIPHER *oqs_aes_256_ecb(void); + + const EVP_CIPHER *oqs_aes_256_ctr(void); ++ ++#ifdef OQS_DLOPEN_OPENSSL ++ ++#define FUNC(ret, name, args, cargs) \ ++ ret _oqs_ossl_##name args; ++#define VOID_FUNC FUNC ++#include "ossl_functions.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#define OSSL_FUNC(name) _oqs_ossl_##name ++ ++#else ++ ++#define OSSL_FUNC(name) name ++ ++#endif ++ + #endif + + #if defined(__cplusplus) +diff --git a/src/common/rand/rand.c b/src/common/rand/rand.c +index b48d8030..5ff7efe0 100644 +--- a/src/common/rand/rand.c ++++ b/src/common/rand/rand.c +@@ -23,7 +23,7 @@ void OQS_randombytes_openssl(uint8_t *random_array, size_t bytes_to_read); + #endif + + #ifdef OQS_USE_OPENSSL +-#include ++#include "../ossl_helpers.h" + // Use OpenSSL's RAND_bytes as the default PRNG + static void (*oqs_randombytes_algorithm)(uint8_t *, size_t) = &OQS_randombytes_openssl; + #else +@@ -113,12 +113,12 @@ void OQS_randombytes_openssl(uint8_t *random_array, size_t bytes_to_read) { + int rep = OQS_RAND_POLL_RETRY; + SIZE_T_TO_INT_OR_EXIT(bytes_to_read, bytes_to_read_int) + do { +- if (RAND_status() == 1) { ++ if (OSSL_FUNC(RAND_status)() == 1) { + break; + } +- RAND_poll(); ++ OSSL_FUNC(RAND_poll)(); + } while (rep-- >= 0); +- if (RAND_bytes(random_array, bytes_to_read_int) != 1) { ++ if (OSSL_FUNC(RAND_bytes)(random_array, bytes_to_read_int) != 1) { + fprintf(stderr, "No OpenSSL randomness retrieved. DRBG available?\n"); + // because of void signature we have no other way to signal the problem + // we cannot possibly return without randomness +diff --git a/src/common/rand/rand_nist.c b/src/common/rand/rand_nist.c +index 5e74b45b..6270a31c 100644 +--- a/src/common/rand/rand_nist.c ++++ b/src/common/rand/rand_nist.c +@@ -22,9 +22,6 @@ You are solely responsible for determining the appropriateness of using and dist + #include + + #ifdef OQS_USE_OPENSSL +-#include +-#include +-#include + #include "../ossl_helpers.h" + #else + #include +@@ -42,7 +39,7 @@ __declspec(noreturn) + __attribute__((noreturn)) + # endif + static void handleErrors(void) { +- ERR_print_errors_fp(stderr); ++ OSSL_FUNC(ERR_print_errors_fp)(stderr); + abort(); + } + #endif +@@ -58,20 +55,20 @@ static void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *bu + int len; + + /* Create and initialise the context */ +- if (!(ctx = EVP_CIPHER_CTX_new())) { ++ if (!(ctx = OSSL_FUNC(EVP_CIPHER_CTX_new)())) { + handleErrors(); + } + +- if (1 != EVP_EncryptInit_ex(ctx, oqs_aes_256_ecb(), NULL, key, NULL)) { ++ if (1 != OSSL_FUNC(EVP_EncryptInit_ex)(ctx, oqs_aes_256_ecb(), NULL, key, NULL)) { + handleErrors(); + } + +- if (1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16)) { ++ if (1 != OSSL_FUNC(EVP_EncryptUpdate)(ctx, buffer, &len, ctr, 16)) { + handleErrors(); + } + + /* Clean up */ +- EVP_CIPHER_CTX_free(ctx); ++ OSSL_FUNC(EVP_CIPHER_CTX_free)(ctx); + #else + void *schedule = NULL; + OQS_AES256_ECB_load_schedule(key, &schedule); +diff --git a/src/common/sha2/sha2.c b/src/common/sha2/sha2.c +index d622b883..9cc732d1 100644 +--- a/src/common/sha2/sha2.c ++++ b/src/common/sha2/sha2.c +@@ -1,132 +1,84 @@ + // SPDX-License-Identifier: MIT + #include + +-#include +- + #include "sha2.h" + #include "sha2_local.h" + +-#if defined(OQS_DIST_ARM64_V8_BUILD) +-#define C_OR_ARM(stmt_c, stmt_arm) \ +- do { \ +- if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA2)) { \ +- stmt_arm; \ +- } else { \ +- stmt_c; \ +- } \ +- } while(0) +-#elif defined(OQS_USE_ARM_SHA2_INSTRUCTIONS) +-#define C_OR_ARM(stmt_c, stmt_arm) \ +- stmt_arm +-#else +-#define C_OR_ARM(stmt_c, stmt_arm) \ +- stmt_c +-#endif +-void OQS_SHA2_sha224_inc_init(OQS_SHA2_sha224_ctx *state) { +- oqs_sha2_sha224_inc_init_c((sha224ctx *) state); +-} +- +-void OQS_SHA2_sha224_inc_ctx_clone(OQS_SHA2_sha224_ctx *dest, const OQS_SHA2_sha224_ctx *src) { +- oqs_sha2_sha224_inc_ctx_clone_c((sha224ctx *) dest, (const sha224ctx *) src); +-} +- +-void OQS_SHA2_sha224_inc_blocks(OQS_SHA2_sha224_ctx *state, const uint8_t *in, size_t inblocks) { +- C_OR_ARM( +- oqs_sha2_sha224_inc_blocks_c((sha224ctx *) state, in, inblocks), +- oqs_sha2_sha224_inc_blocks_armv8((sha224ctx *) state, in, inblocks) +- ); +-} +- +-void OQS_SHA2_sha224_inc_finalize(uint8_t *out, OQS_SHA2_sha224_ctx *state, const uint8_t *in, size_t inlen) { +- oqs_sha2_sha224_inc_finalize_c(out, (sha224ctx *) state, in, inlen); +-} ++static struct OQS_SHA2_callbacks *callbacks = &sha2_default_callbacks; + +-void OQS_SHA2_sha224_inc_ctx_release(OQS_SHA2_sha224_ctx *state) { +- oqs_sha2_sha224_inc_ctx_release_c((sha224ctx *) state); ++OQS_API void OQS_SHA2_set_callbacks(struct OQS_SHA2_callbacks *new_callbacks) { ++ callbacks = new_callbacks; + } + + void OQS_SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { +- oqs_sha2_sha256_inc_init_c((sha256ctx *) state); ++ callbacks->SHA2_sha256_inc_init(state); + } + + void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src) { +- oqs_sha2_sha256_inc_ctx_clone_c((sha256ctx *) dest, (const sha256ctx *) src); ++ callbacks->SHA2_sha256_inc_ctx_clone(dest, src); + } + + void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks) { +- C_OR_ARM( +- oqs_sha2_sha256_inc_blocks_c((sha256ctx *) state, in, inblocks), +- oqs_sha2_sha256_inc_blocks_armv8((sha256ctx *) state, in, inblocks) +- ); ++ callbacks->SHA2_sha256_inc_blocks(state, in, inblocks); + } + + void OQS_SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen) { +- oqs_sha2_sha256_inc_finalize_c(out, (sha256ctx *) state, in, inlen); ++ callbacks->SHA2_sha256_inc_finalize(out, state, in, inlen); + } + + void OQS_SHA2_sha256_inc_ctx_release(OQS_SHA2_sha256_ctx *state) { +- oqs_sha2_sha256_inc_ctx_release_c((sha256ctx *) state); ++ callbacks->SHA2_sha256_inc_ctx_release(state); + } + + void OQS_SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state) { +- oqs_sha2_sha384_inc_init_c((sha384ctx *)state); ++ callbacks->SHA2_sha384_inc_init(state); + } + + void OQS_SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha384_ctx *src) { +- oqs_sha2_sha384_inc_ctx_clone_c((sha384ctx *) dest, (const sha384ctx *) src); ++ callbacks->SHA2_sha384_inc_ctx_clone(dest, src); + } + + void OQS_SHA2_sha384_inc_blocks(OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inblocks) { +- oqs_sha2_sha384_inc_blocks_c((sha384ctx *) state, in, inblocks); ++ callbacks->SHA2_sha384_inc_blocks(state, in, inblocks); + } + + void OQS_SHA2_sha384_inc_finalize(uint8_t *out, OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inlen) { +- oqs_sha2_sha384_inc_finalize_c(out, (sha384ctx *) state, in, inlen); ++ callbacks->SHA2_sha384_inc_finalize(out, state, in, inlen); + } + + void OQS_SHA2_sha384_inc_ctx_release(OQS_SHA2_sha384_ctx *state) { +- oqs_sha2_sha384_inc_ctx_release_c((sha384ctx *) state); ++ callbacks->SHA2_sha384_inc_ctx_release(state); + } + + void OQS_SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state) { +- oqs_sha2_sha512_inc_init_c((sha512ctx *)state); ++ callbacks->SHA2_sha512_inc_init(state); + } + + void OQS_SHA2_sha512_inc_ctx_clone(OQS_SHA2_sha512_ctx *dest, const OQS_SHA2_sha512_ctx *src) { +- oqs_sha2_sha512_inc_ctx_clone_c((sha512ctx *) dest, (const sha512ctx *) src); ++ callbacks->SHA2_sha512_inc_ctx_clone(dest, src); + } + + void OQS_SHA2_sha512_inc_blocks(OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inblocks) { +- oqs_sha2_sha512_inc_blocks_c((sha512ctx *) state, in, inblocks); ++ callbacks->SHA2_sha512_inc_blocks(state, in, inblocks); + } + + void OQS_SHA2_sha512_inc_finalize(uint8_t *out, OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inlen) { +- oqs_sha2_sha512_inc_finalize_c(out, (sha512ctx *) state, in, inlen); ++ callbacks->SHA2_sha512_inc_finalize(out, state, in, inlen); + } + + void OQS_SHA2_sha512_inc_ctx_release(OQS_SHA2_sha512_ctx *state) { +- oqs_sha2_sha512_inc_ctx_release_c((sha512ctx *) state); +-} +- +-void OQS_SHA2_sha224(uint8_t *out, const uint8_t *in, size_t inlen) { +- C_OR_ARM ( +- oqs_sha2_sha224_c(out, in, inlen), +- oqs_sha2_sha224_armv8(out, in, inlen) +- ); ++ callbacks->SHA2_sha512_inc_ctx_release(state); + } + + void OQS_SHA2_sha256(uint8_t *out, const uint8_t *in, size_t inlen) { +- C_OR_ARM ( +- oqs_sha2_sha256_c(out, in, inlen), +- oqs_sha2_sha256_armv8(out, in, inlen) +- ); ++ callbacks->SHA2_sha256(out, in, inlen); + } + + void OQS_SHA2_sha384(uint8_t *out, const uint8_t *in, size_t inlen) { +- oqs_sha2_sha384_c(out, in, inlen); ++ callbacks->SHA2_sha384(out, in, inlen); + } + + void OQS_SHA2_sha512(uint8_t *out, const uint8_t *in, size_t inlen) { +- oqs_sha2_sha512_c(out, in, inlen); ++ callbacks->SHA2_sha512(out, in, inlen); + } + +diff --git a/src/common/sha2/sha2.h b/src/common/sha2/sha2.h +index e50a1639..41562f8f 100644 +--- a/src/common/sha2/sha2.h ++++ b/src/common/sha2/sha2.h +@@ -18,16 +18,12 @@ + #include + #include + ++#include ++ + #if defined(__cplusplus) + extern "C" { + #endif + +-/** Data structure for the state of the SHA-224 incremental hashing API. */ +-typedef struct { +- /** Internal state */ +- void *ctx; +-} OQS_SHA2_sha224_ctx; +- + /** + * \brief Process a message with SHA-256 and return the hash code in the output byte array. + * +@@ -250,6 +246,111 @@ void OQS_SHA2_sha512_inc_finalize(uint8_t *out, OQS_SHA2_sha512_ctx *state, cons + */ + void OQS_SHA2_sha512_inc_ctx_release(OQS_SHA2_sha512_ctx *state); + ++/** Data structure implemented by cryptographic provider for SHA-2 operations. ++ */ ++struct OQS_SHA2_callbacks { ++ /** ++ * Implementation of function OQS_SHA2_sha256. ++ */ ++ void (*SHA2_sha256)(uint8_t *output, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha256_inc_init. ++ */ ++ void (*SHA2_sha256_inc_init)(OQS_SHA2_sha256_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha256_inc_ctx_clone. ++ */ ++ void (*SHA2_sha256_inc_ctx_clone)(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha256_inc_blocks. ++ */ ++ void (*SHA2_sha256_inc_blocks)(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha256_inc_finalize. ++ */ ++ void (*SHA2_sha256_inc_finalize)(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha256_inc_ctx_release. ++ */ ++ void (*SHA2_sha256_inc_ctx_release)(OQS_SHA2_sha256_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha384. ++ */ ++ void (*SHA2_sha384)(uint8_t *output, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha384_inc_init. ++ */ ++ void (*SHA2_sha384_inc_init)(OQS_SHA2_sha384_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha384_inc_ctx_clone. ++ */ ++ void (*SHA2_sha384_inc_ctx_clone)(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha384_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha384_inc_blocks. ++ */ ++ void (*SHA2_sha384_inc_blocks)(OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inblocks); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha384_inc_finalize. ++ */ ++ void (*SHA2_sha384_inc_finalize)(uint8_t *out, OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha384_inc_ctx_release. ++ */ ++ void (*SHA2_sha384_inc_ctx_release)(OQS_SHA2_sha384_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha512. ++ */ ++ void (*SHA2_sha512)(uint8_t *output, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha512_inc_init. ++ */ ++ void (*SHA2_sha512_inc_init)(OQS_SHA2_sha512_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha512_inc_ctx_clone. ++ */ ++ void (*SHA2_sha512_inc_ctx_clone)(OQS_SHA2_sha512_ctx *dest, const OQS_SHA2_sha512_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha512_inc_blocks. ++ */ ++ void (*SHA2_sha512_inc_blocks)(OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inblocks); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha512_inc_finalize. ++ */ ++ void (*SHA2_sha512_inc_finalize)(uint8_t *out, OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA2_sha512_inc_ctx_release. ++ */ ++ void (*SHA2_sha512_inc_ctx_release)(OQS_SHA2_sha512_ctx *state); ++}; ++ ++/** ++ * Set callback functions for SHA2 operations. ++ * ++ * This function may be called before OQS_init to switch the ++ * cryptographic provider for SHA2 operations. If it is not called, ++ * the default provider determined at build time will be used. ++ * ++ * @param[in] new_callbacks Callback functions defined in OQS_SHA2_callbacks ++ */ ++OQS_API void OQS_SHA2_set_callbacks(struct OQS_SHA2_callbacks *new_callbacks); ++ + #if defined(__cplusplus) + } // extern "C" + #endif +diff --git a/src/common/sha2/sha2_impl.c b/src/common/sha2/sha2_impl.c +new file mode 100644 +index 00000000..f7f01b24 +--- /dev/null ++++ b/src/common/sha2/sha2_impl.c +@@ -0,0 +1,123 @@ ++// SPDX-License-Identifier: MIT ++#include ++ ++#include ++ ++#include "sha2.h" ++#include "sha2_local.h" ++ ++#if defined(OQS_DIST_ARM64_V8_BUILD) ++#define C_OR_ARM(stmt_c, stmt_arm) \ ++ do { \ ++ if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA2)) { \ ++ stmt_arm; \ ++ } else { \ ++ stmt_c; \ ++ } \ ++ } while(0) ++#elif defined(OQS_USE_ARM_SHA2_INSTRUCTIONS) ++#define C_OR_ARM(stmt_c, stmt_arm) \ ++ stmt_arm ++#else ++#define C_OR_ARM(stmt_c, stmt_arm) \ ++ stmt_c ++#endif ++ ++static void SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { ++ oqs_sha2_sha256_inc_init_c((sha256ctx *) state); ++} ++ ++static void SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src) { ++ oqs_sha2_sha256_inc_ctx_clone_c((sha256ctx *) dest, (const sha256ctx *) src); ++} ++ ++static void SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks) { ++ C_OR_ARM( ++ oqs_sha2_sha256_inc_blocks_c((sha256ctx *) state, in, inblocks), ++ oqs_sha2_sha256_inc_blocks_armv8((sha256ctx *) state, in, inblocks) ++ ); ++} ++ ++static void SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen) { ++ oqs_sha2_sha256_inc_finalize_c(out, (sha256ctx *) state, in, inlen); ++} ++ ++static void SHA2_sha256_inc_ctx_release(OQS_SHA2_sha256_ctx *state) { ++ oqs_sha2_sha256_inc_ctx_release_c((sha256ctx *) state); ++} ++ ++static void SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state) { ++ oqs_sha2_sha384_inc_init_c((sha384ctx *)state); ++} ++ ++static void SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha384_ctx *src) { ++ oqs_sha2_sha384_inc_ctx_clone_c((sha384ctx *) dest, (const sha384ctx *) src); ++} ++ ++static void SHA2_sha384_inc_blocks(OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inblocks) { ++ oqs_sha2_sha384_inc_blocks_c((sha384ctx *) state, in, inblocks); ++} ++ ++static void SHA2_sha384_inc_finalize(uint8_t *out, OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inlen) { ++ oqs_sha2_sha384_inc_finalize_c(out, (sha384ctx *) state, in, inlen); ++} ++ ++static void SHA2_sha384_inc_ctx_release(OQS_SHA2_sha384_ctx *state) { ++ oqs_sha2_sha384_inc_ctx_release_c((sha384ctx *) state); ++} ++ ++static void SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state) { ++ oqs_sha2_sha512_inc_init_c((sha512ctx *)state); ++} ++ ++static void SHA2_sha512_inc_ctx_clone(OQS_SHA2_sha512_ctx *dest, const OQS_SHA2_sha512_ctx *src) { ++ oqs_sha2_sha512_inc_ctx_clone_c((sha512ctx *) dest, (const sha512ctx *) src); ++} ++ ++static void SHA2_sha512_inc_blocks(OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inblocks) { ++ oqs_sha2_sha512_inc_blocks_c((sha512ctx *) state, in, inblocks); ++} ++ ++static void SHA2_sha512_inc_finalize(uint8_t *out, OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inlen) { ++ oqs_sha2_sha512_inc_finalize_c(out, (sha512ctx *) state, in, inlen); ++} ++ ++static void SHA2_sha512_inc_ctx_release(OQS_SHA2_sha512_ctx *state) { ++ oqs_sha2_sha512_inc_ctx_release_c((sha512ctx *) state); ++} ++ ++static void SHA2_sha256(uint8_t *out, const uint8_t *in, size_t inlen) { ++ C_OR_ARM ( ++ oqs_sha2_sha256_c(out, in, inlen), ++ oqs_sha2_sha256_armv8(out, in, inlen) ++ ); ++} ++ ++static void SHA2_sha384(uint8_t *out, const uint8_t *in, size_t inlen) { ++ oqs_sha2_sha384_c(out, in, inlen); ++} ++ ++static void SHA2_sha512(uint8_t *out, const uint8_t *in, size_t inlen) { ++ oqs_sha2_sha512_c(out, in, inlen); ++} ++ ++struct OQS_SHA2_callbacks sha2_default_callbacks = { ++ SHA2_sha256, ++ SHA2_sha256_inc_init, ++ SHA2_sha256_inc_ctx_clone, ++ SHA2_sha256_inc_blocks, ++ SHA2_sha256_inc_finalize, ++ SHA2_sha256_inc_ctx_release, ++ SHA2_sha384, ++ SHA2_sha384_inc_init, ++ SHA2_sha384_inc_ctx_clone, ++ SHA2_sha384_inc_blocks, ++ SHA2_sha384_inc_finalize, ++ SHA2_sha384_inc_ctx_release, ++ SHA2_sha512, ++ SHA2_sha512_inc_init, ++ SHA2_sha512_inc_ctx_clone, ++ SHA2_sha512_inc_blocks, ++ SHA2_sha512_inc_finalize, ++ SHA2_sha512_inc_ctx_release, ++}; +diff --git a/src/common/sha2/sha2_local.h b/src/common/sha2/sha2_local.h +index 028de764..dcb13928 100644 +--- a/src/common/sha2/sha2_local.h ++++ b/src/common/sha2/sha2_local.h +@@ -79,6 +79,8 @@ void oqs_sha2_sha256_c(uint8_t *out, const uint8_t *in, size_t inlen); + void oqs_sha2_sha384_c(uint8_t *out, const uint8_t *in, size_t inlen); + void oqs_sha2_sha512_c(uint8_t *out, const uint8_t *in, size_t inlen); + ++extern struct OQS_SHA2_callbacks sha2_default_callbacks; ++ + #if defined(__cplusplus) + } // extern "C" + #endif +diff --git a/src/common/sha2/sha2_ossl.c b/src/common/sha2/sha2_ossl.c +index c94a07b7..0953feb1 100644 +--- a/src/common/sha2/sha2_ossl.c ++++ b/src/common/sha2/sha2_ossl.c +@@ -11,35 +11,34 @@ + + #include "sha2.h" + +-#include + #include "../ossl_helpers.h" + + static void do_hash(uint8_t *output, const uint8_t *input, size_t inplen, const EVP_MD *md) { + EVP_MD_CTX *mdctx; + unsigned int outlen; +- mdctx = EVP_MD_CTX_new(); ++ mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); + OQS_EXIT_IF_NULLPTR(mdctx, "OpenSSL"); +- OQS_OPENSSL_GUARD(EVP_DigestInit_ex(mdctx, md, NULL)); +- OQS_OPENSSL_GUARD(EVP_DigestUpdate(mdctx, input, inplen)); +- OQS_OPENSSL_GUARD(EVP_DigestFinal_ex(mdctx, output, &outlen)); +- EVP_MD_CTX_free(mdctx); ++ OSSL_FUNC(EVP_DigestInit_ex)(mdctx, md, NULL); ++ OSSL_FUNC(EVP_DigestUpdate)(mdctx, input, inplen); ++ OSSL_FUNC(EVP_DigestFinal_ex)(mdctx, output, &outlen); ++ OSSL_FUNC(EVP_MD_CTX_free)(mdctx); + } + +-void OQS_SHA2_sha256(uint8_t *output, const uint8_t *input, size_t inplen) { ++static void SHA2_sha256(uint8_t *output, const uint8_t *input, size_t inplen) { + const EVP_MD *md; + md = oqs_sha256(); + OQS_EXIT_IF_NULLPTR(md, "OpenSSL"); + do_hash(output, input, inplen, md); + } + +-void OQS_SHA2_sha384(uint8_t *output, const uint8_t *input, size_t inplen) { ++static void SHA2_sha384(uint8_t *output, const uint8_t *input, size_t inplen) { + const EVP_MD *md; + md = oqs_sha384(); + OQS_EXIT_IF_NULLPTR(md, "OpenSSL"); + do_hash(output, input, inplen, md); + } + +-void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen) { ++static void SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen) { + const EVP_MD *md; + md = oqs_sha512(); + OQS_EXIT_IF_NULLPTR(md, "OpenSSL"); +@@ -48,109 +47,127 @@ void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen) { + + #define SHA2_BLOCK_SIZE 64 + +-void OQS_SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { ++static void SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { + EVP_MD_CTX *mdctx; + const EVP_MD *md = NULL; + md = oqs_sha256(); + OQS_EXIT_IF_NULLPTR(md, "OpenSSL"); +- mdctx = EVP_MD_CTX_new(); ++ mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); + OQS_EXIT_IF_NULLPTR(mdctx, "OpenSSL"); +- OQS_OPENSSL_GUARD(EVP_DigestInit_ex(mdctx, md, NULL)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestInit_ex)(mdctx, md, NULL)); + state->ctx = mdctx; + } + +-void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks) { +- OQS_OPENSSL_GUARD(EVP_DigestUpdate((EVP_MD_CTX *) state->ctx, in, inblocks * SHA2_BLOCK_SIZE)); ++static void SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks) { ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, inblocks * SHA2_BLOCK_SIZE)); + } + +-void OQS_SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen) { ++static void SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen) { + unsigned int md_len; + if (inlen > 0) { +- OQS_OPENSSL_GUARD(EVP_DigestUpdate((EVP_MD_CTX *) state->ctx, in, inlen)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, inlen)); + } +- OQS_OPENSSL_GUARD(EVP_DigestFinal_ex((EVP_MD_CTX *) state->ctx, out, &md_len)); +- EVP_MD_CTX_free((EVP_MD_CTX *) state->ctx); +- state->ctx = NULL; ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestFinal_ex)((EVP_MD_CTX *) state->ctx, out, &md_len)); ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *) state->ctx); + } + +-void OQS_SHA2_sha256_inc_ctx_release(OQS_SHA2_sha256_ctx *state) { +- EVP_MD_CTX_destroy((EVP_MD_CTX *) state->ctx); ++static void SHA2_sha256_inc_ctx_release(OQS_SHA2_sha256_ctx *state) { ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *) state->ctx); + state->ctx = NULL; + } + +-void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src) { +- OQS_SHA2_sha256_inc_init(dest); +- OQS_OPENSSL_GUARD(EVP_MD_CTX_copy_ex((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); ++static void SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src) { ++ SHA2_sha256_inc_init(dest); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_MD_CTX_copy_ex)((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); + } + +-void OQS_SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state) { ++static void SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state) { + EVP_MD_CTX *mdctx; + const EVP_MD *md = NULL; + md = oqs_sha384(); + OQS_EXIT_IF_NULLPTR(md, "OpenSSL"); +- mdctx = EVP_MD_CTX_new(); ++ mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); + OQS_EXIT_IF_NULLPTR(mdctx, "OpenSSL"); +- OQS_OPENSSL_GUARD(EVP_DigestInit_ex(mdctx, md, NULL)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestInit_ex)(mdctx, md, NULL)); + state->ctx = mdctx; + } + +-void OQS_SHA2_sha384_inc_blocks(OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inblocks) { +- OQS_OPENSSL_GUARD(EVP_DigestUpdate((EVP_MD_CTX *) state->ctx, in, inblocks * 2 * SHA2_BLOCK_SIZE)); ++static void SHA2_sha384_inc_blocks(OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inblocks) { ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, inblocks * SHA2_BLOCK_SIZE)); + } + +-void OQS_SHA2_sha384_inc_finalize(uint8_t *out, OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inlen) { ++static void SHA2_sha384_inc_finalize(uint8_t *out, OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inlen) { + unsigned int md_len; + if (inlen > 0) { +- OQS_OPENSSL_GUARD(EVP_DigestUpdate((EVP_MD_CTX *) state->ctx, in, inlen)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, inlen)); + } +- OQS_OPENSSL_GUARD(EVP_DigestFinal_ex((EVP_MD_CTX *) state->ctx, out, &md_len)); +- EVP_MD_CTX_free((EVP_MD_CTX *) state->ctx); +- state->ctx = NULL; ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestFinal_ex)((EVP_MD_CTX *) state->ctx, out, &md_len)); ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *) state->ctx); + } + +-void OQS_SHA2_sha384_inc_ctx_release(OQS_SHA2_sha384_ctx *state) { +- EVP_MD_CTX_destroy((EVP_MD_CTX *) state->ctx); ++static void SHA2_sha384_inc_ctx_release(OQS_SHA2_sha384_ctx *state) { ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *) state->ctx); + state->ctx = NULL; + } + +-void OQS_SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha384_ctx *src) { +- OQS_SHA2_sha384_inc_init(dest); +- OQS_OPENSSL_GUARD(EVP_MD_CTX_copy_ex((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); ++static void SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha384_ctx *src) { ++ SHA2_sha384_inc_init(dest); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_MD_CTX_copy_ex)((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); + } + +-void OQS_SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state) { ++static void SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state) { + EVP_MD_CTX *mdctx; + const EVP_MD *md = NULL; + md = oqs_sha512(); + OQS_EXIT_IF_NULLPTR(md, "OpenSSL"); +- mdctx = EVP_MD_CTX_new(); ++ mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); + OQS_EXIT_IF_NULLPTR(mdctx, "OpenSSL"); +- OQS_OPENSSL_GUARD(EVP_DigestInit_ex(mdctx, md, NULL)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestInit_ex)(mdctx, md, NULL)); + state->ctx = mdctx; + } + +-void OQS_SHA2_sha512_inc_blocks(OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inblocks) { +- OQS_OPENSSL_GUARD(EVP_DigestUpdate((EVP_MD_CTX *) state->ctx, in, inblocks * 2 * SHA2_BLOCK_SIZE)); ++static void SHA2_sha512_inc_blocks(OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inblocks) { ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, inblocks * 2 * SHA2_BLOCK_SIZE)); + } + +-void OQS_SHA2_sha512_inc_finalize(uint8_t *out, OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inlen) { ++static void SHA2_sha512_inc_finalize(uint8_t *out, OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inlen) { + unsigned int md_len; + if (inlen > 0) { +- OQS_OPENSSL_GUARD(EVP_DigestUpdate((EVP_MD_CTX *) state->ctx, in, inlen)); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, inlen)); + } +- OQS_OPENSSL_GUARD(EVP_DigestFinal_ex((EVP_MD_CTX *) state->ctx, out, &md_len)); +- EVP_MD_CTX_free((EVP_MD_CTX *) state->ctx); +- state->ctx = NULL; ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestFinal_ex)((EVP_MD_CTX *) state->ctx, out, &md_len)); ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *) state->ctx); + } + +-void OQS_SHA2_sha512_inc_ctx_release(OQS_SHA2_sha512_ctx *state) { +- EVP_MD_CTX_destroy((EVP_MD_CTX *) state->ctx); ++static void SHA2_sha512_inc_ctx_release(OQS_SHA2_sha512_ctx *state) { ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *) state->ctx); + state->ctx = NULL; + } + +-void OQS_SHA2_sha512_inc_ctx_clone(OQS_SHA2_sha512_ctx *dest, const OQS_SHA2_sha512_ctx *src) { +- OQS_SHA2_sha512_inc_init(dest); +- OQS_OPENSSL_GUARD(EVP_MD_CTX_copy_ex((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); +-} ++static void SHA2_sha512_inc_ctx_clone(OQS_SHA2_sha512_ctx *dest, const OQS_SHA2_sha512_ctx *src) { ++ SHA2_sha512_inc_init(dest); ++ OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_MD_CTX_copy_ex)((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); ++} ++ ++struct OQS_SHA2_callbacks sha2_default_callbacks = { ++ SHA2_sha256, ++ SHA2_sha256_inc_init, ++ SHA2_sha256_inc_ctx_clone, ++ SHA2_sha256_inc_blocks, ++ SHA2_sha256_inc_finalize, ++ SHA2_sha256_inc_ctx_release, ++ SHA2_sha384, ++ SHA2_sha384_inc_init, ++ SHA2_sha384_inc_ctx_clone, ++ SHA2_sha384_inc_blocks, ++ SHA2_sha384_inc_finalize, ++ SHA2_sha384_inc_ctx_release, ++ SHA2_sha512, ++ SHA2_sha512_inc_init, ++ SHA2_sha512_inc_ctx_clone, ++ SHA2_sha512_inc_blocks, ++ SHA2_sha512_inc_finalize, ++ SHA2_sha512_inc_ctx_release, ++}; + + #endif +diff --git a/src/common/sha3/ossl_sha3.c b/src/common/sha3/ossl_sha3.c +index 8b8678a2..de95fc39 100644 +--- a/src/common/sha3/ossl_sha3.c ++++ b/src/common/sha3/ossl_sha3.c +@@ -11,136 +11,135 @@ + + #include "sha3.h" + +-#include + #include "../ossl_helpers.h" + #include + + static void do_hash(uint8_t *output, const uint8_t *input, size_t inplen, const EVP_MD *md) { + EVP_MD_CTX *mdctx; +- mdctx = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(mdctx, md, NULL); +- EVP_DigestUpdate(mdctx, input, inplen); +- EVP_DigestFinal_ex(mdctx, output, NULL); +- EVP_MD_CTX_free(mdctx); ++ mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(mdctx, md, NULL); ++ OSSL_FUNC(EVP_DigestUpdate)(mdctx, input, inplen); ++ OSSL_FUNC(EVP_DigestFinal_ex)(mdctx, output, NULL); ++ OSSL_FUNC(EVP_MD_CTX_free)(mdctx); + } + + static void do_xof(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen, const EVP_MD *md) { + EVP_MD_CTX *mdctx; +- mdctx = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(mdctx, md, NULL); +- EVP_DigestUpdate(mdctx, input, inplen); +- EVP_DigestFinalXOF(mdctx, output, outlen); +- EVP_MD_CTX_free(mdctx); ++ mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(mdctx, md, NULL); ++ OSSL_FUNC(EVP_DigestUpdate)(mdctx, input, inplen); ++ OSSL_FUNC(EVP_DigestFinalXOF)(mdctx, output, outlen); ++ OSSL_FUNC(EVP_MD_CTX_free)(mdctx); + } + + /* SHA3-256 */ + +-void OQS_SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inplen) { ++static void SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inplen) { + do_hash(output, input, inplen, oqs_sha3_256()); + } + + /* SHA3-256 incremental */ + +-void OQS_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { +- state->ctx = EVP_MD_CTX_new(); ++static void SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { ++ state->ctx = OSSL_FUNC(EVP_MD_CTX_new)(); + EVP_MD_CTX *s = (EVP_MD_CTX *)state->ctx; +- EVP_DigestInit_ex(s, oqs_sha3_256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s, oqs_sha3_256(), NULL); + } + +-void OQS_SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inplen) { +- EVP_DigestUpdate((EVP_MD_CTX *)state->ctx, input, inplen); ++static void SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inplen) { ++ OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *)state->ctx, input, inplen); + } + +-void OQS_SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state) { +- EVP_DigestFinal_ex((EVP_MD_CTX *)state->ctx, output, NULL); ++static void SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state) { ++ OSSL_FUNC(EVP_DigestFinal_ex)((EVP_MD_CTX *)state->ctx, output, NULL); + } + +-void OQS_SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state) { +- EVP_MD_CTX_free((EVP_MD_CTX *)state->ctx); ++static void SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state) { ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *)state->ctx); + } + +-void OQS_SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src) { +- EVP_MD_CTX_copy_ex((EVP_MD_CTX *)dest->ctx, (EVP_MD_CTX *)src->ctx); ++static void SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src) { ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)((EVP_MD_CTX *)dest->ctx, (EVP_MD_CTX *)src->ctx); + } + +-void OQS_SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state) { ++static void SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state) { + EVP_MD_CTX *s = state->ctx; +- EVP_MD_CTX_reset(s); +- EVP_DigestInit_ex(s, oqs_sha3_256(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s); ++ OSSL_FUNC(EVP_DigestInit_ex)(s, oqs_sha3_256(), NULL); + } + + /* SHA3-384 */ + +-void OQS_SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inplen) { ++static void SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inplen) { + do_hash(output, input, inplen, oqs_sha3_384()); + } + + /* SHA3-384 incremental */ +-void OQS_SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) { +- state->ctx = EVP_MD_CTX_new(); +- EVP_DigestInit_ex((EVP_MD_CTX *)state->ctx, oqs_sha3_384(), NULL); ++static void SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) { ++ state->ctx = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)((EVP_MD_CTX *)state->ctx, oqs_sha3_384(), NULL); + } + +-void OQS_SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inplen) { +- EVP_DigestUpdate((EVP_MD_CTX *)state->ctx, input, inplen); ++static void SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inplen) { ++ OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *)state->ctx, input, inplen); + } + +-void OQS_SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state) { +- EVP_DigestFinal_ex((EVP_MD_CTX *)state->ctx, output, NULL); ++static void SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state) { ++ OSSL_FUNC(EVP_DigestFinal_ex)((EVP_MD_CTX *)state->ctx, output, NULL); + } + +-void OQS_SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state) { +- EVP_MD_CTX_free((EVP_MD_CTX *)state->ctx); ++static void SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state) { ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *)state->ctx); + } + +-void OQS_SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src) { +- EVP_MD_CTX_copy_ex((EVP_MD_CTX *)dest->ctx, (EVP_MD_CTX *)src->ctx); ++static void SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src) { ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)((EVP_MD_CTX *)dest->ctx, (EVP_MD_CTX *)src->ctx); + } + +-void OQS_SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state) { ++static void SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state) { + EVP_MD_CTX *s = state->ctx; +- EVP_MD_CTX_reset(s); +- EVP_DigestInit_ex(s, oqs_sha3_384(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s); ++ OSSL_FUNC(EVP_DigestInit_ex)(s, oqs_sha3_384(), NULL); + } + + /* SHA3-512 */ + +-void OQS_SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inplen) { ++static void SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inplen) { + do_hash(output, input, inplen, oqs_sha3_512()); + } + + /* SHA3-512 incremental */ + +-void OQS_SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) { +- state->ctx = EVP_MD_CTX_new(); +- EVP_DigestInit_ex((EVP_MD_CTX *)state->ctx, oqs_sha3_512(), NULL); ++static void SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) { ++ state->ctx = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)((EVP_MD_CTX *)state->ctx, oqs_sha3_512(), NULL); + } + +-void OQS_SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inplen) { +- EVP_DigestUpdate((EVP_MD_CTX *)state->ctx, input, inplen); ++static void SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inplen) { ++ OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *)state->ctx, input, inplen); + } + +-void OQS_SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state) { +- EVP_DigestFinal_ex((EVP_MD_CTX *)state->ctx, output, NULL); ++static void SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state) { ++ OSSL_FUNC(EVP_DigestFinal_ex)((EVP_MD_CTX *)state->ctx, output, NULL); + } + +-void OQS_SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state) { +- EVP_MD_CTX_free((EVP_MD_CTX *)state->ctx); ++static void SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state) { ++ OSSL_FUNC(EVP_MD_CTX_free)((EVP_MD_CTX *)state->ctx); + } + +-void OQS_SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src) { +- EVP_MD_CTX_copy_ex((EVP_MD_CTX *)dest->ctx, (EVP_MD_CTX *)src->ctx); ++static void SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src) { ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)((EVP_MD_CTX *)dest->ctx, (EVP_MD_CTX *)src->ctx); + } + +-void OQS_SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state) { ++static void SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state) { + EVP_MD_CTX *s = state->ctx; +- EVP_MD_CTX_reset(s); +- EVP_DigestInit_ex(s, oqs_sha3_512(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s); ++ OSSL_FUNC(EVP_DigestInit_ex)(s, oqs_sha3_512(), NULL); + } + + /* SHAKE-128 */ + +-void OQS_SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen) { ++static void SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen) { + do_xof(output, outlen, input, inplen, oqs_shake128()); + } + +@@ -166,70 +165,70 @@ typedef struct { + size_t n_out; + } intrn_shake128_inc_ctx; + +-void OQS_SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) { + state->ctx = malloc(sizeof(intrn_shake128_inc_ctx)); + + intrn_shake128_inc_ctx *s = (intrn_shake128_inc_ctx *)state->ctx; +- s->mdctx = EVP_MD_CTX_new(); ++ s->mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); + s->n_out = 0; +- EVP_DigestInit_ex(s->mdctx, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx, oqs_shake128(), NULL); + } + +-void OQS_SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inplen) { ++static void SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inplen) { + intrn_shake128_inc_ctx *s = (intrn_shake128_inc_ctx *)state->ctx; +- EVP_DigestUpdate(s->mdctx, input, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx, input, inplen); + } + +-void OQS_SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state) { + (void)state; + } + +-void OQS_SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state) { + intrn_shake128_inc_ctx *s = (intrn_shake128_inc_ctx *)state->ctx; + EVP_MD_CTX *clone; + +- clone = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(clone, oqs_shake128(), NULL); +- EVP_MD_CTX_copy_ex(clone, s->mdctx); ++ clone = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(clone, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx); + if (s->n_out == 0) { +- EVP_DigestFinalXOF(clone, output, outlen); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, output, outlen); + } else { + uint8_t *tmp; + tmp = malloc(s->n_out + outlen); + if (tmp == NULL) { + exit(111); + } +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(output, tmp + s->n_out, outlen); + free(tmp); // IGNORE free-check + } +- EVP_MD_CTX_free(clone); ++ OSSL_FUNC(EVP_MD_CTX_free)(clone); + s->n_out += outlen; + } + +-void OQS_SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state) { + intrn_shake128_inc_ctx *s = (intrn_shake128_inc_ctx *)state->ctx; +- EVP_MD_CTX_free(s->mdctx); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx); + free(s); // IGNORE free-check + } + +-void OQS_SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src) { ++static void SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src) { + intrn_shake128_inc_ctx *s = (intrn_shake128_inc_ctx *)src->ctx; + intrn_shake128_inc_ctx *d = (intrn_shake128_inc_ctx *)dest->ctx; +- EVP_MD_CTX_copy_ex(d->mdctx, s->mdctx); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx, s->mdctx); + d->n_out = s->n_out; + } + +-void OQS_SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state) { + intrn_shake128_inc_ctx *s = (intrn_shake128_inc_ctx *)state->ctx; +- EVP_MD_CTX_reset(s->mdctx); +- EVP_DigestInit_ex(s->mdctx, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx, oqs_shake128(), NULL); + s->n_out = 0; + } + + /* SHAKE-256 */ + +-void OQS_SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen) { ++static void SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen) { + do_xof(output, outlen, input, inplen, oqs_shake256()); + } + +@@ -243,65 +242,107 @@ typedef struct { + size_t n_out; + } intrn_shake256_inc_ctx; + +-void OQS_SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) { + state->ctx = malloc(sizeof(intrn_shake256_inc_ctx)); + + intrn_shake256_inc_ctx *s = (intrn_shake256_inc_ctx *)state->ctx; +- s->mdctx = EVP_MD_CTX_new(); ++ s->mdctx = OSSL_FUNC(EVP_MD_CTX_new)(); + s->n_out = 0; +- EVP_DigestInit_ex(s->mdctx, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx, oqs_shake256(), NULL); + } + +-void OQS_SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inplen) { ++static void SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inplen) { + intrn_shake256_inc_ctx *s = (intrn_shake256_inc_ctx *)state->ctx; +- EVP_DigestUpdate(s->mdctx, input, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx, input, inplen); + } + +-void OQS_SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state) { + (void)state; + } + +-void OQS_SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state) { + intrn_shake256_inc_ctx *s = (intrn_shake256_inc_ctx *)state->ctx; + EVP_MD_CTX *clone; + +- clone = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(clone, oqs_shake256(), NULL); +- EVP_MD_CTX_copy_ex(clone, s->mdctx); ++ clone = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(clone, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx); + if (s->n_out == 0) { +- EVP_DigestFinalXOF(clone, output, outlen); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, output, outlen); + } else { + uint8_t *tmp; + tmp = malloc(s->n_out + outlen); + if (tmp == NULL) { + exit(111); + } +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(output, tmp + s->n_out, outlen); + free(tmp); // IGNORE free-check + } +- EVP_MD_CTX_free(clone); ++ OSSL_FUNC(EVP_MD_CTX_free)(clone); + s->n_out += outlen; + } + +-void OQS_SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state) { + intrn_shake256_inc_ctx *s = (intrn_shake256_inc_ctx *)state->ctx; +- EVP_MD_CTX_free(s->mdctx); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx); + free(s); // IGNORE free-check + } + +-void OQS_SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src) { ++static void SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src) { + intrn_shake256_inc_ctx *s = (intrn_shake256_inc_ctx *)src->ctx; + intrn_shake256_inc_ctx *d = (intrn_shake256_inc_ctx *)dest->ctx; +- EVP_MD_CTX_copy_ex(d->mdctx, s->mdctx); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx, s->mdctx); + d->n_out = s->n_out; + } + +-void OQS_SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state) { + intrn_shake256_inc_ctx *s = (intrn_shake256_inc_ctx *)state->ctx; +- EVP_MD_CTX_reset(s->mdctx); +- EVP_DigestInit_ex(s->mdctx, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx, oqs_shake256(), NULL); + s->n_out = 0; + } + ++extern struct OQS_SHA3_callbacks sha3_default_callbacks; ++ ++struct OQS_SHA3_callbacks sha3_default_callbacks = { ++ SHA3_sha3_256, ++ SHA3_sha3_256_inc_init, ++ SHA3_sha3_256_inc_absorb, ++ SHA3_sha3_256_inc_finalize, ++ SHA3_sha3_256_inc_ctx_release, ++ SHA3_sha3_256_inc_ctx_reset, ++ SHA3_sha3_256_inc_ctx_clone, ++ SHA3_sha3_384, ++ SHA3_sha3_384_inc_init, ++ SHA3_sha3_384_inc_absorb, ++ SHA3_sha3_384_inc_finalize, ++ SHA3_sha3_384_inc_ctx_release, ++ SHA3_sha3_384_inc_ctx_reset, ++ SHA3_sha3_384_inc_ctx_clone, ++ SHA3_sha3_512, ++ SHA3_sha3_512_inc_init, ++ SHA3_sha3_512_inc_absorb, ++ SHA3_sha3_512_inc_finalize, ++ SHA3_sha3_512_inc_ctx_release, ++ SHA3_sha3_512_inc_ctx_reset, ++ SHA3_sha3_512_inc_ctx_clone, ++ SHA3_shake128, ++ SHA3_shake128_inc_init, ++ SHA3_shake128_inc_absorb, ++ SHA3_shake128_inc_finalize, ++ SHA3_shake128_inc_squeeze, ++ SHA3_shake128_inc_ctx_release, ++ SHA3_shake128_inc_ctx_clone, ++ SHA3_shake128_inc_ctx_reset, ++ SHA3_shake256, ++ SHA3_shake256_inc_init, ++ SHA3_shake256_inc_absorb, ++ SHA3_shake256_inc_finalize, ++ SHA3_shake256_inc_squeeze, ++ SHA3_shake256_inc_ctx_release, ++ SHA3_shake256_inc_ctx_clone, ++ SHA3_shake256_inc_ctx_reset, ++}; ++ + #endif +diff --git a/src/common/sha3/ossl_sha3x4.c b/src/common/sha3/ossl_sha3x4.c +index 1e469720..fec62ad6 100644 +--- a/src/common/sha3/ossl_sha3x4.c ++++ b/src/common/sha3/ossl_sha3x4.c +@@ -14,8 +14,8 @@ + + /* SHAKE-128 */ + +-void OQS_SHA3_shake128_x4(uint8_t *output0, uint8_t *output1, uint8_t *output2, uint8_t *output3, size_t outlen, +- const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { ++static void SHA3_shake128_x4(uint8_t *output0, uint8_t *output1, uint8_t *output2, uint8_t *output3, size_t outlen, ++ const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { + OQS_SHA3_shake128(output0, outlen, in0, inplen); + OQS_SHA3_shake128(output1, outlen, in1, inplen); + OQS_SHA3_shake128(output2, outlen, in2, inplen); +@@ -32,108 +32,108 @@ typedef struct { + size_t n_out; + } intrn_shake128_x4_inc_ctx; + +-void OQS_SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { + state->ctx = malloc(sizeof(intrn_shake128_x4_inc_ctx)); + + intrn_shake128_x4_inc_ctx *s = (intrn_shake128_x4_inc_ctx *)state->ctx; +- s->mdctx0 = EVP_MD_CTX_new(); +- s->mdctx1 = EVP_MD_CTX_new(); +- s->mdctx2 = EVP_MD_CTX_new(); +- s->mdctx3 = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(s->mdctx0, oqs_shake128(), NULL); +- EVP_DigestInit_ex(s->mdctx1, oqs_shake128(), NULL); +- EVP_DigestInit_ex(s->mdctx2, oqs_shake128(), NULL); +- EVP_DigestInit_ex(s->mdctx3, oqs_shake128(), NULL); ++ s->mdctx0 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ s->mdctx1 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ s->mdctx2 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ s->mdctx3 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx0, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx1, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx2, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx3, oqs_shake128(), NULL); + s->n_out = 0; + } + +-void OQS_SHA3_shake128_x4_inc_absorb(OQS_SHA3_shake128_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { ++static void SHA3_shake128_x4_inc_absorb(OQS_SHA3_shake128_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { + intrn_shake128_x4_inc_ctx *s = (intrn_shake128_x4_inc_ctx *)state->ctx; +- EVP_DigestUpdate(s->mdctx0, in0, inplen); +- EVP_DigestUpdate(s->mdctx1, in1, inplen); +- EVP_DigestUpdate(s->mdctx2, in2, inplen); +- EVP_DigestUpdate(s->mdctx3, in3, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx0, in0, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx1, in1, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx2, in2, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx3, in3, inplen); + } + +-void OQS_SHA3_shake128_x4_inc_finalize(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_finalize(OQS_SHA3_shake128_x4_inc_ctx *state) { + (void)state; + } + +-void OQS_SHA3_shake128_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake128_x4_inc_ctx *state) { + intrn_shake128_x4_inc_ctx *s = (intrn_shake128_x4_inc_ctx *)state->ctx; + EVP_MD_CTX *clone; + +- clone = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(clone, oqs_shake128(), NULL); ++ clone = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(clone, oqs_shake128(), NULL); + if (s->n_out == 0) { +- EVP_MD_CTX_copy_ex(clone, s->mdctx0); +- EVP_DigestFinalXOF(clone, out0, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx1); +- EVP_DigestFinalXOF(clone, out1, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx2); +- EVP_DigestFinalXOF(clone, out2, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx3); +- EVP_DigestFinalXOF(clone, out3, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx0); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out0, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx1); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out1, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx2); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out2, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx3); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out3, outlen); + } else { + uint8_t *tmp; + tmp = malloc(s->n_out + outlen); + if (tmp == NULL) { + exit(111); + } +- EVP_MD_CTX_copy_ex(clone, s->mdctx0); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx0); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out0, tmp + s->n_out, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx1); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx1); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out1, tmp + s->n_out, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx2); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx2); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out2, tmp + s->n_out, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx3); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx3); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out3, tmp + s->n_out, outlen); + free(tmp); // IGNORE free-check + } +- EVP_MD_CTX_free(clone); ++ OSSL_FUNC(EVP_MD_CTX_free)(clone); + s->n_out += outlen; + } + +-void OQS_SHA3_shake128_x4_inc_ctx_clone(OQS_SHA3_shake128_x4_inc_ctx *dest, const OQS_SHA3_shake128_x4_inc_ctx *src) { ++static void SHA3_shake128_x4_inc_ctx_clone(OQS_SHA3_shake128_x4_inc_ctx *dest, const OQS_SHA3_shake128_x4_inc_ctx *src) { + intrn_shake128_x4_inc_ctx *s = (intrn_shake128_x4_inc_ctx *)src->ctx; + intrn_shake128_x4_inc_ctx *d = (intrn_shake128_x4_inc_ctx *)dest->ctx; +- EVP_MD_CTX_copy_ex(d->mdctx0, s->mdctx0); +- EVP_MD_CTX_copy_ex(d->mdctx1, s->mdctx1); +- EVP_MD_CTX_copy_ex(d->mdctx2, s->mdctx2); +- EVP_MD_CTX_copy_ex(d->mdctx3, s->mdctx3); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx0, s->mdctx0); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx1, s->mdctx1); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx2, s->mdctx2); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx3, s->mdctx3); + d->n_out = s->n_out; + } + +-void OQS_SHA3_shake128_x4_inc_ctx_release(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_ctx_release(OQS_SHA3_shake128_x4_inc_ctx *state) { + intrn_shake128_x4_inc_ctx *s = (intrn_shake128_x4_inc_ctx *)state->ctx; +- EVP_MD_CTX_free(s->mdctx0); +- EVP_MD_CTX_free(s->mdctx1); +- EVP_MD_CTX_free(s->mdctx2); +- EVP_MD_CTX_free(s->mdctx3); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx0); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx1); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx2); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx3); + free(s); // IGNORE free-check + } + +-void OQS_SHA3_shake128_x4_inc_ctx_reset(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_ctx_reset(OQS_SHA3_shake128_x4_inc_ctx *state) { + intrn_shake128_x4_inc_ctx *s = (intrn_shake128_x4_inc_ctx *)state->ctx; +- EVP_MD_CTX_reset(s->mdctx0); +- EVP_MD_CTX_reset(s->mdctx1); +- EVP_MD_CTX_reset(s->mdctx2); +- EVP_MD_CTX_reset(s->mdctx3); +- EVP_DigestInit_ex(s->mdctx0, oqs_shake128(), NULL); +- EVP_DigestInit_ex(s->mdctx1, oqs_shake128(), NULL); +- EVP_DigestInit_ex(s->mdctx2, oqs_shake128(), NULL); +- EVP_DigestInit_ex(s->mdctx3, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx0); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx1); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx2); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx3); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx0, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx1, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx2, oqs_shake128(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx3, oqs_shake128(), NULL); + s->n_out = 0; + } + + /* SHAKE-256 */ + +-void OQS_SHA3_shake256_x4(uint8_t *output0, uint8_t *output1, uint8_t *output2, uint8_t *output3, size_t outlen, +- const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { ++static void SHA3_shake256_x4(uint8_t *output0, uint8_t *output1, uint8_t *output2, uint8_t *output3, size_t outlen, ++ const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { + OQS_SHA3_shake256(output0, outlen, in0, inplen); + OQS_SHA3_shake256(output1, outlen, in1, inplen); + OQS_SHA3_shake256(output2, outlen, in2, inplen); +@@ -150,102 +150,123 @@ typedef struct { + size_t n_out; + } intrn_shake256_x4_inc_ctx; + +-void OQS_SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state) { + state->ctx = malloc(sizeof(intrn_shake256_x4_inc_ctx)); + + intrn_shake256_x4_inc_ctx *s = (intrn_shake256_x4_inc_ctx *)state->ctx; +- s->mdctx0 = EVP_MD_CTX_new(); +- s->mdctx1 = EVP_MD_CTX_new(); +- s->mdctx2 = EVP_MD_CTX_new(); +- s->mdctx3 = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(s->mdctx0, oqs_shake256(), NULL); +- EVP_DigestInit_ex(s->mdctx1, oqs_shake256(), NULL); +- EVP_DigestInit_ex(s->mdctx2, oqs_shake256(), NULL); +- EVP_DigestInit_ex(s->mdctx3, oqs_shake256(), NULL); ++ s->mdctx0 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ s->mdctx1 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ s->mdctx2 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ s->mdctx3 = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx0, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx1, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx2, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx3, oqs_shake256(), NULL); + s->n_out = 0; + } + +-void OQS_SHA3_shake256_x4_inc_absorb(OQS_SHA3_shake256_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { ++static void SHA3_shake256_x4_inc_absorb(OQS_SHA3_shake256_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inplen) { + intrn_shake256_x4_inc_ctx *s = (intrn_shake256_x4_inc_ctx *)state->ctx; +- EVP_DigestUpdate(s->mdctx0, in0, inplen); +- EVP_DigestUpdate(s->mdctx1, in1, inplen); +- EVP_DigestUpdate(s->mdctx2, in2, inplen); +- EVP_DigestUpdate(s->mdctx3, in3, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx0, in0, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx1, in1, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx2, in2, inplen); ++ OSSL_FUNC(EVP_DigestUpdate)(s->mdctx3, in3, inplen); + } + +-void OQS_SHA3_shake256_x4_inc_finalize(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_finalize(OQS_SHA3_shake256_x4_inc_ctx *state) { + (void)state; + } + +-void OQS_SHA3_shake256_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake256_x4_inc_ctx *state) { + intrn_shake256_x4_inc_ctx *s = (intrn_shake256_x4_inc_ctx *)state->ctx; + EVP_MD_CTX *clone; + +- clone = EVP_MD_CTX_new(); +- EVP_DigestInit_ex(clone, oqs_shake256(), NULL); ++ clone = OSSL_FUNC(EVP_MD_CTX_new)(); ++ OSSL_FUNC(EVP_DigestInit_ex)(clone, oqs_shake256(), NULL); + if (s->n_out == 0) { +- EVP_MD_CTX_copy_ex(clone, s->mdctx0); +- EVP_DigestFinalXOF(clone, out0, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx1); +- EVP_DigestFinalXOF(clone, out1, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx2); +- EVP_DigestFinalXOF(clone, out2, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx3); +- EVP_DigestFinalXOF(clone, out3, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx0); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out0, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx1); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out1, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx2); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out2, outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx3); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, out3, outlen); + } else { + uint8_t *tmp; + tmp = malloc(s->n_out + outlen); + if (tmp == NULL) { + exit(111); + } +- EVP_MD_CTX_copy_ex(clone, s->mdctx0); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx0); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out0, tmp + s->n_out, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx1); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx1); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out1, tmp + s->n_out, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx2); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx2); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out2, tmp + s->n_out, outlen); +- EVP_MD_CTX_copy_ex(clone, s->mdctx3); +- EVP_DigestFinalXOF(clone, tmp, s->n_out + outlen); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx3); ++ OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); + memcpy(out3, tmp + s->n_out, outlen); + free(tmp); // IGNORE free-check + } +- EVP_MD_CTX_free(clone); ++ OSSL_FUNC(EVP_MD_CTX_free)(clone); + s->n_out += outlen; + } + +-void OQS_SHA3_shake256_x4_inc_ctx_clone(OQS_SHA3_shake256_x4_inc_ctx *dest, const OQS_SHA3_shake256_x4_inc_ctx *src) { ++static void SHA3_shake256_x4_inc_ctx_clone(OQS_SHA3_shake256_x4_inc_ctx *dest, const OQS_SHA3_shake256_x4_inc_ctx *src) { + intrn_shake256_x4_inc_ctx *s = (intrn_shake256_x4_inc_ctx *)src->ctx; + intrn_shake256_x4_inc_ctx *d = (intrn_shake256_x4_inc_ctx *)dest->ctx; +- EVP_MD_CTX_copy_ex(d->mdctx0, s->mdctx0); +- EVP_MD_CTX_copy_ex(d->mdctx1, s->mdctx1); +- EVP_MD_CTX_copy_ex(d->mdctx2, s->mdctx2); +- EVP_MD_CTX_copy_ex(d->mdctx3, s->mdctx3); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx0, s->mdctx0); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx1, s->mdctx1); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx2, s->mdctx2); ++ OSSL_FUNC(EVP_MD_CTX_copy_ex)(d->mdctx3, s->mdctx3); + d->n_out = s->n_out; + } + +-void OQS_SHA3_shake256_x4_inc_ctx_release(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_ctx_release(OQS_SHA3_shake256_x4_inc_ctx *state) { + intrn_shake256_x4_inc_ctx *s = (intrn_shake256_x4_inc_ctx *)state->ctx; +- EVP_MD_CTX_free(s->mdctx0); +- EVP_MD_CTX_free(s->mdctx1); +- EVP_MD_CTX_free(s->mdctx2); +- EVP_MD_CTX_free(s->mdctx3); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx0); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx1); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx2); ++ OSSL_FUNC(EVP_MD_CTX_free)(s->mdctx3); + free(s); // IGNORE free-check + } + +-void OQS_SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state) { + intrn_shake256_x4_inc_ctx *s = (intrn_shake256_x4_inc_ctx *)state->ctx; +- EVP_MD_CTX_reset(s->mdctx0); +- EVP_MD_CTX_reset(s->mdctx1); +- EVP_MD_CTX_reset(s->mdctx2); +- EVP_MD_CTX_reset(s->mdctx3); +- EVP_DigestInit_ex(s->mdctx0, oqs_shake256(), NULL); +- EVP_DigestInit_ex(s->mdctx1, oqs_shake256(), NULL); +- EVP_DigestInit_ex(s->mdctx2, oqs_shake256(), NULL); +- EVP_DigestInit_ex(s->mdctx3, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx0); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx1); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx2); ++ OSSL_FUNC(EVP_MD_CTX_reset)(s->mdctx3); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx0, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx1, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx2, oqs_shake256(), NULL); ++ OSSL_FUNC(EVP_DigestInit_ex)(s->mdctx3, oqs_shake256(), NULL); + s->n_out = 0; + } + ++extern struct OQS_SHA3_x4_callbacks sha3_x4_default_callbacks; ++ ++struct OQS_SHA3_x4_callbacks sha3_x4_default_callbacks = { ++ SHA3_shake128_x4, ++ SHA3_shake128_x4_inc_init, ++ SHA3_shake128_x4_inc_absorb, ++ SHA3_shake128_x4_inc_finalize, ++ SHA3_shake128_x4_inc_squeeze, ++ SHA3_shake128_x4_inc_ctx_release, ++ SHA3_shake128_x4_inc_ctx_clone, ++ SHA3_shake128_x4_inc_ctx_reset, ++ SHA3_shake256_x4, ++ SHA3_shake256_x4_inc_init, ++ SHA3_shake256_x4_inc_absorb, ++ SHA3_shake256_x4_inc_finalize, ++ SHA3_shake256_x4_inc_squeeze, ++ SHA3_shake256_x4_inc_ctx_release, ++ SHA3_shake256_x4_inc_ctx_clone, ++ SHA3_shake256_x4_inc_ctx_reset, ++}; ++ + #endif +diff --git a/src/common/sha3/sha3.c b/src/common/sha3/sha3.c +new file mode 100644 +index 00000000..600fc198 +--- /dev/null ++++ b/src/common/sha3/sha3.c +@@ -0,0 +1,161 @@ ++// SPDX-License-Identifier: MIT ++ ++#include ++ ++#include "sha3.h" ++ ++extern struct OQS_SHA3_callbacks sha3_default_callbacks; ++ ++static struct OQS_SHA3_callbacks *callbacks = &sha3_default_callbacks; ++ ++OQS_API void OQS_SHA3_set_callbacks(struct OQS_SHA3_callbacks *new_callbacks) { ++ callbacks = new_callbacks; ++} ++ ++void OQS_SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inplen) { ++ callbacks->SHA3_sha3_256(output, input, inplen); ++} ++ ++void OQS_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { ++ callbacks->SHA3_sha3_256_inc_init(state); ++} ++ ++void OQS_SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inlen) { ++ callbacks->SHA3_sha3_256_inc_absorb(state, input, inlen); ++} ++ ++void OQS_SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state) { ++ callbacks->SHA3_sha3_256_inc_finalize(output, state); ++} ++ ++void OQS_SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state) { ++ callbacks->SHA3_sha3_256_inc_ctx_release(state); ++} ++ ++void OQS_SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state) { ++ callbacks->SHA3_sha3_256_inc_ctx_reset(state); ++} ++ ++void OQS_SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src) { ++ callbacks->SHA3_sha3_256_inc_ctx_clone(dest, src); ++} ++ ++void OQS_SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inplen) { ++ callbacks->SHA3_sha3_384(output, input, inplen); ++} ++ ++void OQS_SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) { ++ callbacks->SHA3_sha3_384_inc_init(state); ++} ++ ++void OQS_SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inlen) { ++ callbacks->SHA3_sha3_384_inc_absorb(state, input, inlen); ++} ++ ++void OQS_SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state) { ++ callbacks->SHA3_sha3_384_inc_finalize(output, state); ++} ++ ++void OQS_SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state) { ++ callbacks->SHA3_sha3_384_inc_ctx_release(state); ++} ++ ++void OQS_SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state) { ++ callbacks->SHA3_sha3_384_inc_ctx_reset(state); ++} ++ ++void OQS_SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src) { ++ callbacks->SHA3_sha3_384_inc_ctx_clone(dest, src); ++} ++ ++void OQS_SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inplen) { ++ callbacks->SHA3_sha3_512(output, input, inplen); ++} ++ ++void OQS_SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) { ++ callbacks->SHA3_sha3_512_inc_init(state); ++} ++ ++void OQS_SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inlen) { ++ callbacks->SHA3_sha3_512_inc_absorb(state, input, inlen); ++} ++ ++void OQS_SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state) { ++ callbacks->SHA3_sha3_512_inc_finalize(output, state); ++} ++ ++void OQS_SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state) { ++ callbacks->SHA3_sha3_512_inc_ctx_release(state); ++} ++ ++void OQS_SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state) { ++ callbacks->SHA3_sha3_512_inc_ctx_reset(state); ++} ++ ++void OQS_SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src) { ++ callbacks->SHA3_sha3_512_inc_ctx_clone(dest, src); ++} ++ ++void OQS_SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen) { ++ callbacks->SHA3_shake128(output, outlen, input, inplen); ++} ++ ++void OQS_SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) { ++ callbacks->SHA3_shake128_inc_init(state); ++} ++ ++void OQS_SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inlen) { ++ callbacks->SHA3_shake128_inc_absorb(state, input, inlen); ++} ++ ++void OQS_SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state) { ++ callbacks->SHA3_shake128_inc_finalize(state); ++} ++ ++void OQS_SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state) { ++ callbacks->SHA3_shake128_inc_squeeze(output, outlen, state); ++} ++ ++void OQS_SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state) { ++ callbacks->SHA3_shake128_inc_ctx_release(state); ++} ++ ++void OQS_SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src) { ++ callbacks->SHA3_shake128_inc_ctx_clone(dest, src); ++} ++ ++void OQS_SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state) { ++ callbacks->SHA3_shake128_inc_ctx_reset(state); ++} ++ ++void OQS_SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen) { ++ callbacks->SHA3_shake256(output, outlen, input, inplen); ++} ++ ++void OQS_SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) { ++ callbacks->SHA3_shake256_inc_init(state); ++} ++ ++void OQS_SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inlen) { ++ callbacks->SHA3_shake256_inc_absorb(state, input, inlen); ++} ++ ++void OQS_SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state) { ++ callbacks->SHA3_shake256_inc_finalize(state); ++} ++ ++void OQS_SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state) { ++ callbacks->SHA3_shake256_inc_squeeze(output, outlen, state); ++} ++ ++void OQS_SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state) { ++ callbacks->SHA3_shake256_inc_ctx_release(state); ++} ++ ++void OQS_SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src) { ++ callbacks->SHA3_shake256_inc_ctx_clone(dest, src); ++} ++ ++void OQS_SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state) { ++ callbacks->SHA3_shake256_inc_ctx_reset(state); ++} +diff --git a/src/common/sha3/sha3.h b/src/common/sha3/sha3.h +index d66c7289..ef259f42 100644 +--- a/src/common/sha3/sha3.h ++++ b/src/common/sha3/sha3.h +@@ -18,6 +18,8 @@ + #include + #include + ++#include ++ + #if defined(__cplusplus) + extern "C" { + #endif +@@ -421,6 +423,205 @@ void OQS_SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_ + */ + void OQS_SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state); + ++/** Data structure implemented by cryptographic provider for SHA-3 operations. ++ */ ++struct OQS_SHA3_callbacks { ++ /** ++ * Implementation of function OQS_SHA3_sha3_256. ++ */ ++ void (*SHA3_sha3_256)(uint8_t *output, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_256_inc_init. ++ */ ++ void (*SHA3_sha3_256_inc_init)(OQS_SHA3_sha3_256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_256_inc_absorb. ++ */ ++ void (*SHA3_sha3_256_inc_absorb)(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_256_inc_finalize. ++ */ ++ void (*SHA3_sha3_256_inc_finalize)(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_256_inc_ctx_release. ++ */ ++ void (*SHA3_sha3_256_inc_ctx_release)(OQS_SHA3_sha3_256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_256_inc_ctx_reset. ++ */ ++ void (*SHA3_sha3_256_inc_ctx_reset)(OQS_SHA3_sha3_256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_256_inc_ctx_clone. ++ */ ++ void (*SHA3_sha3_256_inc_ctx_clone)(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_384. ++ */ ++ void (*SHA3_sha3_384)(uint8_t *output, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_384_inc_init. ++ */ ++ void (*SHA3_sha3_384_inc_init)(OQS_SHA3_sha3_384_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_384_inc_absorb. ++ */ ++ void (*SHA3_sha3_384_inc_absorb)(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_384_inc_finalize. ++ */ ++ void (*SHA3_sha3_384_inc_finalize)(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_384_inc_ctx_release. ++ */ ++ void (*SHA3_sha3_384_inc_ctx_release)(OQS_SHA3_sha3_384_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_384_inc_ctx_reset. ++ */ ++ void (*SHA3_sha3_384_inc_ctx_reset)(OQS_SHA3_sha3_384_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_384_inc_ctx_clone. ++ */ ++ void (*SHA3_sha3_384_inc_ctx_clone)(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_512. ++ */ ++ void (*SHA3_sha3_512)(uint8_t *output, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_512_inc_init. ++ */ ++ void (*SHA3_sha3_512_inc_init)(OQS_SHA3_sha3_512_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_512_inc_absorb. ++ */ ++ void (*SHA3_sha3_512_inc_absorb)(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_512_inc_finalize. ++ */ ++ void (*SHA3_sha3_512_inc_finalize)(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_512_inc_ctx_release. ++ */ ++ void (*SHA3_sha3_512_inc_ctx_release)(OQS_SHA3_sha3_512_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_512_inc_ctx_reset. ++ */ ++ void (*SHA3_sha3_512_inc_ctx_reset)(OQS_SHA3_sha3_512_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_sha3_512_inc_ctx_clone. ++ */ ++ void (*SHA3_sha3_512_inc_ctx_clone)(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128. ++ */ ++ void (*SHA3_shake128)(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_inc_init. ++ */ ++ void (*SHA3_shake128_inc_init)(OQS_SHA3_shake128_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_inc_absorb. ++ */ ++ void (*SHA3_shake128_inc_absorb)(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_inc_finalize. ++ */ ++ void (*SHA3_shake128_inc_finalize)(OQS_SHA3_shake128_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_inc_squeeze. ++ */ ++ void (*SHA3_shake128_inc_squeeze)(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_inc_ctx_release. ++ */ ++ void (*SHA3_shake128_inc_ctx_release)(OQS_SHA3_shake128_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_inc_ctx_clone. ++ */ ++ void (*SHA3_shake128_inc_ctx_clone)(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_inc_ctx_reset. ++ */ ++ void (*SHA3_shake128_inc_ctx_reset)(OQS_SHA3_shake128_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256. ++ */ ++ void (*SHA3_shake256)(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_inc_init. ++ */ ++ void (*SHA3_shake256_inc_init)(OQS_SHA3_shake256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_inc_absorb. ++ */ ++ void (*SHA3_shake256_inc_absorb)(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_inc_finalize. ++ */ ++ void (*SHA3_shake256_inc_finalize)(OQS_SHA3_shake256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_inc_squeeze. ++ */ ++ void (*SHA3_shake256_inc_squeeze)(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_inc_ctx_release. ++ */ ++ void (*SHA3_shake256_inc_ctx_release)(OQS_SHA3_shake256_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_inc_ctx_clone. ++ */ ++ void (*SHA3_shake256_inc_ctx_clone)(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_inc_ctx_reset. ++ */ ++ void (*SHA3_shake256_inc_ctx_reset)(OQS_SHA3_shake256_inc_ctx *state); ++}; ++ ++/** ++ * Set callback functions for SHA3 operations. ++ * ++ * This function may be called before OQS_init to switch the ++ * cryptographic provider for SHA3 operations. If it is not called, ++ * the default provider determined at build time will be used. ++ * ++ * @param new_callbacks Callback functions defined in OQS_SHA3_callbacks struct ++ */ ++OQS_API void OQS_SHA3_set_callbacks(struct OQS_SHA3_callbacks *new_callbacks); + + #if defined(__cplusplus) + } // extern "C" +diff --git a/src/common/sha3/sha3x4.c b/src/common/sha3/sha3x4.c +new file mode 100644 +index 00000000..b41ea08d +--- /dev/null ++++ b/src/common/sha3/sha3x4.c +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: MIT ++ ++#include ++ ++#include "sha3x4.h" ++ ++extern struct OQS_SHA3_x4_callbacks sha3_x4_default_callbacks; ++ ++static struct OQS_SHA3_x4_callbacks *callbacks = &sha3_x4_default_callbacks; ++ ++OQS_API void OQS_SHA3_x4_set_callbacks(struct OQS_SHA3_x4_callbacks *new_callbacks) { ++ callbacks = new_callbacks; ++} ++ ++void OQS_SHA3_shake128_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++ callbacks->SHA3_shake128_x4(out0, out1, out2, out3, outlen, in0, in1, in2, in3, inlen); ++} ++ ++void OQS_SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { ++ callbacks->SHA3_shake128_x4_inc_init(state); ++} ++ ++void OQS_SHA3_shake128_x4_inc_absorb(OQS_SHA3_shake128_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++ callbacks->SHA3_shake128_x4_inc_absorb(state, in0, in1, in2, in3, inlen); ++} ++ ++void OQS_SHA3_shake128_x4_inc_finalize(OQS_SHA3_shake128_x4_inc_ctx *state) { ++ callbacks->SHA3_shake128_x4_inc_finalize(state); ++} ++ ++void OQS_SHA3_shake128_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake128_x4_inc_ctx *state) { ++ callbacks->SHA3_shake128_x4_inc_squeeze(out0, out1, out2, out3, outlen, state); ++} ++ ++void OQS_SHA3_shake128_x4_inc_ctx_release(OQS_SHA3_shake128_x4_inc_ctx *state) { ++ callbacks->SHA3_shake128_x4_inc_ctx_release(state); ++} ++ ++void OQS_SHA3_shake128_x4_inc_ctx_clone(OQS_SHA3_shake128_x4_inc_ctx *dest, const OQS_SHA3_shake128_x4_inc_ctx *src) { ++ callbacks->SHA3_shake128_x4_inc_ctx_clone(dest, src); ++} ++ ++void OQS_SHA3_shake128_x4_inc_ctx_reset(OQS_SHA3_shake128_x4_inc_ctx *state) { ++ callbacks->SHA3_shake128_x4_inc_ctx_reset(state); ++} ++ ++void OQS_SHA3_shake256_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++ callbacks->SHA3_shake256_x4(out0, out1, out2, out3, outlen, in0, in1, in2, in3, inlen); ++} ++ ++void OQS_SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state) { ++ callbacks->SHA3_shake256_x4_inc_init(state); ++} ++ ++void OQS_SHA3_shake256_x4_inc_absorb(OQS_SHA3_shake256_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++ callbacks->SHA3_shake256_x4_inc_absorb(state, in0, in1, in2, in3, inlen); ++} ++ ++void OQS_SHA3_shake256_x4_inc_finalize(OQS_SHA3_shake256_x4_inc_ctx *state) { ++ callbacks->SHA3_shake256_x4_inc_finalize(state); ++} ++ ++void OQS_SHA3_shake256_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake256_x4_inc_ctx *state) { ++ callbacks->SHA3_shake256_x4_inc_squeeze(out0, out1, out2, out3, outlen, state); ++} ++ ++void OQS_SHA3_shake256_x4_inc_ctx_release(OQS_SHA3_shake256_x4_inc_ctx *state) { ++ callbacks->SHA3_shake256_x4_inc_ctx_release(state); ++} ++ ++void OQS_SHA3_shake256_x4_inc_ctx_clone(OQS_SHA3_shake256_x4_inc_ctx *dest, const OQS_SHA3_shake256_x4_inc_ctx *src) { ++ callbacks->SHA3_shake256_x4_inc_ctx_clone(dest, src); ++} ++ ++void OQS_SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state) { ++ callbacks->SHA3_shake256_x4_inc_ctx_reset(state); ++} +diff --git a/src/common/sha3/sha3x4.h b/src/common/sha3/sha3x4.h +index cef4e675..1dc3c79e 100644 +--- a/src/common/sha3/sha3x4.h ++++ b/src/common/sha3/sha3x4.h +@@ -18,6 +18,8 @@ + #include + #include + ++#include ++ + #if defined(__cplusplus) + extern "C" { + #endif +@@ -255,6 +257,149 @@ void OQS_SHA3_shake256_x4_inc_ctx_clone( + */ + void OQS_SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state); + ++/** Data structure implemented by cryptographic provider for the ++ * four-way parallel incremental SHAKE-256 operations. ++ */ ++struct OQS_SHA3_x4_callbacks { ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4. ++ */ ++ void (*SHA3_shake128_x4)( ++ uint8_t *out0, ++ uint8_t *out1, ++ uint8_t *out2, ++ uint8_t *out3, ++ size_t outlen, ++ const uint8_t *in0, ++ const uint8_t *in1, ++ const uint8_t *in2, ++ const uint8_t *in3, ++ size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4_inc_init. ++ */ ++ void (*SHA3_shake128_x4_inc_init)(OQS_SHA3_shake128_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4_inc_absorb. ++ */ ++ void (*SHA3_shake128_x4_inc_absorb)( ++ OQS_SHA3_shake128_x4_inc_ctx *state, ++ const uint8_t *in0, ++ const uint8_t *in1, ++ const uint8_t *in2, ++ const uint8_t *in3, ++ size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4_inc_finalize. ++ */ ++ void (*SHA3_shake128_x4_inc_finalize)(OQS_SHA3_shake128_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4_inc_squeeze. ++ */ ++ void (*SHA3_shake128_x4_inc_squeeze)( ++ uint8_t *out0, ++ uint8_t *out1, ++ uint8_t *out2, ++ uint8_t *out3, ++ size_t outlen, ++ OQS_SHA3_shake128_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4_inc_ctx_release. ++ */ ++ void (*SHA3_shake128_x4_inc_ctx_release)(OQS_SHA3_shake128_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4_inc_ctx_clone. ++ */ ++ void (*SHA3_shake128_x4_inc_ctx_clone)( ++ OQS_SHA3_shake128_x4_inc_ctx *dest, ++ const OQS_SHA3_shake128_x4_inc_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake128_x4_inc_ctx_reset. ++ */ ++ void (*SHA3_shake128_x4_inc_ctx_reset)(OQS_SHA3_shake128_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4. ++ */ ++ void (*SHA3_shake256_x4)( ++ uint8_t *out0, ++ uint8_t *out1, ++ uint8_t *out2, ++ uint8_t *out3, ++ size_t outlen, ++ const uint8_t *in0, ++ const uint8_t *in1, ++ const uint8_t *in2, ++ const uint8_t *in3, ++ size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4_inc_init. ++ */ ++ void (*SHA3_shake256_x4_inc_init)(OQS_SHA3_shake256_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4_inc_absorb. ++ */ ++ void (*SHA3_shake256_x4_inc_absorb)( ++ OQS_SHA3_shake256_x4_inc_ctx *state, ++ const uint8_t *in0, ++ const uint8_t *in1, ++ const uint8_t *in2, ++ const uint8_t *in3, ++ size_t inlen); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4_inc_finalize. ++ */ ++ void (*SHA3_shake256_x4_inc_finalize)(OQS_SHA3_shake256_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4_inc_squeeze. ++ */ ++ void (*SHA3_shake256_x4_inc_squeeze)( ++ uint8_t *out0, ++ uint8_t *out1, ++ uint8_t *out2, ++ uint8_t *out3, ++ size_t outlen, ++ OQS_SHA3_shake256_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4_inc_ctx_release. ++ */ ++ void (*SHA3_shake256_x4_inc_ctx_release)(OQS_SHA3_shake256_x4_inc_ctx *state); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4_inc_ctx_clone. ++ */ ++ void (*SHA3_shake256_x4_inc_ctx_clone)( ++ OQS_SHA3_shake256_x4_inc_ctx *dest, ++ const OQS_SHA3_shake256_x4_inc_ctx *src); ++ ++ /** ++ * Implementation of function OQS_SHA3_shake256_x4_inc_ctx_reset. ++ */ ++ void (*SHA3_shake256_x4_inc_ctx_reset)(OQS_SHA3_shake256_x4_inc_ctx *state); ++}; ++ ++/** ++ * Set callback functions for 4-parallel SHA3 operations. ++ * ++ * This function may be called before OQS_init to switch the ++ * cryptographic provider for 4-parallel SHA3 operations. If it is not ++ * called, the default provider determined at build time will be used. ++ * ++ * @param new_callbacks Callback functions defined in OQS_SHA3_x4_callbacks struct ++ */ ++OQS_API void OQS_SHA3_x4_set_callbacks(struct OQS_SHA3_x4_callbacks *new_callbacks); + + #if defined(__cplusplus) + } // extern "C" +diff --git a/src/common/sha3/xkcp_sha3.c b/src/common/sha3/xkcp_sha3.c +index e9192862..2fce9d9f 100644 +--- a/src/common/sha3/xkcp_sha3.c ++++ b/src/common/sha3/xkcp_sha3.c +@@ -190,7 +190,7 @@ static void keccak_inc_squeeze(uint8_t *h, size_t outlen, + + /* SHA3-256 */ + +-void OQS_SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inlen) { ++static void SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inlen) { + OQS_SHA3_sha3_256_inc_ctx s; + OQS_SHA3_sha3_256_inc_init(&s); + OQS_SHA3_sha3_256_inc_absorb(&s, input, inlen); +@@ -198,7 +198,7 @@ void OQS_SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inlen) { + OQS_SHA3_sha3_256_inc_ctx_release(&s); + } + +-void OQS_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { ++static void SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { + state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); + if (state->ctx == NULL) { + exit(111); +@@ -206,30 +206,30 @@ void OQS_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + +-void OQS_SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inlen) { ++static void SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHA3_256_RATE, input, inlen); + } + +-void OQS_SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state) { ++static void SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state) { + keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHA3_256_RATE, 0x06); + keccak_inc_squeeze(output, 32, (uint64_t *)state->ctx, OQS_SHA3_SHA3_256_RATE); + } + +-void OQS_SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state) { ++static void SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state) { + OQS_MEM_aligned_free(state->ctx); + } + +-void OQS_SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src) { ++static void SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src) { + memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES); + } + +-void OQS_SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state) { ++static void SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + + /* SHA3-384 */ + +-void OQS_SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inlen) { ++static void SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inlen) { + OQS_SHA3_sha3_384_inc_ctx s; + OQS_SHA3_sha3_384_inc_init(&s); + OQS_SHA3_sha3_384_inc_absorb(&s, input, inlen); +@@ -237,7 +237,7 @@ void OQS_SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inlen) { + OQS_SHA3_sha3_384_inc_ctx_release(&s); + } + +-void OQS_SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) { ++static void SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) { + state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); + if (state->ctx == NULL) { + exit(111); +@@ -245,30 +245,30 @@ void OQS_SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + +-void OQS_SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inlen) { ++static void SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHA3_384_RATE, input, inlen); + } + +-void OQS_SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state) { ++static void SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state) { + keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHA3_384_RATE, 0x06); + keccak_inc_squeeze(output, 48, (uint64_t *)state->ctx, OQS_SHA3_SHA3_384_RATE); + } + +-void OQS_SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state) { ++static void SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state) { + OQS_MEM_aligned_free(state->ctx); + } + +-void OQS_SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src) { ++static void SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src) { + memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES); + } + +-void OQS_SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state) { ++static void SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + + /* SHA3-512 */ + +-void OQS_SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inlen) { ++static void SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inlen) { + OQS_SHA3_sha3_512_inc_ctx s; + OQS_SHA3_sha3_512_inc_init(&s); + OQS_SHA3_sha3_512_inc_absorb(&s, input, inlen); +@@ -276,7 +276,7 @@ void OQS_SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inlen) { + OQS_SHA3_sha3_512_inc_ctx_release(&s); + } + +-void OQS_SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) { ++static void SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) { + state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); + if (state->ctx == NULL) { + exit(111); +@@ -284,30 +284,30 @@ void OQS_SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + +-void OQS_SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inlen) { ++static void SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHA3_512_RATE, input, inlen); + } + +-void OQS_SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state) { ++static void SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state) { + keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHA3_512_RATE, 0x06); + keccak_inc_squeeze(output, 64, (uint64_t *)state->ctx, OQS_SHA3_SHA3_512_RATE); + } + +-void OQS_SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state) { ++static void SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state) { + OQS_MEM_aligned_free(state->ctx); + } + +-void OQS_SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src) { ++static void SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src) { + memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES); + } + +-void OQS_SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state) { ++static void SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + + /* SHAKE128 */ + +-void OQS_SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) { ++static void SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) { + OQS_SHA3_shake128_inc_ctx s; + OQS_SHA3_shake128_inc_init(&s); + OQS_SHA3_shake128_inc_absorb(&s, input, inlen); +@@ -318,7 +318,7 @@ void OQS_SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, siz + + /* SHAKE128 incremental */ + +-void OQS_SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) { + state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); + if (state->ctx == NULL) { + exit(111); +@@ -326,33 +326,33 @@ void OQS_SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + +-void OQS_SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inlen) { ++static void SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE, input, inlen); + } + +-void OQS_SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state) { + keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE, 0x1F); + } + +-void OQS_SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state) { + keccak_inc_squeeze(output, outlen, (uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE); + } + +-void OQS_SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src) { ++static void SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src) { + memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES); + } + +-void OQS_SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state) { + OQS_MEM_aligned_free(state->ctx); + } + +-void OQS_SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state) { ++static void SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + + /* SHAKE256 */ + +-void OQS_SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) { ++static void SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) { + OQS_SHA3_shake256_inc_ctx s; + OQS_SHA3_shake256_inc_init(&s); + OQS_SHA3_shake256_inc_absorb(&s, input, inlen); +@@ -363,7 +363,7 @@ void OQS_SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, siz + + /* SHAKE256 incremental */ + +-void OQS_SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) { + state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); + if (state->ctx == NULL) { + exit(111); +@@ -371,26 +371,68 @@ void OQS_SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } + +-void OQS_SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inlen) { ++static void SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHAKE256_RATE, input, inlen); + } + +-void OQS_SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state) { + keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHAKE256_RATE, 0x1F); + } + +-void OQS_SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state) { + keccak_inc_squeeze(output, outlen, state->ctx, OQS_SHA3_SHAKE256_RATE); + } + +-void OQS_SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state) { + OQS_MEM_aligned_free(state->ctx); + } + +-void OQS_SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src) { ++static void SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src) { + memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES); + } + +-void OQS_SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state) { ++static void SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state) { + keccak_inc_reset((uint64_t *)state->ctx); + } ++ ++extern struct OQS_SHA3_callbacks sha3_default_callbacks; ++ ++struct OQS_SHA3_callbacks sha3_default_callbacks = { ++ SHA3_sha3_256, ++ SHA3_sha3_256_inc_init, ++ SHA3_sha3_256_inc_absorb, ++ SHA3_sha3_256_inc_finalize, ++ SHA3_sha3_256_inc_ctx_release, ++ SHA3_sha3_256_inc_ctx_reset, ++ SHA3_sha3_256_inc_ctx_clone, ++ SHA3_sha3_384, ++ SHA3_sha3_384_inc_init, ++ SHA3_sha3_384_inc_absorb, ++ SHA3_sha3_384_inc_finalize, ++ SHA3_sha3_384_inc_ctx_release, ++ SHA3_sha3_384_inc_ctx_reset, ++ SHA3_sha3_384_inc_ctx_clone, ++ SHA3_sha3_512, ++ SHA3_sha3_512_inc_init, ++ SHA3_sha3_512_inc_absorb, ++ SHA3_sha3_512_inc_finalize, ++ SHA3_sha3_512_inc_ctx_release, ++ SHA3_sha3_512_inc_ctx_reset, ++ SHA3_sha3_512_inc_ctx_clone, ++ SHA3_shake128, ++ SHA3_shake128_inc_init, ++ SHA3_shake128_inc_absorb, ++ SHA3_shake128_inc_finalize, ++ SHA3_shake128_inc_squeeze, ++ SHA3_shake128_inc_ctx_release, ++ SHA3_shake128_inc_ctx_clone, ++ SHA3_shake128_inc_ctx_reset, ++ SHA3_shake256, ++ SHA3_shake256_inc_init, ++ SHA3_shake256_inc_absorb, ++ SHA3_shake256_inc_finalize, ++ SHA3_shake256_inc_squeeze, ++ SHA3_shake256_inc_ctx_release, ++ SHA3_shake256_inc_ctx_clone, ++ SHA3_shake256_inc_ctx_reset, ++}; +diff --git a/src/common/sha3/xkcp_sha3x4.c b/src/common/sha3/xkcp_sha3x4.c +index fbd9a0e8..8ed5da87 100644 +--- a/src/common/sha3/xkcp_sha3x4.c ++++ b/src/common/sha3/xkcp_sha3x4.c +@@ -155,7 +155,7 @@ static void keccak_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, u + + /********** SHAKE128 ***********/ + +-void OQS_SHA3_shake128_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++static void SHA3_shake128_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { + OQS_SHA3_shake128_x4_inc_ctx s; + OQS_SHA3_shake128_x4_inc_init(&s); + OQS_SHA3_shake128_x4_inc_absorb(&s, in0, in1, in2, in3, inlen); +@@ -166,7 +166,7 @@ void OQS_SHA3_shake128_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t * + + /* SHAKE128 incremental */ + +-void OQS_SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { + state->ctx = OQS_MEM_aligned_alloc(KECCAK_X4_CTX_ALIGNMENT, KECCAK_X4_CTX_BYTES); + if (state->ctx == NULL) { + exit(111); +@@ -174,33 +174,33 @@ void OQS_SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { + keccak_x4_inc_reset((uint64_t *)state->ctx); + } + +-void OQS_SHA3_shake128_x4_inc_absorb(OQS_SHA3_shake128_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++static void SHA3_shake128_x4_inc_absorb(OQS_SHA3_shake128_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { + keccak_x4_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE, in0, in1, in2, in3, inlen); + } + +-void OQS_SHA3_shake128_x4_inc_finalize(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_finalize(OQS_SHA3_shake128_x4_inc_ctx *state) { + keccak_x4_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE, 0x1F); + } + +-void OQS_SHA3_shake128_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake128_x4_inc_ctx *state) { + keccak_x4_inc_squeeze(out0, out1, out2, out3, outlen, (uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE); + } + +-void OQS_SHA3_shake128_x4_inc_ctx_clone(OQS_SHA3_shake128_x4_inc_ctx *dest, const OQS_SHA3_shake128_x4_inc_ctx *src) { ++static void SHA3_shake128_x4_inc_ctx_clone(OQS_SHA3_shake128_x4_inc_ctx *dest, const OQS_SHA3_shake128_x4_inc_ctx *src) { + memcpy(dest->ctx, src->ctx, KECCAK_X4_CTX_BYTES); + } + +-void OQS_SHA3_shake128_x4_inc_ctx_release(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_ctx_release(OQS_SHA3_shake128_x4_inc_ctx *state) { + OQS_MEM_aligned_free(state->ctx); + } + +-void OQS_SHA3_shake128_x4_inc_ctx_reset(OQS_SHA3_shake128_x4_inc_ctx *state) { ++static void SHA3_shake128_x4_inc_ctx_reset(OQS_SHA3_shake128_x4_inc_ctx *state) { + keccak_x4_inc_reset((uint64_t *)state->ctx); + } + + /********** SHAKE256 ***********/ + +-void OQS_SHA3_shake256_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++static void SHA3_shake256_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { + OQS_SHA3_shake256_x4_inc_ctx s; + OQS_SHA3_shake256_x4_inc_init(&s); + OQS_SHA3_shake256_x4_inc_absorb(&s, in0, in1, in2, in3, inlen); +@@ -211,7 +211,7 @@ void OQS_SHA3_shake256_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t * + + /* SHAKE256 incremental */ + +-void OQS_SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state) { + state->ctx = OQS_MEM_aligned_alloc(KECCAK_X4_CTX_ALIGNMENT, KECCAK_X4_CTX_BYTES); + if (state->ctx == NULL) { + exit(111); +@@ -219,26 +219,47 @@ void OQS_SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state) { + keccak_x4_inc_reset((uint64_t *)state->ctx); + } + +-void OQS_SHA3_shake256_x4_inc_absorb(OQS_SHA3_shake256_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { ++static void SHA3_shake256_x4_inc_absorb(OQS_SHA3_shake256_x4_inc_ctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen) { + keccak_x4_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHAKE256_RATE, in0, in1, in2, in3, inlen); + } + +-void OQS_SHA3_shake256_x4_inc_finalize(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_finalize(OQS_SHA3_shake256_x4_inc_ctx *state) { + keccak_x4_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHAKE256_RATE, 0x1F); + } + +-void OQS_SHA3_shake256_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_t *out3, size_t outlen, OQS_SHA3_shake256_x4_inc_ctx *state) { + keccak_x4_inc_squeeze(out0, out1, out2, out3, outlen, (uint64_t *)state->ctx, OQS_SHA3_SHAKE256_RATE); + } + +-void OQS_SHA3_shake256_x4_inc_ctx_clone(OQS_SHA3_shake256_x4_inc_ctx *dest, const OQS_SHA3_shake256_x4_inc_ctx *src) { ++static void SHA3_shake256_x4_inc_ctx_clone(OQS_SHA3_shake256_x4_inc_ctx *dest, const OQS_SHA3_shake256_x4_inc_ctx *src) { + memcpy(dest->ctx, src->ctx, KECCAK_X4_CTX_BYTES); + } + +-void OQS_SHA3_shake256_x4_inc_ctx_release(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_ctx_release(OQS_SHA3_shake256_x4_inc_ctx *state) { + OQS_MEM_aligned_free(state->ctx); + } + +-void OQS_SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state) { ++static void SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state) { + keccak_x4_inc_reset((uint64_t *)state->ctx); + } ++ ++extern struct OQS_SHA3_x4_callbacks sha3_x4_default_callbacks; ++ ++struct OQS_SHA3_x4_callbacks sha3_x4_default_callbacks = { ++ SHA3_shake128_x4, ++ SHA3_shake128_x4_inc_init, ++ SHA3_shake128_x4_inc_absorb, ++ SHA3_shake128_x4_inc_finalize, ++ SHA3_shake128_x4_inc_squeeze, ++ SHA3_shake128_x4_inc_ctx_release, ++ SHA3_shake128_x4_inc_ctx_clone, ++ SHA3_shake128_x4_inc_ctx_reset, ++ SHA3_shake256_x4, ++ SHA3_shake256_x4_inc_init, ++ SHA3_shake256_x4_inc_absorb, ++ SHA3_shake256_x4_inc_finalize, ++ SHA3_shake256_x4_inc_squeeze, ++ SHA3_shake256_x4_inc_ctx_release, ++ SHA3_shake256_x4_inc_ctx_clone, ++ SHA3_shake256_x4_inc_ctx_reset, ++}; +diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake +index 165d5473..f3b2e7c4 100644 +--- a/src/oqsconfig.h.cmake ++++ b/src/oqsconfig.h.cmake +@@ -22,6 +22,8 @@ + #cmakedefine OQS_USE_AES_OPENSSL 1 + #cmakedefine OQS_USE_SHA2_OPENSSL 1 + #cmakedefine OQS_USE_SHA3_OPENSSL 1 ++#cmakedefine OQS_DLOPEN_OPENSSL 1 ++#cmakedefine OQS_OPENSSL_CRYPTO_SONAME "@OQS_OPENSSL_CRYPTO_SONAME@" + + #cmakedefine OQS_EMBEDDED_BUILD 1 + +diff --git a/tests/test_aes.c b/tests/test_aes.c +index f1fab56a..4ba265c6 100644 +--- a/tests/test_aes.c ++++ b/tests/test_aes.c +@@ -116,9 +116,21 @@ static void speed_aes256(void) { + OQS_AES256_free_schedule(schedule_dec); + } + ++extern struct OQS_AES_callbacks aes_default_callbacks; ++ ++static bool aes_callback_called = false; ++static void override_AES128_ECB_load_schedule(const uint8_t *key, void **_schedule) { ++ aes_callback_called = true; ++ aes_default_callbacks.AES128_ECB_load_schedule(key, _schedule); ++} ++ + int main(int argc, char **argv) { + bool bench = false; + ++ struct OQS_AES_callbacks callbacks = aes_default_callbacks; ++ callbacks.AES128_ECB_load_schedule = override_AES128_ECB_load_schedule; ++ OQS_AES_set_callbacks(&callbacks); ++ + OQS_init(); + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { +@@ -156,6 +168,13 @@ int main(int argc, char **argv) { + OQS_destroy(); + return EXIT_FAILURE; + } ++ ++ if (!aes_callback_called) { ++ printf("AES callback was not called\n"); ++ OQS_destroy(); ++ return EXIT_FAILURE; ++ } ++ + printf("Tests passed.\n\n"); + + if (bench) { +diff --git a/tests/test_hash.c b/tests/test_hash.c +index d83f08eb..022fb61a 100644 +--- a/tests/test_hash.c ++++ b/tests/test_hash.c +@@ -14,6 +14,8 @@ + + #define BUFFER_SIZE 30000 + ++static bool sha2_callback_called = false; ++ + static int read_stdin(uint8_t **msg, size_t *msg_len) { + *msg = malloc(BUFFER_SIZE); + if (*msg == NULL) { +@@ -198,7 +200,20 @@ static int do_arbitrary_hash(void (*hash)(uint8_t *, const uint8_t *, size_t), s + return 0; + } + ++extern struct OQS_SHA2_callbacks sha2_default_callbacks; ++ ++static void override_SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { ++ sha2_callback_called = true; ++ sha2_default_callbacks.SHA2_sha256_inc_init(state); ++} ++ + int main(int argc, char **argv) { ++ int ret; ++ struct OQS_SHA2_callbacks sha2_callbacks = sha2_default_callbacks; ++ ++ sha2_callbacks.SHA2_sha256_inc_init = override_SHA2_sha256_inc_init; ++ OQS_SHA2_set_callbacks(&sha2_callbacks); ++ + OQS_init(); + if (argc != 2) { + fprintf(stderr, "Usage: test_hash algname\n"); +@@ -213,26 +228,33 @@ int main(int argc, char **argv) { + char *hash_alg = argv[1]; + + if (strcmp(hash_alg, "sha256inc") == 0) { +- return do_sha256(); ++ ret = do_sha256(); + } else if (strcmp(hash_alg, "sha384inc") == 0) { +- return do_sha384(); ++ ret = do_sha384(); + } else if (strcmp(hash_alg, "sha512inc") == 0) { +- return do_sha512(); ++ ret = do_sha512(); + } else if (strcmp(hash_alg, "sha256") == 0) { +- return do_arbitrary_hash(&OQS_SHA2_sha256, 32); ++ ret = do_arbitrary_hash(&OQS_SHA2_sha256, 32); + } else if (strcmp(hash_alg, "sha384") == 0) { +- return do_arbitrary_hash(&OQS_SHA2_sha384, 48); ++ ret = do_arbitrary_hash(&OQS_SHA2_sha384, 48); + } else if (strcmp(hash_alg, "sha512") == 0) { +- return do_arbitrary_hash(&OQS_SHA2_sha512, 64); ++ ret = do_arbitrary_hash(&OQS_SHA2_sha512, 64); + } else if (strcmp(hash_alg, "sha3_256") == 0) { +- return do_arbitrary_hash(&OQS_SHA3_sha3_256, 32); ++ ret = do_arbitrary_hash(&OQS_SHA3_sha3_256, 32); + } else if (strcmp(hash_alg, "sha3_384") == 0) { +- return do_arbitrary_hash(&OQS_SHA3_sha3_384, 48); ++ ret = do_arbitrary_hash(&OQS_SHA3_sha3_384, 48); + } else if (strcmp(hash_alg, "sha3_512") == 0) { +- return do_arbitrary_hash(&OQS_SHA3_sha3_512, 64); ++ ret = do_arbitrary_hash(&OQS_SHA3_sha3_512, 64); + } else { + fprintf(stderr, "ERROR: Test not implemented\n"); +- OQS_destroy(); +- return EXIT_FAILURE; ++ ret = EXIT_FAILURE; + } ++ ++ if (strcmp(hash_alg, "sha256inc") == 0 && !sha2_callback_called) { ++ fprintf(stderr, "ERROR: SHA2 callback was not called\n"); ++ ret = EXIT_FAILURE; ++ } ++ ++ OQS_destroy(); ++ return ret; + } +diff --git a/tests/test_sha3.c b/tests/test_sha3.c +index 43e1296c..eadd9a09 100644 +--- a/tests/test_sha3.c ++++ b/tests/test_sha3.c +@@ -17,6 +17,9 @@ + #define UNUSED + #endif + ++static bool sha3_callback_called = false; ++static bool sha3_x4_callback_called = false; ++ + /** + * \file sha3_test.h + * \brief SHA3 Known Answer Tests \n +@@ -1037,12 +1040,36 @@ int shake_256_x4_kat_test(void) { + return status; + } + ++extern struct OQS_SHA3_callbacks sha3_default_callbacks; ++ ++static void override_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { ++ sha3_callback_called = true; ++ sha3_default_callbacks.SHA3_sha3_256_inc_init(state); ++} ++ ++extern struct OQS_SHA3_x4_callbacks sha3_x4_default_callbacks; ++ ++static void override_SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { ++ sha3_x4_callback_called = true; ++ sha3_x4_default_callbacks.SHA3_shake128_x4_inc_init(state); ++} ++ + /** + * \brief Run the SHA3 and SHAKE KAT tests + */ + int main(UNUSED int argc, UNUSED char **argv) { + int ret = EXIT_SUCCESS; + ++ struct OQS_SHA3_callbacks sha3_callbacks = sha3_default_callbacks; ++ ++ sha3_callbacks.SHA3_sha3_256_inc_init = override_SHA3_sha3_256_inc_init; ++ OQS_SHA3_set_callbacks(&sha3_callbacks); ++ ++ struct OQS_SHA3_x4_callbacks sha3_x4_callbacks = sha3_x4_default_callbacks; ++ ++ sha3_x4_callbacks.SHA3_shake128_x4_inc_init = override_SHA3_shake128_x4_inc_init; ++ OQS_SHA3_x4_set_callbacks(&sha3_x4_callbacks); ++ + OQS_init(); + print_system_info(); + +@@ -1087,6 +1114,17 @@ int main(UNUSED int argc, UNUSED char **argv) { + printf("Failure! failed four-way parallel shake-256 known answer tests \n"); + ret = EXIT_FAILURE; + } ++ ++ if (!sha3_callback_called) { ++ printf("Failure! SHA3 callback was not called\n"); ++ ret = EXIT_FAILURE; ++ } ++ ++ if (!sha3_x4_callback_called) { ++ printf("Failure! SHA3_x4 callback was not called\n"); ++ ret = EXIT_FAILURE; ++ } ++ + OQS_destroy(); + + +-- +2.44.0 + diff --git a/liboqs.spec b/liboqs.spec index 6040bbc..2c31014 100644 --- a/liboqs.spec +++ b/liboqs.spec @@ -11,6 +11,7 @@ Summary: liboqs is an open source C library for quantum-safe cryptographic al License: MIT AND Apache 2.0 AND BSD 3-Clause AND (BSD-3-Clause OR GPL-1.0-or-later) AND CC0-1.0 AND Unlicense URL: https://github.com/open-quantum-safe/liboqs.git Source: https://github.com/open-quantum-safe/liboqs/archive/refs/tags/%{oqs_version}.tar.gz +Patch1: liboqs-0.10.0-dlopen-openssl.patch BuildRequires: ninja-build BuildRequires: cmake @@ -60,7 +61,7 @@ sed -e '/COMMAND.*pytest/s|$| --ignore tests/test_code_conventions.py|' \ -i tests/CMakeLists.txt %build -%cmake -GNinja -DBUILD_SHARED_LIBS=ON -DOQS_USE_AES_OPENSSL=ON -DOQS_USE_AES_INSTRUCTIONS=OFF -DOQS_DIST_BUILD=ON -DOQS_ALGS_ENABLED=STD -DOQS_USE_SHA3_OPENSSL=ON -DCMAKE_BUILD_TYPE=Debug -LAH .. +%cmake -GNinja -DBUILD_SHARED_LIBS=ON -DOQS_USE_AES_OPENSSL=ON -DOQS_USE_AES_INSTRUCTIONS=OFF -DOQS_DIST_BUILD=ON -DOQS_ALGS_ENABLED=STD -DOQS_USE_SHA3_OPENSSL=ON -DOQS_DLOPEN_OPENSSL=ON -DCMAKE_BUILD_TYPE=Debug -LAH .. %cmake_build #ninja gen_docs @@ -100,6 +101,8 @@ done * Mon Jul 08 2024 Dmitry Belyavskiy - 0.10.1-1 - Rebase to 0.10.1 version (CVE-2024-36405) Resolves: RHEL-40699 +- Use dlopen for OpenSSL algos implementation + Resolves: RHEL-46598 * Mon Jun 24 2024 Troy Dawson - 0.9.2-2 - Bump release for June 2024 mass rebuild