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
|
# Copyright (c) 2024 Vaughn Nugent
# See the LICENSE in this directory for terms of use
#
# This file configures noscrypt with best defaults as possible while offering
# some freedom in terms of crypto libraries if desired. Some defaults and
# worst case fallback functions are defined and will get better as time goes on
#
cmake_minimum_required (VERSION 3.10)
project(
noscrypt
LANGUAGES C
DESCRIPTION "A compact, C90 cross-platform, cryptography library built specifically for nostr"
HOMEPAGE_URL "https://www.vaughnnugent.com/resources/software/modules/noscrypt"
)
set(_NC_PROJ_NAME "noscrypt")
option(NC_BUILD_TESTS "Build tests" OFF)
option(NC_DISABLE_INPUT_VALIDATION "Disables public function input validation" OFF)
option(NC_FETCH_MBEDTLS "Fetch Mbed-TLS from it's source repository locally" OFF)
option(NC_FETCH_SECP256K1 "Fetch and locally build secp256k1 source code" ON)
option(NC_INCLUDE_MONOCYPHER "Statically link to vendored monocypher library" ON)
set(CRYPTO_LIB "" CACHE STRING "The crypto library to link to (mbedtls, openssl)")
set(CRYPTO_LIB_DIR "" CACHE STRING "The path to the crypto library if it's not globally available")
set(SECP256K1_LIB_DIR "" CACHE STRING "An optional path to search for the secp256k1 library if not globally installed")
string(TOLOWER ${CMAKE_BUILD_TYPE} build_type)
#list of noscrypt project defitnions
set(NC_PROJ_DEFINTIONS "")
include(FetchContent)
if(NC_FETCH_SECP256K1)
#Fetch libsecp256k1, and build a minimal static library
set(SECP256K1_BUILD_BENCHMARK OFF)
set(SECP256K1_BUILD_TESTS OFF)
set(SECP256K1_BUILD_EXAMPLES OFF)
set(SECP256K1_BUILD_EXHAUSTIVE_TESTS OFF)
set(SECP256K1_ENABLE_MODULE_ECDH ON)
set(SECP256K1_ENABLE_MODULE_RECOVERY OFF)
set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON)
set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON)
set(SECP256K1_ENABLE_MODULE_ELLSWIFT OFF)
set(SECP256K1_INSTALL OFF)
set(SECP256K1_DISABLE_SHARED ON) #disales shared library output
FetchContent_Declare(
libsecp256k1
GIT_REPOSITORY https://github.com/bitcoin-core/secp256k1
GIT_TAG e3a885d42a7800c1ccebad94ad1e2b82c4df5c65 # release-0.5.0
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(libsecp256k1)
#Must force FPIC when using secp256k1, ld linker complains otherwise
set_target_properties(
secp256k1
secp256k1_precomputed
PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
else()
#search for an existing library, it's a required dependency
find_library(secp256k1
NAMES secp256k1 libsecp256k1
PATHS ${SECP256K1_LIB_DIR}
REQUIRED
)
endif()
#-----------------------------
# MAIN PROJECT
#-----------------------------
set(NOSCRYPT_SRCS
"src/noscrypt.c"
"src/hkdf.c"
"src/nc-crypto.c" #pulls in c impl files as needed
)
set(NOSCRYPT_HEADERS
"include/noscrypt.h"
"include/platform.h"
"src/nc-util.h"
"src/hkdf.h"
"src/nc-crypto.h"
)
#static/shared library
add_library(${_NC_PROJ_NAME} SHARED ${NOSCRYPT_SRCS} ${NOSCRYPT_HEADERS})
add_library(${_NC_PROJ_NAME}_static STATIC ${NOSCRYPT_SRCS} ${NOSCRYPT_HEADERS})
set_target_properties(${_NC_PROJ_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) #fPIC for shared library
#set specific cmake commands to target our projects only
set_target_properties(
${_NC_PROJ_NAME}
${_NC_PROJ_NAME}_static
#Setup the compiler options for c90 standard
PROPERTIES
C_STANDARD 90
C_STANDARD_REQUIRED ON
C_EXTENSIONS ON #enables c++ style comments (only required for mbedtls stuff)
)
target_compile_features(${_NC_PROJ_NAME} PRIVATE c_std_90) #force compiler to use c90 standard for library
target_compile_features(${_NC_PROJ_NAME}_static PRIVATE c_std_90) #force compiler to use c90 standard for library
target_include_directories(${_NC_PROJ_NAME} PRIVATE include)
target_include_directories(${_NC_PROJ_NAME}_static PRIVATE include)
#link libsecp256k1
target_link_libraries(${_NC_PROJ_NAME} PRIVATE secp256k1)
target_link_libraries(${_NC_PROJ_NAME}_static PRIVATE secp256k1)
#include secp256k1 headers
target_include_directories(${_NC_PROJ_NAME} SYSTEM PUBLIC vendor/secp256k1/include)
target_include_directories(${_NC_PROJ_NAME}_static SYSTEM PUBLIC vendor/secp256k1/include)
#############################################
#
# Configure crypto library linking
#
#############################################
#try to load openssl quietly in order to check for its availability
find_package(OpenSSL QUIET)
#setup default linking to crypto libraries for certain plaftorms.
#Windows defaults to bcrypt, openssl otherwise if installed
if(CRYPTO_LIB STREQUAL "")
if(MSVC)
set(CRYPTO_LIB "bcrypt")
elseif(OPENSSL_FOUND)
set(CRYPTO_LIB "openssl")
endif()
endif()
#Include mbedtls if enabled
if(NC_FETCH_MBEDTLS)
###############
# NOTE: Must disable shared libraries to avoid linking errors when using mbedtls
###############
set(BUILD_SHARED_LIBS OFF)
set(ENABLE_PROGRAMS OFF)
set(ENABLE_TESTING OFF)
set(USE_SHARED_MBEDTLS_LIBRARY OFF)
set(USE_STATIC_MBEDTLS_LIBRARY ON)
set(DISABLE_PACKAGE_CONFIG_AND_INSTALL OFF)
set(MBEDTLS_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vendor/mbedtls/mbedtls_noscrypt_config.h" CACHE STRING "" FORCE)
FetchContent_Declare(
libmbedtls
GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git
GIT_TAG v3.6.0
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(libmbedtls)
set(CRYPTO_LIB "mbedtls") #enable linking to mbedtls
endif()
#if mbedtls linking is enabled target the library
if(CRYPTO_LIB STREQUAL "mbedtls")
message(STATUS "Linking to MbedTLS crypto library")
#include mbedtls headers
target_include_directories(${_NC_PROJ_NAME} SYSTEM PUBLIC vendor/mbedtls/include)
target_include_directories(${_NC_PROJ_NAME}_static SYSTEM PUBLIC vendor/mbedtls/include)
if(NC_FETCH_MBEDTLS)
#link to included mbedtls
target_link_libraries(${_NC_PROJ_NAME} PRIVATE mbedcrypto PRIVATE mbedtls)
target_link_libraries(${_NC_PROJ_NAME}_static PRIVATE mbedcrypto PRIVATE mbedtls)
else()
#find the library
find_library(MBEDTLS_LIB_CRYPTO
NAMES mbedcrypto libmbedcrypto
PATHS ${CRYPTO_LIB_DIR}
)
find_library(MBEDTLS_LIB_TLS
NAMES mbedtls libmbedtls
PATHS ${CRYPTO_LIB_DIR}
)
message(STATUS "Found mbedtls crypto library at ${MBEDTLS_LIB_CRYPTO}")
message(STATUS "Found mbedtls tls library at ${MBEDTLS_LIB_TLS}")
#link to the library
target_link_libraries(${_NC_PROJ_NAME} PRIVATE ${MBEDTLS_LIB_CRYPTO} PRIVATE ${MBEDTLS_LIB_TLS})
target_link_libraries(${_NC_PROJ_NAME}_static PRIVATE ${MBEDTLS_LIB_CRYPTO} PRIVATE ${MBEDTLS_LIB_TLS})
endif()
#enable mbedtls crypto library bindings
list(APPEND NC_PROJ_DEFINTIONS MBEDTLS_CRYPTO_LIB)
elseif(CRYPTO_LIB STREQUAL "openssl")
set(OPENSSL_USE_STATIC_LIBS ON)
find_package(OpenSSL REQUIRED)
#include openssl headers
target_include_directories(${_NC_PROJ_NAME} SYSTEM PUBLIC vendor/openssl/include)
target_include_directories(${_NC_PROJ_NAME}_static SYSTEM PUBLIC vendor/openssl/include)
#link to openssl
message(STATUS "Linking to OpenSSL crypto library")
target_link_libraries(${_NC_PROJ_NAME} PRIVATE OpenSSL::Crypto)
target_link_libraries(${_NC_PROJ_NAME}_static PRIVATE OpenSSL::Crypto)
#enable openssl crypto library bindings
list(APPEND NC_PROJ_DEFINTIONS OPENSSL_CRYPTO_LIB)
elseif(CRYPTO_LIB STREQUAL "bcrypt")
if(MSVC)
#link bcrypt for Windows platforms
target_link_libraries(${_NC_PROJ_NAME} PRIVATE "bcrypt.lib")
target_link_libraries(${_NC_PROJ_NAME}_static PRIVATE "bcrypt.lib")
else()
message(FATAL_ERROR "Bcrypt is only supported on Windows platforms")
endif()
else()
message(FATAL_ERROR "You must select a supported cryptography library: openssl, mbedtls, or bcrypt (Windows only)")
endif()
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
add_compile_definitions(NOSCRYPT_EXPORTING) #enable exporting symbols
if(NC_DISABLE_INPUT_VALIDATION)
list(APPEND NC_PROJ_DEFINTIONS NC_INPUT_VALIDATION_OFF)
endif()
set(_NC_COMPILE_OPTS)
#setup flags for windows compilation
if(MSVC)
list(APPEND _NC_COMPILE_OPTS
/sdl #enable additional security checks
/TC #compile as c
/GS #buffer security check
$<$<CONFIG:Debug>:/FC> #show full path in diagnostics
$<$<CONFIG:Debug>:/showIncludes> #show a list of all included header files during build
$<$<CONFIG:Debug>:/wd4820> #disable warnings for struct padding and spectre mitigation wuen WX is enabled
$<$<CONFIG:Debug>:/wd5045> #disable warnings for spectre mitigation insertion
#for debug configs
$<$<CONFIG:Debug>:/options:strict>
$<$<CONFIG:Debug>:/Wall> #enable all warnings
$<$<CONFIG:Debug>:/WX> #warnings as errors (only for our project)
$<$<CONFIG:Debug>:/Zi> #enable rich debug info
$<$<CONFIG:Debug>:/Zo>
)
#set build macros
list(APPEND NC_PROJ_DEFINTIONS
$<$<CONFIG:DEBUG>:DEBUG>
$<$<CONFIG:RELEASE>:RELEASE>
)
#configure gcc flags
elseif(CMAKE_COMPILER_IS_GNUCC)
list(APPEND _NC_COMPILE_OPTS
-Wextra
-fstack-protector
)
#if debug build enable additional debug flags
if(build_type STREQUAL "debug")
list(APPEND _NC_COMPILE_OPTS
-g
-Og
-Wall
-Werror
-pedantic
)
endif()
endif()
target_compile_options(${_NC_PROJ_NAME} PRIVATE ${_NC_COMPILE_OPTS})
target_compile_options(${_NC_PROJ_NAME}_static PRIVATE ${_NC_COMPILE_OPTS})
#############################################
#
# Build/link monocypher
#
#############################################
# Monocypher only provides a few fallback functions
# for builds that don't use a more complete library
# implementation. Specifically cha-cha20 and secure
# erase functions.
if(NC_INCLUDE_MONOCYPHER)
#add monocypher as a static dep to the project
add_library(monocypher STATIC
"vendor/monocypher/monocypher.c"
"vendor/monocypher/monocypher.h"
)
target_link_libraries(${_NC_PROJ_NAME} PRIVATE monocypher)
target_link_libraries(${_NC_PROJ_NAME}_static PRIVATE monocypher)
#share mc header with project
target_include_directories(monocypher SYSTEM PUBLIC vendor/monocypher)
target_compile_features(monocypher PRIVATE c_std_99) #targets c99
if(MSVC)
target_compile_options(monocypher PRIVATE
/sdl #enable additional security checks
/TC #compile as c
/GS #buffer security check
)
#enable monocypher crypto library bindings
list(APPEND NC_PROJ_DEFINTIONS NC_ENABLE_MONOCYPHER)
elseif(CMAKE_COMPILER_IS_GNUCC)
#from monocypher's Makefile
target_compile_options(monocypher PRIVATE -pedantic -Wall -Wextra -O3 -march=native)
#enable monocypher crypto library bindings
list(APPEND NC_PROJ_DEFINTIONS NC_ENABLE_MONOCYPHER)
else()
message(WARNING "Monocypher is not supported on this platform")
endif()
endif()
#Set NC variables to both projects
target_compile_definitions(${_NC_PROJ_NAME} PRIVATE ${NC_PROJ_DEFINTIONS})
target_compile_definitions(${_NC_PROJ_NAME}_static PRIVATE ${NC_PROJ_DEFINTIONS})
#TESTS
if(NC_BUILD_TESTS)
#add test executable and link to shared library for more realistic usage
add_executable(nctest tests/test.c)
target_link_libraries(nctest ${_NC_PROJ_NAME})
target_include_directories(nctest PRIVATE include)
target_include_directories(nctest PRIVATE src) #allow access to internal headers
#enable c11 for testing
target_compile_features(nctest PRIVATE c_std_11)
endif()
###########################
#
# Installing
#
###########################
#export shared library
install(TARGETS ${_NC_PROJ_NAME}
EXPORT MyLibraryTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
#export static library
install(TARGETS ${_NC_PROJ_NAME}_static
EXPORT MyLibraryTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
install(FILES
include/noscrypt.h
include/platform.h
DESTINATION noscrypt
)
# Enable Hot Reload for MSVC compilers if supported.
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()
|