diff --git a/.github/workflows/build-nativeshims.yml b/.github/workflows/build-nativeshims.yml index de1ff95a0..d472e27f4 100644 --- a/.github/workflows/build-nativeshims.yml +++ b/.github/workflows/build-nativeshims.yml @@ -60,6 +60,24 @@ jobs: } else { & ./build-windows.ps1 } + - name: Verify no VC++ Redistributable dependency + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + cd Yubico.NativeShims + set FAILED=0 + for %%a in (win-x64 win-x86 win-arm64) do ( + echo Checking %%a\Yubico.NativeShims.dll for CRT dependencies... + dumpbin /imports %%a\Yubico.NativeShims.dll | findstr /i "VCRUNTIME api-ms-win-crt" && ( + echo FAIL: %%a\Yubico.NativeShims.dll has VC++ Redistributable dependency + set FAILED=1 + ) || ( + echo PASS: %%a\Yubico.NativeShims.dll has no CRT dependencies + ) + ) + if %FAILED%==1 exit /b 1 + echo All Windows builds verified: no VC++ Redistributable required + exit /b 0 - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: win-x64 diff --git a/Yubico.NativeShims/CMakeLists.txt b/Yubico.NativeShims/CMakeLists.txt index d173a1dd0..05ecdf4ed 100644 --- a/Yubico.NativeShims/CMakeLists.txt +++ b/Yubico.NativeShims/CMakeLists.txt @@ -1,17 +1,30 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.15) -# Set default version if not provided via command line +# +# Project version +# if(NOT DEFINED PROJECT_VERSION) set(PROJECT_VERSION "1.14.0") endif() - -# Set VCPKG manifest version to match project version set(VCPKG_MANIFEST_VERSION ${PROJECT_VERSION}) project(Yubico.NativeShims VERSION ${PROJECT_VERSION}) include(CheckCCompilerFlag) +# ============================================================================= +# Platform configuration +# +# Each platform sets: +# PLATFORM_* — boolean flag for conditional logic later +# BACKEND — which smart card API to use (winscard/pcsc/macscard) +# exports file — controls which symbols are visible in the shared library +# hardening — platform-appropriate security compiler/linker flags +# ============================================================================= + if (APPLE OR UNIX) + + # --- macOS / Linux: platform identity and symbol exports --- + if (APPLE) set(PLATFORM_MACOS true) set(BACKEND "macscard") @@ -20,23 +33,31 @@ if (APPLE OR UNIX) find_package(PkgConfig REQUIRED) set(PLATFORM_LINUX true) set(BACKEND "pcsc") + # RELRO + NOW = full read-only relocations (exploit mitigation) add_link_options("-Wl,-z,relro,-z,now,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exports.gnu") endif() + + # --- macOS / Linux: security hardening (GCC/Clang) --- + if (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU") + # Warnings — treat all as errors add_compile_options(-Wall -Wextra -Werror) add_compile_options(-Wformat -Wformat-nonliteral -Wformat-security) - add_compile_options(-Wshadow) - add_compile_options(-Wcast-qual) - add_compile_options(-Wbad-function-cast) + add_compile_options(-Wshadow -Wcast-qual -Wbad-function-cast) add_compile_options(-pedantic -pedantic-errors) + + # Position-independent code (required for shared libraries) add_compile_options(-fpic) - add_compile_options(-O2) - add_compile_definitions (-D_FORTIFY_SOURCE=2) add_link_options(-fpic) + # Optimization and runtime hardening + add_compile_options(-O2) + add_compile_definitions(-D_FORTIFY_SOURCE=2) # Buffer overflow detection in libc calls + + # Stack protection — prefer -all variant, fall back to basic check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL) if (HAVE_STACK_PROTECTOR_ALL) message(STATUS "-fstack-protector-all support detected") @@ -55,31 +76,42 @@ if (APPLE OR UNIX) elseif() message(WARNING "No compatible compiler found for setting additional security compiler flags.") endif() + elseif(WIN32) + + # --- Windows: platform identity --- + set(PLATFORM_WINDOWS true) set(BACKEND "winscard") - add_link_options("/guard:cf" "/def:${CMAKE_CURRENT_SOURCE_DIR}/exports.msvc") - add_compile_options("/GS" "/Gs") -endif() + # Security hardening + add_link_options("/guard:cf") # Control Flow Guard + add_compile_options("/GS" "/Gs") # Buffer security check + stack probe -# -# Library dependencies -# + # Symbol exports + add_link_options("/def:${CMAKE_CURRENT_SOURCE_DIR}/exports.msvc") + + # Static CRT to avoid VC++ Redistributable dependency (see #391) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + +endif() + +# ============================================================================= +# Dependencies +# ============================================================================= include(${CMAKE_SOURCE_DIR}/cmake/pcscd.cmake) find_pcscd() find_package(OpenSSL REQUIRED) -# -# Build definition -# +# ============================================================================= +# Build target +# ============================================================================= + add_library(Yubico.NativeShims SHARED) -# Enable IPO/LTO (Link time optimization) if supported -# Optional IPO. Do not use IPO if it's not supported by compiler. +# Link-time optimization (cross-file inlining, dead code elimination) include(CheckIPOSupported) - check_ipo_supported(RESULT result OUTPUT output) if(result) message(INFO "IPO is enabled.") @@ -88,7 +120,7 @@ else() message(WARNING "IPO is not supported: ${output}") endif() -# Pre-processor +# Generate header from template (substitutes @VERSION@ etc.) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Yubico.NativeShims.h.in ${CMAKE_CURRENT_SOURCE_DIR}/Yubico.NativeShims.h @@ -101,33 +133,38 @@ target_include_directories( "${PROJECT_BINARY_DIR}" ) -# Source +# ============================================================================= +# Sources +# ============================================================================= + target_sources( Yubico.NativeShims PRIVATE - pcsc.c - ssl.bignum.c - ssl.ecgroup.c - ssl.ecpoint.c - ssl.gcmevp.c - ssl.cmac.c + pcsc.c # Smart card (PC/SC) shim + ssl.bignum.c # OpenSSL BIGNUM operations + ssl.ecgroup.c # OpenSSL EC group operations + ssl.ecpoint.c # OpenSSL EC point operations + ssl.gcmevp.c # OpenSSL AES-GCM via EVP interface + ssl.cmac.c # OpenSSL CMAC operations ) -# Add Windows resource file for version info if(WIN32) target_sources( Yubico.NativeShims PRIVATE - Yubico.NativeShims.rc + Yubico.NativeShims.rc # Windows version info resource ) endif() -# Linker +# ============================================================================= +# Link libraries +# ============================================================================= + target_link_libraries( Yubico.NativeShims - ${PCSC_LIBRARIES} - ${PCSC_WIN_LIBS} - ${PCSC_MACOSX_LIBS} - ${PCSC_CUSTOM_LIBS} - OpenSSL::Crypto + ${PCSC_LIBRARIES} # Linux: libpcsclite + ${PCSC_WIN_LIBS} # Windows: winscard.lib + ${PCSC_MACOSX_LIBS} # macOS: PCSC.framework + ${PCSC_CUSTOM_LIBS} # Cross-compilation overrides + OpenSSL::Crypto # libcrypto (static via vcpkg on Windows) ) diff --git a/Yubico.NativeShims/readme.md b/Yubico.NativeShims/readme.md index 9d02ecb63..2544063d3 100644 --- a/Yubico.NativeShims/readme.md +++ b/Yubico.NativeShims/readme.md @@ -20,6 +20,8 @@ Yubico.NativeShims is a cross-platform C library designed to bridge the gap in n - Install Visual Studio with C++ workload and ARM64 build tools. - Use "x64 Native tools command prompt" to navigate and run `./build-windows.ps1`. +> **Note:** The Windows build statically links the MSVC C runtime (`/MT`) so that the resulting DLL does not require the Visual C++ Redistributable to be installed on end-user systems. + ### macOS Build - Requires XCode