Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update FindOpenSSLFeatures module. #16

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 58 additions & 13 deletions FindOpenSSLFeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
# -----------
#
# Find OpenSSL features: supported hashes, ciphers, curves and public-key algorithms.
# Requires FindOpenSSL to be included first, and C compiler to be set as module
# Requires FindOpenSSL to be included first, and C compiler to be set as module
# compiles and executes program which do checks against installed OpenSSL library.
#
# Result variables
Expand All @@ -53,57 +53,102 @@ if (NOT OPENSSL_FOUND)
message(FATAL_ERROR "OpenSSL is not found. Please make sure that you call find_package(OpenSSL) first.")
endif()

message(STATUS "Querying OpenSSL features")

# Copy and build findopensslfeatures.c in fossl-build subfolder.
set(_fossl_work_dir "${CMAKE_BINARY_DIR}/fossl-build")
set(_fossl_work_dir "${CMAKE_BINARY_DIR}/fossl")
file(MAKE_DIRECTORY "${_fossl_work_dir}")
file(COPY "${CMAKE_CURRENT_LIST_DIR}/findopensslfeatures.c"
DESTINATION "${_fossl_work_dir}"
)
# As it's short enough let's keep it here.
# Reuse OPENSSL parameters from the upstream project
# otherwise there is a good chance to find another instance of openssl
# We assume that OpenSSL root is one level up openssl include directory
# This does not look as a good solution, however it is the only one that
# works with all Windows configuration options

message(STATUS "Using OpenSSL root directory at ${OPENSSL_INCLUDE_DIR}/..")

file(WRITE "${_fossl_work_dir}/CMakeLists.txt"
"cmake_minimum_required(VERSION 3.14)\n\
"cmake_minimum_required(VERSION 3.18)\n\
project(findopensslfeatures LANGUAGES C)\n\
set(CMAKE_C_STANDARD 99)\n\
include(FindOpenSSL)\n\
find_package(OpenSSL REQUIRED)\n\
add_executable(findopensslfeatures findopensslfeatures.c)\n\
target_link_libraries(findopensslfeatures PRIVATE OpenSSL::Crypto)\n"
target_include_directories(findopensslfeatures PRIVATE ${OPENSSL_INCLUDE_DIR})\n\
target_link_libraries(findopensslfeatures PRIVATE OpenSSL::Crypto)\n\
if (OpenSSL::applink)\n\
target_link_libraries(findopensslfeatures PRIVATE OpenSSL::applink)\n\
endif(OpenSSL::applink)\n"
)

set(MKF ${MKF} "-DCMAKE_BUILD_TYPE=Release" "-DOPENSSL_ROOT_DIR=${OPENSSL_INCLUDE_DIR}/..")

if(CMAKE_PREFIX_PATH)
set(MKF ${MKF} "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}")
endif(CMAKE_PREFIX_PATH)

if(CMAKE_TOOLCHAIN_FILE)
set(MKF ${MKF} "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}")
endif(CMAKE_TOOLCHAIN_FILE)

if(CMAKE_GENERATOR_PLATFORM)
set(MKF ${MKF} "-A" "${CMAKE_GENERATOR_PLATFORM}")
endif(CMAKE_GENERATOR_PLATFORM)

if(CMAKE_GENERATOR_TOOLSET)
set(MKF ${MKF} "-T" "${CMAKE_GENERATOR_TOOLSET}")
endif(CMAKE_GENERATOR_TOOLSET)

execute_process(
COMMAND "cmake" "." "-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}"
COMMAND "${CMAKE_COMMAND}" "-Bbuild" ${MKF} "."
WORKING_DIRECTORY "${_fossl_work_dir}"
OUTPUT_VARIABLE output
ERROR_VARIABLE error
RESULT_VARIABLE result
COMMAND_ECHO STDOUT
ECHO_OUTPUT_VARIABLE
ECHO_ERROR_VARIABLE
)

if (NOT ${result} EQUAL 0)
message(FATAL_ERROR "Error configuring findopensslfeatures: ${result}\n${error}")
message(FATAL_ERROR "Error configuring findopensslfeatures")
endif()

execute_process(
COMMAND "cmake" "--build" "."
COMMAND "${CMAKE_COMMAND}" "--build" "build" --config "Release"
WORKING_DIRECTORY "${_fossl_work_dir}"
OUTPUT_VARIABLE output
ERROR_VARIABLE error
RESULT_VARIABLE result
COMMAND_ECHO STDOUT
ECHO_OUTPUT_VARIABLE
ECHO_ERROR_VARIABLE
)

if (NOT ${result} EQUAL 0)
message(FATAL_ERROR "Error building findopensslfeatures: ${result}\n${error}")
message(FATAL_ERROR "Error building findopensslfeatures")
endif()

set(OPENSSL_SUPPORTED_FEATURES "")
foreach(feature "hashes" "ciphers" "curves" "publickey")
if(WIN32 AND NOT MINGW)
set(FOF "build/Release/findopensslfeatures")
else(WIN32 AND NOT MINGW)
set(FOF "build/findopensslfeatures")
endif(WIN32 AND NOT MINGW)

foreach(feature "hashes" "ciphers" "curves" "publickey" "providers")
execute_process(
COMMAND "./findopensslfeatures" "${feature}"
COMMAND "${FOF}" "${feature}"
WORKING_DIRECTORY "${_fossl_work_dir}"
OUTPUT_VARIABLE feature_val
ERROR_VARIABLE error
RESULT_VARIABLE result
)

if(NOT ${result} EQUAL 0)
message(FATAL_ERROR "Error getting supported OpenSSL ${feature}: \n${error}")
message(FATAL_ERROR "Error getting supported OpenSSL ${feature}: ${result}\n${error}")
endif()

string(TOUPPER ${feature} feature_up)
Expand All @@ -114,7 +159,7 @@ foreach(feature "hashes" "ciphers" "curves" "publickey")
list(APPEND OPENSSL_SUPPORTED_FEATURES ${OPENSSL_SUPPORTED_${feature_up}})
endforeach()

message(STATUS "Fetched OpenSSL features: ${hashes_len} hashes, ${ciphers_len} ciphers, ${curves_len} curves, ${publickey_len} publickey.")
message(STATUS "Fetched OpenSSL features: ${hashes_len} hashes, ${ciphers_len} ciphers, ${curves_len} curves, ${publickey_len} publickey, ${providers_len} providers.")

function(OpenSSLHasFeature FEATURE VARIABLE)
string(TOUPPER ${FEATURE} _feature_up)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ FindOpenSSLFeatures.cmake
-------------------------

This module can be used to list available OpenSSL features, without dependency on openssl binary. Instead of running openssl binary it compiles small utility (see `findopensslfeatures.c`) and runs it to retrieve all needed lists.
Following features are supported: hashes, symmetric ciphers, elliptic curves and publickey engines.
Following features are supported: hashes, symmetric ciphers, elliptic curves, publickey engines and available providers (basically, to check whether legacy provider is available).

FindBotan.cmake
---------------
Expand Down
8 changes: 6 additions & 2 deletions ci/findossl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ project(test-findopenssl
LANGUAGES C
)

include(FindOpenSSL)
find_package(OpenSSL 1.1.1 REQUIRED)
include(FindOpenSSLFeatures)

Expand All @@ -15,7 +14,12 @@ foreach(feature "HASHES" "CIPHERS" "CURVES" "PUBLICKEY" "FEATURES")
endif()
endforeach()

foreach(feature "AES-128-ECB" "AES-256-ECB" "rsaEncryption" "dsaEncryption" "Ed25519" "X25519")
list(LENGTH "OPENSSL_SUPPORTED_PROVIDERS" _providers_len)
if(_providers_len LESS 1)
message(FATAL_ERROR "OPENSSL_SUPPORTED_PROVIDERS contains too few elements")
endif()

foreach(feature "AES-128-ECB" "AES-256-ECB" "rsaEncryption" "dsaEncryption" "Ed25519" "X25519" "default")
OpenSSLHasFeature("${feature}" _openssl_has_${feature})
if (NOT _openssl_has_${feature})
message(FATAL_ERROR "OpenSSL feature is missing: ${feature}")
Expand Down
29 changes: 28 additions & 1 deletion findopensslfeatures.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <openssl/ec.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
#endif

int
list_curves()
Expand Down Expand Up @@ -99,11 +102,32 @@ list_publickey()
return 0;
}

int
list_providers()
{
printf("default\n");
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
const char *known_names[] = {"legacy", "fips"};
for (size_t i = 0; i < sizeof(known_names) / sizeof(known_names[0]); i++) {
OSSL_PROVIDER *prov = OSSL_PROVIDER_load(NULL, known_names[i]);
if (prov) {
printf("%s\n", known_names[i]);
OSSL_PROVIDER_unload(prov);
}
}
#else
/* OpenSSL < 3.0 includes all legacy algorithms in the default provider */
printf("legacy\n");
#endif
return 0;
}

int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: opensslfeatures [curves|hashes|ciphers|publickey]\n");
fprintf(stderr,
"Usage: opensslfeatures [curves|hashes|ciphers|publickey|providers]\n");
return 1;
}
if (!strcmp(argv[1], "hashes")) {
Expand All @@ -118,6 +142,9 @@ main(int argc, char *argv[])
if (!strcmp(argv[1], "publickey")) {
return list_publickey();
}
if (!strcmp(argv[1], "providers")) {
return list_providers();
}
fprintf(stderr, "Unknown command: %s\n", argv[1]);
return 1;
}