# CMakeList.txt # # Copyright (C) 2006-2026 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # # Usage: # $ mkdir build # $ cd build # $ cmake .. # $ cmake --build . # # To build with debugging use: # $ cmake .. -DCMAKE_BUILD_TYPE=Debug # # See "Building with CMake" in INSTALL for more. #################################################### # Project #################################################### cmake_minimum_required(VERSION 3.16) project(wolfTPM VERSION 4.2.0 LANGUAGES C) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(WOLFTPM_DEFINITIONS) # Firmware TPM (fwTPM) server set(WOLFTPM_FWTPM "no" CACHE STRING "Enable firmware TPM (fwTPM) server (default: disabled)") set_property(CACHE WOLFTPM_FWTPM PROPERTY STRINGS "yes;no") set(WOLFTPM_FWTPM_ONLY "no" CACHE STRING "Build only the fwTPM server, skip client library and examples (default: disabled)") set_property(CACHE WOLFTPM_FWTPM_ONLY PROPERTY STRINGS "yes;no") set(WOLFTPM_FWTPM_FUZZ "no" CACHE STRING "Enable fwTPM fuzz target (requires libFuzzer, default: disabled)") set_property(CACHE WOLFTPM_FWTPM_FUZZ PROPERTY STRINGS "yes;no") set(WOLFTPM_FWTPM_NV_APPEND_ONLY "no" CACHE STRING "Enable append-only NV journal for write-once flash fwTPM ports (default: disabled)") set_property(CACHE WOLFTPM_FWTPM_NV_APPEND_ONLY PROPERTY STRINGS "yes;no") # fwtpm-only forces fwtpm on if(WOLFTPM_FWTPM_ONLY) set(WOLFTPM_FWTPM "yes" CACHE STRING "" FORCE) endif() # Build wolftpm client library unless fwtpm-only mode if(WOLFTPM_FWTPM_ONLY) set(BUILD_WOLFTPM_LIB OFF) else() set(BUILD_WOLFTPM_LIB ON) endif() set(TPM_SOURCES src/tpm2.c src/tpm2_linux.c src/tpm2_packet.c src/tpm2_param_enc.c src/tpm2_swtpm.c src/tpm2_tis.c src/tpm2_winapi.c src/tpm2_wrap.c src/tpm2_asn.c src/tpm2_crypto.c src/tpm2_util.c src/tpm2_cryptocb.c hal/tpm_io.c ) # default to build shared library option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" ON) if(BUILD_WOLFTPM_LIB) add_library(wolftpm ${TPM_SOURCES}) target_compile_definitions(wolftpm PRIVATE "BUILDING_WOLFTPM" ) endif() include(CheckIncludeFile) check_include_file("fcntl.h" HAVE_FCNTL_H) check_include_file("netdb.h" HAVE_NETDB_H) check_include_file("time.h" HAVE_TIME_H) check_include_file("sys/ioctl.h" HAVE_SYS_IOCTL_H) check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H) check_include_file("sys/time.h" HAVE_SYS_TIME_H) check_include_file("errno.h" HAVE_ERRNO_H) check_include_file("stdint.h" HAVE_STDINT_H) check_include_file("stdlib.h" HAVE_STDLIB_H) check_include_file("string.h" HAVE_STRING_H) check_include_file("sys/stat.h" HAVE_SYS_STAT_H) check_include_file("sys/types.h" HAVE_SYS_TYPES_H) check_include_file("unistd.h" HAVE_UNISTD_H) include(CheckFunctionExists) check_function_exists("gethostbyname" HAVE_GETHOSTBYNAME) check_function_exists("getaddrinfo" HAVE_GETADDRINFO) check_function_exists("gettimeofday" HAVE_GETTIMEOFDAY) check_function_exists("getpid" HAVE_GETPID) # TODO # * (All major options have been implemented) # Single threaded set(WOLFTPM_SINGLE_THREADED "no" CACHE STRING "Enable wolfTPM single threaded (default: disabled)") set_property(CACHE WOLFTPM_SINGLE_THREADED PROPERTY STRINGS "yes;no") if(WOLFTPM_SINGLE_THREADED) list(APPEND WOLFTPM_DEFINITIONS "-DSINGLE_THREADED") endif() # Mutex locking if(WOLFTPM_SINGLE_THREADED) set(_WOLFTPM_NO_LOCK_DEFAULT "yes") else() set(_WOLFTPM_NO_LOCK_DEFAULT "no") endif() set(WOLFTPM_NO_LOCK "${_WOLFTPM_NO_LOCK_DEFAULT}" CACHE STRING "Disable thread mutex locking (default: ${_WOLFTPM_NO_LOCK_DEFAULT})") set_property(CACHE WOLFTPM_NO_LOCK PROPERTY STRINGS "yes;no") if(WOLFTPM_NO_LOCK) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_NO_LOCK") endif() # Active TPM - Thread local storage set(WOLFTPM_NO_ACTIVE_THREAD_LS "no" CACHE STRING "Disable active TPM thread local storage (default: disabled)") set_property(CACHE WOLFTPM_NO_ACTIVE_THREAD_LS PROPERTY STRINGS "yes;no") if(WOLFTPM_NO_ACTIVE_THREAD_LS) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_NO_ACTIVE_THREAD_LS") endif() # Provisioning set(WOLFTPM_PROVISIONING "yes" CACHE STRING "Enable support for Provisioning Initial Device Identity (IDevID) and Attestation Identity Keys (default: enabled)") set_property(CACHE WOLFTPM_PROVISIONING PROPERTY STRINGS "yes;no") if(WOLFTPM_PROVISIONING) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_PROVISIONING") endif() # Enable Debugging set(WOLFTPM_DEBUG "no" CACHE STRING "Enables option for debug (default: disabled)") set_property(CACHE WOLFTPM_DEBUG PROPERTY STRINGS "no;yes;verbose;io") if(NOT "${WOLFTPM_DEBUG}" STREQUAL "no") list(APPEND WOLFTPM_DEFINITIONS "-DDEBUG_WOLFTPM" "-DDEBUG") if("${WOLFTPM_DEBUG}" STREQUAL "verbose" OR "${WOLFTPM_DEBUG}" STREQUAL "io") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_DEBUG_VERBOSE") endif() if("${WOLFTPM_DEBUG}" STREQUAL "io") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_DEBUG_IO") endif() endif() # Device Interface set(WOLFTPM_INTERFACE "auto" CACHE STRING "Select interface to TPM") set_property(CACHE WOLFTPM_INTERFACE PROPERTY STRINGS "auto;SWTPM;WINAPI;DEVTPM;SPI;I2C;MMIO") # automatically set message("INTERFACE ${WOLFTPM_INTERFACE}") if("${WOLFTPM_INTERFACE}" STREQUAL "auto") message("auto") if(WIN32 OR MINGW OR MSYS) message("Detected windows, using WIN TBS API") set_property(CACHE WOLFTPM_INTERFACE PROPERTY VALUE "WINAPI") elseif(UNIX) message("Detected *nix. using kernel device for interface") set_property(CACHE WOLFTPM_INTERFACE PROPERTY VALUE "DEVTPM") else() set_property(CACHE WOLFTPM_INTERFACE PROPERTY VALUE "SWTPM") endif(WIN32 OR MINGW OR MSYS) endif("${WOLFTPM_INTERFACE}" STREQUAL "auto") if(WIN32 AND BUILD_WOLFTPM_LIB) target_compile_definitions(wolftpm PRIVATE "WOLFTPM_DLL" ) endif() if("${WOLFTPM_INTERFACE}" STREQUAL "SWTPM") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_SWTPM") # SWTPM port configuration set(WOLFTPM_SWTPM_PORT "2321" CACHE STRING "Set SWTPM socket port (default: 2321)") list(APPEND WOLFTPM_DEFINITIONS "-DTPM2_SWTPM_PORT=${WOLFTPM_SWTPM_PORT}") # Link Winsock for socket transport on Windows if(WIN32 AND BUILD_WOLFTPM_LIB) target_link_libraries(wolftpm PRIVATE ws2_32) endif() elseif("${WOLFTPM_INTERFACE}" STREQUAL "DEVTPM") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_LINUX_DEV") elseif("${WOLFTPM_INTERFACE}" STREQUAL "WINAPI") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_WINAPI") if(BUILD_WOLFTPM_LIB) target_link_libraries(wolftpm PRIVATE tbs) endif() elseif("${WOLFTPM_INTERFACE}" STREQUAL "SPI") # SPI interface elseif("${WOLFTPM_INTERFACE}" STREQUAL "I2C") # I2C interface - requires I2C (ADV_IO will be enabled automatically in ADV_IO section) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_I2C") elseif("${WOLFTPM_INTERFACE}" STREQUAL "MMIO") # MMIO interface - requires MMIO (ADV_IO will be enabled automatically in ADV_IO section) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_MMIO") else() get_property(INTERFACE_OPTS CACHE WOLFTPM_INTERFACE PROPERTY STRINGS) message(FATAL_ERROR "\"${WOLFTPM_INTERFACE}\" is not known WOLFTPM_INTERFACE:" " ${INTERFACE_OPTS}") endif() # TPM Module Selection set(WOLFTPM_MODULE "auto" CACHE STRING "Select TPM hardware module (default: auto)") set_property(CACHE WOLFTPM_MODULE PROPERTY STRINGS "auto;microchip;attpm20;mchp;st33;nuvoton;npct75x;slb9670;slb9672;slb9673") message("TPM MODULE ${WOLFTPM_MODULE}") if("${WOLFTPM_MODULE}" STREQUAL "auto") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_AUTODETECT") elseif("${WOLFTPM_MODULE}" STREQUAL "microchip" OR "${WOLFTPM_MODULE}" STREQUAL "attpm20" OR "${WOLFTPM_MODULE}" STREQUAL "mchp") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_MICROCHIP") elseif("${WOLFTPM_MODULE}" STREQUAL "st33") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_ST33") elseif("${WOLFTPM_MODULE}" STREQUAL "nuvoton" OR "${WOLFTPM_MODULE}" STREQUAL "npct75x") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_NUVOTON") elseif("${WOLFTPM_MODULE}" STREQUAL "slb9670") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_SLB9670") elseif("${WOLFTPM_MODULE}" STREQUAL "slb9672") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_SLB9672") elseif("${WOLFTPM_MODULE}" STREQUAL "slb9673") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_SLB9673") else() get_property(MODULE_OPTS CACHE WOLFTPM_MODULE PROPERTY STRINGS) message(FATAL_ERROR "\"${WOLFTPM_MODULE}\" is not a known WOLFTPM_MODULE:" " ${MODULE_OPTS}") endif() # Wrapper set(WOLFTPM_WRAPPER "yes" CACHE STRING "Enable wrapper code (default: enabled)") set_property(CACHE WOLFTPM_WRAPPER PROPERTY STRINGS "yes;no") if(NOT WOLFTPM_WRAPPER) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM2_NO_WRAPPER") endif() # I2C Support (for backward compatibility - use WOLFTPM_INTERFACE=I2C for new code) set(WOLFTPM_I2C "no" CACHE STRING "Enable I2C TPM Support (default: disabled, use WOLFTPM_INTERFACE=I2C for new code)") set_property(CACHE WOLFTPM_I2C PROPERTY STRINGS "yes;no") # Handle I2C option for backward compatibility # If interface is not SPI or I2C, and I2C is explicitly enabled, set interface to I2C if(WOLFTPM_I2C OR "${WOLFTPM_INTERFACE}" STREQUAL "I2C") # Backward compatibility: if I2C is enabled and interface is not SPI/I2C, enable I2C definition list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_I2C") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_ADV_IO") endif() # MMIO Support (deprecated - use WOLFTPM_INTERFACE=MMIO for new code) set(WOLFTPM_MMIO "no" CACHE STRING "Enable built-in MMIO callbacks (deprecated: use WOLFTPM_INTERFACE=MMIO for new code)") set_property(CACHE WOLFTPM_MMIO PROPERTY STRINGS "yes;no") # Handle MMIO option for backward compatibility # If interface is MMIO or MMIO is explicitly enabled, set MMIO definition if(WOLFTPM_MMIO OR "${WOLFTPM_INTERFACE}" STREQUAL "MMIO") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_MMIO") endif() # Advanced IO set(WOLFTPM_ADVIO "no" CACHE STRING "Enable Advanced IO (default: disabled)") set_property(CACHE WOLFTPM_ADVIO PROPERTY STRINGS "yes;no") # ADV_IO is automatically enabled for I2C or MMIO interfaces if(WOLFTPM_ADVIO OR WOLFTPM_I2C OR WOLFTPM_MMIO OR "${WOLFTPM_INTERFACE}" STREQUAL "I2C" OR "${WOLFTPM_INTERFACE}" STREQUAL "MMIO") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_ADV_IO") endif() # TIS / SPI Check Wait State support set(WOLFTPM_CHECK_WAIT_STATE "auto" CACHE STRING "Enable TIS / SPI Check Wait State support (default: auto - depends on chip)") set_property(CACHE WOLFTPM_CHECK_WAIT_STATE PROPERTY STRINGS "yes;no;auto") # Check wait state is required for all TPM except Infineon if("${WOLFTPM_CHECK_WAIT_STATE}" STREQUAL "auto") if(NOT "${WOLFTPM_MODULE}" STREQUAL "infineon" AND NOT "${WOLFTPM_MODULE}" STREQUAL "slb9670" AND NOT "${WOLFTPM_MODULE}" STREQUAL "slb9672" AND NOT "${WOLFTPM_MODULE}" STREQUAL "slb9673") set(WOLFTPM_CHECK_WAIT_STATE_ENABLED ON) else() set(WOLFTPM_CHECK_WAIT_STATE_ENABLED OFF) endif() elseif(WOLFTPM_CHECK_WAIT_STATE) set(WOLFTPM_CHECK_WAIT_STATE_ENABLED ON) else() set(WOLFTPM_CHECK_WAIT_STATE_ENABLED OFF) endif() if(WOLFTPM_CHECK_WAIT_STATE_ENABLED) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_CHECK_WAIT_STATE") endif() # TIS Layer Named Semaphore locking set(WOLFTPM_TIS_LOCK "no" CACHE STRING "TIS Layer Named Semaphore locking for concurrent access between processes (default: disabled)") set_property(CACHE WOLFTPM_TIS_LOCK PROPERTY STRINGS "yes;no") if(WOLFTPM_TIS_LOCK) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_TIS_LOCK") endif() # Small Stack set(WOLFTPM_SMALL_STACK "no" CACHE STRING "Enable Small Stack Usage (default: disabled)") set_property(CACHE WOLFTPM_SMALL_STACK PROPERTY STRINGS "yes;no") if(WOLFTPM_SMALL_STACK) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_SMALL_STACK") list(APPEND WOLFTPM_DEFINITIONS "-DMAX_COMMAND_SIZE=1024") list(APPEND WOLFTPM_DEFINITIONS "-DMAX_RESPONSE_SIZE=1350") list(APPEND WOLFTPM_DEFINITIONS "-DMAX_DIGEST_BUFFER=896") # If wolfCrypt is disabled, set MAX_SESSION_NUM=1 if(NOT WITH_WOLFSSL AND NOT WITH_WOLFSSL_TREE AND NOT WOLFSSL_FOUND AND NOT wolfssl_FOUND) list(APPEND WOLFTPM_DEFINITIONS "-DMAX_SESSION_NUM=1") endif() endif() # Example HAL set(WOLFTPM_HAL "yes" CACHE STRING "Enable example HAL interfaces (default: enabled)") set_property(CACHE WOLFTPM_HAL PROPERTY STRINGS "yes;no") if(WOLFTPM_HAL OR WOLFTPM_MMIO OR "${WOLFTPM_INTERFACE}" STREQUAL "MMIO") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_EXAMPLE_HAL") endif() # Firmware Upgrade set(WOLFTPM_FIRMWARE "yes" CACHE STRING "Enable support for TPM firmware upgrades (default: enabled)") set_property(CACHE WOLFTPM_FIRMWARE PROPERTY STRINGS "yes;no") if(WOLFTPM_FIRMWARE) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_FIRMWARE_UPGRADE") endif() # fwTPM definitions (after interface detection) if(WOLFTPM_FWTPM) # WOLFTPM_FWTPM_BUILD goes into options.h for build detection # Note: WOLFTPM_FWTPM itself is only set per-target on fwtpm_server/unit_test list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_FWTPM_BUILD") # Determine TIS vs socket transport if(NOT "${WOLFTPM_INTERFACE}" STREQUAL "SWTPM") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_FWTPM_HAL") list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_ADV_IO") set(WOLFTPM_FWTPM_TIS ON) else() set(WOLFTPM_FWTPM_TIS OFF) endif() endif() # If fwtpm-only, force examples off and disable wrapper if(WOLFTPM_FWTPM_ONLY) set(WOLFTPM_EXAMPLES OFF CACHE BOOL "" FORCE) list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM2_NO_WRAPPER") endif() set(WOLFTPM_FWTPM_THREAD_LIBS) set(WOLFTPM_FWTPM_TIS_LIBS) if(WOLFTPM_FWTPM AND UNIX) find_package(Threads REQUIRED) list(APPEND WOLFTPM_FWTPM_THREAD_LIBS Threads::Threads) if(WOLFTPM_FWTPM_TIS) set(WOLFTPM_FWTPM_TIS_LIBS ${WOLFTPM_FWTPM_THREAD_LIBS}) if(NOT APPLE) include(CheckLibraryExists) check_library_exists(rt sem_open "" WOLFTPM_FWTPM_HAVE_LIBRT) if(WOLFTPM_FWTPM_HAVE_LIBRT) list(APPEND WOLFTPM_FWTPM_TIS_LIBS rt) endif() endif() endif() endif() if(WOLFTPM_FWTPM_TIS AND BUILD_WOLFTPM_LIB AND UNIX) target_link_libraries(wolftpm PRIVATE ${WOLFTPM_FWTPM_TIS_LIBS}) endif() # Examples set(WOLFTPM_EXAMPLES "yes" CACHE BOOL "Build examples") if(BUILD_WOLFTPM_LIB) target_include_directories(wolftpm PUBLIC $ $ $ ) endif() # wolfSSL/wolfCrypt dependency (shared between wolftpm library and fwtpm targets) add_library(wolftpm_wolfssl_dep INTERFACE) set(WOLFCRYPT_AVAILABLE OFF) if (WITH_WOLFSSL) target_link_libraries(wolftpm_wolfssl_dep INTERFACE wolfssl) target_include_directories(wolftpm_wolfssl_dep INTERFACE ${WITH_WOLFSSL}/include) target_link_directories(wolftpm_wolfssl_dep INTERFACE ${WITH_WOLFSSL}/lib) set(WOLFCRYPT_AVAILABLE ON) elseif (WITH_WOLFSSL_TREE) set(WOLFSSL_TPM "yes" CACHE STRING "") set(WOLFSSL_EXAMPLES "no" CACHE STRING "") set(WOLFSSL_CRYPT_TESTS "no" CACHE STRING "") add_subdirectory(${WITH_WOLFSSL_TREE} wolfssl) target_link_libraries(wolftpm_wolfssl_dep INTERFACE wolfssl) set(WOLFCRYPT_AVAILABLE ON) else() find_package(PkgConfig) pkg_check_modules(WOLFSSL wolfssl) if (WOLFSSL_FOUND) target_link_libraries(wolftpm_wolfssl_dep INTERFACE ${WOLFSSL_LIBRARIES}) target_include_directories(wolftpm_wolfssl_dep INTERFACE ${WOLFSSL_INCLUDE_DIRS}) target_link_directories(wolftpm_wolfssl_dep INTERFACE ${WOLFSSL_LIBRARY_DIRS}) target_compile_options(wolftpm_wolfssl_dep INTERFACE ${WOLFSSL_CFLAGS_OTHER}) set(WOLFCRYPT_AVAILABLE ON) else() # For support with vcpkg find_package(wolfssl CONFIG REQUIRED) if (wolfssl_FOUND) target_link_libraries(wolftpm_wolfssl_dep INTERFACE wolfssl::wolfssl) set(WOLFCRYPT_AVAILABLE ON) else() list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM2_NO_WOLFCRYPT") endif() endif() endif() # Link wolftpm library to wolfSSL. # PRIVATE so the wolftpm_wolfssl_dep INTERFACE helper does not become part # of wolftpm's export set (it is build-tree-only). Downstream consumers of # wolftpm should `find_package(wolfssl)` themselves before find_package(wolftpm). if(BUILD_WOLFTPM_LIB) target_link_libraries(wolftpm PRIVATE $) endif() # fwTPM requires wolfCrypt if(WOLFTPM_FWTPM AND NOT WOLFCRYPT_AVAILABLE) message(FATAL_ERROR "fwTPM requires wolfCrypt. Provide wolfSSL via -DWITH_WOLFSSL=, " "-DWITH_WOLFSSL_TREE=, or install it system-wide.") endif() if (WOLFTPM_EXAMPLES AND BUILD_WOLFTPM_LIB) add_library(tpm_test_lib STATIC examples/tpm_test_keys.c ) # wolftpm_wolfssl_dep is needed explicitly because wolftpm now links it # PRIVATE (so wolfSSL does not leak into wolftpm's installed export set). target_link_libraries(tpm_test_lib PRIVATE wolftpm wolftpm_wolfssl_dep) endif() function(add_tpm_example name src) # Optional additional sources may be passed after 'src' (ARGN) set(_example_srcs examples/${src}) foreach(_extra ${ARGN}) list(APPEND _example_srcs examples/${_extra}) endforeach() add_executable(${name} ${_example_srcs} ) target_link_libraries(${name} PRIVATE wolftpm tpm_test_lib wolftpm_wolfssl_dep) if(WIN32) target_link_libraries(${name} PRIVATE ws2_32) endif() endfunction() #################################################### # fwTPM targets #################################################### if(WOLFTPM_FWTPM) # Core fwTPM sources (shared between server, unit test, and fuzz) set(FWTPM_CORE_SOURCES src/fwtpm/fwtpm.c src/fwtpm/fwtpm_command.c src/fwtpm/fwtpm_crypto.c src/fwtpm/fwtpm_nv.c src/tpm2_util.c src/tpm2_packet.c src/tpm2_crypto.c src/tpm2_param_enc.c ) # Server-specific sources set(FWTPM_SERVER_SOURCES ${FWTPM_CORE_SOURCES} src/fwtpm/fwtpm_io.c src/fwtpm/fwtpm_main.c ) # TIS sources (when not using SWTPM socket transport) if(WOLFTPM_FWTPM_TIS) list(APPEND FWTPM_SERVER_SOURCES src/fwtpm/fwtpm_tis.c src/fwtpm/fwtpm_tis_shm.c ) endif() # fwtpm_server executable add_executable(fwtpm_server ${FWTPM_SERVER_SOURCES}) target_compile_definitions(fwtpm_server PRIVATE "WOLFTPM_FWTPM") if(WOLFTPM_FWTPM_TIS) target_compile_definitions(fwtpm_server PRIVATE "WOLFTPM_FWTPM_TIS") endif() if(WOLFTPM_FWTPM_NV_APPEND_ONLY) target_compile_definitions(fwtpm_server PRIVATE "WOLFTPM_FWTPM_NV_APPEND_ONLY") endif() target_link_libraries(fwtpm_server PRIVATE wolftpm_wolfssl_dep) target_include_directories(fwtpm_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) if(UNIX) if(WOLFTPM_FWTPM_TIS) target_link_libraries(fwtpm_server PRIVATE ${WOLFTPM_FWTPM_TIS_LIBS}) else() target_link_libraries(fwtpm_server PRIVATE ${WOLFTPM_FWTPM_THREAD_LIBS}) endif() elseif(WIN32) target_link_libraries(fwtpm_server PRIVATE ws2_32) endif() # fwtpm_unit_test executable add_executable(fwtpm_unit_test tests/fwtpm_unit_tests.c ${FWTPM_CORE_SOURCES} ) target_compile_definitions(fwtpm_unit_test PRIVATE "WOLFTPM_FWTPM" "WOLFTPM_FWTPM_UNIT_TEST" "FWTPM_NV_FILE=\"fwtpm_test_nv.bin\"" ) if(WOLFTPM_FWTPM_NV_APPEND_ONLY) target_compile_definitions(fwtpm_unit_test PRIVATE "WOLFTPM_FWTPM_NV_APPEND_ONLY") endif() target_link_libraries(fwtpm_unit_test PRIVATE wolftpm_wolfssl_dep) target_include_directories(fwtpm_unit_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) if(UNIX) target_link_libraries(fwtpm_unit_test PRIVATE ${WOLFTPM_FWTPM_THREAD_LIBS}) endif() if(WOLFTPM_FWTPM_TIS) add_executable(fwtpm_hal_unit_test tests/fwtpm_hal_unit_tests.c ) target_compile_definitions(fwtpm_hal_unit_test PRIVATE "WOLFTPM_FWTPM_HAL" "WOLFTPM_ADV_IO" "WOLFTPM_EXAMPLE_HAL" ) target_link_libraries(fwtpm_hal_unit_test PRIVATE wolftpm_wolfssl_dep) target_include_directories(fwtpm_hal_unit_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) if(UNIX) target_link_libraries(fwtpm_hal_unit_test PRIVATE ${WOLFTPM_FWTPM_TIS_LIBS}) endif() endif() # fwTPM fuzz target (libFuzzer) if(WOLFTPM_FWTPM_FUZZ) add_executable(fwtpm_fuzz tests/fuzz/fwtpm_fuzz.c ${FWTPM_CORE_SOURCES} ) target_compile_definitions(fwtpm_fuzz PRIVATE "WOLFTPM_FWTPM") if(WOLFTPM_FWTPM_NV_APPEND_ONLY) target_compile_definitions(fwtpm_fuzz PRIVATE "WOLFTPM_FWTPM_NV_APPEND_ONLY") endif() target_link_libraries(fwtpm_fuzz PRIVATE wolftpm_wolfssl_dep) target_include_directories(fwtpm_fuzz PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) target_compile_options(fwtpm_fuzz PRIVATE "-fsanitize=fuzzer-no-link") target_link_options(fwtpm_fuzz PRIVATE "-fsanitize=fuzzer") endif() # CTest integration enable_testing() add_test(NAME fwtpm_unit_test COMMAND fwtpm_unit_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) if(WOLFTPM_FWTPM_TIS) add_test(NAME fwtpm_hal_unit_test COMMAND fwtpm_hal_unit_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) endif() message(STATUS "fwTPM server: enabled") if(WOLFTPM_FWTPM_TIS) message(STATUS "fwTPM transport: TIS/shared-memory") else() message(STATUS "fwTPM transport: socket (SWTPM)") endif() if(WOLFTPM_FWTPM_ONLY) message(STATUS "fwTPM mode: server-only (no client library)") endif() endif() function(add_to_options_file DEFINITIONS OPTION_FILE) list(REMOVE_DUPLICATES DEFINITIONS) foreach(DEF IN LISTS DEFINITIONS) if(DEF MATCHES "^-D") if(DEF MATCHES "^-D(N)?DEBUG(=.+)?") message("not outputting (N)DEBUG to ${OPTION_FILE}") endif() string(REGEX REPLACE "^-D" "" DEF_NO_PREFIX ${DEF}) string(REGEX REPLACE "=.*$" "" DEF_NO_EQUAL_NO_VAL ${DEF_NO_PREFIX}) string(REPLACE "=" " " DEF_NO_EQUAL ${DEF_NO_PREFIX}) file(APPEND ${OPTION_FILE} "#undef ${DEF_NO_EQUAL_NO_VAL}\n") file(APPEND ${OPTION_FILE} "#define ${DEF_NO_EQUAL}\n") file(APPEND ${OPTION_FILE} "\n") else() message("option w/o begin -D is ${DEF}, not saving to ${OPTION_FILE}") endif() endforeach() endfunction() add_definitions(${WOLFTPM_DEFINITIONS}) # generate options file message("Generating user options header...") if (${CMAKE_DISABLE_SOURCE_CHANGES}) set(WOLFTPM_BUILD_OUT_OF_TREE_DEFAULT "${CMAKE_DISABLE_SOURCE_CHANGES}") else() set(WOLFTPM_BUILD_OUT_OF_TREE_DEFAULT "no") endif() set(WOLFTPM_BUILD_OUT_OF_TREE "${WOLFTPM_BUILD_OUT_OF_TREE_DEFAULT}" CACHE STRING "Don't generate files in the source tree (default: ${WOLFTPM_BUILD_OUT_OF_TREE_DEFAULT})") set_property(CACHE WOLFTPM_BUILD_OUT_OF_TREE PROPERTY STRINGS "yes;no") if (${WOLFTPM_BUILD_OUT_OF_TREE}) set(WOLFTPM_OUTPUT_BASE ${CMAKE_CURRENT_BINARY_DIR}) else() set(WOLFTPM_OUTPUT_BASE ${CMAKE_CURRENT_SOURCE_DIR}) endif() set(OPTION_FILE "${WOLFTPM_OUTPUT_BASE}/wolftpm/options.h") file(REMOVE ${OPTION_FILE}) file(APPEND ${OPTION_FILE} "/* wolftpm options.h\n") file(APPEND ${OPTION_FILE} " * generated from cmake configure options\n") file(APPEND ${OPTION_FILE} " *\n") file(APPEND ${OPTION_FILE} " * Copyright (C) 2006-2026 wolfSSL Inc.\n") file(APPEND ${OPTION_FILE} " *\n") file(APPEND ${OPTION_FILE} " * This file is part of wolfSSL.\n") file(APPEND ${OPTION_FILE} " *\n") file(APPEND ${OPTION_FILE} " */\n\n") file(APPEND ${OPTION_FILE} "#ifndef WOLFTPM_OPTIONS_H\n") file(APPEND ${OPTION_FILE} "#define WOLFTPM_OPTIONS_H\n\n\n") file(APPEND ${OPTION_FILE} "#ifdef __cplusplus\n") file(APPEND ${OPTION_FILE} "extern \"C\" {\n") file(APPEND ${OPTION_FILE} "#endif\n\n") add_to_options_file("${WOLFTPM_DEFINITIONS}" "${OPTION_FILE}") # CMAKE_C_FLAGS is just a string of space-separated flags to pass to the C # compiler. We need to replace those spaces with semicolons in order to treat it # as a CMake list. string(REPLACE " " ";" CMAKE_C_FLAGS_LIST "${CMAKE_C_FLAGS}") add_to_options_file("${CMAKE_C_FLAGS_LIST}" "${OPTION_FILE}") file(APPEND ${OPTION_FILE} "\n#ifdef __cplusplus\n") file(APPEND ${OPTION_FILE} "}\n") file(APPEND ${OPTION_FILE} "#endif\n\n\n") file(APPEND ${OPTION_FILE} "#endif /* WOLFTPM_OPTIONS_H */\n\n") # generate config.h message("Generating config header...") set(WOLFTPM_CONFIG_H "yes" CACHE STRING "Enable generation of config.h and define HAVE_CONFIG_H (default: enabled)") set_property(CACHE WOLFTPM_DEBUG PROPERTY STRINGS "yes;no;verbose;io") if(WOLFTPM_CONFIG_H) add_definitions("-DHAVE_CONFIG_H") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h" ) # If config.h exists, delete it to avoid a mixup with build/config.h if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.h") file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/config.h") endif() endif() if (WOLFTPM_EXAMPLES AND BUILD_WOLFTPM_LIB) add_tpm_example(activate_credential attestation/activate_credential.c) add_tpm_example(certify attestation/certify.c) add_tpm_example(make_credential attestation/make_credential.c) add_tpm_example(bench bench/bench.c) add_tpm_example(secret_seal boot/secret_seal.c) add_tpm_example(secret_unseal boot/secret_unseal.c) add_tpm_example(secure_rot boot/secure_rot.c) add_tpm_example(csr csr/csr.c) add_tpm_example(get_ek_certs endorsement/get_ek_certs.c) # firmware_policy.c is entirely inside a WOLFTPM_FIRMWARE_UPGRADE guard, so # compiling it with firmware upgrade disabled yields an empty translation # unit (which ISO C forbids and -Wpedantic rejects). if(WOLFTPM_FIRMWARE) add_tpm_example(ifx_fw_update firmware/ifx_fw_update.c firmware/firmware_policy.c) else() add_tpm_example(ifx_fw_update firmware/ifx_fw_update.c) endif() add_tpm_example(gpio_config gpio/gpio_config.c) add_tpm_example(gpio_read gpio/gpio_read.c) add_tpm_example(gpio_set gpio/gpio_set.c) add_tpm_example(create_primary keygen/create_primary.c) add_tpm_example(external_import keygen/external_import.c) add_tpm_example(keygen keygen/keygen.c) add_tpm_example(keyimport keygen/keyimport.c) add_tpm_example(keyload keygen/keyload.c) add_tpm_example(flush management/flush.c) add_tpm_example(tpmclear management/tpmclear.c) add_tpm_example(native_test native/native_test.c) add_tpm_example(counter nvram/counter.c) add_tpm_example(nvextend nvram/extend.c) add_tpm_example(policy_nv nvram/policy_nv.c) add_tpm_example(read nvram/read.c) add_tpm_example(store nvram/store.c) add_tpm_example(seal_nv nvram/seal_nv.c) add_tpm_example(extend pcr/extend.c) add_tpm_example(policy_sign pcr/policy_sign.c) add_tpm_example(policy pcr/policy.c) add_tpm_example(quote pcr/quote.c) add_tpm_example(read_pcr pcr/read_pcr.c) add_tpm_example(reset pcr/reset.c) add_tpm_example(pkcs7 pkcs7/pkcs7.c) add_tpm_example(seal seal/seal.c) add_tpm_example(unseal seal/unseal.c) add_tpm_example(seal_pcr seal/seal_pcr.c) add_tpm_example(seal_policy_auth seal/seal_policy_auth.c) add_tpm_example(clock_set timestamp/clock_set.c) add_tpm_example(signed_timestamp timestamp/signed_timestamp.c) add_tpm_example(tls_client_notpm tls/tls_client_notpm.c) add_tpm_example(tls_client tls/tls_client.c) add_tpm_example(tls_server tls/tls_server.c) add_tpm_example(caps wrap/caps.c) add_tpm_example(wrap_test wrap/wrap_test.c) endif() #################################################### # Installation #################################################### include(GNUInstallDirs) if(BUILD_WOLFTPM_LIB) include(CMakePackageConfigHelpers) set(WOLFTPM_CONFIG_NEEDS_THREADS OFF) if(WOLFTPM_FWTPM_TIS AND UNIX) set(WOLFTPM_CONFIG_NEEDS_THREADS ON) endif() configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/wolftpm-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/wolftpm-config.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/wolftpm" ) # Note: wolftpm_wolfssl_dep is an INTERFACE helper used only at build # time to share wolfSSL include/link settings. It is intentionally NOT # installed/exported — downstream `find_package(wolftpm)` should only # see the real wolftpm target and discover wolfSSL via its own config. install(TARGETS wolftpm EXPORT wolftpm-targets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin ) # Install the export set install(EXPORT wolftpm-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wolftpm FILE wolftpm-targets.cmake NAMESPACE wolfssl::) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/wolftpm-config.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wolftpm) endif() # Install fwTPM server if(WOLFTPM_FWTPM) install(TARGETS fwtpm_server RUNTIME DESTINATION bin ) endif() # Install the headers install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/wolftpm/ DESTINATION include/wolftpm FILES_MATCHING PATTERN "*.h") install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wolftpm/ DESTINATION include/wolftpm FILES_MATCHING PATTERN "*.h") #################################################### # SBOM generation target #################################################### # # Usage: # cmake -B build -DWOLFSSL_DIR=/path/to/wolfssl/source . # cmake --build build # cmake --build build --target sbom # # WOLFSSL_DIR must point to a wolfssl source tree that contains # scripts/gen-sbom (available on the feat/sbom-embedded branch). # # Outputs written to the build directory: # wolftpm-.cdx.json (CycloneDX) # wolftpm-.spdx.json (SPDX JSON) # wolftpm-.spdx (SPDX tag-value, pyspdxtools validation output) if(BUILD_WOLFTPM_LIB) set(WOLFSSL_DIR "" CACHE PATH "Path to wolfssl source tree with scripts/gen-sbom") # wolfTPM is GPLv3-or-later (per the per-file source headers: "either # version 3 of the License, or (at your option) any later version") or # commercial. Pin the header-accurate SPDX id so the SBOM is correct # regardless of the gen-sbom version's licence detection; commercial # licensees can override it (e.g. LicenseRef-wolfSSL-Commercial). This # mirrors SBOM_LICENSE_OVERRIDE in the autotools build. set(SBOM_LICENSE_OVERRIDE "GPL-3.0-or-later" CACHE STRING "SPDX licence expression recorded in the SBOM") # Derive the version from wolftpm/version.h, NOT from PROJECT_VERSION. # autotools `make sbom` uses PACKAGE_VERSION, which is sourced from # version.h. Reading the same header here keeps the cmake and autotools # SBOMs bit-identical in the version field even if the project() call in # this file drifts out of sync with the header. file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/wolftpm/version.h" _sbom_version_line REGEX "^#define[ ]+LIBWOLFTPM_VERSION_STRING[ ]+\"") string(REGEX REPLACE "^#define[ ]+LIBWOLFTPM_VERSION_STRING[ ]+\"([^\"]+)\".*" "\\1" SBOM_VERSION "${_sbom_version_line}") if(NOT SBOM_VERSION) message(FATAL_ERROR "sbom: could not parse LIBWOLFTPM_VERSION_STRING from " "wolftpm/version.h") endif() # Validate the SBOM prerequisites at configure time so the user learns # what is missing immediately, instead of after a full library build. # # These checks must NOT abort configuration of a normal build: someone who # just wants `cmake -B build && cmake --build build` should never be forced # to set WOLFSSL_DIR. So when a prerequisite is missing we still define a # `sbom` target, but one that prints the reason and fails at build time. # Only when the user explicitly opts in via -DWOLFSSL_DIR=... and that path # turns out to be wrong do we hard-error at configure time, because at that # point the user clearly intends to build SBOMs and a typo'd path is a # mistake worth surfacing right away. find_program(PYTHON3_CMD python3) find_program(PYSPDXTOOLS_CMD pyspdxtools) set(_sbom_error "") if(WOLFSSL_DIR STREQUAL "") set(_sbom_error "WOLFSSL_DIR is not set. Re-run cmake with -DWOLFSSL_DIR=/path/to/wolfssl") elseif(NOT EXISTS "${WOLFSSL_DIR}/scripts/gen-sbom") # User opted in with a bad path -> fail configure now, not at build. message(FATAL_ERROR "sbom: ${WOLFSSL_DIR}/scripts/gen-sbom not found.\n" " Check that WOLFSSL_DIR points to a wolfSSL tree with " "SBOM support.") elseif(NOT PYTHON3_CMD) set(_sbom_error "'python3' not found in PATH. Cannot generate SBOM.") elseif(NOT PYSPDXTOOLS_CMD) set(_sbom_error "'pyspdxtools' not found in PATH (install: pip install spdx-tools)") endif() if(NOT _sbom_error STREQUAL "") # Prerequisite missing: keep configuration working, but make the sbom # target fail loudly if someone actually invokes it. add_custom_target(sbom VERBATIM COMMAND ${CMAKE_COMMAND} -E echo "sbom: ${_sbom_error}" COMMAND ${CMAKE_COMMAND} -E false COMMENT "SBOM prerequisites missing") return() endif() set(SBOM_CDX "${CMAKE_BINARY_DIR}/wolftpm-${SBOM_VERSION}.cdx.json") set(SBOM_SPDX "${CMAKE_BINARY_DIR}/wolftpm-${SBOM_VERSION}.spdx.json") set(SBOM_SPDX_TV "${CMAKE_BINARY_DIR}/wolftpm-${SBOM_VERSION}.spdx") set(SBOM_STAGING "${CMAKE_BINARY_DIR}/_sbom_staging") # Staged install path. Derive the installed artifact name from the target # itself so it tracks the real output - a versioned .so/.dylib, a static # .a/.lib, or the Windows DLL - instead of a hardcoded # libwolftpm${CMAKE_SHARED_LIBRARY_SUFFIX} that only matches a Unix shared # build. install(TARGETS) sends the Windows DLL (RUNTIME) to bin/ and # everything else (LIBRARY/ARCHIVE) to lib/. if(WIN32 AND BUILD_SHARED_LIBS) set(SBOM_LIB "${SBOM_STAGING}/bin/$") else() set(SBOM_LIB "${SBOM_STAGING}/lib/$") endif() # wolfTPM links wolfSSL/wolfCrypt, so record wolfSSL as a dependency in the # SBOM (matches the autotools SBOM_DEP_WOLFSSL=yes). Recording it needs the # gen-sbom from wolfSSL/wolfssl#10343; older gen-sbom rejects unknown flags, # so probe --help and only pass --dep-wolfssl when supported. Against an # older gen-sbom the SBOM is still valid but omits the wolfSSL entry. set(_sbom_dep_wolfssl "") execute_process( COMMAND ${PYTHON3_CMD} ${WOLFSSL_DIR}/scripts/gen-sbom --help OUTPUT_VARIABLE _sbom_help ERROR_QUIET) if(_sbom_help MATCHES "--dep-wolfssl") set(_sbom_dep_wolfssl --dep-wolfssl yes) else() message(WARNING "sbom: ${WOLFSSL_DIR}/scripts/gen-sbom has no --dep-wolfssl; " "the SBOM will omit the wolfSSL dependency entry. Use the gen-sbom " "from wolfSSL/wolfssl#10343 (or master once merged) to record it.") endif() # ${OPTION_FILE} is the generated wolftpm/options.h, the same compile-time # option fingerprint autotools `make sbom` feeds to gen-sbom via # --options-h. Using it (rather than a raw `cc -dM` dump, which would only # capture compiler builtins) keeps the cmake SBOM consistent with autotools. add_custom_target(sbom VERBATIM # Stage a clean install so gen-sbom inspects the same artifact layout # the user would actually ship. COMMAND ${CMAKE_COMMAND} -E remove_directory ${SBOM_STAGING} COMMAND ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --prefix ${SBOM_STAGING} --config $ COMMAND ${PYTHON3_CMD} ${WOLFSSL_DIR}/scripts/gen-sbom --name wolftpm --version ${SBOM_VERSION} --supplier "wolfSSL Inc." --license-file ${CMAKE_SOURCE_DIR}/COPYING --options-h ${OPTION_FILE} --lib ${SBOM_LIB} --license-override ${SBOM_LICENSE_OVERRIDE} ${_sbom_dep_wolfssl} --cdx-out ${SBOM_CDX} --spdx-out ${SBOM_SPDX} # Validate the SPDX JSON and emit the tag-value rendering as a side # effect; a malformed SBOM makes pyspdxtools exit non-zero and fails # the target. COMMAND ${PYSPDXTOOLS_CMD} --infile ${SBOM_SPDX} --outfile ${SBOM_SPDX_TV} COMMAND ${CMAKE_COMMAND} -E remove_directory ${SBOM_STAGING} COMMENT "Generating SBOM for wolfTPM ${SBOM_VERSION}") # gen-sbom reads the staged library, so the library must build first. add_dependencies(sbom wolftpm) endif()