diff --git a/CMakeLists.txt b/CMakeLists.txt index 11d97729..08b85cd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,17 +7,28 @@ include(CheckFunctionExists) include(CheckCSourceRuns) include(CheckCSourceCompiles) +if(NOT DEFINED OPENSSL_ROOT_DIR) + message(FATAL_ERROR "OPENSSL_ROOT_DIR is required") +endif() + find_package(OpenSSL 3.4 REQUIRED) +get_filename_component(GOST_OPENSSL_ROOT "${OPENSSL_ROOT_DIR}" REALPATH) +get_filename_component(GOST_OPENSSL_INCLUDE "${OPENSSL_INCLUDE_DIR}" REALPATH) +get_filename_component(GOST_OPENSSL_CRYPTO "${OPENSSL_CRYPTO_LIBRARY}" REALPATH) +get_filename_component(GOST_OPENSSL_SSL "${OPENSSL_SSL_LIBRARY}" REALPATH) +foreach(path IN ITEMS GOST_OPENSSL_INCLUDE GOST_OPENSSL_CRYPTO GOST_OPENSSL_SSL) + string(FIND "${${path}}/" "${GOST_OPENSSL_ROOT}/" pos) + if(NOT pos EQUAL 0) + message(FATAL_ERROR "OpenSSL path escapes OPENSSL_ROOT_DIR: ${${path}}") + endif() +endforeach() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build." FORCE) endif() -if (NOT DEFINED OPENSSL_ROOT_DIR) - get_filename_component(OPENSSL_ROOT_DIR ${OPENSSL_INCLUDE_DIR} DIRECTORY) - message(STATUS "Setting OpenSSL root: ${OPENSSL_ROOT_DIR}") -endif() find_program(OPENSSL_PROGRAM openssl PATHS ${OPENSSL_ROOT_DIR} PATH_SUFFIXES apps bin NO_DEFAULT_PATH) message(STATUS "Found OpenSSL application: ${OPENSSL_PROGRAM}") @@ -27,16 +38,17 @@ set(OPENSSL_MODULES_DIR ${CMAKE_INSTALL_LIBDIR}/ossl-modules) include("cmake/utils.cmake") check_have_engine_api(HAVE_ENGINE_API) -option(GOST_BUILD_ENGINE "Build gost engine module" ${HAVE_ENGINE_API}) -option(GOST_BUILD_PROVIDER "Build gost provider module" ON) +option(GOST_BUILD_ENGINE "Build gost engine module" ${HAVE_ENGINE_API}) +option(GOST_BUILD_STATIC_ENGINE "Build gost engine static library" OFF) +option(GOST_BUILD_PROVIDER "Build gost provider module" ON) -if(GOST_BUILD_ENGINE AND NOT HAVE_ENGINE_API) +if((GOST_BUILD_ENGINE OR GOST_BUILD_STATIC_ENGINE) AND NOT HAVE_ENGINE_API) message(FATAL_ERROR - "GOST_BUILD_ENGINE=ON, but libcrypto has no ENGINE API. " - "Rebuild OpenSSL without no-engine, or pass -DGOST_BUILD_ENGINE=OFF.") + "GOST engine requested, but libcrypto has no ENGINE API. " + "Rebuild OpenSSL without no-engine, or disable GOST engine builds.") endif() -if(NOT GOST_BUILD_ENGINE) +if(NOT GOST_BUILD_ENGINE AND NOT GOST_BUILD_STATIC_ENGINE) # We may depend on ENGINE API only if there is an engine target add_compile_definitions(OPENSSL_NO_ENGINE) set(HAVE_ENGINE_API FALSE) @@ -130,12 +142,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}) # Remove when https://gitlab.kitware.com/cmake/cmake/issues/18525 is addressed set(OPENSSL_ENGINES_DIR "" CACHE PATH "OpenSSL Engines Directory") -if ("${OPENSSL_ENGINES_DIR}" STREQUAL "") - include(FindPkgConfig) - pkg_get_variable(OPENSSL_ENGINES_DIR libcrypto enginesdir) - if ("${OPENSSL_ENGINES_DIR}" STREQUAL "") - message( FATAL_ERROR "Unable to discover the OpenSSL engines directory. Provide the path using -DOPENSSL_ENGINES_DIR" ) - endif() +if("${OPENSSL_ENGINES_DIR}" STREQUAL "") + message(FATAL_ERROR "OPENSSL_ENGINES_DIR is required") endif() set(GOST_89_SOURCE_FILES @@ -274,7 +282,7 @@ add_custom_target(tags WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -if(GOST_BUILD_ENGINE) +if(GOST_BUILD_ENGINE OR GOST_BUILD_STATIC_ENGINE) include(engine) endif() if(GOST_BUILD_PROVIDER) diff --git a/cmake/engine.cmake b/cmake/engine.cmake index f28d05d3..6e2a7e3e 100644 --- a/cmake/engine.cmake +++ b/cmake/engine.cmake @@ -9,38 +9,62 @@ set(GOST_ENGINE_SOURCE_FILES gost_eng_pmeth.c ) -# The GOST engine in module form -add_library(gost_engine MODULE ${GOST_ENGINE_SOURCE_FILES}) -# Set the suffix explicitly to adapt to OpenSSL's idea of what a -# module suffix should be -set_target_properties(gost_engine PROPERTIES -PREFIX "" OUTPUT_NAME "gost" SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) -target_link_libraries(gost_engine PRIVATE gost_core gost_err) - -if (NOT MSVC) - # The GOST engine in library form - add_library(lib_gost_engine SHARED ${GOST_ENGINE_SOURCE_FILES}) - set_target_properties(lib_gost_engine PROPERTIES - COMPILE_DEFINITIONS "BUILDING_ENGINE_AS_LIBRARY" - PUBLIC_HEADER gost-engine.h - OUTPUT_NAME "gost") - target_link_libraries(lib_gost_engine PRIVATE gost_core gost_err) +if(GOST_BUILD_ENGINE) + # The GOST engine in module form + add_library(gost_engine MODULE ${GOST_ENGINE_SOURCE_FILES}) + set_target_properties(gost_engine PROPERTIES + PREFIX "" OUTPUT_NAME "gost" SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) + target_link_libraries(gost_engine PRIVATE gost_core gost_err) + + if(NOT MSVC) + # The GOST engine in shared-library form + add_library(lib_gost_engine SHARED ${GOST_ENGINE_SOURCE_FILES}) + set_target_properties(lib_gost_engine PROPERTIES + COMPILE_DEFINITIONS "BUILDING_ENGINE_AS_LIBRARY" + PUBLIC_HEADER gost-engine.h + OUTPUT_NAME "gost") + target_link_libraries(lib_gost_engine PRIVATE gost_core gost_err) + endif() + + install(TARGETS gost_engine EXPORT GostEngineConfig + LIBRARY DESTINATION ${OPENSSL_ENGINES_DIR} + RUNTIME DESTINATION ${OPENSSL_ENGINES_DIR}) + + if(NOT MSVC) + install(TARGETS lib_gost_engine EXPORT GostEngineConfig + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() endif() -install(TARGETS gost_engine EXPORT GostEngineConfig - LIBRARY DESTINATION ${OPENSSL_ENGINES_DIR} - RUNTIME DESTINATION ${OPENSSL_ENGINES_DIR}) +if(GOST_BUILD_STATIC_ENGINE) + set(GOST_ENGINE_STATIC_SOURCE_FILES + ${GOST_ENGINE_SOURCE_FILES} + ${GOST_89_SOURCE_FILES} + ${GOST_HASH_SOURCE_FILES} + ${GOST_HASH_2012_SOURCE_FILES} + ${GOST_TLS12_ADDITIONAL_SOURCE_FILES} + ${GOST_LIB_SOURCE_FILES} + ${GOST_ERR_SOURCE_FILES}) + list(REMOVE_DUPLICATES GOST_ENGINE_STATIC_SOURCE_FILES) + + add_library(gost_engine_static STATIC ${GOST_ENGINE_STATIC_SOURCE_FILES}) + set_target_properties(gost_engine_static PROPERTIES + COMPILE_DEFINITIONS "BUILDING_ENGINE_AS_LIBRARY" + OUTPUT_NAME "gost") + target_link_libraries(gost_engine_static PUBLIC OpenSSL::Crypto) -if (NOT MSVC) - install(TARGETS lib_gost_engine EXPORT GostEngineConfig - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(TARGETS gost_engine_static EXPORT GostEngineConfig + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(FILES gost-engine.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif() -if (MSVC) +if(GOST_BUILD_ENGINE OR GOST_BUILD_STATIC_ENGINE) + install(EXPORT GostEngineConfig DESTINATION share/cmake/GostEngine) +endif() + +if(MSVC AND GOST_BUILD_ENGINE) install(FILES $ $ EXPORT GostEngineConfig DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) install(FILES $ EXPORT GostEngineConfig DESTINATION ${OPENSSL_ENGINES_DIR} OPTIONAL) endif() - -install(EXPORT GostEngineConfig DESTINATION share/cmake/GostEngine) diff --git a/gost_eng.c b/gost_eng.c index 41018c75..bcc6dbc3 100644 --- a/gost_eng.c +++ b/gost_eng.c @@ -534,20 +534,25 @@ IMPLEMENT_DYNAMIC_CHECK_FN() #else /* - * When building gost-engine as a shared library, the application that uses - * it must manually call ENGINE_load_gost() for it to bind itself into the - * libcrypto libraries. + * When building gost-engine as a library, the application that uses it must + * manually call ENGINE_load_gost() for it to bind itself into libcrypto. */ -void ENGINE_load_gost(void) { - ENGINE* toadd; - int ret = 0; +void ENGINE_load_gost(void) +{ + ENGINE *e; + + e = ENGINE_new(); + if (e == NULL) { + return; + } + if (!make_gost_engine(e, engine_gost_id) || + !ENGINE_add(e) || !ENGINE_register_pkey_asn1_meths(e)) { + goto out; + } + ERR_clear_error(); - if ((toadd = ENGINE_new()) != NULL - && (ret = make_gost_engine(toadd, engine_gost_id)) > 0) - ENGINE_add(toadd); - ENGINE_free(toadd); - if (ret > 0) - ERR_clear_error(); +out: + ENGINE_free(e); } #endif #endif