Skip to content

Commit

Permalink
Allow the user to build oqs-provider as a static library. (open-quant…
Browse files Browse the repository at this point in the history
…um-safe#201)

This commit removes the `SHARED` argument of the `add_library`.
By doing so, we let the user choose the build type of library.

By default, CMake will build a static library. Thus, [`BUILD_SHARED_LIBS`]
must be used to switch to a shared library.

`oqs-provider` as a static library allows us to use the provider without
having to store its shared library somewhere. In addition, it happens that
some operating systems prohibit the use of `dlopen`/`dlsym`.

To load `oqs-provider` when it is embedded into a library of a binary, one
can use the [`OSSL_PROVIDER_add_builtin`] API from OpenSSL 3. The `cmake`
define `OQS_PROVIDER_BUILD_STATIC` is introduced to drive building this variant.

[`BUILD_SHARED_LIBS`]: https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html
[`OSSL_PROVIDER_add_builtin`]: https://www.openssl.org/docs/man3.1/man3/OSSL_PROVIDER_add_builtin.html

Signed-off-by: Felipe Ventura <[email protected]>
  • Loading branch information
thb-sb authored and feventura committed Mar 13, 2024
1 parent 907d469 commit f95923f
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 51 deletions.
104 changes: 79 additions & 25 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ jobs:
OPENSSL_PREINSTALL:
description: "OpenSSL version preinstalled."
type: string
OQS_PROVIDER_BUILD_STATIC:
description: "Build oqsprovider as a static library"
type: boolean
default: false
docker:
- image: << parameters.IMAGE >>
steps:
Expand Down Expand Up @@ -61,20 +65,30 @@ jobs:
- run:
name: Build OQS-OpenSSL provider (<< parameters.CMAKE_ARGS >> with QSC encoding support)
command: |
mkdir _build && cd _build && cmake -GNinja << parameters.CMAKE_ARGS >> -DUSE_ENCODING_LIB=ON -DCMAKE_PREFIX_PATH=$(pwd)/../.local .. && ninja && cd ..
oqsprovider_cmake_args="<< parameters.CMAKE_ARGS >>"
if << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
oqsprovider_cmake_args="${oqsprovider_cmake_args} -DOQS_PROVIDER_BUILD_STATIC=ON"
fi
mkdir _build && cd _build && cmake -GNinja ${oqsprovider_cmake_args} -DUSE_ENCODING_LIB=ON -DCMAKE_PREFIX_PATH=$(pwd)/../.local .. && ninja && cd ..
- run:
name: Run tests
command: |
./scripts/runtests.sh -V
if << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
ctest --test-dir _build/
else
./scripts/runtests.sh -V
fi
- run:
name: Run tests (with encodings, positive and negative test)
command: |
./scripts/runtests_encodings.sh -V > log
if [ grep "Skipping testing of buggy OpenSSL" -eq 1 ]; then
cat log
! OQS_ENCODING_DILITHIUM2=foo OQS_ENCODING_DILITHIUM2_ALGNAME=bar ./scripts/runtests.sh -V
else
cat log
if ! << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
./scripts/runtests_encodings.sh -V > log
if [ grep "Skipping testing of buggy OpenSSL" -eq 1 ]; then
cat log
! OQS_ENCODING_DILITHIUM2=foo OQS_ENCODING_DILITHIUM2_ALGNAME=bar ./scripts/runtests.sh -V
else
cat log
fi
fi
- run:
name: Build OQS-OpenSSL provider (<< parameters.CMAKE_ARGS >>) with NOPUBKEY_IN_PRIVKEY and QSC encoding support
Expand All @@ -83,16 +97,22 @@ jobs:
- run:
name: Run tests (-DNOPUBKEY_IN_PRIVKEY=ON)
command: |
./scripts/runtests.sh -V
if << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
ctest --test-dir _build/
else
./scripts/runtests.sh -V
fi
- run:
name: Run tests (-DNOPUBKEY_IN_PRIVKEY=ON, with encodings, positive and negative test)
command: |
./scripts/runtests_encodings.sh -V
if [ grep "Skipping testing of buggy OpenSSL" -eq 1 ]; then
cat log
! OQS_ENCODING_DILITHIUM2=foo OQS_ENCODING_DILITHIUM2_ALGNAME=bar ./scripts/runtests.sh -V
else
cat log
if ! << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
./scripts/runtests_encodings.sh -V
if [ grep "Skipping testing of buggy OpenSSL" -eq 1 ]; then
cat log
! OQS_ENCODING_DILITHIUM2=foo OQS_ENCODING_DILITHIUM2_ALGNAME=bar ./scripts/runtests.sh -V
else
cat log
fi
fi
macOS:
Expand All @@ -104,6 +124,10 @@ jobs:
OPENSSL_PREINSTALL:
description: "OpenSSL version preinstalled."
type: string
OQS_PROVIDER_BUILD_STATIC:
description: "Build oqsprovider as a static library"
type: boolean
default: false
macos:
xcode: "13.2.1"
steps:
Expand Down Expand Up @@ -134,7 +158,11 @@ jobs:
- run:
name: Build OQS-OpenSSL provider
command: |
export OPENSSL_INSTALL=$(pwd)/.local && mkdir _build && cd _build && cmake -GNinja -DOPENSSL_ROOT_DIR=$OPENSSL_INSTALL -DCMAKE_PREFIX_PATH=$(pwd)/../.local << parameters.CMAKE_ARGS >> .. && ninja && echo "export OPENSSL_INSTALL=$OPENSSL_INSTALL" >> "$BASH_ENV"
oqsprovider_cmake_args="<< parameters.CMAKE_ARGS >>"
if << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
oqsprovider_cmake_args="${oqsprovider_cmake_args} -DOQS_PROVIDER_BUILD_STATIC=ON"
fi
export OPENSSL_INSTALL=$(pwd)/.local && mkdir _build && cd _build && cmake -GNinja -DOPENSSL_ROOT_DIR=$OPENSSL_INSTALL -DCMAKE_PREFIX_PATH=$(pwd)/../.local ${oqsprovider_cmake_args} .. && ninja && echo "export OPENSSL_INSTALL=$OPENSSL_INSTALL" >> "$BASH_ENV"
- when:
condition:
equal: [ [email protected], << parameters.OPENSSL_PREINSTALL >> ]
Expand All @@ -146,24 +174,38 @@ jobs:
- run:
name: Run tests
command: |
./scripts/runtests.sh -V
if << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
ctest --test-dir _build/ --output-on-failure
else
./scripts/runtests.sh -V
fi
- run:
name: Build OQS-OpenSSL provider with QSC encoding support
command: |
rm -rf _build && mkdir _build && cd _build && cmake -GNinja -DUSE_ENCODING_LIB=ON -DOPENSSL_ROOT_DIR=$OPENSSL_INSTALL -DCMAKE_PREFIX_PATH=$(pwd)/../.local << parameters.CMAKE_ARGS >> .. && ninja
oqsprovider_cmake_args="<< parameters.CMAKE_ARGS >>"
if << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
oqsprovider_cmake_args="${oqsprovider_cmake_args} -DOQS_PROVIDER_BUILD_STATIC=ON"
fi
rm -rf _build && mkdir _build && cd _build && cmake -GNinja -DUSE_ENCODING_LIB=ON -DOPENSSL_ROOT_DIR=$OPENSSL_INSTALL -DCMAKE_PREFIX_PATH=$(pwd)/../.local ${oqsprovider_cmake_args} .. && ninja
- run:
name: Run tests
command: |
./scripts/runtests.sh -V
if << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
ctest --test-dir _build/ --output-on-failure
else
./scripts/runtests.sh -V
fi
- run:
name: Run tests (with encodings)
command: |
./scripts/runtests_encodings.sh -V > log
if [ grep "Skipping testing of buggy OpenSSL" -eq 1 ]; then
cat log
! OQS_ENCODING_DILITHIUM2=foo OQS_ENCODING_DILITHIUM2_ALGNAME=bar ./scripts/runtests.sh -V
else
cat log
if ! << parameters.OQS_PROVIDER_BUILD_STATIC >> ; then
./scripts/runtests_encodings.sh -V > log
if [ grep "Skipping testing of buggy OpenSSL" -eq 1 ]; then
cat log
! OQS_ENCODING_DILITHIUM2=foo OQS_ENCODING_DILITHIUM2_ALGNAME=bar ./scripts/runtests.sh -V
else
cat log
fi
fi
trigger-downstream-ci:
Expand Down Expand Up @@ -202,6 +244,13 @@ workflows:
IMAGE: openquantumsafe/ci-ubuntu-jammy:latest
CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_ALGS_ENABLED=STD
OPENSSL_PREINSTALL: openssl@3
- ubuntu:
name: ubuntu-jammy-static
context: openquantumsafe
IMAGE: openquantumsafe/ci-ubuntu-jammy:latest
OQS_PROVIDER_BUILD_STATIC: true
CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_ALGS_ENABLED=STD
OPENSSL_PREINSTALL: openssl@3
- macOS:
name: macOS-noopenssl
CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=OFF
Expand All @@ -210,6 +259,11 @@ workflows:
name: macOS-shared
CMAKE_ARGS: -DBUILD_SHARED_LIBS=ON -DOQS_DIST_BUILD=OFF -DOQS_ENABLE_KEM_CLASSIC_MCELIECE=OFF
OPENSSL_PREINSTALL: [email protected]
- macOS:
name: macOS-static
OQS_PROVIDER_BUILD_STATIC: true
CMAKE_ARGS: -DOQS_DIST_BUILD=OFF -DOQS_ENABLE_KEM_CLASSIC_MCELIECE=OFF
OPENSSL_PREINSTALL: [email protected]
on-main-branch:
when:
or:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
if: steps.cache-openssl32.outputs.cache-hit != 'true'
run: bash -c "./config --prefix=/opt/openssl32 ${{ matrix.platform.config }} && perl configdata.pm --dump && make $MAKE_PARAMS && make install_sw"
working-directory: openssl
- name: Check OpenSSL install3
- name: Check OpenSSL install3
run: dir c:\cygwin\opt\openssl32
- name: Save OpenSSL
id: cache-openssl-save
Expand Down
15 changes: 15 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ else()
message(STATUS "Build will not include external encoding library for SPKI/PKCS#8")
endif()

option(OQS_PROVIDER_BUILD_STATIC "Build a static library instead of a shared library" OFF)
if(OQS_PROVIDER_BUILD_STATIC AND BUILD_SHARED_LIBS)
message(FATAL_ERROR "`OQS_PROVIDER_BUILD_STATIC` is not compatible with `BUILD_SHARED_LIBS`.")
endif()

include(CheckLibraryExists)
include(CheckFunctionExists)

Expand All @@ -62,6 +67,16 @@ get_target_property(LIBOQS_INCLUDE_DIR OQS::oqs INTERFACE_INCLUDE_DIRECTORIES)
message(STATUS "liboqs found: Include dir at ${LIBOQS_INCLUDE_DIR}")
include_directories(${LIBOQS_INCLUDE_DIR})

# Hints the compiler on the fact that the provider is being compiled into a static library.
function(targets_set_static_provider)
foreach(target ${ARGN})
target_compile_definitions(${target} PRIVATE "OQS_PROVIDER_STATIC")
if(NOT target STREQUAL oqsprovider)
target_link_libraries(${target} PRIVATE oqsprovider)
endif()
endforeach()
endfunction()

# Provider module
add_subdirectory(oqsprov)

Expand Down
34 changes: 33 additions & 1 deletion CONFIGURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,38 @@ By setting this to "ON", it can be specified to omit explicitly serializing
the public key in a `privateKey` structure, e.g., for interoperability testing.
The default value is `OFF`.

### OQS_PROVIDER_BUILD_STATIC

By setting `-DOQS_PROVIDER_BUILD_STATIC=ON` at compile-time, oqs-provider can be
compiled as a static library (`oqs-provider.a`).
When built as a static library, the name of the provider entrypoint is `oqs_provider_init`.
The provider can be added using the [`OSSL_PROVIDER_add_builtin`](https://www.openssl.org/docs/man3.1/man3/OSSL_PROVIDER_add_builtin.html)
function:

```c
#include <openssl/provider.h>

// Entrypoint.
extern OSSL_provider_init_fn oqs_provider_init;

void load_oqs_provider(OSSL_LIB_CTX *libctx) {
int err;

if (OSSL_PROVIDER_add_builtin(libctx, "oqsprovider", oqs_provider_init) == 1) {
if (OSSL_PROVIDER_load(libctx, "oqsprovider") == 1) {
fputs("successfully loaded `oqsprovider`.", stderr);
} else {
fputs("failed to load `oqsprovider`", stderr);
}
} else {
fputs("failed to add the builtin provider `oqsprovider`", stderr);
}
}
```
> **Warning**
> `OQS_PROVIDER_BUILD_STATIC` and `BUILD_SHARED_LIBS` are mutually exclusive.
## Convenience build script options
For anyone interested in building the complete software stack
Expand Down Expand Up @@ -106,7 +138,7 @@ performed by default but can be manually enabled in the script `scripts/runtests
### OPENSSL_CONF
This test environment variable can be used to instruct `openssl` to use a
This test environment variable can be used to instruct `openssl` to use a
configuration file from a non-standard location. Setting this value also
disables the automation logic built into `runtests.sh`, thus requiring
knowledge of `openssl` operations when setting it.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ Contributors to the `oqsprovider` include:
- Julian Segeth
- Alex Zaslavsky
- Will Childs-Klein
- Thomas Bailleux

History
-------
Expand Down
15 changes: 12 additions & 3 deletions oqsprov/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ set(PROVIDER_SOURCE_FILES
set(PROVIDER_HEADER_FILES
oqs_prov.h oqs_endecoder_local.h
)
add_library(oqsprovider MODULE ${PROVIDER_SOURCE_FILES})

set(OQS_LIBRARY_TYPE MODULE)
if(OQS_PROVIDER_BUILD_STATIC)
set(OQS_LIBRARY_TYPE STATIC)
endif()

add_library(oqsprovider ${OQS_LIBRARY_TYPE} ${PROVIDER_SOURCE_FILES})
if (USE_ENCODING_LIB)
add_dependencies(oqsprovider encoder)
endif()
Expand Down Expand Up @@ -72,9 +78,9 @@ if (CYGWIN OR MSVC)
)
endif()

target_link_libraries(oqsprovider OQS::oqs ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
target_link_libraries(oqsprovider PUBLIC OQS::oqs ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
if (USE_ENCODING_LIB)
target_link_libraries(oqsprovider qsc_key_encoder)
target_link_libraries(oqsprovider PUBLIC qsc_key_encoder)
target_include_directories(oqsprovider PRIVATE ${encoder_LIBRARY_INCLUDE})
endif()
install(TARGETS oqsprovider
Expand All @@ -87,3 +93,6 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, openssl (>= 3.0.0), liboqs (>= 0.8.0)")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "www.openquantumsafe.org")
include(CPack)

if (OQS_PROVIDER_BUILD_STATIC)
targets_set_static_provider(oqsprovider)
endif()
8 changes: 7 additions & 1 deletion oqsprov/oqsprov.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,13 @@ static const OSSL_DISPATCH oqsprovider_dispatch_table[] = {
{ 0, NULL }
};

int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
#ifdef OQS_PROVIDER_STATIC
#define OQS_PROVIDER_ENTRYPOINT_NAME oqs_provider_init
#else
#define OQS_PROVIDER_ENTRYPOINT_NAME OSSL_provider_init
#endif // ifdef OQS_PROVIDER_STATIC

int OQS_PROVIDER_ENTRYPOINT_NAME(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out,
void **provctx)
Expand Down
19 changes: 14 additions & 5 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ set_tests_properties(oqs_signatures
endif()

add_executable(oqs_test_signatures oqs_test_signatures.c test_common.c)
target_link_libraries(oqs_test_signatures ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
target_link_libraries(oqs_test_signatures PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})

add_test(
NAME oqs_kems
Expand All @@ -41,7 +41,7 @@ set_tests_properties(oqs_kems
endif()

add_executable(oqs_test_kems oqs_test_kems.c test_common.c)
target_link_libraries(oqs_test_kems ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
target_link_libraries(oqs_test_kems PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})

add_test(
NAME oqs_groups
Expand All @@ -62,7 +62,7 @@ set_tests_properties(oqs_groups
)
endif()
add_executable(oqs_test_groups oqs_test_groups.c test_common.c tlstest_helpers.c)
target_link_libraries(oqs_test_groups ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
target_link_libraries(oqs_test_groups PRIVATE ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})

add_test(
NAME oqs_tlssig
Expand All @@ -84,10 +84,10 @@ set_tests_properties(oqs_tlssig
)
endif()
add_executable(oqs_test_tlssig oqs_test_tlssig.c test_common.c tlstest_helpers.c)
target_link_libraries(oqs_test_tlssig ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
target_link_libraries(oqs_test_tlssig PRIVATE ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})

add_executable(oqs_test_endecode oqs_test_endecode.c test_common.c)
target_link_libraries(oqs_test_endecode ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
target_link_libraries(oqs_test_endecode PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${OQS_ADDL_SOCKET_LIBS})
add_test(
NAME oqs_endecode
COMMAND oqs_test_endecode
Expand All @@ -105,3 +105,12 @@ set_tests_properties(oqs_endecode
PROPERTIES ENVIRONMENT "OPENSSL_MODULES=${OQS_PROV_BINARY_DIR}"
)
endif()

if (OQS_PROVIDER_BUILD_STATIC)
targets_set_static_provider(oqs_test_signatures
oqs_test_kems
oqs_test_groups
oqs_test_tlssig
oqs_test_endecode
)
endif()
8 changes: 4 additions & 4 deletions test/oqs_test_endecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,14 +212,14 @@ int main(int argc, char *argv[]) {
modulename = argv[1];
configfile = argv[2];

T(OSSL_LIB_CTX_load_config(libctx, configfile));
load_oqs_provider(libctx, modulename, configfile);

T(OSSL_PROVIDER_available(libctx, modulename));
keyctx = OSSL_LIB_CTX_new();
dfltprov = OSSL_PROVIDER_load(NULL, "default");

load_oqs_provider(keyctx, modulename, configfile);

dfltprov = OSSL_PROVIDER_load(keyctx, "default");
keyprov = OSSL_PROVIDER_load(keyctx, modulename);

oqsprov = OSSL_PROVIDER_load(libctx, modulename);

sigalgs = OSSL_PROVIDER_query_operation(oqsprov, OSSL_OP_SIGNATURE, &query_nocache);
Expand Down
Loading

0 comments on commit f95923f

Please sign in to comment.