diff --git a/FindOpenSSLFeatures.cmake b/FindOpenSSLFeatures.cmake index 6c56805..c3e3e33 100644 --- a/FindOpenSSLFeatures.cmake +++ b/FindOpenSSLFeatures.cmake @@ -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 @@ -53,49 +53,94 @@ 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 @@ -103,7 +148,7 @@ foreach(feature "hashes" "ciphers" "curves" "publickey") ) 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) @@ -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) diff --git a/README.md b/README.md index 0896594..09697df 100644 --- a/README.md +++ b/README.md @@ -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 --------------- diff --git a/ci/findossl/CMakeLists.txt b/ci/findossl/CMakeLists.txt index 689693d..37eca4f 100644 --- a/ci/findossl/CMakeLists.txt +++ b/ci/findossl/CMakeLists.txt @@ -4,7 +4,6 @@ project(test-findopenssl LANGUAGES C ) -include(FindOpenSSL) find_package(OpenSSL 1.1.1 REQUIRED) include(FindOpenSSLFeatures) @@ -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}") diff --git a/findopensslfeatures.c b/findopensslfeatures.c index 1f2b14e..ed7eb8e 100644 --- a/findopensslfeatures.c +++ b/findopensslfeatures.c @@ -4,6 +4,9 @@ #include #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif int list_curves() @@ -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")) { @@ -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; }