Merged PR 6884452: Support proper shared object library versioning

- Moved shared CMake logic into a single common file that can be included from individual module directories.
- Renamed some directories to hopefully make the directory structure more logical.
- Updated CMake commands to include appropriate versioning info in modules. This causes CMake to automatically build the module with a versioned shared object name (libsymcrypt.so -> libsymcrypt.so.100 -> libsymcrypt.so.100.21.0). The appropriate SONAME is also set in the module's DYNAMIC section, so that applications or modules taking a dependency on us will correctly link to libsymcrypt.so.100.
This commit is contained in:
Mitch Lindgren 🦎 2022-01-28 19:20:57 +00:00
Родитель 3623da8c2c
Коммит d7e322ef75
29 изменённых файлов: 173 добавлений и 184 удалений

Просмотреть файл

@ -5,7 +5,24 @@ if(WIN32)
set(CMAKE_SYSTEM_VERSION 10.0.18362)
endif()
project(SymCrypt)
# Parse the version number from symcrypt_internal_shared.inc
file(READ "${CMAKE_SOURCE_DIR}/inc/symcrypt_internal_shared.inc" SYMCRYPT_VERSION_FILE_CONTENTS)
string(REGEX MATCH "SYMCRYPT_CODE_VERSION_API[ \t]+([0-9]+)" _ ${SYMCRYPT_VERSION_FILE_CONTENTS})
set(SYMCRYPT_CODE_VERSION_API ${CMAKE_MATCH_1})
string(REGEX MATCH "SYMCRYPT_CODE_VERSION_MINOR[ \t]+([0-9]+)" _ ${SYMCRYPT_VERSION_FILE_CONTENTS})
set(SYMCRYPT_CODE_VERSION_MINOR ${CMAKE_MATCH_1})
string(REGEX MATCH "SYMCRYPT_CODE_VERSION_PATCH[ \t]+([0-9]+)" _ ${SYMCRYPT_VERSION_FILE_CONTENTS})
set(SYMCRYPT_CODE_VERSION_PATCH ${CMAKE_MATCH_1})
message(STATUS "SymCrypt version ${SYMCRYPT_CODE_VERSION_API}.${SYMCRYPT_CODE_VERSION_MINOR}.${SYMCRYPT_CODE_VERSION_PATCH}")
project(SymCrypt
VERSION ${SYMCRYPT_CODE_VERSION_API}.${SYMCRYPT_CODE_VERSION_MINOR}.${SYMCRYPT_CODE_VERSION_PATCH}
DESCRIPTION "Cryptographic library"
HOMEPAGE_URL "https://github.com/microsoft/SymCrypt")
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
@ -71,7 +88,6 @@ else()
add_compile_options(-g)
add_compile_options(-Wno-multichar)
add_compile_options(-fPIC)
add_compile_options(-fno-stack-protector)
add_compile_options(-fno-plt)
add_compile_options(-fno-builtin-bcmp)
@ -149,12 +165,15 @@ include_directories(inc)
include_directories(${CMAKE_BINARY_DIR}/inc)
include(build/buildInfo.cmake)
# Process pkg-config file
configure_file(build/symcrypt.pc.in symcrypt.pc @ONLY)
add_subdirectory(lib)
if(NOT WIN32 AND NOT CMAKE_BUILD_TYPE MATCHES Sanitize)
# Module integrity check is seen as OOB access by sanitizers, and sanitizer instrumentation
# breaks integrity check assumptions. Only enable module when not running with sanitizers
add_subdirectory(module)
add_subdirectory(modules_linux)
endif()
add_subdirectory(unittest)

11
build/symcrypt.pc.in Normal file
Просмотреть файл

@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
Version: @PROJECT_VERSION@
Libs: -L${libdir} -lsymcrypt
Cflags: -I${includedir}

Просмотреть файл

@ -194,8 +194,8 @@ extern "C" {
typedef _Return_type_success_( return == SYMCRYPT_NO_ERROR ) enum {
SYMCRYPT_NO_ERROR = 0,
SYMCRYPT_UNUSED = SYMCRYPT_API_VERSION << 5, // This value changes all the time!
SYMCRYPT_WRONG_KEY_SIZE,
SYMCRYPT_UNUSED = 0x8000, // Start our error codes here so they're easier to distinguish
SYMCRYPT_WRONG_KEY_SIZE,
SYMCRYPT_WRONG_BLOCK_SIZE,
SYMCRYPT_WRONG_DATA_SIZE,
SYMCRYPT_WRONG_NONCE_SIZE,
@ -513,15 +513,14 @@ VOID
SYMCRYPT_CALL
SymCryptModuleInit(
_In_ UINT32 api,
_In_ UINT32 minor,
_In_ UINT32 patch);
_In_ UINT32 minor);
#define SYMCRYPT_MODULE_INIT() SymCryptModuleInit(SYMCRYPT_CODE_VERSION_API, SYMCRYPT_CODE_VERSION_MINOR, SYMCRYPT_CODE_VERSION_PATCH);
#define SYMCRYPT_MODULE_INIT() SymCryptModuleInit( SYMCRYPT_CODE_VERSION_API, SYMCRYPT_CODE_VERSION_MINOR );
//
// Initialize the SymCrypt shared object module/dynamic-link library. This function verifies
// that the module version supports the version requested by the application. If the version
// is unsupported, a fatal error will occur. The macro SYMCRYPT_MODULE_INIT can be used
// to call SymCryptModuleInit with the correct arguments.
// is unsupported, a fatal error will occur. Rather than explicitly calling SymCryptModuleInit,
// the macro SYMCRYPT_MODULE_INIT should be used to call it with the correct arguments.
//
//==========================================================================

Просмотреть файл

@ -1,28 +0,0 @@
# For release builds, we strip the modules of symbols except for the following symbols which are
# required by the FIPS post-processing script. On some systems, symbol stripping would normally
# be done at package install time, but our modules must be stripped before being run through the
# FIPS post-processing script or the the runtime integrity verification will not work. Although
# the symbol table is not in a loadable segment and is therefore not part of our FIPS boundary,
# stripping symbols changes size and offset information stored in the ELF header, which is
# within the FIPS boundary and therefore affects the result of the integrity check.
set(KEEP_SYMBOL_ARGS
"-K" "SymCryptVolatileFipsHmacKey"
"-K" "SymCryptVolatileFipsHmacKeyRva"
"-K" "SymCryptVolatileFipsBoundaryOffset"
"-K" "SymCryptVolatileFipsHmacDigest"
)
# Determine the which executable to use for stripping binaries
if(CMAKE_SYSTEM_PROCESSOR MATCHES ARM64 AND NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES ARM64|aarch64)
set(STRIP_COMMAND ${TARGET_TRIPLE}-strip)
else()
set(STRIP_COMMAND strip)
endif()
add_subdirectory(linux_common) # Common functionality for Linux modules
add_subdirectory(generic_linux) # Generic Linux module
if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
add_subdirectory(oe_full) # OpenEnclave with all functionality
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
add_subdirectory(embedded) # Embedded Linux module
endif()

Просмотреть файл

@ -1,54 +0,0 @@
set(SOURCES
../linux_common/integrity.c
../linux_common/optional/rngfipsjitter.c
../linux_common/optional/rngsecureurandom.c)
include_directories(${CMAKE_SOURCE_DIR}/inc ../linux_common ${CMAKE_SOURCE_DIR}/jitterentropy-library)
add_library(symcrypt_embedded SHARED ${SOURCES})
# Link jitterentropy
target_link_libraries(symcrypt_embedded ${CMAKE_SOURCE_DIR}/jitterentropy-library/libjitterentropy.a pthread)
target_link_options(symcrypt_embedded PRIVATE
-Wl,--whole-archive
$<TARGET_FILE:symcrypt_module_linux_common>
$<TARGET_FILE:symcrypt_linuxusermode>
$<TARGET_FILE:symcrypt_common>
-Wl,--no-whole-archive
-Wl,-Bsymbolic
-Wl,-z,noexecstack
-Wl,-z,now
-Wl,-gc-sections
-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../linux_common/exports.ver
-nostdlib
-nodefaultlibs
-nostartfiles
)
add_dependencies(symcrypt_embedded symcrypt_linuxusermode symcrypt_common symcrypt_module_linux_common jitterentropy_lib)
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
add_compile_options(-mllvm -x86-speculative-load-hardening)
endif()
set_target_properties(symcrypt_embedded PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/embedded)
set_target_properties(symcrypt_embedded PROPERTIES LIBRARY_OUTPUT_NAME "symcrypt")
if(CMAKE_BUILD_TYPE MATCHES Release)
add_custom_command(
TARGET symcrypt_embedded
POST_BUILD
COMMAND cp $<TARGET_FILE:symcrypt_embedded> $<TARGET_FILE:symcrypt_embedded>.debug
COMMAND ${STRIP_COMMAND} --strip-unneeded ${KEEP_SYMBOL_ARGS} $<TARGET_FILE:symcrypt_embedded>
COMMENT "Stripping binary for release build"
COMMAND_EXPAND_LISTS
)
endif()
add_custom_command(
TARGET symcrypt_embedded
POST_BUILD
COMMAND python3 ${CMAKE_SOURCE_DIR}/scripts/process_fips_module.py $<TARGET_FILE:symcrypt_embedded> -d
COMMENT "Postprocessing SymCrypt shared object for FIPS integrity verification"
)

Просмотреть файл

@ -1,34 +0,0 @@
set(SOURCES
../linux_common/nointegrity.c
../linux_common/optional/rngfipsjitter.c
../linux_common/optional/rngsecureurandom.c)
include_directories(${CMAKE_SOURCE_DIR}/inc ../linux_common ${CMAKE_SOURCE_DIR}/jitterentropy-library)
add_library(symcrypt_linux SHARED ${SOURCES})
# Link jitterentropy
target_link_libraries(symcrypt_linux ${CMAKE_SOURCE_DIR}/jitterentropy-library/libjitterentropy.a pthread)
target_link_options(symcrypt_linux PRIVATE
-Wl,--whole-archive
$<TARGET_FILE:symcrypt_module_linux_common>
$<TARGET_FILE:symcrypt_linuxusermode>
$<TARGET_FILE:symcrypt_common>
-Wl,--no-whole-archive
-Wl,-Bsymbolic
-Wl,-z,noexecstack
-Wl,-z,now
-Wl,-gc-sections
-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../linux_common/exports.ver
-nostartfiles
)
add_dependencies(symcrypt_linux symcrypt_linuxusermode symcrypt_common symcrypt_module_linux_common jitterentropy_lib)
set_target_properties(symcrypt_linux PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/generic_linux)
set_target_properties(symcrypt_linux PROPERTIES LIBRARY_OUTPUT_NAME "symcrypt")
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
add_compile_options(-mllvm -x86-speculative-load-hardening)
endif()

Просмотреть файл

@ -1,51 +0,0 @@
set(SOURCES
../linux_common/integrity.c
rng.c)
include_directories(${CMAKE_SOURCE_DIR}/inc ../linux_common)
add_library(symcrypt_oe SHARED ${SOURCES})
target_link_options(symcrypt_oe PRIVATE
-Wl,--whole-archive
$<TARGET_FILE:symcrypt_module_linux_common>
$<TARGET_FILE:symcrypt_linuxusermode>
$<TARGET_FILE:symcrypt_common>
-Wl,--no-whole-archive
-Wl,-Bsymbolic
-Wl,-z,noexecstack
-Wl,-z,now
-Wl,-gc-sections
-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../linux_common/exports.ver
-nostdlib
-nodefaultlibs
-nostartfiles
)
add_dependencies(symcrypt_oe symcrypt_linuxusermode symcrypt_common symcrypt_module_linux_common)
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
add_compile_options(-mllvm -x86-speculative-load-hardening)
endif()
set_target_properties(symcrypt_oe PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/oe_full)
set_target_properties(symcrypt_oe PROPERTIES LIBRARY_OUTPUT_NAME "symcrypt")
if(CMAKE_BUILD_TYPE MATCHES Release)
add_custom_command(
TARGET symcrypt_oe
POST_BUILD
COMMAND cp $<TARGET_FILE:symcrypt_oe> $<TARGET_FILE:symcrypt_oe>.debug
COMMAND ${STRIP_COMMAND} --strip-unneeded ${KEEP_SYMBOL_ARGS} $<TARGET_FILE:symcrypt_oe>
COMMENT "Stripping binary for release build"
COMMAND_EXPAND_LISTS
)
endif()
add_custom_command(
TARGET symcrypt_oe
POST_BUILD
COMMAND python3 ${CMAKE_SOURCE_DIR}/scripts/process_fips_module.py $<TARGET_FILE:symcrypt_oe> -d
COMMENT "Postprocessing SymCrypt shared object for FIPS integrity verification"
)

Просмотреть файл

@ -0,0 +1,7 @@
add_subdirectory(common) # Common functionality for Linux modules
add_subdirectory(generic) # Generic Linux module
if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
add_subdirectory(oe_full) # OpenEnclave with all functionality
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
add_subdirectory(embedded) # Embedded Linux module
endif()

Просмотреть файл

@ -1,6 +1,5 @@
set(SOURCES
module.c
#integrity.c
rng.c)
include_directories(${CMAKE_SOURCE_DIR}/inc)

Просмотреть файл

@ -0,0 +1,76 @@
# Common build steps for all SymCrypt Linux modules
# Set the following variables before including this file:
#
# TARGET_NAME - name of the target being built. This should be the same value given to add_library
# OUTPUT_DIR - the directory to output the module to
# DO_FIPS_POSTPROCESSING - optional, set to true if the module uses FIPS integrity verification and
# needs to be run through the FIPS postprocessing Python script.
# For release builds, we strip the modules of symbols except for the following symbols which are
# required by the FIPS post-processing script. On some systems, symbol stripping would normally
# be done at package install time, but our modules must be stripped before being run through the
# FIPS post-processing script or the the runtime integrity verification will not work. Although
# the symbol table is not in a loadable segment and is therefore not part of our FIPS boundary,
# stripping symbols changes size and offset information stored in the ELF header, which is
# within the FIPS boundary and therefore affects the result of the integrity check.
set(KEEP_SYMBOL_ARGS
"-K" "SymCryptVolatileFipsHmacKey"
"-K" "SymCryptVolatileFipsHmacKeyRva"
"-K" "SymCryptVolatileFipsBoundaryOffset"
"-K" "SymCryptVolatileFipsHmacDigest"
)
# Determine the which executable to use for stripping binaries
if(CMAKE_SYSTEM_PROCESSOR MATCHES ARM64 AND NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES ARM64|aarch64)
set(STRIP_COMMAND ${TARGET_TRIPLE}-strip)
else()
set(STRIP_COMMAND strip)
endif()
target_link_options(${TARGET_NAME} PRIVATE
-Wl,--whole-archive
$<TARGET_FILE:symcrypt_module_linux_common>
$<TARGET_FILE:symcrypt_linuxusermode>
$<TARGET_FILE:symcrypt_common>
-Wl,--no-whole-archive
-Wl,-Bsymbolic
-Wl,-z,noexecstack
-Wl,-z,now
-Wl,-gc-sections
-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../common/exports.ver
-nostdlib
-nodefaultlibs
-nostartfiles
)
add_dependencies(${TARGET_NAME} symcrypt_linuxusermode symcrypt_common symcrypt_module_linux_common)
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
add_compile_options(-mllvm -x86-speculative-load-hardening)
endif()
set_target_properties(${TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR})
set_target_properties(${TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_NAME "symcrypt")
set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(${TARGET_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR})
if(CMAKE_BUILD_TYPE MATCHES Release)
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND cp $<TARGET_FILE:${TARGET_NAME}> $<TARGET_FILE:${TARGET_NAME}>.debug
COMMAND ${STRIP_COMMAND} --strip-unneeded ${KEEP_SYMBOL_ARGS} $<TARGET_FILE:${TARGET_NAME}>
COMMENT "Stripping binary for release build"
COMMAND_EXPAND_LISTS
)
endif()
if(DO_FIPS_POSTPROCESSING)
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND python3 ${CMAKE_SOURCE_DIR}/scripts/process_fips_module.py $<TARGET_FILE:${TARGET_NAME}> -d
COMMENT "Postprocessing SymCrypt shared object for FIPS integrity verification"
)
endif()

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -94,9 +94,10 @@ SymCryptCallbackRandom( PBYTE pbBuffer, SIZE_T cbBuffer )
return SYMCRYPT_NO_ERROR;
}
VOID SYMCRYPT_CALL SymCryptModuleInit( UINT32 api, UINT32 minor, UINT32 patch )
VOID SYMCRYPT_CALL SymCryptModuleInit( UINT32 api, UINT32 minor )
{
if( api > SYMCRYPT_CODE_VERSION_API )
if( api != SYMCRYPT_CODE_VERSION_API ||
(api == SYMCRYPT_CODE_VERSION_API && minor > SYMCRYPT_CODE_VERSION_MINOR) )
{
SymCryptFatal( 'vers' );
}

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,17 @@
set(SOURCES
../common/integrity.c
../common/optional/rngfipsjitter.c
../common/optional/rngsecureurandom.c)
include_directories(${CMAKE_SOURCE_DIR}/inc ../common ${CMAKE_SOURCE_DIR}/jitterentropy-library)
add_library(symcrypt_embedded SHARED ${SOURCES})
# Link jitterentropy
target_link_libraries(symcrypt_embedded ${CMAKE_SOURCE_DIR}/jitterentropy-library/libjitterentropy.a pthread)
set(TARGET_NAME symcrypt_embedded)
set(OUTPUT_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/embedded)
set(DO_FIPS_POSTPROCESSING True)
include(../common/ModuleCommon.cmake)

Просмотреть файл

Просмотреть файл

@ -0,0 +1,16 @@
set(SOURCES
../common/nointegrity.c
../common/optional/rngfipsjitter.c
../common/optional/rngsecureurandom.c)
include_directories(${CMAKE_SOURCE_DIR}/inc ../common ${CMAKE_SOURCE_DIR}/jitterentropy-library)
add_library(symcrypt_generic_linux SHARED ${SOURCES})
# Link jitterentropy
target_link_libraries(symcrypt_generic_linux ${CMAKE_SOURCE_DIR}/jitterentropy-library/libjitterentropy.a pthread)
set(TARGET_NAME symcrypt_generic_linux)
set(OUTPUT_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/generic)
include(../common/ModuleCommon.cmake)

Просмотреть файл

Просмотреть файл

@ -0,0 +1,13 @@
set(SOURCES
../common/integrity.c
rng.c)
include_directories(${CMAKE_SOURCE_DIR}/inc ../common)
add_library(symcrypt_oe SHARED ${SOURCES})
set(TARGET_NAME symcrypt_oe)
set(OUTPUT_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/oe_full)
set(DO_FIPS_POSTPROCESSING True)
include(../common/ModuleCommon.cmake)

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -3,7 +3,7 @@ set(SOURCES
)
add_executable(symcryptmoduletest_linux ${SOURCES})
target_link_libraries(symcryptmoduletest_linux symcrypt_linux)
target_link_libraries(symcryptmoduletest_linux symcrypt_generic_linux)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
add_executable(symcryptmoduletest_oe ${SOURCES})
@ -11,6 +11,4 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
add_executable(symcryptmoduletest_embedded ${SOURCES})
target_link_libraries(symcryptmoduletest_embedded symcrypt_embedded)
endif()
#add_dependencies(symcryptmoduletest_embedded symcrypt_embedded_fips)
endif()