1# Copyright (c) 2018-2021 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 "10") 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" ON) 44option(NFC_LINUX "Enable NFC support on Linux" ON) 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 OR MINGW) 51 set(WIN32 1) 52endif() 53 54if(WIN32) 55 add_definitions(-DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600) 56endif() 57 58if(APPLE) 59 set(CMAKE_INSTALL_NAME_DIR 60 "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") 61endif() 62 63if(NOT MSVC) 64 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_POSIX_C_SOURCE=200809L") 65 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_BSD_SOURCE") 66 if(APPLE) 67 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DARWIN_C_SOURCE") 68 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__STDC_WANT_LIB_EXT1__=1") 69 elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") 70 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_GNU_SOURCE") 71 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DEFAULT_SOURCE") 72 elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR 73 CMAKE_SYSTEM_NAME STREQUAL "MidnightBSD") 74 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__BSD_VISIBLE=1") 75 elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") 76 set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_NETBSD_SOURCE") 77 endif() 78 set(FIDO_CFLAGS "${FIDO_CFLAGS} -std=c99") 79 set(CMAKE_C_FLAGS "${FIDO_CFLAGS} ${CMAKE_C_FLAGS}") 80endif() 81 82check_c_compiler_flag("-Wshorten-64-to-32" HAVE_SHORTEN_64_TO_32) 83check_c_compiler_flag("-Werror -fstack-protector-all" HAVE_STACK_PROTECTOR_ALL) 84 85check_include_files(cbor.h HAVE_CBOR_H) 86check_include_files(endian.h HAVE_ENDIAN_H) 87check_include_files(err.h HAVE_ERR_H) 88check_include_files(openssl/opensslv.h HAVE_OPENSSLV_H) 89check_include_files(signal.h HAVE_SIGNAL_H) 90check_include_files(sys/random.h HAVE_SYS_RANDOM_H) 91check_include_files(unistd.h HAVE_UNISTD_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(strlcat string.h HAVE_STRLCAT) 105check_symbol_exists(strlcpy string.h HAVE_STRLCPY) 106check_symbol_exists(strsep string.h HAVE_STRSEP) 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_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 112try_compile(HAVE_POSIX_IOCTL 113 "${CMAKE_CURRENT_BINARY_DIR}/posix_ioctl_check.o" 114 "${CMAKE_CURRENT_SOURCE_DIR}/openbsd-compat/posix_ioctl_check.c" 115 COMPILE_DEFINITIONS "-Werror -Woverflow -Wsign-conversion") 116 117list(APPEND CHECK_VARIABLES 118 HAVE_ARC4RANDOM_BUF 119 HAVE_CBOR_H 120 HAVE_CLOCK_GETTIME 121 HAVE_ENDIAN_H 122 HAVE_ERR_H 123 HAVE_FREEZERO 124 HAVE_GETLINE 125 HAVE_GETOPT 126 HAVE_GETPAGESIZE 127 HAVE_GETRANDOM 128 HAVE_MEMSET_S 129 HAVE_OPENSSLV_H 130 HAVE_POSIX_IOCTL 131 HAVE_READPASSPHRASE 132 HAVE_RECALLOCARRAY 133 HAVE_SIGNAL_H 134 HAVE_STRLCAT 135 HAVE_STRLCPY 136 HAVE_STRSEP 137 HAVE_SYSCONF 138 HAVE_SYS_RANDOM_H 139 HAVE_TIMESPECSUB 140 HAVE_TIMINGSAFE_BCMP 141 HAVE_UNISTD_H 142) 143 144foreach(v ${CHECK_VARIABLES}) 145 if (${v}) 146 add_definitions(-D${v}) 147 endif() 148endforeach() 149 150if(HAVE_EXPLICIT_BZERO AND NOT LIBFUZZER) 151 add_definitions(-DHAVE_EXPLICIT_BZERO) 152endif() 153 154if(UNIX) 155 add_definitions(-DHAVE_DEV_URANDOM) 156endif() 157 158if(MSVC) 159 if((NOT CBOR_INCLUDE_DIRS) OR (NOT CBOR_LIBRARY_DIRS) OR 160 (NOT CBOR_BIN_DIRS) OR (NOT CRYPTO_INCLUDE_DIRS) OR 161 (NOT CRYPTO_LIBRARY_DIRS) OR (NOT CRYPTO_BIN_DIRS) OR 162 (NOT ZLIB_INCLUDE_DIRS) OR (NOT ZLIB_LIBRARY_DIRS) OR 163 (NOT ZLIB_BIN_DIRS)) 164 message(FATAL_ERROR "please define " 165 "{CBOR,CRYPTO,ZLIB}_{INCLUDE,LIBRARY,BIN}_DIRS when " 166 "building under msvc") 167 endif() 168 set(CBOR_LIBRARIES cbor) 169 set(ZLIB_LIBRARIES zlib) 170 set(CRYPTO_LIBRARIES crypto-47) 171 set(MSVC_DISABLED_WARNINGS_LIST 172 "C4152" # nonstandard extension used: function/data pointer 173 # conversion in expression; 174 "C4200" # nonstandard extension used: zero-sized array in 175 # struct/union; 176 "C4201" # nonstandard extension used: nameless struct/union; 177 "C4204" # nonstandard extension used: non-constant aggregate 178 # initializer; 179 "C4706" # assignment within conditional expression; 180 "C4996" # The POSIX name for this item is deprecated. Instead, 181 # use the ISO C and C++ conformant name; 182 "C6287" # redundant code: the left and right subexpressions are identical 183 ) 184 # The construction in the following 3 lines was taken from LibreSSL's 185 # CMakeLists.txt. 186 string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR 187 ${MSVC_DISABLED_WARNINGS_LIST}) 188 string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) 189 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 -WX ${MSVC_DISABLED_WARNINGS_STR}") 190 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od /Z7 /guard:cf /sdl /RTCcsu") 191 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi /guard:cf /sdl") 192 if(USE_WINHELLO) 193 add_definitions(-DUSE_WINHELLO) 194 endif() 195 set(NFC_LINUX OFF) 196else() 197 include(FindPkgConfig) 198 pkg_search_module(CBOR libcbor) 199 pkg_search_module(CRYPTO libcrypto) 200 pkg_search_module(ZLIB zlib) 201 202 if(NOT CBOR_FOUND AND NOT HAVE_CBOR_H) 203 message(FATAL_ERROR "could not find libcbor") 204 endif() 205 if(NOT CRYPTO_FOUND AND NOT HAVE_OPENSSLV_H) 206 message(FATAL_ERROR "could not find libcrypto") 207 endif() 208 if(NOT ZLIB_FOUND) 209 message(FATAL_ERROR "could not find zlib") 210 endif() 211 212 set(CBOR_LIBRARIES "cbor") 213 set(CRYPTO_LIBRARIES "crypto") 214 215 if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 216 pkg_search_module(UDEV libudev REQUIRED) 217 set(UDEV_NAME "udev") 218 # If using hidapi, use hidapi-hidraw. 219 set(HIDAPI_SUFFIX -hidraw) 220 if(NOT HAVE_CLOCK_GETTIME) 221 # Look for clock_gettime in librt. 222 check_library_exists(rt clock_gettime "time.h" 223 HAVE_CLOCK_GETTIME) 224 if (HAVE_CLOCK_GETTIME) 225 add_definitions(-DHAVE_CLOCK_GETTIME) 226 set(BASE_LIBRARIES ${BASE_LIBRARIES} rt) 227 endif() 228 endif() 229 else() 230 set(NFC_LINUX OFF) 231 endif() 232 233 if(MINGW) 234 # MinGW is stuck with a flavour of C89. 235 add_definitions(-DFIDO_NO_DIAGNOSTIC) 236 add_definitions(-DWC_ERR_INVALID_CHARS=0x80) 237 add_compile_options(-Wno-unused-parameter) 238 endif() 239 240 if(USE_HIDAPI) 241 add_definitions(-DUSE_HIDAPI) 242 pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED) 243 set(HIDAPI_LIBRARIES hidapi${HIDAPI_SUFFIX}) 244 endif() 245 246 if(NFC_LINUX) 247 add_definitions(-DNFC_LINUX) 248 endif() 249 250 if(WIN32) 251 if(USE_WINHELLO) 252 add_definitions(-DUSE_WINHELLO) 253 endif() 254 else() 255 set(USE_WINHELLO OFF) 256 endif() 257 258 add_compile_options(-Wall) 259 add_compile_options(-Wextra) 260 add_compile_options(-Werror) 261 add_compile_options(-Wshadow) 262 add_compile_options(-Wcast-qual) 263 add_compile_options(-Wwrite-strings) 264 add_compile_options(-Wmissing-prototypes) 265 add_compile_options(-Wbad-function-cast) 266 add_compile_options(-pedantic) 267 add_compile_options(-pedantic-errors) 268 269 if(WIN32) 270 add_compile_options(-Wno-type-limits) 271 add_compile_options(-Wno-cast-function-type) 272 endif() 273 if(HAVE_SHORTEN_64_TO_32) 274 add_compile_options(-Wshorten-64-to-32) 275 endif() 276 if(HAVE_STACK_PROTECTOR_ALL) 277 add_compile_options(-fstack-protector-all) 278 endif() 279 280 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g2") 281 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer") 282 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") 283 284 if(CRYPTO_VERSION VERSION_GREATER_EQUAL 3.0) 285 add_definitions(-DOPENSSL_API_COMPAT=0x10100000L) 286 endif() 287 288 if(FUZZ) 289 add_definitions(-DFIDO_FUZZ) 290 endif() 291 292 if(LIBFUZZER) 293 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link") 294 endif() 295endif() 296 297# Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 298if(CMAKE_COMPILER_IS_GNUCC) 299 add_compile_options(-Wno-unused-result) 300endif() 301 302# Decide which keyword to use for thread-local storage. 303if(CMAKE_COMPILER_IS_GNUCC OR 304 CMAKE_C_COMPILER_ID STREQUAL "Clang" OR 305 CMAKE_C_COMPILER_ID STREQUAL "AppleClang") 306 set(TLS "__thread") 307elseif(WIN32) 308 set(TLS "__declspec(thread)") 309endif() 310add_definitions(-DTLS=${TLS}) 311 312# export list 313if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR 314 CMAKE_C_COMPILER_ID STREQUAL "AppleClang")) 315 # clang + lld 316 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 317 " -exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/src/export.llvm") 318elseif(NOT MSVC) 319 # clang/gcc + gnu ld 320 if(FUZZ) 321 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 322 " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/export.gnu") 323 else() 324 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 325 " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/export.gnu") 326 endif() 327 if(NOT WIN32) 328 string(CONCAT CMAKE_SHARED_LINKER_FLAGS 329 ${CMAKE_SHARED_LINKER_FLAGS} 330 " -Wl,-z,noexecstack -Wl,-z,relro,-z,now") 331 string(CONCAT CMAKE_EXE_LINKER_FLAGS 332 ${CMAKE_EXE_LINKER_FLAGS} 333 " -Wl,-z,noexecstack -Wl,-z,relro,-z,now") 334 if(FUZZ) 335 file(STRINGS fuzz/wrapped.sym WRAPPED_SYMBOLS) 336 foreach(s ${WRAPPED_SYMBOLS}) 337 string(CONCAT CMAKE_SHARED_LINKER_FLAGS 338 ${CMAKE_SHARED_LINKER_FLAGS} 339 " -Wl,--wrap=${s}") 340 endforeach() 341 endif() 342 endif() 343else() 344 string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} 345 " /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"") 346endif() 347 348include_directories(${CMAKE_SOURCE_DIR}/src) 349include_directories(${CBOR_INCLUDE_DIRS}) 350include_directories(${CRYPTO_INCLUDE_DIRS}) 351include_directories(${HIDAPI_INCLUDE_DIRS}) 352include_directories(${UDEV_INCLUDE_DIRS}) 353include_directories(${ZLIB_INCLUDE_DIRS}) 354 355link_directories(${CBOR_LIBRARY_DIRS}) 356link_directories(${CRYPTO_LIBRARY_DIRS}) 357link_directories(${HIDAPI_LIBRARY_DIRS}) 358link_directories(${UDEV_LIBRARY_DIRS}) 359link_directories(${ZLIB_LIBRARY_DIRS}) 360 361message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}") 362message(STATUS "BUILD_EXAMPLES: ${BUILD_EXAMPLES}") 363message(STATUS "BUILD_MANPAGES: ${BUILD_MANPAGES}") 364message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") 365message(STATUS "BUILD_STATIC_LIBS: ${BUILD_STATIC_LIBS}") 366message(STATUS "BUILD_TOOLS: ${BUILD_TOOLS}") 367message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}") 368message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}") 369message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}") 370message(STATUS "CBOR_VERSION: ${CBOR_VERSION}") 371message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") 372message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") 373message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}") 374message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") 375message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}") 376message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") 377message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") 378message(STATUS "CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}") 379message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}") 380message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}") 381message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}") 382message(STATUS "CRYPTO_VERSION: ${CRYPTO_VERSION}") 383message(STATUS "FIDO_VERSION: ${FIDO_VERSION}") 384message(STATUS "FUZZ: ${FUZZ}") 385message(STATUS "ZLIB_INCLUDE_DIRS: ${ZLIB_INCLUDE_DIRS}") 386message(STATUS "ZLIB_LIBRARIES: ${ZLIB_LIBRARIES}") 387message(STATUS "ZLIB_LIBRARY_DIRS: ${ZLIB_LIBRARY_DIRS}") 388message(STATUS "ZLIB_VERSION: ${ZLIB_VERSION}") 389if(USE_HIDAPI) 390 message(STATUS "HIDAPI_INCLUDE_DIRS: ${HIDAPI_INCLUDE_DIRS}") 391 message(STATUS "HIDAPI_LIBRARIES: ${HIDAPI_LIBRARIES}") 392 message(STATUS "HIDAPI_LIBRARY_DIRS: ${HIDAPI_LIBRARY_DIRS}") 393 message(STATUS "HIDAPI_VERSION: ${HIDAPI_VERSION}") 394endif() 395message(STATUS "LIBFUZZER: ${LIBFUZZER}") 396message(STATUS "TLS: ${TLS}") 397message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}") 398message(STATUS "UDEV_LIBRARIES: ${UDEV_LIBRARIES}") 399message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}") 400message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}") 401message(STATUS "UDEV_VERSION: ${UDEV_VERSION}") 402message(STATUS "USE_HIDAPI: ${USE_HIDAPI}") 403message(STATUS "USE_WINHELLO: ${USE_WINHELLO}") 404message(STATUS "NFC_LINUX: ${NFC_LINUX}") 405 406subdirs(src) 407if(BUILD_EXAMPLES) 408 subdirs(examples) 409endif() 410if(BUILD_TOOLS) 411 subdirs(tools) 412endif() 413if(BUILD_MANPAGES) 414 subdirs(man) 415endif() 416 417if(NOT WIN32) 418 if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FUZZ) 419 enable_testing() 420 subdirs(regress) 421 endif() 422 if(FUZZ) 423 subdirs(fuzz) 424 endif() 425 if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 426 subdirs(udev) 427 endif() 428endif() 429