cmake_minimum_required(VERSION 3.13)

# Two builds share the authenticator core in src/:
#   default        Pico firmware (pass -DPICO_BOARD=pico2 for a Pico 2)
#   -DSKEY_HOST=ON skey_sim, a desktop simulator driven by the tests in tests/
option(SKEY_HOST "Build the host simulator instead of the Pico firmware" OFF)

if (SKEY_HOST)
    project(skey C)
else()
    if (NOT PICO_SDK_PATH)
        if (DEFINED ENV{PICO_SDK_PATH})
            set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
        else()
            set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR}/deps/pico-sdk)
        endif()
    endif()
    include(${PICO_SDK_PATH}/pico_sdk_init.cmake)
    project(skey C CXX ASM)
    pico_sdk_init()
endif()

set(CMAKE_C_STANDARD 11)
find_package(Python3 REQUIRED COMPONENTS Interpreter)

set(GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
add_custom_command(
    OUTPUT ${GENERATED_DIR}/attestation_data.c
    COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/gen_attestation.py
            --key-dir ${CMAKE_CURRENT_SOURCE_DIR}/attestation
            --out ${GENERATED_DIR}/attestation_data.c
    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/gen_attestation.py
    COMMENT "Generating attestation certificate")

set(CORE_SOURCES
    src/cbor.c
    src/cred.c
    src/crypto.c
    src/ctap1.c
    src/ctap2.c
    src/ctaphid.c
    src/pin.c
    src/presence.c
    src/storage.c)
set(WARNINGS -Wall -Wextra)

if (SKEY_HOST)
    option(SKEY_SANITIZE "Build the simulator with ASan and UBSan" ON)
    find_path(MBEDTLS_INCLUDE_DIR mbedtls/ecdsa.h)
    find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
    if (NOT MBEDTLS_INCLUDE_DIR OR NOT MBEDCRYPTO_LIBRARY)
        message(FATAL_ERROR "mbedtls not found (apt install libmbedtls-dev)")
    endif()

    add_executable(skey_sim host/main.c host/platform_host.c ${CORE_SOURCES} ${GENERATED_DIR}/attestation_data.c)
    target_include_directories(skey_sim PRIVATE src host ${MBEDTLS_INCLUDE_DIR})
    target_link_libraries(skey_sim PRIVATE ${MBEDCRYPTO_LIBRARY})
    target_compile_options(skey_sim PRIVATE ${WARNINGS})
    if (SKEY_SANITIZE)
        target_compile_options(skey_sim PRIVATE -fsanitize=address,undefined -fno-omit-frame-pointer)
        target_link_options(skey_sim PRIVATE -fsanitize=address,undefined)
    endif()
else()
    set(PICO_SOURCES firmware/button.c firmware/main.c firmware/platform_pico.c firmware/usb.c)
    add_executable(skey ${PICO_SOURCES} ${CORE_SOURCES} ${GENERATED_DIR}/attestation_data.c)
    target_include_directories(skey PRIVATE src firmware)
    target_link_libraries(skey PRIVATE
        pico_stdlib
        pico_rand
        pico_unique_id
        hardware_flash
        tinyusb_device
        pico_mbedtls)
    # The deepest path (makeCredential -> mbedtls ECDSA) needs ~2.3 KB of stack,
    # more than the SDK's 2 KB default. Reserve all of SCRATCH_Y instead.
    target_compile_definitions(skey PRIVATE PICO_STACK_SIZE=0x1000)
    # Only our own sources: the SDK and mbedtls compile into this target too.
    set_source_files_properties(${PICO_SOURCES} ${CORE_SOURCES} PROPERTIES COMPILE_OPTIONS "${WARNINGS}")
    pico_enable_stdio_usb(skey 0)
    pico_enable_stdio_uart(skey 0)
    pico_add_extra_outputs(skey)
endif()
