#
# Copyright (c) 2023 Linaro Limited
#
# SPDX-License-Identifier: Apache-2.0
#

if(CONFIG_MBEDTLS)

  if(CONFIG_MBEDTLS_BUILTIN)
    # Create an interface library named "mbedtls_iface":
    # - This is the library other modules/subsystems link against.
    # - It contains some Mbed TLS configuration flags (ex: MBEDTLS_CONFIG_FILE
    #   and TF_PSA_CRYPTO_CONFIG_FILE) which are used in Mbed TLS build, but
    #   which must also be defined when Zephyr code includes headers
    #   from Mbed TLS.
    # - It contains public include directories which are provided by Mbed TLS.
    zephyr_interface_library_named(mbedtls_iface)

    # Keep mbedTLS library as alias since downstream versions of Zephyr or
    # modules might still refer to it.
    add_library(mbedTLS ALIAS mbedtls_iface)
    set_property(GLOBAL APPEND PROPERTY ZEPHYR_INTERFACE_LIBS mbedTLS)

    # Explicitly link zephyr_interface to mbedtls_iface
    zephyr_link_libraries(mbedtls_iface)

    target_compile_definitions(mbedtls_iface INTERFACE
      MBEDTLS_CONFIG_FILE="${CONFIG_MBEDTLS_CONFIG_FILE}"
      TF_PSA_CRYPTO_CONFIG_FILE="${CONFIG_TF_PSA_CRYPTO_CONFIG_FILE}"
    )

    # Some CMake variables that are used in Mbed TLS build
    set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
    set(MBEDTLS_AS_SUBPROJECT ON)
    set(ENABLE_PROGRAMS OFF)
    set(ENABLE_TESTING OFF)
    set(GEN_FILES OFF)
    # Workaround to get rid of a warning generated by the Mbed TLS build system.
    set(CMAKE_INSTALL_LIBDIR "lib" CACHE PATH "")
    set(TF_PSA_CRYPTO_DIR ${CONFIG_TF_PSA_CRYPTO_MODULE_DIR})
    set(MLDSA_NATIVE_DIR ${ZEPHYR_MLDSA_NATIVE_MODULE_DIR})

    # Add Mbed TLS (TF-PSA-Crypto is automatically included from there).
    # This creates 3 libraries: mbedtls, mbedx509 and tfpsacrypto.
    add_subdirectory(${ZEPHYR_MBEDTLS_MODULE_DIR} mbedtls)

    set(libs mbedtls mbedx509)
    if(CONFIG_TF_PSA_CRYPTO_BUILTIN)
      list(APPEND libs tfpsacrypto builtin p256-m everest pqcp extras platform utilities)
    endif()
    foreach(lib ${libs})
      # Mbed TLS libraries are normal CMake libraries.
      # To ensure Mbed TLS libraries are including Zephyr include directories and
      # Zephyr compile options we link those libraries with 'zephyr_interface'.
      target_link_libraries(${lib} PRIVATE zephyr_interface)
      # Mbed TLS libraries are external CMake targets (not zephyr_library()),
      # so they miss the automatic add_dependencies on zephyr_generated_headers
      # that zephyr_library() targets get. Without this, generated headers
      # like heap_constants.h may not exist when Mbed TLS sources compile.
      add_dependencies(${lib} zephyr_generated_headers)
    endforeach()

    if(CONFIG_ARCH_POSIX AND CONFIG_ASAN AND NOT CONFIG_64BIT AND NOT CONFIG_NO_OPTIMIZATIONS)
      # i386 assembly code used in TF-PSA-Crypto does not compile with size
      # optimization if address sanitizer is enabled, as such switch default
      # optimization level to speed.
      set_source_files_properties(
        ${CONFIG_TF_PSA_CRYPTO_MODULE_DIR}/drivers/builtin/src/bignum_core.c
        DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mbedtls/tf-psa-crypto/drivers/builtin
        PROPERTIES COMPILE_OPTIONS "${COMPILER_OPTIMIZE_FOR_SPEED_FLAG}")
    endif()

    if(CONFIG_TF_PSA_CRYPTO_BUILTIN AND CONFIG_SECURE_STORAGE)
      # For Secure Storage to be able to differentiate callers.
      target_compile_definitions(tfpsacrypto PRIVATE BUILDING_PSA_CRYPTO)
    endif()

    # Add Mbed TLS libraries ("tfpsacrypto" and "mbedx509" are linked to "mbedtls")
    # to ZEPHYR_LIBS list.
    zephyr_append_cmake_library(mbedtls)

    # Add Mbed TLS public include directories to the "mbedtls_iface" interface library.
    target_include_directories(mbedtls_iface INTERFACE
      $<TARGET_PROPERTY:mbedtls,INTERFACE_INCLUDE_DIRECTORIES>
    )

    # Add local include directories to the "mbedtls_iface" interface library.
    target_include_directories(mbedtls_iface INTERFACE
      ${CMAKE_CURRENT_LIST_DIR}/configs
      ${CMAKE_CURRENT_LIST_DIR}/include
    )

    if(CONFIG_TF_PSA_CRYPTO_BUILTIN)
      # Add some support for legacy crypto that unfortunately is still required
      # in some scenarios.
      include(${CMAKE_CURRENT_LIST_DIR}/legacy_support.cmake)
    endif()

    # Add another library to provide Zephyr-specific support
    list_append_ifdef(CONFIG_TF_PSA_CRYPTO_BUILTIN zephyr_mbedtls_src
      ${CMAKE_CURRENT_LIST_DIR}/zephyr_entropy.c
      ${CMAKE_CURRENT_LIST_DIR}/zephyr_init.c
    )
    list_append_ifdef(CONFIG_MBEDTLS_DEBUG zephyr_mbedtls_src
      ${CMAKE_CURRENT_LIST_DIR}/debug.c
    )
    list_append_ifdef(CONFIG_MBEDTLS_SHELL zephyr_mbedtls_src
      ${CMAKE_CURRENT_LIST_DIR}/shell.c
    )
    if(zephyr_mbedtls_src)
      zephyr_library()
      zephyr_library_sources(${zephyr_mbedtls_src})
      zephyr_library_link_libraries(mbedtls_iface)
    endif()

  endif()

  if(CONFIG_MBEDTLS_TLS_VERSION_1_2 OR CONFIG_MBEDTLS_TLS_VERSION_1_3)
    if(NOT CONFIG_MBEDTLS_HAVE_TIME_DATE)
      message(WARNING "
      The option CONFIG_MBEDTLS_HAVE_TIME_DATE is required for proper
      certificate validation. If it is not enabled, certificates will
      not be checked for expiration or validity dates, which may lead
      to security vulnerabilities.
      ")
    endif()
  endif()

endif()
