summaryrefslogtreecommitdiff
path: root/CMakeLists.txt
blob: 0bb2e879f2a4c53c36b052fe0fdbc6e2c4ce51b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# Copyright (c) 2018 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# detect AppleClang; needs to come before project()
cmake_policy(SET CMP0025 NEW)

project(libfido2 C)
cmake_minimum_required(VERSION 3.0)

include(CheckCCompilerFlag)
include(CheckFunctionExists)
include(CheckIncludeFiles)
include(CheckTypeSize)
include(GNUInstallDirs)

set(CMAKE_COLOR_MAKEFILE off)
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(FIDO_MAJOR "1")
set(FIDO_MINOR "4")
set(FIDO_PATCH "0")
set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH})

add_definitions(-D_FIDO_MAJOR=${FIDO_MAJOR})
add_definitions(-D_FIDO_MINOR=${FIDO_MINOR})
add_definitions(-D_FIDO_PATCH=${FIDO_PATCH})

if(CYGWIN OR MSYS)
	set(WIN32 1)
	add_definitions(-DWINVER=0x0a00)
endif()

if(WIN32)
	add_definitions(-DWIN32_LEAN_AND_MEAN)
endif()

if(APPLE)
	set(CMAKE_INSTALL_NAME_DIR
		"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
endif()

# Observe OpenBSD's library versioning scheme.
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
	set(LIB_VERSION ${FIDO_MAJOR}.${FIDO_MINOR})
	set(LIB_SOVERSION ${LIB_VERSION})
else()
	set(LIB_VERSION ${FIDO_VERSION})
	set(LIB_SOVERSION ${FIDO_MAJOR})
endif()

if(MSVC)
	if((NOT CBOR_INCLUDE_DIRS) OR (NOT CBOR_LIBRARY_DIRS) OR
	   (NOT CRYPTO_INCLUDE_DIRS) OR (NOT CRYPTO_LIBRARY_DIRS))
		message(FATAL_ERROR "please provide definitions for "
		    "{CBOR,CRYPTO}_{INCLUDE,LIBRARY}_DIRS when building "
		    "under msvc")
	endif()
	set(CBOR_LIBRARIES cbor)
	set(CRYPTO_LIBRARIES crypto-45)
	set(MSVC_DISABLED_WARNINGS_LIST
		"C4200" # nonstandard extension used: zero-sized array in
			# struct/union;
		"C4204" # nonstandard extension used: non-constant aggregate
			# initializer;
		"C4706" # assignment within conditional expression;
		"C4996" # The POSIX name for this item is deprecated. Instead,
			# use the ISO C and C++ conformant name
		)
	# The construction in the following 3 lines was taken from LibreSSL's
	# CMakeLists.txt.
	string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
		${MSVC_DISABLED_WARNINGS_LIST})
	string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 ${MSVC_DISABLED_WARNINGS_STR}")
	set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7")
	set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi")
else()
	include(FindPkgConfig)
	pkg_search_module(CBOR libcbor)
	pkg_search_module(CRYPTO libcrypto)

	# XXX workaround libcbor's missing .pc file
	if(NOT CBOR_FOUND)
		check_include_files(cbor.h HAVE_CBOR_H)
		if(NOT HAVE_CBOR_H)
			message(FATAL_ERROR "could not find cbor header files")
		endif()
		set(CBOR_LIBRARIES "cbor")
	endif()

	# XXX workaround libcrypto's missing .pc file
	if(NOT CRYPTO_FOUND)
		check_include_files(openssl/opensslv.h HAVE_OPENSSLV_H)
		if(NOT HAVE_OPENSSLV_H)
			message(FATAL_ERROR "could not find crypto header files")
		endif()
		set(CRYPTO_LIBRARIES "crypto")
	endif()

	if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
		pkg_search_module(UDEV libudev REQUIRED)
		set(UDEV_NAME "udev")
		# Define be32toh().
		add_definitions(-D_GNU_SOURCE)
		# If using hidapi, use hidapi-hidraw.
		set(HIDAPI_SUFFIX -hidraw)
	elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
	       CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
		set(BASE_LIBRARIES usbhid)
	endif()

	if(MINGW)
		# MinGW is stuck with a flavour of C89.
		add_definitions(-DFIDO_NO_DIAGNOSTIC)
		add_definitions(-DWC_ERR_INVALID_CHARS=0x80)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
	endif()

	if(USE_HIDAPI)
		add_definitions(-DUSE_HIDAPI)
		pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED)
		if(HIDAPI_FOUND)
			set(HIDAPI_LIBRARIES hidapi${HIDAPI_SUFFIX})
		endif()
	endif()

	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wwrite-strings")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wbad-function-cast")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic")
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors")
	check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
	if(HAVE_STACK_PROTECTOR_ALL)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-all")
	endif()

	add_definitions(-D_DEFAULT_SOURCE)
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")

	set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g2")
	set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer")

	if(FUZZ)
		if(LIBFUZZER)
			set(FUZZ_LDFLAGS "-fsanitize=fuzzer")
			set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link")
		endif()
		add_definitions(-DFIDO_FUZZ)
	endif()

	if(ASAN)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,leak")
	endif()

	if(MSAN)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory")
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-memory-track-origins")
	endif()

	if(UBSAN)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-trap=undefined")
	endif()

	if(COVERAGE)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
	endif()
endif()

# Use -Wshorten-64-to-32 if available.
check_c_compiler_flag("-Wshorten-64-to-32" HAVE_SHORTEN_64_TO_32)
if(HAVE_SHORTEN_64_TO_32)
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshorten-64-to-32")
endif()

# Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
if(CMAKE_COMPILER_IS_GNUCC)
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result")
endif()

# Decide which keyword to use for thread-local storage.
if(CMAKE_COMPILER_IS_GNUCC OR
   CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
   CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
	set(TLS "__thread")
elseif(WIN32)
	set(TLS "__declspec(thread)")
endif()

add_definitions(-DTLS=${TLS})

# endian.h
check_include_files(endian.h HAVE_ENDIAN_H)
if(HAVE_ENDIAN_H)
	add_definitions(-DHAVE_ENDIAN_H)
endif()

# err.h
check_include_files(err.h HAVE_ERR_H)
if(HAVE_ERR_H)
	add_definitions(-DHAVE_ERR_H)
endif()

# unistd.h
check_include_files(unistd.h HAVE_UNISTD_H)
if(HAVE_UNISTD_H)
	add_definitions(-DHAVE_UNISTD_H)
endif()

# signal.h
check_include_files(signal.h HAVE_SIGNAL_H)
if(HAVE_SIGNAL_H)
	add_definitions(-DHAVE_SIGNAL_H)
endif()

# sys/random.h
check_include_files(sys/random.h HAVE_SYS_RANDOM_H)
if(HAVE_SYS_RANDOM_H)
	add_definitions(-DHAVE_SYS_RANDOM_H)
endif()

# strlcpy
check_function_exists(strlcpy HAVE_STRLCPY)
if(HAVE_STRLCPY)
	add_definitions(-DHAVE_STRLCPY)
endif()

# strlcat
check_function_exists(strlcpy HAVE_STRLCAT)
if(HAVE_STRLCAT)
	add_definitions(-DHAVE_STRLCAT)
endif()

# recallocarray
check_function_exists(recallocarray HAVE_RECALLOCARRAY)
if(HAVE_RECALLOCARRAY)
	add_definitions(-DHAVE_RECALLOCARRAY)
endif()

# XXX getpagesize is incorrectly detected when cross-compiling
# with mingw on Linux. Avoid.
if(NOT WIN32)
	check_function_exists(getpagesize HAVE_GETPAGESIZE)
endif()
if(HAVE_GETPAGESIZE)
	add_definitions(-DHAVE_GETPAGESIZE)
endif()

# sysconf
check_function_exists(sysconf HAVE_SYSCONF)
if(HAVE_SYSCONF)
	add_definitions(-DHAVE_SYSCONF)
endif()

# memset_s
if(APPLE)
	add_definitions(-D__STDC_WANT_LIB_EXT1__=1)
endif()
check_function_exists(memset_s HAVE_MEMSET_S)
if(HAVE_MEMSET_S)
	add_definitions(-DHAVE_MEMSET_S)
endif()

# explicit_bzero
if(NOT LIBFUZZER)
	check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
	if(HAVE_EXPLICIT_BZERO)
		add_definitions(-DHAVE_EXPLICIT_BZERO)
	endif()
endif()

# timingsafe_bcmp
check_function_exists(timingsafe_bcmp HAVE_TIMINGSAFE_BCMP)
if(HAVE_TIMINGSAFE_BCMP)
	add_definitions(-DHAVE_TIMINGSAFE_BCMP)
endif()

# readpassphrase
check_function_exists(readpassphrase HAVE_READPASSPHRASE)
if(HAVE_READPASSPHRASE)
	add_definitions(-DHAVE_READPASSPHRASE)
endif()

# getline
check_function_exists(getline HAVE_GETLINE)
if(HAVE_GETLINE)
	add_definitions(-DHAVE_GETLINE)
endif()

# getopt
check_function_exists(getopt HAVE_GETOPT)
if(HAVE_GETOPT)
	add_definitions(-DHAVE_GETOPT)
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-qual")
else()
	if(CMAKE_COMPILER_IS_GNUCC)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-discarded-qualifiers")
	endif()
	if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-incompatible-pointer-types-discards-qualifiers")
	endif()
endif()

# usable sigaction
set(CMAKE_EXTRA_INCLUDE_FILES signal.h)
check_function_exists(sigaction HAVE_SIGACTION)
check_type_size("sig_atomic_t" HAVE_SIG_ATOMIC_T)
if(HAVE_SIGACTION AND (NOT HAVE_SIG_ATOMIC_T STREQUAL ""))
	add_definitions(-DSIGNAL_EXAMPLE)
endif()
set(CMAKE_EXTRA_INCLUDE_FILES)

# arc4random_buf
check_function_exists(arc4random_buf HAVE_ARC4RANDOM_BUF)
if(HAVE_ARC4RANDOM_BUF)
	add_definitions(-DHAVE_ARC4RANDOM_BUF)
endif()

# getrandom
check_function_exists(getrandom HAVE_GETRANDOM)
if(HAVE_GETRANDOM)
	add_definitions(-DHAVE_GETRANDOM)
endif()

# /dev/urandom
if(UNIX)
	add_definitions(-DHAVE_DEV_URANDOM)
endif()

# export list
if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
   CMAKE_C_COMPILER_ID STREQUAL "AppleClang"))
	# clang + lld
	string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
	    " -exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/src/export.llvm")
elseif(NOT MSVC)
	# clang/gcc + gnu ld
	if(FUZZ)
		string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
                    " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/export.gnu")
	else()
		string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
                    " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/export.gnu")
	endif()
	if(NOT WIN32)
		string(CONCAT CMAKE_SHARED_LINKER_FLAGS
		    ${CMAKE_SHARED_LINKER_FLAGS}
		    " -Wl,-z,noexecstack -Wl,-z,relro,-z,now")
		string(CONCAT CMAKE_EXE_LINKER_FLAGS
		    ${CMAKE_EXE_LINKER_FLAGS}
		    " -Wl,-z,noexecstack -Wl,-z,relro,-z,now")
		if(FUZZ)
			file(STRINGS fuzz/wrapped.sym WRAPPED_SYMBOLS)
			foreach(s ${WRAPPED_SYMBOLS})
				string(CONCAT CMAKE_SHARED_LINKER_FLAGS
				    ${CMAKE_SHARED_LINKER_FLAGS}
				    " -Wl,--wrap=${s}")
			endforeach()
		endif()
	endif()
else()
	string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
		" /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"")
endif()

include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${CBOR_INCLUDE_DIRS})
include_directories(${CRYPTO_INCLUDE_DIRS})

link_directories(${CBOR_LIBRARY_DIRS})
link_directories(${CRYPTO_LIBRARY_DIRS})

message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}")
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}")
message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}")
message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}")
message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}")
message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}")
message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}")
message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}")
message(STATUS "HIDAPI_LIBRARIES: ${HIDAPI_LIBRARIES}")
message(STATUS "VERSION: ${FIDO_VERSION}")
message(STATUS "LIB_VERSION: ${LIB_VERSION}")
message(STATUS "LIB_SOVERSION: ${LIB_SOVERSION}")
message(STATUS "FUZZ: ${FUZZ}")
message(STATUS "AFL: ${AFL}")
message(STATUS "LIBFUZZER: ${LIBFUZZER}")
message(STATUS "ASAN: ${ASAN}")
message(STATUS "MSAN: ${MSAN}")
message(STATUS "COVERAGE: ${COVERAGE}")
message(STATUS "TLS: ${TLS}")
message(STATUS "USE_HIDAPI: ${USE_HIDAPI}")

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
	message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}")
	message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}")
	message(STATUS "UDEV_LIBRARIES: ${UDEV_LIBRARIES}")
	message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}")
endif()

subdirs(src)
subdirs(examples)
subdirs(tools)
subdirs(man)

if(NOT WIN32)
	if(CMAKE_BUILD_TYPE STREQUAL "Debug")
		if(NOT MSAN AND NOT LIBFUZZER)
			subdirs(regress)
		endif()
	endif()
	if(FUZZ)
		subdirs(fuzz)
	endif()

	if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
		subdirs(udev)
	endif()
endif()