1# Copyright (c) 2018 Yubico AB. All rights reserved. 2# Use of this source code is governed by a BSD-style 3# license that can be found in the LICENSE file. 4 5# detect AppleClang; needs to come before project() 6cmake_policy(SET CMP0025 NEW) 7 8project(libfido2 C) 9cmake_minimum_required(VERSION 3.0) 10# Set PIE flags for POSITION_INDEPENDENT_CODE targets, added in CMake 3.14. 11if(POLICY CMP0083) 12 cmake_policy(SET CMP0083 NEW) 13endif() 14 15include(CheckCCompilerFlag) 16include(CheckFunctionExists) 17include(CheckLibraryExists) 18include(CheckSymbolExists) 19include(CheckIncludeFiles) 20include(CheckTypeSize) 21include(GNUInstallDirs) 22include(CheckPIESupported OPTIONAL RESULT_VARIABLE CHECK_PIE_SUPPORTED) 23if(CHECK_PIE_SUPPORTED) 24 check_pie_supported(LANGUAGES C) 25endif() 26 27set(CMAKE_POSITION_INDEPENDENT_CODE ON) 28set(CMAKE_COLOR_MAKEFILE OFF) 29set(CMAKE_VERBOSE_MAKEFILE ON) 30set(FIDO_MAJOR "1") 31set(FIDO_MINOR "8") 32set(FIDO_PATCH "0") 33set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH}) 34 35option(BUILD_EXAMPLES "Build example programs" ON) 36option(BUILD_MANPAGES "Build man pages" ON) 37option(BUILD_SHARED_LIBS "Build the shared library" ON) 38option(BUILD_STATIC_LIBS "Build the static library" ON) 39option(BUILD_TOOLS "Build tool programs" ON) 40option(FUZZ "Enable fuzzing instrumentation" OFF) 41option(LIBFUZZER "Build libfuzzer harnesses" OFF) 42option(USE_HIDAPI "Use hidapi as the HID backend" OFF) 43option(USE_WINHELLO "Abstract Windows Hello as a FIDO device" OFF) 44option(NFC_LINUX "Experimental NFC support on Linux" OFF) 45 46add_definitions(-D_FIDO_MAJOR=${FIDO_MAJOR}) 47add_definitions(-D_FIDO_MINOR=${FIDO_MINOR}) 48add_definitions(-D_FIDO_PATCH=${FIDO_PATCH}) 49 50if(CYGWIN OR MSYS) 51 set(WIN32 1) 52 add_definitions(-DWINVER=0x0a00) 53endif() 54 55if(WIN32) 56 add_definitions(-DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600) 57endif() 58 59if(APPLE) 60 set(CMAKE_INSTALL_NAME_DIR 61 "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") 62endif() 63 64if(NOT MSVC) 65 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_POSIX_C_SOURCE=200809L") 66 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_BSD_SOURCE") 67 if(APPLE) 68 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DARWIN_C_SOURCE") 69 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__STDC_WANT_LIB_EXT1__=1") 70 elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") 71 set(NFC_LINUX OFF) 72 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_GNU_SOURCE") 73 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DEFAULT_SOURCE") 74 elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") 75 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__BSD_VISIBLE=1") 76 endif() 77 set(FIDO_CFLAGS "${FIDO_CFLAGS} -std=c99") 78 set(CMAKE_C_FLAGS "${FIDO_CFLAGS} ${CMAKE_C_FLAGS}") 79endif() 80 81check_c_compiler_flag("-Wshorten-64-to-32" HAVE_SHORTEN_64_TO_32) 82check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL) 83 84check_include_files(cbor.h HAVE_CBOR_H) 85check_include_files(endian.h HAVE_ENDIAN_H) 86check_include_files(err.h HAVE_ERR_H) 87check_include_files(openssl/opensslv.h HAVE_OPENSSLV_H) 88check_include_files(signal.h HAVE_SIGNAL_H) 89check_include_files(sys/random.h HAVE_SYS_RANDOM_H) 90check_include_files(unistd.h HAVE_UNISTD_H) 91check_include_files("windows.h;webauthn.h" HAVE_WEBAUTHN_H) 92 93check_symbol_exists(arc4random_buf stdlib.h HAVE_ARC4RANDOM_BUF) 94check_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME) 95check_symbol_exists(explicit_bzero string.h HAVE_EXPLICIT_BZERO) 96check_symbol_exists(freezero stdlib.h HAVE_FREEZERO) 97check_symbol_exists(getline stdio.h HAVE_GETLINE) 98check_symbol_exists(getopt unistd.h HAVE_GETOPT) 99check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE) 100check_symbol_exists(getrandom sys/random.h HAVE_GETRANDOM) 101check_symbol_exists(memset_s string.h HAVE_MEMSET_S) 102check_symbol_exists(readpassphrase readpassphrase.h HAVE_READPASSPHRASE) 103check_symbol_exists(recallocarray stdlib.h HAVE_RECALLOCARRAY) 104check_symbol_exists(sigaction signal.h HAVE_SIGACTION) 105check_symbol_exists(strlcat string.h HAVE_STRLCAT) 106check_symbol_exists(strlcpy string.h HAVE_STRLCPY) 107check_symbol_exists(sysconf unistd.h HAVE_SYSCONF) 108check_symbol_exists(timespecsub sys/time.h HAVE_TIMESPECSUB) 109check_symbol_exists(timingsafe_bcmp string.h HAVE_TIMINGSAFE_BCMP) 110 111set(CMAKE_EXTRA_INCLUDE_FILES signal.h) 112check_type_size("sig_atomic_t" HAVE_SIG_ATOMIC_T) 113set(CMAKE_EXTRA_INCLUDE_FILES) 114 115set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 116try_compile(HAVE_POSIX_IOCTL 117 "${CMAKE_CURRENT_BINARY_DIR}/posix_ioctl_check.o" 118 "${CMAKE_CURRENT_SOURCE_DIR}/openbsd-compat/posix_ioctl_check.c" 119 COMPILE_DEFINITIONS "-Werror -Woverflow -Wsign-conversion") 120 121list(APPEND CHECK_VARIABLES 122 HAVE_ARC4RANDOM_BUF 123 HAVE_CBOR_H 124 HAVE_CLOCK_GETTIME 125 HAVE_ENDIAN_H 126 HAVE_ERR_H 127 HAVE_FREEZERO 128 HAVE_GETLINE 129 HAVE_GETOPT 130 HAVE_GETPAGESIZE 131 HAVE_GETRANDOM 132 HAVE_MEMSET_S 133 HAVE_OPENSSLV_H 134 HAVE_POSIX_IOCTL 135 HAVE_READPASSPHRASE 136 HAVE_RECALLOCARRAY 137 HAVE_SIGACTION 138 HAVE_SIGNAL_H 139 HAVE_STRLCAT 140 HAVE_STRLCPY 141 HAVE_SYSCONF 142 HAVE_SYS_RANDOM_H 143 HAVE_TIMESPECSUB 144 HAVE_TIMINGSAFE_BCMP 145 HAVE_UNISTD_H 146 HAVE_WEBAUTHN_H 147) 148 149foreach(v ${CHECK_VARIABLES}) 150 if (${v}) 151 add_definitions(-D${v}) 152 endif() 153endforeach() 154 155if(HAVE_EXPLICIT_BZERO AND NOT LIBFUZZER) 156 add_definitions(-DHAVE_EXPLICIT_BZERO) 157endif() 158 159if(HAVE_SIGACTION AND (NOT HAVE_SIG_ATOMIC_T STREQUAL "")) 160 add_definitions(-DSIGNAL_EXAMPLE) 161endif() 162 163if(UNIX) 164 add_definitions(-DHAVE_DEV_URANDOM) 165endif() 166 167if(MSVC) 168 if((NOT CBOR_INCLUDE_DIRS) OR (NOT CBOR_LIBRARY_DIRS) OR 169 (NOT CRYPTO_INCLUDE_DIRS) OR (NOT CRYPTO_LIBRARY_DIRS) OR 170 (NOT ZLIB_INCLUDE_DIRS) OR (NOT ZLIB_LIBRARY_DIRS)) 171 message(FATAL_ERROR "please provide definitions for " 172 "{CBOR,CRYPTO,ZLIB}_{INCLUDE,LIBRARY}_DIRS when building " 173 "under msvc") 174 endif() 175 set(CBOR_LIBRARIES cbor) 176 set(ZLIB_LIBRARIES zlib) 177 set(CRYPTO_LIBRARIES crypto-46) 178 set(MSVC_DISABLED_WARNINGS_LIST 179 "C4200" # nonstandard extension used: zero-sized array in 180 # struct/union; 181 "C4204" # nonstandard extension used: non-constant aggregate 182 # initializer; 183 "C4706" # assignment within conditional expression; 184 "C4996" # The POSIX name for this item is deprecated. Instead, 185 # use the ISO C and C++ conformant name; 186 "C6287" # redundant code: the left and right subexpressions are identical 187 ) 188 # The construction in the following 3 lines was taken from LibreSSL's 189 # CMakeLists.txt. 190 string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR 191 ${MSVC_DISABLED_WARNINGS_LIST}) 192 string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) 193 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 -WX ${MSVC_DISABLED_WARNINGS_STR}") 194 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7 /guard:cf /sdl /RTCcsu") 195 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi /guard:cf /sdl") 196 if (HAVE_WEBAUTHN_H) 197 add_definitions(-DUSE_WINHELLO) 198 set(USE_WINHELLO ON) 199 endif() 200else() 201 include(FindPkgConfig) 202 pkg_search_module(CBOR libcbor) 203 pkg_search_module(CRYPTO libcrypto) 204 pkg_search_module(ZLIB zlib) 205 206 if(NOT CBOR_FOUND AND NOT HAVE_CBOR_H) 207 message(FATAL_ERROR "could not find libcbor") 208 endif() 209 if(NOT CRYPTO_FOUND AND NOT HAVE_OPENSSLV_H) 210 message(FATAL_ERROR "could not find libcrypto") 211 endif() 212 if(NOT ZLIB_FOUND) 213 message(FATAL_ERROR "could not find zlib") 214 endif() 215 216 set(CBOR_LIBRARIES "cbor") 217 set(CRYPTO_LIBRARIES "crypto") 218 219 if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 220 pkg_search_module(UDEV libudev REQUIRED) 221 set(UDEV_NAME "udev") 222 # If using hidapi, use hidapi-hidraw. 223 set(HIDAPI_SUFFIX -hidraw) 224 if(NOT HAVE_CLOCK_GETTIME) 225 # Look for clock_gettime in librt. 226 check_library_exists(rt clock_gettime "time.h" 227 HAVE_CLOCK_GETTIME) 228 if (HAVE_CLOCK_GETTIME) 229 add_definitions(-DHAVE_CLOCK_GETTIME) 230 set(BASE_LIBRARIES ${BASE_LIBRARIES} rt) 231 endif() 232 endif() 233 endif() 234 235 if(MINGW) 236 # MinGW is stuck with a flavour of C89. 237 add_definitions(-DFIDO_NO_DIAGNOSTIC) 238 add_definitions(-DWC_ERR_INVALID_CHARS=0x80) 239 add_compile_options(-Wno-unused-parameter) 240 endif() 241 242 if(USE_HIDAPI) 243 add_definitions(-DUSE_HIDAPI) 244 pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED) 245 set(HIDAPI_LIBRARIES hidapi${HIDAPI_SUFFIX}) 246 endif() 247 248 if(FUZZ) 249 set(NFC_LINUX ON) 250 endif() 251 252 if(NFC_LINUX) 253 add_definitions(-DNFC_LINUX) 254 endif() 255 256 add_compile_options(-Wall) 257 add_compile_options(-Wextra) 258 add_compile_options(-Werror) 259 add_compile_options(-Wshadow) 260 add_compile_options(-Wcast-qual) 261 add_compile_options(-Wwrite-strings) 262 add_compile_options(-Wmissing-prototypes) 263 add_compile_options(-Wbad-function-cast) 264 add_compile_options(-pedantic) 265 add_compile_options(-pedantic-errors) 266 267 if(HAVE_SHORTEN_64_TO_32) 268 add_compile_options(-Wshorten-64-to-32) 269 endif() 270 if(HAVE_STACK_PROTECTOR_ALL) 271 add_compile_options(-fstack-protector-all) 272 endif() 273 274 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g2") 275 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer") 276 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") 277 278 if(FUZZ) 279 add_definitions(-DFIDO_FUZZ) 280 endif() 281 if(LIBFUZZER) 282 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link") 283 endif() 284endif() 285 286# Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 287if(CMAKE_COMPILER_IS_GNUCC) 288 add_compile_options(-Wno-unused-result) 289endif() 290 291# Decide which keyword to use for thread-local storage. 292if(CMAKE_COMPILER_IS_GNUCC OR 293 CMAKE_C_COMPILER_ID STREQUAL "Clang" OR 294 CMAKE_C_COMPILER_ID STREQUAL "AppleClang") 295 set(TLS "__thread") 296elseif(WIN32) 297 set(TLS "__declspec(thread)") 298endif() 299add_definitions(-DTLS=${TLS}) 300 301# export list 302if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR 303 CMAKE_C_COMPILER_ID STREQUAL "AppleClang")) 304 # clang + lld 305 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 306 " -exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/src/export.llvm") 307elseif(NOT MSVC) 308 # clang/gcc + gnu ld 309 if(FUZZ) 310 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 311 " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/export.gnu") 312 else() 313 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 314 " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/export.gnu") 315 endif() 316 if(NOT WIN32) 317 string(CONCAT CMAKE_SHARED_LINKER_FLAGS 318 ${CMAKE_SHARED_LINKER_FLAGS} 319 " -Wl,-z,noexecstack -Wl,-z,relro,-z,now") 320 string(CONCAT CMAKE_EXE_LINKER_FLAGS 321 ${CMAKE_EXE_LINKER_FLAGS} 322 " -Wl,-z,noexecstack -Wl,-z,relro,-z,now") 323 if(FUZZ) 324 file(STRINGS fuzz/wrapped.sym WRAPPED_SYMBOLS) 325 foreach(s ${WRAPPED_SYMBOLS}) 326 string(CONCAT CMAKE_SHARED_LINKER_FLAGS 327 ${CMAKE_SHARED_LINKER_FLAGS} 328 " -Wl,--wrap=${s}") 329 endforeach() 330 endif() 331 endif() 332else() 333 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 334 " /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"") 335endif() 336 337include_directories(${CMAKE_SOURCE_DIR}/src) 338include_directories(${CBOR_INCLUDE_DIRS}) 339include_directories(${CRYPTO_INCLUDE_DIRS}) 340include_directories(${HIDAPI_INCLUDE_DIRS}) 341include_directories(${UDEV_INCLUDE_DIRS}) 342include_directories(${ZLIB_INCLUDE_DIRS}) 343 344link_directories(${CBOR_LIBRARY_DIRS}) 345link_directories(${CRYPTO_LIBRARY_DIRS}) 346link_directories(${HIDAPI_LIBRARY_DIRS}) 347link_directories(${UDEV_LIBRARY_DIRS}) 348link_directories(${ZLIB_LIBRARY_DIRS}) 349 350message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}") 351message(STATUS "BUILD_EXAMPLES: ${BUILD_EXAMPLES}") 352message(STATUS "BUILD_MANPAGES: ${BUILD_MANPAGES}") 353message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") 354message(STATUS "BUILD_STATIC_LIBS: ${BUILD_STATIC_LIBS}") 355message(STATUS "BUILD_TOOLS: ${BUILD_TOOLS}") 356message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}") 357message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}") 358message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}") 359message(STATUS "CBOR_VERSION: ${CBOR_VERSION}") 360message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") 361message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") 362message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}") 363message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") 364message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}") 365message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") 366message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") 367message(STATUS "CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}") 368message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}") 369message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}") 370message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}") 371message(STATUS "CRYPTO_VERSION: ${CRYPTO_VERSION}") 372message(STATUS "FIDO_VERSION: ${FIDO_VERSION}") 373message(STATUS "FUZZ: ${FUZZ}") 374message(STATUS "ZLIB_INCLUDE_DIRS: ${ZLIB_INCLUDE_DIRS}") 375message(STATUS "ZLIB_LIBRARIES: ${ZLIB_LIBRARIES}") 376message(STATUS "ZLIB_LIBRARY_DIRS: ${ZLIB_LIBRARY_DIRS}") 377message(STATUS "ZLIB_VERSION: ${ZLIB_VERSION}") 378if(USE_HIDAPI) 379 message(STATUS "HIDAPI_INCLUDE_DIRS: ${HIDAPI_INCLUDE_DIRS}") 380 message(STATUS "HIDAPI_LIBRARIES: ${HIDAPI_LIBRARIES}") 381 message(STATUS "HIDAPI_LIBRARY_DIRS: ${HIDAPI_LIBRARY_DIRS}") 382 message(STATUS "HIDAPI_VERSION: ${HIDAPI_VERSION}") 383endif() 384message(STATUS "LIBFUZZER: ${LIBFUZZER}") 385message(STATUS "TLS: ${TLS}") 386message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}") 387message(STATUS "UDEV_LIBRARIES: ${UDEV_LIBRARIES}") 388message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}") 389message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}") 390message(STATUS "UDEV_VERSION: ${UDEV_VERSION}") 391message(STATUS "USE_HIDAPI: ${USE_HIDAPI}") 392message(STATUS "USE_WINHELLO: ${USE_WINHELLO}") 393message(STATUS "NFC_LINUX: ${NFC_LINUX}") 394 395subdirs(src) 396if(BUILD_EXAMPLES) 397 subdirs(examples) 398endif() 399if(BUILD_TOOLS) 400 subdirs(tools) 401endif() 402if(BUILD_MANPAGES) 403 subdirs(man) 404endif() 405 406if(NOT WIN32) 407 if(CMAKE_BUILD_TYPE STREQUAL "Debug") 408 if(NOT LIBFUZZER AND NOT FUZZ) 409 subdirs(regress) 410 endif() 411 endif() 412 if(FUZZ) 413 subdirs(fuzz) 414 endif() 415 if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 416 subdirs(udev) 417 endif() 418endif() 419