From b0f8501132ee7edb562d399b1726012da01dea80 Mon Sep 17 00:00:00 2001 From: Pavel Polach Date: Tue, 1 Oct 2024 13:46:37 +0000 Subject: [PATCH] Initial release of libtropic! --- .github/workflows/build_docs.yml | 59 + .github/workflows/integration_tests.yml | 20 + .github/workflows/main.yml | 20 - .github/workflows/unit_tests.yml | 19 + .gitlab-ci.yml | 25 +- .gitmodules | 4 +- CHANGELOG.md | 8 + CMakeLists.txt | 155 +- CONTRIBUTING.md | 13 + README.md | 22 +- build_docs.sh | 13 + docs/Doxyfile.in | 760 ++++++---- docs/index.md | 153 +- docs/latex/libtropic_header.tex | 346 ++--- examples/crypto_tests/CMakeLists.txt | 42 - examples/crypto_tests/crypto_tests.h | 9 - examples/crypto_tests/main.c | 449 ------ examples/hw_wallet/hw_wallet.c | 660 ++++++++ examples/hw_wallet/hw_wallet.h | 25 + examples/readme.MD | 70 - examples/stm32_example/CMakeLists.txt | 140 -- examples/stm32_example/Inc/main.h | 84 - .../stm32_example/Inc/stm32f4xx_hal_conf.h | 460 ------ examples/stm32_example/Inc/stm32f4xx_it.h | 46 - examples/stm32_example/STM32F429ZITX_FLASH.ld | 206 --- .../stm32_example/Src/cryptography_tests.c | 409 ----- .../stm32_example/Src/cryptography_tests.h | 10 - examples/stm32_example/Src/main.c | 614 -------- .../stm32_example/Src/stm32f4xx_hal_msp.c | 179 --- examples/stm32_example/Src/stm32f4xx_it.c | 164 -- examples/stm32_example/Src/system_stm32f4xx.c | 253 ---- .../System/Startup/startup_stm32f429zitx.s | 542 ------- examples/stm32_example/System/User/syscalls.c | 176 --- examples/stm32_example/System/User/sysmem.c | 79 - examples/stm32_example/readme.MD | 68 - examples/stm32_example/toolchain.cmake | 31 - examples/unix_example/CMakeLists.txt | 45 - examples/unix_example/main.c | 372 ----- hal/crypto/trezor_crypto/CMakeLists.txt | 10 - ...zor_aesgcm.c => lt_crypto_trezor_aesgcm.c} | 34 +- .../trezor_crypto/lt_crypto_trezor_ed25519.c | 16 + ...zor_sha256.c => lt_crypto_trezor_sha256.c} | 14 +- .../trezor_crypto/lt_crypto_trezor_x25519.c | 21 + hal/crypto/trezor_crypto/ts_trezor_x25519.c | 21 - hal/port/stm32/lt_port_stm32.c | 373 +++++ .../unix/lt_port_unix.c} | 231 ++- hal/spi/readme.MD | 10 - hal/spi/ts_l1_stm32_spi.c | 139 -- hal/spi/ts_l1_stm32_uart.c | 288 ---- hal/system/ts_random_stm32.c | 15 - hal/system/ts_random_unix.c | 12 - include/TROPIC01_configuration_objects.h | 395 +++++ include/bits.h | 89 ++ include/libtropic.h | 455 +++++- include/libtropic_common.h | 143 ++ include/libtropic_port.h | 83 + project.yml | 12 +- src/libtropic.c | 1345 +++++++++++++---- src/{ts_aesgcm.h => lt_aesgcm.h} | 46 +- src/{ts_crc16.c => lt_crc16.c} | 10 +- src/{ts_crc16.h => lt_crc16.h} | 12 +- src/lt_ed25519.h | 14 + src/{ts_hkdf.c => lt_hkdf.c} | 20 +- src/{ts_hkdf.h => lt_hkdf.h} | 16 +- src/{ts_hmac_sha256.h => lt_hmac_sha256.h} | 14 +- src/lt_l1.c | 161 ++ src/lt_l1.h | 68 + src/lt_l1_port_wrap.c | 81 + src/lt_l1_port_wrap.h | 78 + src/lt_l2.c | 145 ++ src/lt_l2.h | 46 + src/lt_l2_api_structs.h | 167 ++ src/lt_l2_frame_check.c | 55 + src/lt_l2_frame_check.h | 53 + src/lt_l3.c | 88 ++ src/lt_l3.h | 57 + src/lt_l3_api_structs.h | 641 ++++++++ src/lt_random.c | 19 + src/lt_random.h | 23 + src/{ts_sha256.h => lt_sha256.h} | 28 +- src/{ts_x25519.h => lt_x25519.h} | 12 +- src/ts_common.c | 77 - src/ts_common.h | 121 -- src/ts_l1.c | 173 --- src/ts_l1.h | 97 -- src/ts_l2.c | 182 --- src/ts_l2.h | 239 --- src/ts_l3.c | 83 - src/ts_l3.h | 555 ------- src/ts_random.c | 19 - src/ts_random.h | 22 - tests/integration/CMakeLists.txt | 72 + tests/integration/integration_tests.md | 44 + tests/integration/main.c | 13 + tests/support/support_ts_l1.h | 41 - tests/test_ts_common.c | 39 - tests/test_ts_l1.c | 85 -- tests/test_ts_l1_input_params.c | 88 -- tests/test_ts_l2.c | 139 -- tests/test_ts_l2_input_params.c | 28 - tests/test_ts_l3.c | 127 -- tests/test_ts_l3_input_params.c | 35 - tests/test_ts_libtropic_input_params.c | 125 -- tests/{ => unit}/support/.gitkeep | 0 tests/unit/test_libtropic.c | 894 +++++++++++ tests/{test_ts_crc.c => unit/test_lt_crc.c} | 5 +- tests/unit/test_lt_l1.c | 283 ++++ tests/unit/test_lt_l1_input_params.c | 97 ++ tests/unit/test_lt_l1_port_wrap.c | 155 ++ .../test_lt_l1_port_wrap_input_parameters.c | 57 + tests/unit/test_lt_l2.c | 213 +++ tests/unit/test_lt_l2_frame_check.c | 129 ++ .../test_lt_l2_frame_check_input_params.c | 21 + tests/unit/test_lt_l2_input_params.c | 31 + tests/unit/test_lt_l3.c | 134 ++ tests/unit/test_lt_l3_input_params.c | 38 + tests/unit/test_lt_libtropic_handshake.c | 181 +++ tests/unit/test_lt_libtropic_input_params.c | 716 +++++++++ ts_sw_setup.yml | 14 +- vendor/STM32CubeF4 | 1 - vendor/trezor_crypto/CMakeLists.txt | 19 +- 121 files changed, 9225 insertions(+), 8477 deletions(-) create mode 100644 .github/workflows/build_docs.yml create mode 100644 .github/workflows/integration_tests.yml delete mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/unit_tests.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100755 build_docs.sh delete mode 100644 examples/crypto_tests/CMakeLists.txt delete mode 100644 examples/crypto_tests/crypto_tests.h delete mode 100644 examples/crypto_tests/main.c create mode 100644 examples/hw_wallet/hw_wallet.c create mode 100644 examples/hw_wallet/hw_wallet.h delete mode 100644 examples/readme.MD delete mode 100644 examples/stm32_example/CMakeLists.txt delete mode 100644 examples/stm32_example/Inc/main.h delete mode 100644 examples/stm32_example/Inc/stm32f4xx_hal_conf.h delete mode 100644 examples/stm32_example/Inc/stm32f4xx_it.h delete mode 100644 examples/stm32_example/STM32F429ZITX_FLASH.ld delete mode 100644 examples/stm32_example/Src/cryptography_tests.c delete mode 100644 examples/stm32_example/Src/cryptography_tests.h delete mode 100644 examples/stm32_example/Src/main.c delete mode 100644 examples/stm32_example/Src/stm32f4xx_hal_msp.c delete mode 100644 examples/stm32_example/Src/stm32f4xx_it.c delete mode 100644 examples/stm32_example/Src/system_stm32f4xx.c delete mode 100644 examples/stm32_example/System/Startup/startup_stm32f429zitx.s delete mode 100644 examples/stm32_example/System/User/syscalls.c delete mode 100644 examples/stm32_example/System/User/sysmem.c delete mode 100644 examples/stm32_example/readme.MD delete mode 100644 examples/stm32_example/toolchain.cmake delete mode 100644 examples/unix_example/CMakeLists.txt delete mode 100644 examples/unix_example/main.c delete mode 100644 hal/crypto/trezor_crypto/CMakeLists.txt rename hal/crypto/trezor_crypto/{ts_trezor_aesgcm.c => lt_crypto_trezor_aesgcm.c} (75%) create mode 100644 hal/crypto/trezor_crypto/lt_crypto_trezor_ed25519.c rename hal/crypto/trezor_crypto/{ts_trezor_sha256.c => lt_crypto_trezor_sha256.c} (68%) create mode 100644 hal/crypto/trezor_crypto/lt_crypto_trezor_x25519.c delete mode 100644 hal/crypto/trezor_crypto/ts_trezor_x25519.c create mode 100644 hal/port/stm32/lt_port_stm32.c rename hal/{spi/ts_l1_unix_tcp.c => port/unix/lt_port_unix.c} (62%) delete mode 100644 hal/spi/readme.MD delete mode 100644 hal/spi/ts_l1_stm32_spi.c delete mode 100644 hal/spi/ts_l1_stm32_uart.c delete mode 100644 hal/system/ts_random_stm32.c delete mode 100644 hal/system/ts_random_unix.c create mode 100644 include/TROPIC01_configuration_objects.h create mode 100644 include/bits.h create mode 100644 include/libtropic_common.h create mode 100644 include/libtropic_port.h rename src/{ts_aesgcm.h => lt_aesgcm.h} (75%) rename src/{ts_crc16.c => lt_crc16.c} (90%) rename src/{ts_crc16.h => lt_crc16.h} (61%) create mode 100644 src/lt_ed25519.h rename src/{ts_hkdf.c => lt_hkdf.c} (58%) rename src/{ts_hkdf.h => lt_hkdf.h} (64%) rename src/{ts_hmac_sha256.h => lt_hmac_sha256.h} (66%) create mode 100644 src/lt_l1.c create mode 100644 src/lt_l1.h create mode 100644 src/lt_l1_port_wrap.c create mode 100644 src/lt_l1_port_wrap.h create mode 100644 src/lt_l2.c create mode 100644 src/lt_l2.h create mode 100644 src/lt_l2_api_structs.h create mode 100644 src/lt_l2_frame_check.c create mode 100644 src/lt_l2_frame_check.h create mode 100644 src/lt_l3.c create mode 100644 src/lt_l3.h create mode 100644 src/lt_l3_api_structs.h create mode 100644 src/lt_random.c create mode 100644 src/lt_random.h rename src/{ts_sha256.h => lt_sha256.h} (61%) rename src/{ts_x25519.h => lt_x25519.h} (62%) delete mode 100644 src/ts_common.c delete mode 100644 src/ts_common.h delete mode 100644 src/ts_l1.c delete mode 100644 src/ts_l1.h delete mode 100644 src/ts_l2.c delete mode 100644 src/ts_l2.h delete mode 100644 src/ts_l3.c delete mode 100644 src/ts_l3.h delete mode 100644 src/ts_random.c delete mode 100644 src/ts_random.h create mode 100644 tests/integration/CMakeLists.txt create mode 100644 tests/integration/integration_tests.md create mode 100644 tests/integration/main.c delete mode 100644 tests/support/support_ts_l1.h delete mode 100644 tests/test_ts_common.c delete mode 100644 tests/test_ts_l1.c delete mode 100644 tests/test_ts_l1_input_params.c delete mode 100644 tests/test_ts_l2.c delete mode 100644 tests/test_ts_l2_input_params.c delete mode 100644 tests/test_ts_l3.c delete mode 100644 tests/test_ts_l3_input_params.c delete mode 100644 tests/test_ts_libtropic_input_params.c rename tests/{ => unit}/support/.gitkeep (100%) create mode 100644 tests/unit/test_libtropic.c rename tests/{test_ts_crc.c => unit/test_lt_crc.c} (66%) create mode 100644 tests/unit/test_lt_l1.c create mode 100644 tests/unit/test_lt_l1_input_params.c create mode 100644 tests/unit/test_lt_l1_port_wrap.c create mode 100644 tests/unit/test_lt_l1_port_wrap_input_parameters.c create mode 100644 tests/unit/test_lt_l2.c create mode 100644 tests/unit/test_lt_l2_frame_check.c create mode 100644 tests/unit/test_lt_l2_frame_check_input_params.c create mode 100644 tests/unit/test_lt_l2_input_params.c create mode 100644 tests/unit/test_lt_l3.c create mode 100644 tests/unit/test_lt_l3_input_params.c create mode 100644 tests/unit/test_lt_libtropic_handshake.c create mode 100644 tests/unit/test_lt_libtropic_input_params.c delete mode 160000 vendor/STM32CubeF4 diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml new file mode 100644 index 0000000..02a0814 --- /dev/null +++ b/.github/workflows/build_docs.yml @@ -0,0 +1,59 @@ +#name: Build documentation +#on: +# push: +# branches: +# - 'master' +# - 'develop' +# +#jobs: +# build: +# runs-on: ubuntu-22.04 +# +# steps: +# - name: Checkout Repository +# uses: actions/checkout@v4.1.7 +# +# - name: Build Docs +# uses: mattnotmitt/doxygen-action@v1.9.5 +# with: +# doxyfile-path: 'docs/Doxyfile.in' +# enable-latex: false + + +name: Build documentation +on: + push: + branches: + - 'master' + - 'develop' + +jobs: + build: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout Repository + uses: actions/checkout@v4.1.7 + + - uses: ssciwr/doxygen-install@v1 + # with: + # version: "1.12.0" + + - name: Build docs + uses: threeal/cmake-action@v2.0.0 + with: + source-dir: ./ + build-dir: build + options: | + BUILD_DOCS=ON + USE_TREZOR_CRYPTO=ON + + - name: Create html release + uses: svenstaro/upload-release-action@latest + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: build/docs/doxygen/html/ + release_name: HTML Documentation + make_latest: true + overwrite: true + file_glob: true diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml new file mode 100644 index 0000000..0bda731 --- /dev/null +++ b/.github/workflows/integration_tests.yml @@ -0,0 +1,20 @@ +name: Integration test +on: + push: + branches: + - 'master' + - 'develop' + +jobs: + build: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout Repository + uses: actions/checkout@v4.1.7 + + - name: Build Integration tests + uses: threeal/cmake-action@v2.0.0 + with: + source-dir: tests/integration/ + build-dir: tests/integration/build \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 0c620c0..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,20 +0,0 @@ - -name: tests -on: - push: - branches: [ master ] - -jobs: - tests: - name: "Testing" - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v2 - - name: Run tests - uses: batov/ceedling_action@master - - name: Publish Unit Test Results - uses: EnricoMi/publish-unit-test-result-action@v1 - if: always() - with: - files: build/artifacts/test/junit_report.xml diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000..6214a13 --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,19 @@ +name: Unit tests and coverage +on: + push: + branches: + - 'master' + - 'develop' + +jobs: + build: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout Repository + uses: actions/checkout@v4.1.7 + + - name: Run Ceedling Unit Tests + uses: pavelpolach321/action-ceedling-unit-test@2.0.0 + with: + unit-test-path: '${{ github.workspace }}/' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7aae9e5..5d17bf9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,7 @@ stages: - test - - build + - build_lib + - build_integration - docs run_ceedling_tests: @@ -29,17 +30,28 @@ run_ceedling_tests: build_library: - stage: build + stage: build_lib tags: - shell script: - source setup_env - - cd examples/unix_example + - rm -rf build/ - mkdir build - cd build - - cmake .. + - cmake -DUSE_TREZOR_CRYPTO=1 .. - make +build_integration_tests: + stage: build_integration + tags: + - shell + script: + - source setup_env + - cd tests/integration/ + - mkdir build + - cd build + - cmake -DUSE_TREZOR_CRYPTO=1 .. + - make build_docs: stage: docs @@ -47,10 +59,11 @@ build_docs: - shell script: - source setup_env - - ls -la + - rm -rf build/ + - mkdir build - cd build - cmake -DBUILD_DOCS=1 .. - - make + - make doc_doxygen - cd docs/doxygen/latex - make - mv refman.pdf libtropic.pdf diff --git a/.gitmodules b/.gitmodules index 870801c..5458769 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "vendor/STM32CubeF4"] - path = vendor/STM32CubeF4 +[submodule "stm32_example/drivers/STM32CubeF4"] + path = stm32_example/drivers/STM32CubeF4 url = https://github.com/STMicroelectronics/STM32CubeF4 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..15a61af --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] diff --git a/CMakeLists.txt b/CMakeLists.txt index cce9978..ff4e379 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,120 +1,109 @@ cmake_minimum_required(VERSION 3.21.0) - -project(libtropic_SDK - VERSION 0.0.1 - DESCRIPTION "Tropic Square software development kit" - HOMEPAGE_URL "www.tropicsquare.com" - LANGUAGES C) - - ########################################################################### # # -# Library setup # +# Setup # # # ########################################################################### -option(TS_HAL_UNIX "Use TCP and connect to model" OFF) -option(TS_HAL_STM32_UART "Use UART and connect to model" OFF) -option(TS_HAL_STM32_SPI "Use SPI and connect to real chip" OFF) +option(USE_TREZOR_CRYPTO "Use trezor_crypto as a cryptography provider" OFF) +option(LT_CRYPTO_MBEDTLS "Use mbedtls as a cryptography provider" OFF) +option(BUILD_DOCS "Build documentation" OFF) +option(EXPERIMENTAL_SPI_UART "Experimental feature for spi slave to serial hw convertor" OFF) +option(EXPERIMENTAL_SPI_RASPBERRYPI "Experimental feature for spi slave on rpi 4" OFF) -option(TS_CRYPTO_TREZOR "Use trezor_crypto as a cryptography provider" ON) -option(TS_CRYPTO_MBEDTLS "Use mbedtls as a cryptography provider" OFF) +########################################################################### +# # +# Building documentation # +# # +########################################################################### -option(DEBUG "Compile with -g -Wextra -Wpedantic -Werror" ON) -option(BUILD_DOCS "Build documentation" OFF) +if(BUILD_DOCS) + find_package(Doxygen) + if(Doxygen_FOUND) + add_subdirectory(docs) + message(STATUS "Doxygen found, building docs") + else() + message(STATUS "Doxygen not found, not building docs") + endif() +endif() +# Check if cryptography provider is defined +if((NOT USE_TREZOR_CRYPTO) AND (NOT LT_CRYPTO_MBEDTLS) AND (NOT BUILD_DOCS)) + message(FATAL_ERROR "Mbed TLS or trezor_crypto must be enabled!") +endif() ########################################################################### # # -# libtropic source files # +# Collect files # # # ########################################################################### -# Enable l1 implementation for a target platform -if (TS_HAL_UNIX) - message(DEBUG "UNIX TCP HAL selected (for model)") - add_definitions(-DTS_HAL_UNIX=1) - # Main program is responsible for adding file from - # appropriate hal/XXX/XXX/folder into its sources and compile it, - # For more info check examples. -elseif(TS_HAL_STM32_SPI) - message(DEBUG "STM32 HAL selected ") - add_definitions(-DTS_HAL_STM32_SPI=1) - # TODO get rid of HOST_KEY_* once get info req with cert is working - add_definitions(-DHOST_KEY_FPGA=1) - # Main program is responsible for adding file from - # appropriate hal/XXX/XXX/folder into its sources and compile it, - # For more info check examples. -elseif(TS_HAL_STM32_UART) - message(DEBUG "STM32 HAL selected ") - add_definitions(-DTS_HAL_STM32_UART=1) - # Main program is responsible for adding file from - # appropriate hal/XXX/XXX/folder into its sources and compile it, - # For more info check examples. -else() - message(WARNING "No HAL enabled, add your own implementation for L1 functions !! ") - set(SDK_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_l1.c) -endif() +project(libtropic_SDK + VERSION 0.0.1 + DESCRIPTION "TROPIC01 software development kit" + HOMEPAGE_URL "www.tropicsquare.com" + LANGUAGES C) set(SDK_SRCS ${SDK_SRCS} - ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_common.c ${CMAKE_CURRENT_SOURCE_DIR}/src/libtropic.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_crc16.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_l1.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_l2.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_l3.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_hkdf.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ts_random.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_crc16.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l1_port_wrap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l1.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l2.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l2_frame_check.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l3.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_hkdf.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_random.c ) -add_library(tropic ${SDK_SRCS}) +set(SDK_INCS ${SDK_INCS} + ${CMAKE_CURRENT_SOURCE_DIR}/include/libtropic_common.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/libtropic.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/libtropic_port.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_crc16.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l1_port_wrap.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l1.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l2.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l2_frame_check.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_l3.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_hkdf.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/lt_random.h +) -target_include_directories(tropic PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include/ - ${CMAKE_CURRENT_SOURCE_DIR}/src/ +set(SDK_SRCS ${SDK_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/hal/crypto/trezor_crypto/lt_crypto_trezor_aesgcm.c + ${CMAKE_CURRENT_SOURCE_DIR}/hal/crypto/trezor_crypto/lt_crypto_trezor_ed25519.c + ${CMAKE_CURRENT_SOURCE_DIR}/hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/hal/crypto/trezor_crypto/lt_crypto_trezor_x25519.c ) -target_compile_options(tropic PRIVATE -Wall) +add_library(tropic ${SDK_SRCS} ${SDK_INCS}) -if(DEBUG) - target_compile_options(tropic PRIVATE -g -Wextra -Wpedantic -Werror) -endif() +target_include_directories(tropic PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/) +target_include_directories(tropic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/) +target_compile_definitions(tropic PRIVATE "$<$:LIBT_DEBUG>") ########################################################################### # # -# Setting up crypto backend based on option switches # +# Compile and link # # # ########################################################################### -if (TS_CRYPTO_TREZOR) - # Trezor library - add_subdirectory(vendor/trezor_crypto/ "trezor_crypto") - target_link_libraries(tropic PUBLIC trezor_crypto) - - # libtropic wrappers for trezor library - add_subdirectory(hal/crypto/trezor_crypto) - target_compile_definitions(tropic PRIVATE USE_TS_CRYPTO) +# This options just add 10ms synchronisation delay before read and write functions. +# Needed for hardware spi slave to uart converter. +if(EXPERIMENTAL_SPI_UART) + target_compile_definitions(tropic PRIVATE EXPERIMENTAL_SPI_UART=1) endif() -if (TS_CRYPTO_MBEDTLS) - message(FATAL_ERROR "Mbedtls support is not implemented yet") +if(EXPERIMENTAL_SPI_RASPBERRYPI) + target_compile_definitions(tropic PRIVATE EXPERIMENTAL_SPI_RASPBERRYPI=1) endif() - -########################################################################### -# # -# Building documentation is off by default # -# # -########################################################################### - -if(BUILD_DOCS) - find_package(Doxygen) - if(Doxygen_FOUND) - add_subdirectory(docs) - message(STATUS "Doxygen found, building docs") - else() - message(STATUS "Doxygen not found, not building docs") - endif() +if(USE_TREZOR_CRYPTO) + add_subdirectory(vendor/trezor_crypto/ "trezor_crypto") + target_compile_definitions(trezor_crypto PRIVATE AES_VAR) + target_link_libraries(tropic PRIVATE trezor_crypto) + target_compile_definitions(tropic PRIVATE USE_TREZOR_CRYPTO) endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..74fd973 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing + +To make contributing simple for both sides: + +## [1] Open an Issue + +- Describe how you would like to contribute and discuss details with us +- We will create a branch for you + +## [2] Create a Pull Request: + +- Make sure the code is properly tested and must pass on CI +- MAke sure the code is properly formatted diff --git a/README.md b/README.md index 3f647ec..de67332 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # libtropic -![](https://github.com/tropicsquare/libtropic/actions/workflows/main.yml/badge.svg) ![](https://tropic-gitlab.corp.sldev.cz/internal/sw-design/libtropic/badges/master/coverage.svg) +![](https://github.com/tropicsquare/libtropic/actions/workflows/unit_tests.yml/badge.svg) ![](https://github.com/tropicsquare/libtropic/actions/workflows/integration_tests.yml/badge.svg) ![](https://github.com/tropicsquare/libtropic/actions/workflows/build_docs.yml/badge.svg) ![](https://tropic-gitlab.corp.sldev.cz/internal/sw-design/libtropic/badges/master/coverage.svg) TROPIC01's SDK written in C. @@ -11,13 +11,25 @@ For more info about TROPIC01 check datasheet and API pdf. # Repository structure * `docs/` Documentation -* `examples/` Examples of usage +* `examples/` A few examples how libtropic might be used * `hal/` Support code for various platforms - transport layer, delay function and RNG -* `include/` Public header file +* `include/` Public API header files * `src/` Library's source files -* `tests/` Tests +* `tests/` Unit tests and integration tests * `vendor/` Third party libraries and tools +# Get started! + +Instructions differ based on whether you have physical chip on hand or not: + +### Physical TROPIC01 + +[This](https://github.com/tropicsquare/libtropic-stm32) link leads to an example embedded project, featuring `STM32` devboard and `real TROPIC01` chip. + +### Emulated TROPIC01 + +[This](tests/integration/integration_tests.md) link leads to an example project, featuring `Unix` environment and `emulated TROPIC01` chip. + # Documentation -Start with reading `docs/index.md` +More info can be found here: `docs/index.md` diff --git a/build_docs.sh b/build_docs.sh new file mode 100755 index 0000000..44269e8 --- /dev/null +++ b/build_docs.sh @@ -0,0 +1,13 @@ +rm -rf build +mkdir build +cd build +cmake -DBUILD_DOCS=1 -DUSE_TREZOR_CRYPTO=1 .. +make doc_doxygen +mkdir packed +cd docs/doxygen/latex/ +make +mv refman.pdf ../../../packed/ +cd ../ +mv html/ ../../packed/ +cd ../../ +tar -zcvf packed.tar.gz packed/ diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index 3641e8b..0bf2081 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -1,4 +1,4 @@ -# Doxyfile 1.9.1 +# Doxyfile 1.10.0 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -12,6 +12,16 @@ # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -32,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "libtropic-c" +PROJECT_NAME = libtropic # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -44,7 +54,7 @@ PROJECT_NUMBER = # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "C library for TROPIC01" +PROJECT_BRIEF = "C library for TROPIC01 chip" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -53,6 +63,12 @@ PROJECT_BRIEF = "C library for TROPIC01" PROJECT_LOGO = +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If @@ -60,16 +76,28 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = ../docs/doxygen/ -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes -# performance problems for the file system. +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode @@ -81,26 +109,18 @@ ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -115,7 +135,7 @@ BRIEF_MEMBER_DESC = YES # brief descriptions will be completely suppressed. # The default value is: YES. -REPEAT_BRIEF = YES +REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found @@ -158,7 +178,7 @@ INLINE_INHERITED_MEMB = NO # shortest path that makes the file name unique will be used # The default value is: YES. -FULL_PATH_NAMES = YES +FULL_PATH_NAMES = NO # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand @@ -170,7 +190,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = ../../libtropic/ +STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -246,7 +266,7 @@ INHERIT_DOCS = YES # of the file/class/namespace that contains it. # The default value is: NO. -SEPARATE_MEMBER_PAGES = NO +SEPARATE_MEMBER_PAGES = YES # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. @@ -258,16 +278,16 @@ TAB_SIZE = 4 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:\n" +# "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) ALIASES = @@ -312,8 +332,8 @@ OPTIMIZE_OUTPUT_SLICE = NO # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make doxygen treat .inc files @@ -349,6 +369,17 @@ MARKDOWN_SUPPORT = YES TOC_INCLUDE_HEADINGS = 5 +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or @@ -460,19 +491,27 @@ TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 -# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, -# which efficively disables parallel processing. Please report any issues you +# which effectively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 1 +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -554,7 +593,8 @@ HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO @@ -585,14 +625,15 @@ INTERNAL_DOCS = NO # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that -# are not case sensitive the option should be be set to NO to properly deal with +# are not case sensitive the option should be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. -# The default value is: system dependent. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. CASE_SENSE_NAMES = YES @@ -610,6 +651,12 @@ HIDE_SCOPE_NAMES = NO HIDE_COMPOUND_REFERENCE= NO +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -640,7 +687,7 @@ INLINE_INFO = YES # name. If set to NO, the members will appear in declaration order. # The default value is: YES. -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member @@ -767,7 +814,8 @@ FILE_VERSION_FILTER = # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE @@ -813,27 +861,50 @@ WARNINGS = YES WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = NO +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about +# undocumented enumeration values. If set to NO, doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the doxygen process doxygen will return with a non-zero status. -# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. WARN_AS_ERROR = NO @@ -844,13 +915,27 @@ WARN_AS_ERROR = NO # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard -# error (stderr). +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). WARN_LOGFILE = @@ -864,17 +949,30 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../src/ @CMAKE_CURRENT_SOURCE_DIR@/index.md +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../include/ \ + @CMAKE_CURRENT_SOURCE_DIR@/../src/ \ + @CMAKE_CURRENT_SOURCE_DIR@/index.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. @@ -886,12 +984,12 @@ INPUT_ENCODING = UTF-8 # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, -# *.ucf, *.qsf and *.ice. +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, +# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to +# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.cc \ @@ -974,10 +1072,7 @@ EXCLUDE_PATTERNS = *.c # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* +# ANamespace::AClass, ANamespace::*Test EXCLUDE_SYMBOLS = @@ -1022,6 +1117,11 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. @@ -1061,7 +1161,16 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = index.md +USE_MDFILE_AS_MAINPAGE = @CMAKE_CURRENT_SOURCE_DIR@/index.md + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -1077,7 +1186,8 @@ USE_MDFILE_AS_MAINPAGE = index.md SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. +# multi-line macros, enums or list initialized variables directly into the +# documentation. # The default value is: NO. INLINE_SOURCES = NO @@ -1149,44 +1259,6 @@ USE_HTAGS = NO VERBATIM_HEADERS = NO -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: -# http://clang.llvm.org/) for more accurate parsing at the cost of reduced -# performance. This can be particularly helpful with template rich C++ code for -# which doxygen's built-in parser lacks the necessary type information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse_libclang=ON option for CMake. -# The default value is: NO. - -CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to -# YES then doxygen will add the directory of each input to the include path. -# The default value is: YES. - -CLANG_ADD_INC_PATHS = YES - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -CLANG_OPTIONS = - -# If clang assisted parsing is enabled you can provide the clang parser with the -# path to the directory containing a file called compile_commands.json. This -# file is the compilation database (see: -# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the -# options used when the source files were built. This is equivalent to -# specifying the -p option to a clang tool, such as clang-check. These options -# will then be passed to the parser. Any options specified with CLANG_OPTIONS -# will be added as well. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse_libclang=ON option for CMake. - -CLANG_DATABASE_PATH = - #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1198,10 +1270,11 @@ CLANG_DATABASE_PATH = ALPHABETICAL_INDEX = YES -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1280,10 +1353,16 @@ HTML_STYLESHEET = # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/html/doxygen-awesome.css @CMAKE_CURRENT_SOURCE_DIR@/html/doxygen-awesome-sidebar-only.css +HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/html/doxygen-awesome.css \ + @CMAKE_CURRENT_SOURCE_DIR@/html/doxygen-awesome-sidebar-only.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -1295,9 +1374,22 @@ HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/html/doxygen-awesome.css @CM HTML_EXTRA_FILES = +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generate light mode output, DARK always +# generate dark mode output, AUTO_LIGHT automatically set the mode according to +# the user preference, use light mode if no preference is set (the default), +# AUTO_DARK automatically set the mode according to the user preference, use +# dark mode if no preference is set and TOGGLE allow to user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see +# this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1307,7 +1399,7 @@ HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A +# in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1325,15 +1417,6 @@ HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will @@ -1353,6 +1436,33 @@ HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = NO +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to @@ -1389,6 +1499,13 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. @@ -1414,8 +1531,12 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: -# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1472,6 +1593,16 @@ BINARY_TOC = NO TOC_EXPAND = NO +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help @@ -1574,16 +1705,28 @@ DISABLE_INDEX = NO # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # @@ -1608,6 +1751,13 @@ TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for @@ -1628,17 +1778,6 @@ HTML_FORMULA_FORMAT = png FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. @@ -1656,11 +1795,29 @@ FORMULA_MACROFILE = USE_MATHJAX = NO +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1673,15 +1830,21 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = @@ -1810,7 +1973,7 @@ LATEX_OUTPUT = latex # the output language. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_CMD_NAME = +LATEX_CMD_NAME = "\"pdflatex\" --shell-escape" # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # index for LaTeX. @@ -1860,30 +2023,32 @@ PAPER_TYPE = a4 # This tag requires that the tag GENERATE_LATEX is set to YES. EXTRA_PACKAGES = -#tropic_includes -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the -# generated LaTeX document. The header should contain everything until the first -# chapter. If it is left blank doxygen will generate a standard header. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that doxygen normally uses. # -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_HEADER =@CMAKE_CURRENT_SOURCE_DIR@/latex/libtropic_header.tex -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See +LATEX_HEADER = @CMAKE_CURRENT_SOURCE_DIR@/latex/libtropic_header.tex + +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = @@ -1905,7 +2070,8 @@ LATEX_EXTRA_STYLESHEET = # markers available. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_EXTRA_FILES =@CMAKE_CURRENT_SOURCE_DIR@/img/TS_logo_blue.pdf @CMAKE_CURRENT_SOURCE_DIR@/img/TS_logo_blue_symbol.pdf +LATEX_EXTRA_FILES = @CMAKE_CURRENT_SOURCE_DIR@/img/TS_logo_blue.pdf \ + @CMAKE_CURRENT_SOURCE_DIR@/img/TS_logo_blue_symbol.pdf # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will @@ -1926,10 +2092,16 @@ PDF_HYPERLINKS = YES USE_PDFLATEX = YES -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode -# command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. This option is also used -# when generating formulas in HTML. +# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. +# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch +# mode nothing is printed on the terminal, errors are scrolled as if is +# hit at every error; missing files that TeX tries to input or request from +# keyboard input (\read on a not open input stream) cause the job to abort, +# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, +# but there is no possibility of user interaction just like in batch mode, +# SCROLL In scroll mode, TeX will stop only for missing files to input or if +# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at +# each error, asking for user intervention. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1942,16 +2114,6 @@ LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO -# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source -# code with syntax highlighting in the LaTeX output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. @@ -1960,14 +2122,6 @@ LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_TIMESTAMP = NO - # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # path from which the emoji images will be read. If a relative path is entered, # it will be relative to the LATEX_OUTPUT directory. If left blank the @@ -2032,16 +2186,6 @@ RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_SOURCE_CODE = NO - #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- @@ -2138,27 +2282,44 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures # the structure of the code including all documentation. Note that this feature # is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + +# If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3 +# database with symbols found by doxygen stored in tables. +# The default value is: NO. + +GENERATE_SQLITE3 = NO + +# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be +# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put +# in front of it. +# The default directory is: sqlite3. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_OUTPUT = sqlite3 + +# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db +# database file will be recreated with each doxygen run. If set to NO, doxygen +# will warn if a database file is already found and not modify it. +# The default value is: YES. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_RECREATE_DB = YES + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- @@ -2233,7 +2394,8 @@ SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the -# preprocessor. +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @@ -2300,15 +2462,15 @@ TAGFILES = GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES, all external class will be listed in -# the class index. If set to NO, only the inherited external classes will be -# listed. +# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces +# will be listed in the class and namespace index. If set to NO, only the +# inherited external classes will be listed. # The default value is: NO. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will be +# in the topic index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. @@ -2322,25 +2484,9 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to diagram generator tools #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - -# You can include diagrams made with dia in doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. - -DIA_PATH = - # If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. @@ -2349,10 +2495,10 @@ HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO -# The default value is: YES. +# The default value is: NO. HAVE_DOT = YES @@ -2366,53 +2512,81 @@ HAVE_DOT = YES DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = Helvetica +DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" + +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for -# each documented class showing the direct and indirect inheritance relations. -# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will +# generate a graph for each documented class showing the direct and indirect +# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and +# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case +# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the +# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. +# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance +# relations will be shown as texts / links. Explicit enabling an inheritance +# graph or choosing a different representation for an inheritance graph of a +# specific class, can be accomplished by means of the command \inheritancegraph. +# Disabling an inheritance graph can be accomplished by means of the command +# \hideinheritancegraph. +# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a # graph for each documented class showing the direct and indirect implementation # dependencies (inheritance, containment, and class references variables) of the -# class with other documented classes. +# class with other documented classes. Explicit enabling a collaboration graph, +# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the +# command \collaborationgraph. Disabling a collaboration graph can be +# accomplished by means of the command \hidecollaborationgraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. -COLLABORATION_GRAPH = YES +COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. +# groups, showing the direct groups dependencies. Explicit enabling a group +# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means +# of the command \groupgraph. Disabling a directory graph can be accomplished by +# means of the command \hidegroupgraph. See also the chapter Grouping in the +# manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. -GROUP_GRAPHS = YES +GROUP_GRAPHS = NO # If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling @@ -2450,8 +2624,8 @@ DOT_UML_DETAILS = NO # The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters # to display on a single line. If the actual line length exceeds this threshold -# significantly it will wrapped across multiple lines. Some heuristics are apply -# to avoid ugly line breaks. +# significantly it will be wrapped across multiple lines. Some heuristics are +# applied to avoid ugly line breaks. # Minimum value: 0, maximum value: 1000, default value: 17. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2468,7 +2642,9 @@ TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to # YES then doxygen will generate a graph for each documented file showing the # direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# can be accomplished by means of the command \includegraph. Disabling an +# include graph can be accomplished by means of the command \hideincludegraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2477,7 +2653,10 @@ INCLUDE_GRAPH = YES # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are # set to YES then doxygen will generate a graph for each documented file showing # the direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set +# to NO, can be accomplished by means of the command \includedbygraph. Disabling +# an included by graph can be accomplished by means of the command +# \hideincludedbygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2517,22 +2696,30 @@ GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the # dependencies a directory has on other directories in a graphical way. The # dependency relations are determined by the #include relations between the -# files in the directories. +# files in the directories. Explicit enabling a directory graph, when +# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command +# \directorygraph. Disabling a directory graph can be accomplished by means of +# the command \hidedirectorygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. DIRECTORY_GRAPH = YES +# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels +# of child directories generated in directory dependency graphs by dot. +# Minimum value: 1, maximum value: 25, default value: 1. +# This tag requires that the tag DIRECTORY_GRAPH is set to YES. + +DIR_GRAPH_MAX_DEPTH = 1 + # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: -# http://www.graphviz.org/)). +# https://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). -# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, -# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, -# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, +# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, # png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and # png:gdiplus:gdiplus. # The default value is: png. @@ -2565,11 +2752,12 @@ DOT_PATH = DOTFILE_DIRS = -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. -MSCFILE_DIRS = +DIA_PATH = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile @@ -2578,10 +2766,10 @@ MSCFILE_DIRS = DIAFILE_DIRS = # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. PLANTUML_JAR_PATH = @@ -2619,18 +2807,6 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2643,6 +2819,8 @@ DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2651,8 +2829,24 @@ GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. # -# Note: This setting is not only used for dot files but also for msc and -# plantuml temporary files. +# Note: This setting is not only used for dot files but also for msc temporary +# files. # The default value is: YES. DOT_CLEANUP = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will +# use a built-in version of mscgen tool to produce the charts. Alternatively, +# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, +# specifying prog as the value, doxygen will call the tool as prog -T +# -o . The external tool should support +# output file formats "png", "eps", "svg", and "ismap". + +MSCGEN_TOOL = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = diff --git a/docs/index.md b/docs/index.md index 454ab3b..e10a1d9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,123 +1,136 @@ -# libtropic +# Introduction -## Introduction +`libtropic` is a C library, which implements functionalities for interfacing applications with TROPIC01 device. It comes without any security claims and shall be used for evaluation purpose only. -This library implements functionalities for interfacing applications with TROPIC01 device. It comes without any security claims and shall be used for evaluation purpose only. -Supported TROPIC devices: +|Supported devices |Description | +|--------------------------------------------------------|---------------------------------------------------------| +|[TROPIC01](https://www.tropicsquare.com/TROPIC01) | First generation TROPIC01 | -|Device |Comment | -|--------------------------------------------------------|------------------------------------------------------| -|[TROPIC01](https://www.tropicsquare.com/TROPIC01) | First generation TROPIC01 | +# Repository overview +Codebase consists of: +* `examples`: C code concepts to show how libtropic might be used on host system +* `hal`: Contains `crypto` and `port` interfaces. Files in these folders allows libtropic to be used with various cryptography libraries and on different hardware platforms. Both `crypto` and `port` folders are meant to be compiled within a main project (the one which consumes libtropic library). They provide a way for libtropic core to interact with host's cryptography primitives and hardware layer. +* `src`: Libtropic's core source files, facilitating data handling between host's application and TROPIC01 chip +* `tests`: Unit and integration tests +* `vendor`: External libraries and tools +# Library usage ## Dependencies Used build system is **cmake 3.21**: ``` - $ sudo apt install cmake +$ sudo apt install cmake ``` -[Ceedling](https://www.throwtheswitch.com) is used for running tests and creating code coverage report, install it like this: +## Options -``` - # Install Ruby - $ sudo apt-get install ruby-full +This library was designed to be compiled during the build of a parent project. - # Ceedling install - $ gem install ceedling +It provides following options to be defined during building: - # Code coverage tool used by Ceedling - $ pip install gcovr +``` +option(USE_TREZOR_CRYPTO "Use trezor_crypto as a cryptography provider" OFF) +option(LT_CRYPTO_MBEDTLS "Use mbedtls as a cryptography provider" OFF) +option(BUILD_DOCS "Build documentation" OFF) ``` +Options could be passed as a command line argument, or they could be defined in main project's cmake files when this library is added to its build tree. -## Examples -A few examples of library's usage are placed in `examples/` folder. +## Examples +List of projects which uses `libtropic`: +* `tests/integration/integration_tests.md`: Unix program to test API calls against model of TROPIC01 +* `STM32 example`: Firmware for STM32f429 discovery board which implements libropic's API calls against TROPIC01 chip (or model) -## Running tests +## Static archive -Make sure you have Ceedling installed (as described in Dependencies). +*Note: When compiling the library standalone as a static archive, a cryptography provider must be defined through cmake -D arguments* -Expected version: +Compile `libtropic` as a static archive under Unix: ``` -$ ceedling version - Ceedling:: 0.31.1 - Unity:: 2.5.4 - CMock:: 2.5.4 - CException:: 1.3.3 - +$ mkdir build +$ cd build +$ cmake -DUSE_TREZOR_CRYPTO=1 .. +$ make ``` -Running tests and creating code coverage report: +Cross-compile `libtropic` as a static archive: ``` -$ ceedling gcov:all utils:gcov +$ mkdir build +$ cd build +$ cmake -DUSE_TREZOR_CRYPTO=1 -DCMAKE_TOOLCHAIN_FILE=/toolchain.cmake -DLINKER_SCRIPT=/linker_script.ld .. +$ make ``` -## Library configuration +## Build documentation -See option() calls in root **CMakelists.txt** and check also how CMakeLists.txt looks in example projects. - -### Cryptography support - -For certain operations on application's side, libtropic needs cryptography support. It is possible to choose a cryptography provider, because definitions of crypto functions are chosen during compilation. - -Current default provider of cryptogprahy is `vendor/trezor_crypto`. +We use Doxygen (1.9.1) and LaTeX (pdfTeX 3.141592653-2.6-1.40.24 (TeX Live 2022)) +Build html docs: ``` -# Use trezor_crypto library: - -option(TS_CRYPTO_TREZOR "Use trezor_crypto as a cryptography provider" ON) +$ mkdir build/ +$ cd build/ +$ cmake -DBUILD_DOCS=1 .. +$ make doc_doxygen ``` +Build pdf documentation: +``` +$ cd docs/doxygen/latex +$ make +``` -## Library overview - -**Tropic layer 1** - - This layer is processing raw data transfers. +# Testing - Available L1 implementations are: +## Unit tests -* SPI (libtropic on embedded target and Physical chip, or FPGA) -* TCP (libtropic on Unix and TROPIC01's model on Unix) -* Serialport (libtropic on embedded target and TROPIC01's model on Unix) +Unit tests files are in `tests/unit/` folder. They are written in [Ceedling](https://www.throwtheswitch.com) framework, install it like this: -Use `option()` switch to enable libtropic support for a certain platform, have a look in examples. +``` + # Install Ruby + $ sudo apt-get install ruby-full -If there is no support for a platform, user is expected to provide own implementation for weak functions in this layer. + # Ceedling install + $ gem install ceedling -Related code: -* ts_l1.c -* ts_l1.h + # Code coverage tool used by Ceedling + $ pip install gcovr +``` -**Tropic layer 2** +Then make sure that you have correct version: -This layer is responsible for executing l2 request/response functions. +``` +$ ceedling version + Ceedling:: 0.31.1 + Unity:: 2.5.4 + CMock:: 2.5.4 + CException:: 1.3.3 -Related code: -* ts_l2.c -* ts_l2.h +``` -**Tropic layer 3** +Once ceedling is installed, run tests and create code coverage report: -This layer is preparing and parsing l3 commands/results, it uses l2 functions to send and receive payloads. +``` +$ ceedling gcov:all utils:gcov +``` -Related code: -* ts_l3.c -* ts_l3.h +### Randomization +Some tests use a rudimentary randomization mechanism using standard C functions. The PRNG is normally +seeded with current time. Used seed is always printed to stdout. You can find the seed in logs +(`build/gcov/results/...`). -**libtropic** +To run tests with fixed seed, set `RNG_SEED` parameter to your +desired seed (either directly in the file, or in the project.yml section `:defines:`). This is +useful mainly to replicate a failed test run -- just find out what seed was used and then +set `RNG_SEED` to this. -This is a highest abstraction of tropic chip functionalities. -Library offers various calls to simplify tropic chip usage on a target platform: +## Integration tests -Related code: -* libtropic.c -* libtropic.h +For more info check `tests/integration/integration_tests.md` diff --git a/docs/latex/libtropic_header.tex b/docs/latex/libtropic_header.tex index 141fd3c..62113ca 100644 --- a/docs/latex/libtropic_header.tex +++ b/docs/latex/libtropic_header.tex @@ -1,131 +1,105 @@ -% Latex header for doxygen 1.9.1 -%\let\mypdfximage\pdfximage\def\pdfximage{\immediate\mypdfximage}\documentclass[twoside]{report} -\documentclass{report} -\renewcommand{\thesection}{\arabic{section}} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Header and footer TODO make git stuff automatic +%% +%% Copyright © 2022 Tropic Square s.r.o. (https://tropicsquare.com/) +%% +%% This work is subject to the license terms of the LICENSE.txt file in the +%% root directory of this source tree. +%% +%% If a copy of the LICENSE file was not distributed with this work, you can +%% obtain one at (https://tropicsquare.com/license). +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Parameters Needed by Design spec class (must be inside document) -% Set these parameters according to your project. -\def \projectname {libtropic} -\def \documentname {C library for TROPIC devices} -\def \versionnumber {0.0.1} -\def \GitTag {v0.0.1} -\def \GitHash {0xhashhash} -%% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package -\usepackage{ifthen} -\ifx\requestedLaTeXdate\undefined -\usepackage{array} -\else -\usepackage{array}[=2016-10-06] -\fi -%% +% Specify Tropic Square document class +\documentclass[notconfidential]{tropic_design_spec} + +% Undefine these commands defined in ts-latex-lib (doxygen redefines it) +\makeatletter + \let\c@LT@tables\undefined + \let\c@LT@chunks\undefined +\makeatother + % Packages required by doxygen -\usepackage{fixltx2e} +\PassOptionsToPackage{rgb,table}{xcolor} \usepackage{doxygen} -\usepackage{graphicx} -\usepackage[utf8]{inputenc} \usepackage{makeidx} -\PassOptionsToPackage{warn}{textcomp} -\usepackage{textcomp} -\usepackage[nointegrals]{wasysym} -\usepackage{ifxetex} -% Font selection -\usepackage[T1]{fontenc} -\usepackage[scaled=.90]{helvet} -\usepackage{courier} -\renewcommand{\familydefault}{\sfdefault} -\usepackage{sectsty} -\allsectionsfont{% - \fontseries{bc}\selectfont% - \color{darkgray}% +\makeindex + +% Put sections on new page +\AddToHook{cmd/doxysection/before}{\clearpage} + +% Use itemize and enumerate from ts-latex-lib +\let\DoxyItemize\itemize +\let\DoxyEnumerate\enumerate + +% TODO: redo this +\newenvironment{TropicRatioTableTwoCol}[3] +{% + \renewcommand{\tropicnumtablecols}{2} + \TropicRatioGuts {2}{#3}{#1}{#2}{0}{0}{0}{0}{0} } -\renewcommand{\DoxyLabelFont}{% - \fontseries{bc}\selectfont% - \color{darkgray}% +{% + \endtabularx% } -\newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}} -% Arguments of doxygenemoji: -% 1) '::' form of the emoji, already "LaTeX"-escaped -% 2) file with the name of the emoji without the .png extension -% in case image exist use this otherwise use the '::' form -\newcommand{\doxygenemoji}[2]{% - \IfFileExists{./#2.png}{\raisebox{-0.1em}{\includegraphics[height=0.9em]{./#2.png}}}{#1}% +% TODO: redo this +\newenvironment{TropicRatioTableThreeCol}[4] +{% + \renewcommand{\tropicnumtablecols}{3} + \TropicRatioGuts {3}{#4}{#1}{#2}{#3}{0}{0}{0}{0} } -% Page & text layout -\usepackage{geometry} -\geometry{% - a4paper,% - top=2.5cm,% - bottom=2.5cm,% - left=1.5cm,% - right=1.5cm% +{% + \endtabularx% } -\tolerance=750 -\hfuzz=15pt -\hbadness=750 -\setlength{\emergencystretch}{15pt} -\setlength{\parindent}{0cm} -\newcommand{\doxynormalparskip}{\setlength{\parskip}{3ex plus 2ex minus 2ex}} -\newcommand{\doxytocparskip}{\setlength{\parskip}{1ex plus 0ex minus 0ex}} -\doxynormalparskip -\makeatletter -\renewcommand{\paragraph}{% - \@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{% - \normalfont\normalsize\bfseries\SS@parafont% - }% + +% Redefine environment for tables with params +\renewenvironment{DoxyParams}[2][0] +{% + \doxysubsubsubsubsection*{#2}% + \TropicRatioTableTwoCol% + {0.2} {0.8}% + {Name & Description}% } -\renewcommand{\subparagraph}{% - \@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{% - \normalfont\normalsize\bfseries\SS@subparafont% - }% +{% + \endTropicRatioTableTwoCol% } -\makeatother - -\makeatletter -\newcommand\hrulefilll{\leavevmode\leaders\hrule\hskip 0pt plus 1filll\kern\z@} -\makeatother -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Header and footer -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\usepackage{fancyhdr} -\pagestyle{fancy} -\renewcommand{\footrulewidth}{0.4pt} -% -\fancyhf{} -\fancyhead[R]{\leftmark} -\fancyhead[L]{% - % Then put table with two rows and two columns - \begin{tabular}{ c l } - \multirow{2}{*} - {\includegraphics[width=0.8cm]{\detokenize{TS_logo_blue_symbol.pdf}}} & \projectname\space \\ - & \documentname \\ - \end{tabular}% +% Redefine environment for tables with data fields +\renewenvironment{DoxyFields}[2][0] +{% + \doxysubsubsubsubsection*{#2}% + \TropicRatioTableThreeCol% + {0.22} {0.43} {0.35}% + {Type & Name & Description}% +} +{% + \endTropicRatioTableThreeCol% } -\fancyhf[cf]{\textcolor{red}{\textbf{WORK IN PROGRESS}}} - -\rfoot{Page: \thepage} -\lfoot{Version: \versionnumber \newline Git commit: \GitHash} - -\renewcommand{\chaptermark}[1]{% - \markboth{#1}{}% +% Redefine environment for tables with enumerators +\renewenvironment{DoxyEnumFields}[2][0] +{% + \doxysubsubsubsubsection*{#2}% + \TropicRatioTableTwoCol% + {0.4} {0.6}% + {Name & Description}% } -\renewcommand{\sectionmark}[1]{% - \markright{\thesection\ #1}% +{% + \endTropicRatioTableTwoCol% } -% Indices & bibliography -\usepackage{natbib} -\usepackage[titles]{tocloft} -\setcounter{tocdepth}{3} -\setcounter{secnumdepth}{5} -\makeindex +% Redefine DoxyCodeLine cmd to make code bigger +\renewcommand\DoxyCodeLine[1] +{ + \ifthenelse{\equal{\detokenize{#1}}{}} + { + \vspace*{\baselineskip} + } + { + \hangpara{\DoxyCodeWidth}{1}{\normalsize #1}\par + } +} \usepackage{newunicodechar} \newunicodechar{⁻}{${}^{-}$}% Superscript minus @@ -133,142 +107,64 @@ \newunicodechar{³}{${}^{3}$}% Superscript three % Hyperlinks (required, but should be loaded last) -\ifpdf - \usepackage[pdftex,pagebackref=true]{hyperref} -\else - \ifxetex - \usepackage[pagebackref=true]{hyperref} - \else - \usepackage[ps2pdf,pagebackref=true]{hyperref} - \fi -\fi - -\hypersetup{% - colorlinks=true,% - linkcolor=blue,% - citecolor=blue,% - unicode% -} - -% Custom commands +% \ifpdf +% \PassOptionsToPackage{pdftex,pagebackref=true}{hyperref} +% \else +% \ifxetex +% \PassOptionsToPackage{pagebackref=true}{hyperref} +% \else +% \PassOptionsToPackage{ps2pdf,pagebackref=true}{hyperref} +% \fi +% \fi +% \hypersetup{% +% colorlinks=true,% +% linkcolor=TropicBlue,% +% citecolor=TropicBlue,% +% unicode% +% } + +% Custom commands for Doxygen \newcommand{\clearemptydoublepage}{% \newpage{\pagestyle{empty}\cleardoublepage}% } - -\usepackage{caption} -\captionsetup{labelsep=space,justification=centering,font={bf},singlelinecheck=off,skip=4pt,position=top} - -\usepackage{etoc} -\etocsettocstyle{\doxytocparskip}{\doxynormalparskip} -\renewcommand{\numberline}[1]{#1~} - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Define Tropic Square colors based on graphic manual -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\definecolor{TropicBlue}{RGB}{0,50,255} -\definecolor{TropicDarkBlue}{RGB}{26,55,97} -\definecolor{TropicVeryDarkBlue}{RGB}{18,21,33} -% Color for requirements which are "DESIGNED" -\definecolor{ReqDesignedGreen}{RGB}{0.0, 125, 0.0} -% Colors for Code highlighting -\definecolor{CodeGreen}{rgb}{0,0.6,0} -\definecolor{CodeGray}{rgb}{0.5,0.5,0.5} -\definecolor{CodePurple}{rgb}{0.58,0,0.82} -\definecolor{CodeBgGray}{rgb}{0.95,0.95,0.92} +\newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}} % Hyperlinks (required, but should be loaded last) \usepackage{ifpdf} \ifpdf - \usepackage[pdftex,pagebackref=true]{hyperref} + \PassOptionsToPackage{pdftex,pagebackref=true}{hyperref} \else - \usepackage[ps2pdf,pagebackref=true]{hyperref} + \PassOptionsToPackage{ps2pdf,pagebackref=true}{hyperref} \fi \hypersetup{% - colorlinks=true,% - linkcolor=TropicBlue,% - citecolor=TropicBlue,% + colorlinks = true,% + linkcolor = TropicBlue,% + citecolor = TropicBlue,% + urlcolor = TropicBlue,% + anchorcolor = TropicBlue,% unicode% } - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Title page +% Document properties and title page %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\renewcommand*{\maketitle}{ -\begin{titlepage} - \begin{flushright} - - % Draw horizontal line above the page - \color{TropicBlue} - \par\noindent\rule{\textwidth}{5pt} - \color{black} - - \vspace*{1cm} - - \huge - \textbf{\projectname} - - \vspace{0.5cm} - - \large - \textbf{\documentname} - - \vspace{0.1cm} - - \normalsize - \textbf{Version: \versionnumber} - - \vspace{0.1cm} - - \normalsize - \textbf{Git tag: \GitTag} - \vfill - - \vfill - - \large - Tropic Square - - - % Current date - \normalsize - \today - - \vspace{0.5cm} - - \includegraphics[width=0.4\textwidth]{\detokenize{TS_logo_blue.pdf}} - - % Line below the title page - \color{TropicBlue} - \par\noindent\rule{\textwidth}{5pt} - - \end{flushright} -\end{titlepage} -} - - -%===== C O N T E N T S ===== +\title{Design specification - Template} +\author{Ondrej Ille, Tropic Square} +\date{July 2021} +% Start of document \begin{document} -\raggedbottom -% Titlepage & ToC -\hypersetup{pageanchor=false, - bookmarksnumbered=true, - pdfencoding=unicode - } -\pagenumbering{alph} +% Parameters Needed by Design spec class (must be inside document) +% Set these parameters according to your project. +\def \projectname {libtropic} +\def \documentname {C library for TROPIC01 devices} +\def \versionnumber {0.0.1} -% Make title page +% Title page \maketitle +\pagebreak -\pagenumbering{roman} +% Table of contents \tableofcontents -\clearemptydoublepage -\pagenumbering{arabic} -\hypersetup{pageanchor=true} - -%--- Begin generated contents --- +\pagebreak \ No newline at end of file diff --git a/examples/crypto_tests/CMakeLists.txt b/examples/crypto_tests/CMakeLists.txt deleted file mode 100644 index 7520489..0000000 --- a/examples/crypto_tests/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -cmake_minimum_required(VERSION 3.21.0) - - -########################################################################### -# # -# Define project's name # -# # -########################################################################### - -project(crypto_tests - LANGUAGES C) - -########################################################################### -# # -# Configure libtropic for this exmaple # -# # -########################################################################### - -# This example is compiled for linux, so use unix hal functions: -#set(TS_HAL_UNIX ON) -# Use trezor crypto as a source of backend cryptography code -set(TS_CRYPTO_TREZOR ON) - - -########################################################################### -# # -# Add path to libtropic's repository root folder # -# # -########################################################################### - -add_subdirectory(../../ "src") - - -########################################################################### -# # -# Building crypto tests # -# # -########################################################################### - -add_executable(main main.c) -target_compile_definitions(main PRIVATE USE_TS_CRYPTO) -target_link_libraries(main PUBLIC tropic) diff --git a/examples/crypto_tests/crypto_tests.h b/examples/crypto_tests/crypto_tests.h deleted file mode 100644 index e1d9ea4..0000000 --- a/examples/crypto_tests/crypto_tests.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CRYPTO_TESTS_H -#define CRYPTO_TESTS_H - - - - - - -#endif diff --git a/examples/crypto_tests/main.c b/examples/crypto_tests/main.c deleted file mode 100644 index 32bdca4..0000000 --- a/examples/crypto_tests/main.c +++ /dev/null @@ -1,449 +0,0 @@ -#include -//#include "crypto_tests.h" - -// Host cryptography -#include "ts_hkdf.h" -#include "ts_aesgcm.h" -#include "ts_sha256.h" -#include "ts_x25519.h" - - -int test_tropic_host_crypto(void); -int test_aesgcm(); -int test_hkdf(); -int test_sha256(void); -int test_X25519(); - -#define FROMHEX_MAXLEN 512 - -#define ASSERT(x) if(x) { \ - printf("OK"); \ - } else { \ - printf("ERROR"); \ - return 1; \ - } - -int test_tropic_host_crypto(void) -{ - printf("\n\tTest hash: "); - ASSERT(!test_sha256()) - - printf("\n\tTest hkdf: "); - ASSERT(!test_hkdf()) - - printf("\n\tTest AESGCM: "); - ASSERT(!test_aesgcm()) - - printf("\n\tTest X25519: "); - ASSERT(!test_X25519()) - - return 0; -} - -const uint8_t *fromhex(const char *str) { - static uint8_t buf[FROMHEX_MAXLEN]; - size_t len = strlen(str) / 2; - if (len > FROMHEX_MAXLEN) len = FROMHEX_MAXLEN; - for (size_t i = 0; i < len; i++) { - uint8_t c = 0; - if (str[i * 2] >= '0' && str[i * 2] <= '9') c += (str[i * 2] - '0') << 4; - if ((str[i * 2] & ~0x20) >= 'A' && (str[i * 2] & ~0x20) <= 'F') - c += (10 + (str[i * 2] & ~0x20) - 'A') << 4; - if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') - c += (str[i * 2 + 1] - '0'); - if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F') - c += (10 + (str[i * 2 + 1] & ~0x20) - 'A'); - buf[i] = c; - } - return buf; -} - -struct { - char *key; - char *iv; - char *aad; - char *plaintext; - char *ciphertext; - char *tag; - } vectors[] = { - // Test case 1 - { - "00000000000000000000000000000000", - "000000000000000000000000", - "", - "", - "", - "58e2fccefa7e3061367f1d57a4e7455a", - }, - // Test case 2 - { - "00000000000000000000000000000000", - "000000000000000000000000", - "", - "00000000000000000000000000000000", - "0388dace60b6a392f328c2b971b2fe78", - "ab6e47d42cec13bdf53a67b21257bddf", - }, - // Test case 3 - { - "feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", - "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d5" - "14b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985", - "4d5c2af327cd64a62cf35abd2ba6fab4", - }, - // Test case 4 - { - "feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d5" - "14b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091", - "5bc94fbc3221a5db94fae95ae7121a47", - }, - // Test case 5 - { - "feffe9928665731c6d6a8f9467308308", - "cafebabefacedbad", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c74237380" - "6900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598", - "3612d2e79e3b0785561be14aaca2fccb", - }, - // Test case 6 - { - "feffe9928665731c6d6a8f9467308308", - "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0" - "c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4" - "a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5", - "619cc5aefffe0bfa462af43c1699d050", - }, - // Test case 7 - { - "000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "", - "", - "cd33b28ac773f74ba00ed1f312572435", - }, - // Test case 8 - { - "000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "00000000000000000000000000000000", - "98e7247c07f0fe411c267e4384b0f600", - "2ff58d80033927ab8ef4d4587514f0fb", - }, - // Test case 9 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "cafebabefacedbaddecaf888", - "", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", - "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d77" - "3d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256", - "9924a7c8587336bfb118024db8674a14", - }, - // Test case 10 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "cafebabefacedbaddecaf888", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d77" - "3d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710", - "2519498e80f1478f37ba55bd6d27618c", - }, - // Test case 11 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "cafebabefacedbad", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc" - "29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7", - "65dcc57fcf623a24094fcca40d3533f8", - }, - // Test case 12 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0" - "c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e7" - "9012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b", - "dcf566ff291c25bbb8568fc3d376a6d9", - }, - // Test case 13 - { - "0000000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "", - "", - "530f8afbc74536b9a963b4f1c4cb738b", - }, - // Test case 14 - { - "0000000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "00000000000000000000000000000000", - "cea7403d4d606b6e074ec5d3baf39d18", - "d0d1c8a799996bf0265b98b5d48ab919", - }, - // Test case 15 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", - "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb0" - "8e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad", - "b094dac5d93471bdec1a502270e3cc6c", - }, - // Test case 16 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb0" - "8e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662", - "76fc6ece0f4e1768cddf8853bb2d551b", - }, - // Test case 17 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbad", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb5" - "82d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f", - "3a337dbf46a792c45e454913fe2ea8f2", - }, - // Test case 18 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0" - "c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0" - "c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f", - "a44a8266ee1c8eb0c8b5d4cf5ae9f19a", - }, - }; - -int test_aesgcm() -{ - uint8_t iv[60] = {0}; - uint8_t aad[20] = {0}; - uint8_t msg[64] = {0}; - uint8_t tag[16] = {0}; - - for (uint32_t i=0; i < (sizeof(vectors)/sizeof(vectors[0])); i++) { - - size_t iv_len = strlen(vectors[i].iv) / 2; - memcpy(iv, fromhex(vectors[i].iv), iv_len); - size_t aad_len = strlen(vectors[i].aad) / 2; - memcpy(aad, fromhex(vectors[i].aad), aad_len); - size_t msg_len = strlen(vectors[i].plaintext) / 2; - memcpy(msg, fromhex(vectors[i].plaintext), msg_len); - size_t tag_len = strlen(vectors[i].tag) / 2; - - // Set key. - ts_aes_gcm_ctx_t ctx_enc = {0}; - int ret = ts_aesgcm_init_and_key( - &ctx_enc, /* the mode context */ - fromhex(vectors[i].key), /* the key value */ - strlen(vectors[i].key) / 2 /* and its length in bytes */ - ); - - ret = ts_aesgcm_encrypt( - &ctx_enc, /* the mode context */ - iv, /* the initialisation vector */ - iv_len, /* and its length in bytes */ - aad, /* the header buffer */ - aad_len, /* and its length in bytes */ - msg, /* the message buffer */ - msg_len, /* and its length in bytes */ - tag, /* the buffer for the tag */ - tag_len /* and its length in bytes */ - ); - - //memset(&ctx, 0, sizeof(ts_aes_gcm_ctx_t)); - if(RETURN_GOOD != ret) { - return 1; - } - //TEST_ASSERT_EQUAL(RETURN_GOOD, ret); - if ((msg_len > 0)) - { - if(memcmp(msg, fromhex(vectors[i].ciphertext), msg_len) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(msg, fromhex(vectors[i].ciphertext), msg_len); - } - if ((tag_len > 0)) - { - if(memcmp(tag, fromhex(vectors[i].tag), tag_len) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(tag, fromhex(vectors[i].tag), tag_len); - } - - ts_aes_gcm_ctx_t ctx_dec = {0}; - - ret = ts_aesgcm_init_and_key(&ctx_dec, - fromhex(vectors[i].key), /* the key value */ - strlen(vectors[i].key) / 2 /* and its length in bytes */ - ); - - ret = ts_aesgcm_decrypt( &ctx_dec, /* the mode context */ - iv, /* the initialisation vector */ - iv_len, /* and its length in bytes */ - aad, /* the header buffer */ - aad_len, /* and its length in bytes */ - msg, /* the message buffer */ - msg_len, /* and its length in bytes */ - tag, /* the buffer for the tag */ - tag_len); /* and its length in bytes */ - - - if(msg_len > 0) { - if(memcmp(fromhex(vectors[i].plaintext), msg, msg_len) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(fromhex(vectors[i].plaintext), msg, msg_len); - } - } - return 0; -} - -int test_hkdf() { - - uint8_t output_1[33] = {0}; - uint8_t output_2[32] = {0}; - // round 1, output_2 is not used - uint8_t protocol_name[32] = {'N','o','i','s','e','_','K','K','1','_','2','5','5','1','9','_','A','E','S','G','C','M','_','S','H','A','2','5','6',0x00,0x00,0x00}; - uint8_t s_s_1[32] = {0x3d,0x9c,0xf1,0x6d,0x28,0x96,0x11,0x5e,0x4e,0x6a,0x9f,0xce,0x07,0x10,0x39,0xd9,0xa2,0x06,0x80,0xd3,0x24,0xa6,0xd1,0x6d,0xcb,0x83,0x3c,0xd6,0xd5,0x85,0xdf,0x3b}; - ts_hkdf(protocol_name, 32, s_s_1, 32, 1, output_1, output_2); - uint8_t ck1[32] = {0x8e,0x5d,0xae,0xbc,0xbc,0xe7,0xa3,0x0d,0xd6,0x6e,0xb7,0x23,0x01,0x53,0x50,0xd9,0x05,0x7f,0x53,0xaf,0x0f,0x81,0xce,0x0d,0xae,0x51,0xda,0xf8,0x70,0x4e,0xca,0x1b}; - - if(memcmp(ck1, output_1, 32) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(ck1, output_1, 32); - // round 2, output_2 is not used - uint8_t s_s_2[32] = {0xdf,0xf8,0x1a,0xa2,0x04,0x78,0x5e,0x0b,0x53,0x28,0xfe,0xed,0x8d,0xec,0x02,0x0d,0xbb,0xcb,0xda,0xb3,0x07,0x67,0xdd,0x3b,0xb1,0xa6,0xc5,0x6c,0x93,0xcb,0x3a,0x13}; - ts_hkdf(ck1, 32, s_s_2, 32, 1, output_1, output_2); - uint8_t ck2[32] = {0x2f,0x5b,0xc4,0xcb,0xae,0xe1,0x00,0x4d,0x57,0x58,0x53,0x16,0xbc,0xa4,0x06,0x6e,0xac,0x66,0xa8,0xc0,0xe6,0x68,0x0a,0x46,0x97,0x2c,0xe3,0x91,0xa4,0x34,0x48,0x63}; - if(memcmp(ck2, output_1, 32) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(ck2, output_1, 32); - // round 3, output_2 is also used - uint8_t s_s_3[32] = {0xb9,0x1c,0x94,0x87,0x9c,0x54,0x09,0x09,0x6d,0x79,0x2d,0x2b,0x98,0xba,0xb0,0x11,0xbf,0x8e,0x49,0xbf,0x8f,0x8d,0x26,0x0b,0x90,0x85,0x1c,0x7e,0x75,0xa9,0xfb,0x6a}; - ts_hkdf(ck2, 32, s_s_3, 32, 2, output_1, output_2); - uint8_t ck3[32] = {0xa3,0xb3,0x38,0x0a,0x6f,0xf2,0xbb,0x64,0x03,0xc3,0x4f,0xec,0xa4,0x4b,0xf5,0xde,0xb2,0xed,0xc9,0x2f,0xfb,0x4c,0x1b,0xa6,0xcb,0x20,0xdc,0x97,0xb6,0xe2,0xc8,0x34}; - uint8_t kauth[32] = {0xa1,0x97,0x09,0x67,0x11,0xf5,0x8e,0x5d,0x10,0x4c,0xbf,0xfb,0xa7,0x16,0xa0,0x57,0x38,0x28,0x09,0x65,0x6f,0xa5,0xd7,0xfd,0x56,0x93,0x08,0x41,0xf8,0xef,0xf6,0x29}; - if(memcmp(ck3, output_1, 32) == 1) { - return 1; - } - if(memcmp(kauth, output_2, 32) == 1) { - return 1; - } - - //TEST_ASSERT_EQUAL_HEX8_ARRAY(ck3, output_1, 32); - //TEST_ASSERT_EQUAL_HEX8_ARRAY(kauth, output_2, 32); - // round 4, output_2 is also used - ts_hkdf(ck3, 32, (uint8_t *)"", 0, 2, output_1, output_2); - uint8_t kcmd[32] = {0x10,0xf3,0x29,0xf6,0x85,0xc3,0x44,0x25,0xa3,0x79,0x0e,0xdb,0xcf,0x42,0xa5,0x88,0xe8,0x87,0x64,0x07,0x73,0x87,0xe3,0x0e,0x57,0x58,0xbd,0xb1,0x9d,0x68,0x45,0xcb}; - uint8_t kres[32] = {0x32,0xb3,0x1d,0x65,0xad,0xf4,0xab,0x0e,0x2c,0xba,0xd8,0x0d,0xe9,0x1f,0xa4,0x66,0xf5,0x76,0x26,0x71,0x81,0x5a,0x75,0x04,0xdf,0x1c,0x32,0xaf,0xfe,0xba,0xaf,0x15}; - //TEST_ASSERT_EQUAL_HEX8_ARRAY(kcmd, output_1, 32); - //TEST_ASSERT_EQUAL_HEX8_ARRAY(kres, output_2, 32); - - if(memcmp(kcmd, output_1, 32) == 1) { - return 1; - } - if(memcmp(kres, output_2, 32) == 1) { - return 1; - } - - return 0; -} - -int test_sha256(void) { - - uint8_t protocol_name[32] = {'N','o','i','s','e','_','K','K','1','_','2','5','5','1','9','_','A','E','S','G','C','M','_','S','H','A','2','5','6'}; - uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; - ts_sha256_ctx_t ctx = {0}; - ts_sha256_init(&ctx); - ts_sha256_start(&ctx); - ts_sha256_update(&ctx, protocol_name, 29); - ts_sha256_finish(&ctx, hash); - uint8_t expected[] = {0x92,0x5b,0x44,0xac,0xed,0xc4,0x53,0x3b,0x48,0x42,0xa0,0x66,0x0d,0x81,0x5e,0x16,0x84,0x0a,0xee,0x64,0x63,0x28,0x0f,0x07,0xa8,0x28,0xe1,0x5d,0x07,0x0c,0x73,0x78}; - - if(memcmp(expected, hash, 32)) { - return 1; - } - return 0; -} - -// vectors taken from python model -int test_X25519() -{ - uint8_t priv[32] = {0x38,0xc9,0xd9,0xb1,0x79,0x11,0xde,0x26,0xed,0x81,0x2f,0x5c,0xc1,0x9c,0x00,0x29,0xe8,0xd0,0x16,0xbc,0xbc,0x60,0x78,0xbc,0x9d,0xb2,0xaf,0x33,0xf1,0x76,0x1e,0x4a}; - uint8_t pub[32] = {0x31,0x1b,0x62,0x48,0xaf,0x8d,0xab,0xec,0x5c,0xc8,0x1e,0xac,0x5b,0xf2,0x29,0x92,0x5f,0x6d,0x21,0x8a,0x12,0xe0,0x54,0x7f,0xb1,0x85,0x6e,0x01,0x5c,0xc7,0x6f,0x5d}; - uint8_t out[32] = {0}; - ts_X25519(priv, pub, out); - uint8_t expected[32] = {0xa9,0x3d,0xbd,0xb2,0x3e,0x5c,0x99,0xda,0x74,0x3e,0x20,0x3b,0xd3,0x91,0xaf,0x79,0xf2,0xb8,0x3f,0xb8,0xd0,0xfd,0x6e,0xc8,0x13,0x37,0x1c,0x71,0xf0,0x8f,0x2d,0x4d}; - if(memcmp(expected, out, 32) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, out, 32); - - uint8_t priv2[32] = {0x38,0xc9,0xd9,0xb1,0x79,0x11,0xde,0x26,0xed,0x81,0x2f,0x5c,0xc1,0x9c,0x00,0x29,0xe8,0xd0,0x16,0xbc,0xbc,0x60,0x78,0xbc,0x9d,0xb2,0xaf,0x33,0xf1,0x76,0x1e,0x4a}; - uint8_t pub2[32] = {0x31,0x1b,0x62,0x48,0xaf,0x8d,0xab,0xec,0x5c,0xc8,0x1e,0xac,0x5b,0xf2,0x29,0x92,0x5f,0x6d,0x21,0x8a,0x12,0xe0,0x54,0x7f,0xb1,0x85,0x6e,0x01,0x5c,0xc7,0x6f,0x5d}; - uint8_t out2[32] = {0}; - ts_X25519(priv2, pub2, out2); - uint8_t expected2[32] = {0xa9,0x3d,0xbd,0xb2,0x3e,0x5c,0x99,0xda,0x74,0x3e,0x20,0x3b,0xd3,0x91,0xaf,0x79,0xf2,0xb8,0x3f,0xb8,0xd0,0xfd,0x6e,0xc8,0x13,0x37,0x1c,0x71,0xf0,0x8f,0x2d,0x4d}; - if(memcmp(expected2, out2, 32) == 1) { - return 1; - } - return 0; - //TEST_ASSERT_EQUAL_HEX8_ARRAY(expected2, out2, 32); -} - - -//--------------------------------------------------------------------------------------------------// -int main(void) { - printf("\nRunning tests for implemented crypto functions: \n"); - if (test_tropic_host_crypto() == 1) { - printf("\n\n!!! CRYPTO ERROR !!!\n"); - return 1; - } - printf("\n"); -} diff --git a/examples/hw_wallet/hw_wallet.c b/examples/hw_wallet/hw_wallet.c new file mode 100644 index 0000000..9e37084 --- /dev/null +++ b/examples/hw_wallet/hw_wallet.c @@ -0,0 +1,660 @@ + + +#include "string.h" + +#include "libtropic.h" +#include "libtropic_common.h" +#include "hw_wallet.h" + +/* +[Note] We recommend reading TROPIC01's datasheet before diving into this example! + + CONCEPT: Generic Hardware Wallet + +This code aims to show an example usage of TROPIC01 chip in a generic 'hardware wallet' project. + +It is not focused on final application's usage, even though there is a few +hints in session_H3() function. Instead of that, this code mainly walks you through a different stages during a chip's lifecycle: + * Initial power up during PCB manufacturing + * Attestation key uploading + * Final product usage + +Example shows how content of config objects might be used to set different access rights and how chip behaves +during the device's lifecycle. + +*/ + +// Default factory pairing keys +uint8_t pkey_index_0 = PAIRING_KEY_SLOT_INDEX_0; +uint8_t sh0priv[] = {0xf0,0xc4,0xaa,0x04,0x8f,0x00,0x13,0xa0,0x96,0x84,0xdf,0x05,0xe8,0xa2,0x2e,0xf7,0x21,0x38,0x98,0x28,0x2b,0xa9,0x43,0x12,0xf3,0x13,0xdf,0x2d,0xce,0x8d,0x41,0x64}; +uint8_t sh0pub[] = {0x84,0x2f,0xe3,0x21,0xa8,0x24,0x74,0x08,0x37,0x37,0xff,0x2b,0x9b,0x88,0xa2,0xaf,0x42,0x44,0x2d,0xb0,0xd8,0xaa,0xcc,0x6d,0xc6,0x9e,0x99,0x53,0x33,0x44,0xb2,0x46}; +// Keys with acces to write attestation key in slot 1 +uint8_t pkey_index_1 = PAIRING_KEY_SLOT_INDEX_1; +uint8_t sh1priv[] = {0x58,0xc4,0x81,0x88,0xf8,0xb1,0xcb,0xd4,0x19,0x00,0x2e,0x9c,0x8d,0xf8,0xce,0xea,0xf3,0xa9,0x11,0xde,0xb6,0x6b,0xc8,0x87,0xae,0xe7,0x88,0x10,0xfb,0x48,0xb6,0x74}; +uint8_t sh1pub[] = {0xe1,0xdc,0xf9,0xc3,0x46,0xbc,0xf2,0xe7,0x8b,0xa8,0xf0,0x27,0xd8,0x0a,0x8a,0x33,0xcc,0xf3,0xe9,0xdf,0x6b,0xdf,0x65,0xa2,0xc1,0xae,0xc4,0xd9,0x21,0xe1,0x8d,0x51}; +// Keys with access only to read serial number +uint8_t pkey_index_2 = PAIRING_KEY_SLOT_INDEX_2; +uint8_t sh2priv[] = {0x00,0x40,0x5e,0x19,0x46,0x75,0xab,0xe1,0x5f,0x0b,0x57,0xf2,0x5b,0x12,0x86,0x62,0xab,0xb0,0xe9,0xc6,0xa7,0xc3,0xca,0xdf,0x1c,0xb1,0xd2,0xb7,0xf8,0xcf,0x35,0x47}; +uint8_t sh2pub[] = {0x66,0xb9,0x92,0x5a,0x85,0x66,0xe8,0x09,0x5c,0x56,0x80,0xfb,0x22,0xd4,0xb8,0x4b,0xf8,0xe3,0x12,0xb2,0x7c,0x4b,0xac,0xce,0x26,0x3c,0x78,0x39,0x6d,0x4c,0x16,0x6c}; +// Keys for application +uint8_t pkey_index_3 = PAIRING_KEY_SLOT_INDEX_3; +uint8_t sh3priv[] = {0xb0,0x90,0x9f,0xe1,0xf3,0x1f,0xa1,0x21,0x75,0xef,0x45,0xb1,0x42,0xde,0x0e,0xdd,0xa1,0xf4,0x51,0x01,0x40,0xc2,0xe5,0x2c,0xf4,0x68,0xac,0x96,0xa1,0x0e,0xcb,0x46}; +uint8_t sh3pub[] = {0x22,0x57,0xa8,0x2f,0x85,0x8f,0x13,0x32,0xfa,0x0f,0xf6,0x0c,0x76,0x29,0x42,0x70,0xa9,0x58,0x9d,0xfd,0x47,0xa5,0x23,0x78,0x18,0x4d,0x2d,0x38,0xf0,0xa7,0xc4,0x01}; + +#define LT_SESSION_H0(x) ((x) << 0) +#define LT_SESSION_H1(x) ((x) << 8) +#define LT_SESSION_H2(x) ((x) << 16) +#define LT_SESSION_H3(x) ((x) << 24) + +#define LT_KEY_0 (uint8_t)0x01 +#define LT_KEY_1 (uint8_t)0x02 +#define LT_KEY_2 (uint8_t)0x04 +#define LT_KEY_3 (uint8_t)0x08 + +struct lt_config_obj_desc_t { + char desc[60]; + enum CONFIGURATION_OBJECTS_REGS addr; +}; + +static struct lt_config_obj_desc_t config_description[27] = { + {"CONFIGURATION_OBJECTS_CFG_START_UP ", CONFIGURATION_OBJECTS_CFG_START_UP_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_SLEEP_MODE ", CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_SENSORS ", CONFIGURATION_OBJECTS_CFG_SENSORS_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_DEBUG ", CONFIGURATION_OBJECTS_CFG_DEBUG_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE ", CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ ", CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE ", CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_WRITE_ERASE ", CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_WRITE_ERASE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ ", CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE ", CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ ", CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_PING ", CONFIGURATION_OBJECTS_CFG_UAP_PING_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE ", CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ ", CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE ", CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_RANDOM_VALUE_GET ", CONFIGURATION_OBJECTS_CFG_UAP_RANDOM_VALUE_GET_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE ", CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE ", CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ ", CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE ", CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN ", CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN ", CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT ", CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET ", CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE ", CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY ", CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_ADDR}, + {"CONFIGURATION_OBJECTS_CFG_UAP_SERIAL_CODE_GET ", CONFIGURATION_OBJECTS_CFG_UAP_SERIAL_CODE_GET_ADDR} +}; + +/** + * @brief This function establish a secure channel between host MCU and TROPIC01 chip + * + * @param h Device's handle + * @param shipriv Host's private pairing key (SHiPUB) + * @param shipub Host's public pairing key (SHiPUB) + * @param pkey_index Pairing key's index + * @return LT_OK if success, otherwise returns other error code. + */ +static lt_ret_t verify_chip_and_start_secure_session(lt_handle_t *h, uint8_t *shipriv, uint8_t *shipub, uint8_t pkey_index) +{ + lt_ret_t ret = LT_FAIL; + + // This is not used in this example, but let's read it anyway + uint8_t chip_id[LT_L2_GET_INFO_CHIP_ID_SIZE] = {0}; + ret = lt_get_info_chip_id(h, chip_id, LT_L2_GET_INFO_CHIP_ID_SIZE); + if (ret != LT_OK) { + return ret; + } + + // This is not used in this example, but let's read it anyway + uint8_t riscv_fw_ver[LT_L2_GET_INFO_RISCV_FW_SIZE] = {0}; + ret = lt_get_info_riscv_fw_ver(h, riscv_fw_ver, LT_L2_GET_INFO_RISCV_FW_SIZE); + if (ret != LT_OK) { + return ret; + } + + // This is not used in this example, but let's read it anyway + uint8_t spect_fw_ver[LT_L2_GET_INFO_SPECT_FW_SIZE] = {0}; + ret = lt_get_info_spect_fw_ver(h, spect_fw_ver, LT_L2_GET_INFO_SPECT_FW_SIZE); + if (ret != LT_OK) { + return ret; + } + + // This is not used in this example, but let's read it anyway + uint8_t header[LT_L2_GET_INFO_FW_HEADER_SIZE] = {0}; + ret = lt_get_info_fw_bank(h, header, LT_L2_GET_INFO_FW_HEADER_SIZE); + if (ret != LT_OK) { + return ret; + } + + uint8_t X509_cert[LT_L2_GET_INFO_REQ_CERT_SIZE] = {0}; + ret = lt_get_info_cert(h, X509_cert, LT_L2_GET_INFO_REQ_CERT_SIZE); + if (ret != LT_OK) { + return ret; + } + + uint8_t stpub[32] = {0}; + ret = lt_cert_verify_and_parse(X509_cert, LT_L2_GET_INFO_REQ_CERT_SIZE, stpub); + if (ret != LT_OK) { + return ret; + } + + ret = lt_session_start(h, stpub, pkey_index, shipriv, shipub); + if (ret != LT_OK) { + return ret; + } + + return LT_OK; +} + +/** + * @brief This function reads config objects and print them out + * + * @param h Device's handle + * @return LT_OK if success, otherwise returns other error code. + */ +static lt_ret_t read_whole_I_config(lt_handle_t *h) +{ + lt_ret_t ret; + + printf("\r\n"); + for (int i=0; i<27;i++) { + uint32_t check = 0; + ret = lt_i_config_read(h, config_description[i].addr, &check); + if(ret != LT_OK) { + return ret; + } + printf("\t\t%s %08X\r\n", config_description[i].desc, check); + } + printf("\r\n"); + + return LT_OK; +} + +/** + * @brief This function reads config objects and print them out + * + * @param h Device's handle + * @return LT_OK if success, otherwise returns other error code. + */ +static lt_ret_t read_whole_R_config(lt_handle_t *h) +{ + lt_ret_t ret; + + printf("\r\n"); + for (int i=0; i<27;i++) { + uint32_t check = 0; + ret = lt_r_config_read(h, config_description[i].addr, &check); + if(ret != LT_OK) { + return ret; + } + printf("\t\t%s %08X\r\n", config_description[i].desc, check); + } + printf("\r\n"); + + return LT_OK; +} + +/** + * @brief This function writes config objecs of TROPIC01 + * + * @param h Device's handle + * @return LT_OK if success, otherwise returns other error code. + */ +static lt_ret_t write_whole_R_config(lt_handle_t *h) +{ + lt_ret_t ret; + + uint32_t content; + // Reset value: 0x0000003E + content = CONFIGURATION_OBJECTS_CFG_START_UP_MBIST_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_START_UP_RNGTEST_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_START_UP_MAINTENANCE_ENA_MASK | + CONFIGURATION_OBJECTS_CFG_START_UP_CPU_FW_VERIFY_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_START_UP_SPECT_FW_VERIFY_DIS_MASK; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_START_UP_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x00000003 + content = CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_SLEEP_MODE_EN_MASK | + CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_DEEP_SLEEP_MODE_EN_MASK; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x0003FFFF + content = CONFIGURATION_OBJECTS_CFG_SENSORS_PTRNG0_TEST_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_PTRNG1_TEST_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_OSCILLATOR_MON_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_SHIELD_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_VOLTAGE_MON_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_GLITCH_DET_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_TEMP_SENS_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_LASER_DET_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_EM_PULSE_DET_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_CPU_ALERT_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_PIN_VERIF_BIT_FLIP_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_SCB_BIT_FLIP_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_CPB_BIT_FLIP_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_ECC_BIT_FLIP_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_R_MEM_BIT_FLIP_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_EKDB_BIT_FLIP_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_I_MEM_BIT_FLIP_DIS_MASK | + CONFIGURATION_OBJECTS_CFG_SENSORS_PLATFORM_BIT_FLIP_DIS_MASK; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_SENSORS_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x00000001 + content = CONFIGURATION_OBJECTS_CFG_DEBUG_FW_LOG_EN_MASK; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_DEBUG_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0xFFFFFFFF + content = 0; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0xFFFFFFFF + content = LT_SESSION_H0(LT_KEY_0 | LT_KEY_1 | LT_KEY_2 | LT_KEY_3) | + LT_SESSION_H1(LT_KEY_0 | LT_KEY_1 | LT_KEY_2 | LT_KEY_3) | + LT_SESSION_H2(LT_KEY_0 | LT_KEY_1 | LT_KEY_2 | LT_KEY_3) | + LT_SESSION_H3(LT_KEY_0 | LT_KEY_1 | LT_KEY_2 | LT_KEY_3); + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0xFFFFFFFF + content = LT_SESSION_H0(LT_KEY_0 ) | + LT_SESSION_H3(LT_KEY_0 | LT_KEY_1 | LT_KEY_2 | LT_KEY_3); + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x000000FF + content = 0x000000ff; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_WRITE_ERASE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x0000FFFF + content = 0x0000ffff; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x0000FFFF + content = 0x0000ffff; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x0000FFFF + content = 0x0000ffff; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0x000000ff + content = 0x000000ff; // All keys can ping + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_PING_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0xffffffff + content = 0xffffffff; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value:0xffffffff + content = 0xffffffff; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + // Reset value: 0xffffffff + content = 0xffffffff; + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0x000000ff + content = 0x000000ff; // all slots can get random values + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_RANDOM_VALUE_GET_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080800; // No session can generate key in ecc key slot 0-7 + // H3 can generate key in slots 8-31 + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080802; // H1 can store key into ecc key slot 0-7 + // H3 can store key into ecc key slot 8-31 + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x0f0f0f0f; // All keys can read pubkey + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080802; // H1 key can erase keys in slot 0-7 + // H3 key can erase key in slot 8-31 + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080808; // H3 can sign with all ecdsa key slots + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0xffffffff; // H3 can sign with all ecc key slots + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080808; // H3 can init all counters + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080808; // H3 can get all counters + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080808; // H3 can update all counters + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0xffffffff + content = 0x08080808; // H3 can use mac and destroy areas + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_ADDR, content); + if(ret != LT_OK) { + return ret; + } + // Reset value: 0x000000ff + content = 0x00000000; // This command is disabled for all sessions + ret = lt_r_config_write(h, CONFIGURATION_OBJECTS_CFG_UAP_SERIAL_CODE_GET_ADDR, content); + if(ret != LT_OK) { + return ret; + } + + return LT_OK; +} + +/** + * @brief Initial session, when chip is powered for the first time during manufacturing. + * This function writes chip's configuration into r config area. + * + * @param h Device's handle + * @return 0 if success, otherwise -1 + */ +static int session_initial(lt_handle_t *h) { + lt_ret_t ret; + + // Establish secure handshake with default H0 pairing keys + LOG_OUT_SESSION("%s", "Creating session with initial factory keys H0"); + LT_ASSERT(LT_OK, verify_chip_and_start_secure_session(h, sh0priv, sh0pub, pkey_index_0)); + LOG_OUT_SESSION("%s", "Secure session established with initial factory keys H0"); + //LOG_OUT_SESSION("%s\r\n", "TODO: show I config values"); + //LOG_OUT_SESSION("%s\r\n", "R CONFIG read:"); + //LT_ASSERT(LT_OK, read_whole_R_config(h)); + LT_ASSERT(LT_OK, write_whole_R_config(h)); + LOG_OUT_SESSION("%s\r\n", "R CONFIG written!"); + LOG_OUT_SESSION("%s\r\n", "Reading R CONFIG again"); + read_whole_R_config(h); + + // Writing pairing keys 1-3 + LOG_OUT_SESSION("%s", "Writing pairing key H1"); + LT_ASSERT(LT_OK, lt_pairing_key_write(h, sh1pub, pkey_index_1)); + LOG_OUT_SESSION("%s", "Writing pairing key H2"); + LT_ASSERT(LT_OK, lt_pairing_key_write(h, sh2pub, pkey_index_2)); + LOG_OUT_SESSION("%s", "Writing pairing key H3"); + LT_ASSERT(LT_OK, lt_pairing_key_write(h, sh3pub, pkey_index_3)); + LOG_OUT_SESSION("%s", "Invalidating H0 pairing key"); + LT_ASSERT(LT_OK, lt_pairing_key_invalidate(h, pkey_index_0)); + + LOG_OUT_SESSION("%s", "Closing session H0"); + LT_ASSERT(LT_OK, lt_session_abort(h)); + + LOG_OUT_SESSION("%s", "Rebooting TROPIC01"); + LT_ASSERT(LT_OK, lt_reboot(h, LT_L2_STARTUP_ID_REBOOT)); + + return 0; +} + +/** + * @brief Session with H0 pairing keys + * + * @param h Device's handle + * @return 0 if success, otherwise -1 + */ +static int session_H0(lt_handle_t *h) { + lt_ret_t ret; + + /* Establish secure handshake with default H0 pairing keys should fail, because this H0 key was invalidated at the end of initial session */ + LOG_OUT_SESSION("%s", "Establish session with H0 must fail"); + LT_ASSERT(LT_L2_HSK_ERR, verify_chip_and_start_secure_session(h, sh0priv, sh0pub, pkey_index_0)); + + return 0; +} + +/** + * @brief Session with H1 pairing keys + * + * @param h Device's handle + * @return 0 if success, otherwise -1 + */ +static int session_H1(lt_handle_t *h) { + lt_ret_t ret; + + /* Establish secure handshake with default H0 pairing keys */ + LOG_OUT_SESSION("%s", "Creating session with H1 keys"); + LT_ASSERT(LT_OK, verify_chip_and_start_secure_session(h, sh1priv, sh1pub, pkey_index_1)); + + uint8_t in[100]; + uint8_t out[100]; + LOG_OUT_SESSION("%s", "lt_ping() "); + LT_ASSERT(LT_OK, lt_ping(h, out, in, 100)); + + uint8_t attestation_key[32] = {0x22,0x57,0xa8,0x2f,0x85,0x8f,0x13,0x32,0xfa,0x0f,0xf6,0x0c,0x76,0x29,0x42,0x70,0xa9,0x58,0x9d,0xfd,0x47,0xa5,0x23,0x78,0x18,0x4d,0x2d,0x38,0xf0,0xa7,0xc4,0x01}; + LOG_OUT_SESSION("%s", "Storing attestation key into slot 0"); + LT_ASSERT(LT_OK, lt_ecc_key_store(h, ECC_SLOT_1, CURVE_ED25519, attestation_key)); + + uint8_t serial_code[SERIAL_CODE_SIZE] = {0}; + LOG_OUT_SESSION("%s","Serial code get must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_serial_code_get(h, serial_code, SERIAL_CODE_SIZE)); + + uint8_t dummykey[32]; + LOG_OUT_SESSION("%s","Pairing key write into slot 0 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_0)); + LOG_OUT_SESSION("%s","Pairing key write into slot 1 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_1)); + LOG_OUT_SESSION("%s","Pairing key write into slot 2 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_2)); + LOG_OUT_SESSION("%s","Pairing key write into slot 3 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_3)); + + + LOG_OUT_SESSION("%s", "Aborting session H1"); + LT_ASSERT(LT_OK, lt_session_abort(h)); + + return LT_OK; +} + +/** + * @brief Session with H2 pairing keys + * + * @param h Device's handle + * @return 0 if success, otherwise -1 + */ +static int session_H2(lt_handle_t *h) { + lt_ret_t ret; + + LOG_OUT_SESSION("%s", "Creating session with H2 keys"); + LT_ASSERT(LT_OK, verify_chip_and_start_secure_session(h, sh2priv, sh2pub, pkey_index_2)); + + uint8_t in[100]; + uint8_t out[100]; + LOG_OUT_SESSION("%s", "lt_ping() "); + LT_ASSERT(LT_OK, lt_ping(h, out, in, 100)); + + uint8_t serial_code[SERIAL_CODE_SIZE] = {0}; + LOG_OUT_SESSION("%s","Serial code get must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_serial_code_get(h, serial_code, SERIAL_CODE_SIZE)); + + uint8_t dummykey[32]; + LOG_OUT_SESSION("%s","ECC key store into slot 1 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_ecc_key_store(h, ECC_SLOT_1, CURVE_ED25519, dummykey)); + + LOG_OUT_SESSION("%s","Pairing key write into slot 0 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_0)); + LOG_OUT_SESSION("%s","Pairing key write into slot 1 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_1)); + LOG_OUT_SESSION("%s","Pairing key write into slot 2 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_2)); + LOG_OUT_SESSION("%s","Pairing key write into slot 3 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_3)); + + // TODO Unauthorized sign with attestation key + + LOG_OUT_SESSION("%s", "Aborting session H2"); + LT_ASSERT(LT_OK, lt_session_abort(h)); + + return LT_OK; +} + +/** + * @brief Session with H3 pairing keys + * + * @param h Device's handle + * @return 0 if success, otherwise -1 + */ +static int session_H3(lt_handle_t *h) { + lt_ret_t ret; + + LOG_OUT_SESSION("%s", "Creating session with H3 keys"); + LT_ASSERT(LT_OK, verify_chip_and_start_secure_session(h, sh3priv, sh3pub, pkey_index_3)); + + uint8_t in[100]; + uint8_t out[100]; + LOG_OUT_SESSION("%s", "lt_ping() "); + LT_ASSERT(LT_OK, lt_ping(h, out, in, 100)); + + uint8_t serial_code[SERIAL_CODE_SIZE] = {0}; + LOG_OUT_SESSION("%s","Serial code get must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_serial_code_get(h, serial_code, SERIAL_CODE_SIZE)); + + uint8_t dummykey[32]; + LOG_OUT_SESSION("%s","ECC key store into slot 1 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_ecc_key_store(h, ECC_SLOT_1, CURVE_ED25519, dummykey)); + + LOG_OUT_SESSION("%s","Pairing key write into slot 0 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_0)); + LOG_OUT_SESSION("%s","Pairing key write into slot 1 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_1)); + LOG_OUT_SESSION("%s","Pairing key write into slot 2 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_2)); + LOG_OUT_SESSION("%s","Pairing key write into slot 3 must fail"); + LT_ASSERT(LT_L3_UNAUTHORIZED, lt_pairing_key_write(h, dummykey, PAIRING_KEY_SLOT_INDEX_3)); + + // TODO generate key + // TODO write R config + // TODO read R config + + LOG_OUT_SESSION("%s", "Aborting session H2"); + LT_ASSERT(LT_OK, lt_session_abort(h)); + + return LT_OK; +} + +int tropic01_hw_wallet_example(void) +{ + lt_handle_t h; + lt_ret_t ret; + + LOG_OUT("\r\n"); + LOG_OUT("\t=======================================================================\r\n"); + LOG_OUT("\t===== TROPIC01 example 1 - Hardware Wallet ===\r\n"); + LOG_OUT("\t=======================================================================\r\n\n"); + + ret = lt_init(&h); + if (ret != LT_OK) { + LOG_OUT("\t\tlt_init() ERROR\r\n\n"); + return -1; + } + LOG_OUT_LINE(); + printf("\t Session initial: \r\n\n"); + if(session_initial(&h) == -1) { + printf("\r\nError during session_initial()\r\n"); + return -1; + } + LOG_OUT_LINE(); + printf("\t Session H0: \r\n\n"); + if(session_H0(&h) == -1) { + printf("\r\nError during session_H0()\r\n"); + return -1; + } + LOG_OUT_LINE(); + printf("\t Session H1: \r\n\n"); + if(session_H1(&h) == -1) { + printf("\r\nError during session_H1()\r\n"); + return -1; + } + LOG_OUT_LINE(); + printf("\t Session H2: \r\n\n"); + if(session_H2(&h) == -1) { + printf("\r\nError during session_H2()\r\n"); + return -1; + } + LOG_OUT_LINE(); + printf("\t Session H3: \r\n\n"); + if(session_H3(&h) == -1) { + printf("\r\nError during session_H3()\r\n"); + return -1; + } + LOG_OUT_LINE(); + + ret = lt_deinit(&h); + if (ret != LT_OK) { + LOG_OUT("\t\tlt_deinit ERROR\r\n\n"); + return -1; + } + + LOG_OUT("\t\tlt_deinit() OK\r\n\n"); + + return 0; +} diff --git a/examples/hw_wallet/hw_wallet.h b/examples/hw_wallet/hw_wallet.h new file mode 100644 index 0000000..1cd51a2 --- /dev/null +++ b/examples/hw_wallet/hw_wallet.h @@ -0,0 +1,25 @@ +#ifndef HW_WALLET +#define HW_WALLET + +#include +#include + + +#define LOG_OUT(f_, ...) printf(f_, ##__VA_ARGS__) +#define LOG_OUT_INFO(f_, ...) printf("\t[INFO] "f_, ##__VA_ARGS__) +#define LOG_OUT_VALUE(f_, ...) printf("\t\t\t\t\t"f_, ##__VA_ARGS__) +#define LOG_OUT_LINE(f_, ...) printf("\t-------------------------------------------------------------------------------------------------------------\r\n"f_, ##__VA_ARGS__) + +#define LOG_OUT_SESSION(f_, ...) printf("\t\t- "f_, ##__VA_ARGS__) + +#define LT_ASSERT(func, expected) \ + ret = (func); \ + if(func!=expected) \ + { \ + printf("\t\t\tERROR\r\n"); return -1; \ + } else {printf(" %s\r\n", "(ok)");}; + + +int tropic01_hw_wallet_example(void); + +#endif diff --git a/examples/readme.MD b/examples/readme.MD deleted file mode 100644 index 057c9b4..0000000 --- a/examples/readme.MD +++ /dev/null @@ -1,70 +0,0 @@ -# Examples - -Each example can be built with the same commands, for example: - -``` -$ cd crypto_tests/ -$ mkdir build -$ cd build -$ cmake .. -$ make - -``` - -## Crypto tests - -This code does not communicate with TROPIC01. Its only purpose is to run cryptographic test vectors through library's crypto interfaces and check if they calculate correct results. Might be practical to keep this for the future, when another cryptography backend is introduced. - - -## Unix example - -This code communicates with running TROPIC01 model over TCP. - -It expects TROPIC01's model running within a reach of example's TCP client. Tropic's L1 data transfers are over TCP. - - -## STM32 example - -This example is prepared for stm32 target, therefore it expects **arm-none-eabi-gcc** installed on a system. - -Once compiled, it is meant to be flashed on NUCLEO-F439ZI devboard. There are two options for L1 transport layer: - -### SPI - default - -Set it in CMakeLists.txt: - -``` -set(TS_HAL_STM32_SPI ON) -``` - -Used pins are: - -| | | -|-------|----------| -| MISO | GPIOE_5 | -| MOSI | GPIOE_6 | -| SCK | GPIOE_2 | -| CS | GPIOE_4 | - - -### UART - -This option is meant to be used when libtropic application runs on stm32 devboard and instead of a physical chip (or FPGA) it is talking to the model, which is running on the PC. - -Usb-to-serial converter is used. - - -Set it in CMakeLists.txt: - -``` -set(TS_HAL_STM32_UART ON) -``` - -Used pins are: - -| | | -|-------|-----------| -| TX | GPIOC_12 | -| RX | GPIOD_2 | - - diff --git a/examples/stm32_example/CMakeLists.txt b/examples/stm32_example/CMakeLists.txt deleted file mode 100644 index 10a546a..0000000 --- a/examples/stm32_example/CMakeLists.txt +++ /dev/null @@ -1,140 +0,0 @@ -cmake_minimum_required(VERSION 3.21.0) - - -########################################################################### -# # -# Define project's name # -# # -########################################################################### - -set(TARGET stm32_example) - - -########################################################################### -# # -# Define toolchaion file and linker script # -# # -########################################################################### - -set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/STM32F429ZITX_FLASH.ld) -set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/toolchain.cmake) - - -########################################################################### -# # -# Define project # -# # -########################################################################### - -project(${TARGET} LANGUAGES C ASM) - -########################################################################### -# # -# Add and configure libtropic for this exmaple # -# # -########################################################################### - -# This example is compiled for stm32F439, UART transport layer is set as default -set(TS_HAL_STM32_SPI ON) -#set(TS_HAL_STM32_UART ON) -# Use trezor crypto as a source of backend cryptography code -set(TS_CRYPTO_TREZOR ON) -# Provide path to a root of libtropic repository -add_subdirectory(../../ "libtropic") - - -########################################################################### -# # -# Example's source files # -# # -########################################################################### - -# Path to cloned STM32CubeF4 repository -set(PATH_TO_STM32CUBEF4 "../../vendor" ) -# Openocd config file for used nucleo board -set(OPENOCD_CFG "/usr/share/openocd/scripts/board/stm32f429discovery.cfg") - -# Fill in your source files here (duh). -set(SOURCES - Src/main.c - Src/cryptography_tests.c - Src/stm32f4xx_it.c - Src/stm32f4xx_hal_msp.c - Src/system_stm32f4xx.c - System/Startup/startup_stm32f429zitx.s - System/User/syscalls.c - System/User/sysmem.c - # Sources related to STM32f439ZInucleo board - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/BSP/STM32F4xx_Nucleo_144/stm32f4xx_nucleo_144.c - # Sources for HAL functionalities used in this example - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c -) -if(TS_HAL_STM32_SPI) - add_definitions(-DHAL_SPI) - message(INFO "Using SPI as a transport layer") - set(SOURCES ${SOURCES} ../../hal/spi/ts_l1_stm32_spi.c) - set(SOURCES ${SOURCES} ../../hal/system/ts_random_stm32.c) -elseif(TS_HAL_STM32_UART) - add_definitions(-DHAL_UART) - message(WARNING "Using UART as a transport layer") - set(SOURCES ${SOURCES} ../../hal/spi/ts_l1_stm32_uart.c) -else() - message(FATAL_ERROR "No transport layer selected") -endif() - -# Find all HAL header files -file(GLOB_RECURSE HAL_HEADERS ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Inc/*.h) - -set(HEADERS - Inc/main.h - Inc/stm32f4xx_hal_conf.h - Inc/stm32f4xx_it.h - # BSP header file - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/BSP/STM32F4xx_Nucleo_144/stm32f4xx_nucleo_144.h - # HAL headers - ${HAL_HEADERS} -) - -# Include path for directories containing header files -include_directories( - Inc/ - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/BSP/STM32F4xx_Nucleo_144/ - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/ - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Inc/ - ${PATH_TO_STM32CUBEF4}/STM32CubeF4/Drivers/CMSIS/Core/Include/ -) - - -########################################################################### -# # -# Example's compilation # -# # -########################################################################### - -# Add this so HAL knows what target MCU we use -add_definitions(-DSTM32F439xx) -add_definitions(-DUSE_TS_CRYPTO) # TODO unify and fix this definition with option - -# Compile the sources to an .elf -add_executable(${TARGET}.elf ${SOURCES} ${HEADERS}) - -# Link with libtropic -target_link_libraries(${TARGET}.elf PUBLIC tropic) - -# Create a binary from the elf -add_custom_command(TARGET ${TARGET}.elf POST_BUILD - COMMAND arm-none-eabi-objcopy -Oihex ${TARGET}.elf ${TARGET}.hex - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) - -add_custom_target(flash - COMMAND openocd -f ${OPENOCD_CFG} -c 'program ${TARGET}.elf verify reset exit' - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${TARGET}.elf -) diff --git a/examples/stm32_example/Inc/main.h b/examples/stm32_example/Inc/main.h deleted file mode 100644 index f261a02..0000000 --- a/examples/stm32_example/Inc/main.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - ****************************************************************************** - * @file UART/UART_Printf/Inc/main.h - * @author MCD Application Team - * @brief Header for main.c module - ****************************************************************************** - * @attention - * - * Copyright (c) 2017 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __MAIN_H -#define __MAIN_H - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f4xx_hal.h" -#include "stm32f4xx_nucleo_144.h" -#include "stdio.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* User can use this section to tailor USARTx/UARTx instance used and associated - resources */ -/* Definition for USARTx clock resources */ -#define USARTx USART3 -#define USARTx_CLK_ENABLE() __HAL_RCC_USART3_CLK_ENABLE(); -#define USARTx_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE() -#define USARTx_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE() - -#define USARTx_FORCE_RESET() __HAL_RCC_USART3_FORCE_RESET() -#define USARTx_RELEASE_RESET() __HAL_RCC_USART3_RELEASE_RESET() - -/* Definition for USARTx Pins */ -#define USARTx_TX_PIN GPIO_PIN_8 -#define USARTx_TX_GPIO_PORT GPIOD -#define USARTx_TX_AF GPIO_AF7_USART3 -#define USARTx_RX_PIN GPIO_PIN_9 -#define USARTx_RX_GPIO_PORT GPIOD -#define USARTx_RX_AF GPIO_AF7_USART3 - - -/* User can use this section to tailor SPIx instance used and associated - resources */ -/* Definition for SPIx clock resources */ -#define SPIx SPI4 -#define SPIx_CLK_ENABLE() __HAL_RCC_SPI4_CLK_ENABLE() -#define SPIx_SCK_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE() -#define SPIx_MISO_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE() -#define SPIx_MOSI_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE() -#define SPIx_NSS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE() - -#define SPIx_FORCE_RESET() __HAL_RCC_SPI4_FORCE_RESET() -#define SPIx_RELEASE_RESET() __HAL_RCC_SPI4_RELEASE_RESET() - -/* Definition for SPIx Pins */ -#define SPIx_SCK_PIN GPIO_PIN_2 -#define SPIx_SCK_GPIO_PORT GPIOE -#define SPIx_SCK_AF GPIO_AF5_SPI4 -#define SPIx_MISO_PIN GPIO_PIN_5 -#define SPIx_MISO_GPIO_PORT GPIOE -#define SPIx_MISO_AF GPIO_AF5_SPI4 -#define SPIx_MOSI_PIN GPIO_PIN_6 -#define SPIx_MOSI_GPIO_PORT GPIOE -#define SPIx_MOSI_AF GPIO_AF5_SPI4 - -/* Size of buffer */ -#define BUFFERSIZE (COUNTOF(aTxBuffer) - 1) - -/* Exported macro ------------------------------------------------------------*/ -#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__))) -/* Exported functions ------------------------------------------------------- */ - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -#endif /* __MAIN_H */ diff --git a/examples/stm32_example/Inc/stm32f4xx_hal_conf.h b/examples/stm32_example/Inc/stm32f4xx_hal_conf.h deleted file mode 100644 index 6a5000f..0000000 --- a/examples/stm32_example/Inc/stm32f4xx_hal_conf.h +++ /dev/null @@ -1,460 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - * Copyright (c) 2017 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -/* #define HAL_ADC_MODULE_ENABLED */ -/* #define HAL_CAN_MODULE_ENABLED */ -/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ -/* #define HAL_CEC_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -/* #define HAL_DAC_MODULE_ENABLED */ -#define HAL_DCMI_MODULE_ENABLED -#define HAL_DMA_MODULE_ENABLED -#define HAL_DMA2D_MODULE_ENABLED -#define HAL_ETH_MODULE_ENABLED -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_SDRAM_MODULE_ENABLED -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -#define HAL_LTDC_MODULE_ENABLED -#define HAL_DSI_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -/* #define HAL_RNG_MODULE_ENABLED */ -/* #define HAL_RTC_MODULE_ENABLED */ -/* #define HAL_SAI_MODULE_ENABLED */ -/* #define HAL_SD_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_PCD_MODULE_ENABLED */ -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_SPDIFRX_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE (8000000U) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT (100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE (16000000U) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE (32000U) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE (32768U) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT (5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE (12288000U) /*!< Value of the External oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE (3300U) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY (0x0FU) /*!< tick interrupt priority */ -#define USE_RTOS 0U -#define PREFETCH_ENABLE 1U -#define INSTRUCTION_CACHE_ENABLE 1U - -#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ -#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ -#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ -#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ -#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ -#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ -#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ -#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ -#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ -#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ -#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ -#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ -#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ -#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */ -#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ -#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ -#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ -#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ -#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ -#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ -#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ -#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ -#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ -#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ -#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ -#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ -#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ -#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ -#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ -#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ -#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ -#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ -#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ -#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ -#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ -#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ -#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ -#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1U*/ - -/* ################## Ethernet peripheral configuration for NUCLEO 144 board ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2U -#define MAC_ADDR1 0U -#define MAC_ADDR2 0U -#define MAC_ADDR3 0U -#define MAC_ADDR4 0U -#define MAC_ADDR5 0U - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE (1528U) /* ETH max buffer size for receive */ -#define ETH_TX_BUF_SIZE (1528U) /* ETH max buffer size for transmit */ -#define ETH_RXBUFNB (5U) /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB (5U) /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ -/* LAN8742A PHY Address*/ -#define LAN8742A_PHY_ADDRESS 0x00U -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY (0x00000FFFU) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY (0x00000FFFU) - -#define PHY_READ_TO (0x0000FFFFU) -#define PHY_WRITE_TO (0x0000FFFFU) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x1F) /*!< PHY special control/ status register Offset */ - -#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< PHY Duplex mask */ - - -#define PHY_ISFR ((uint16_t)0x1D) /*!< PHY Interrupt Source Flag register Offset */ -#define PHY_ISFR_INT4 ((uint16_t)0x0010) /*!< PHY Link down inturrupt */ - -/* ################## SPI peripheral configuration ########################## */ - -/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver -* Activated: CRC code is present inside driver -* Deactivated: CRC code cleaned from driver -*/ - -#define USE_SPI_CRC 1U - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CAN_LEGACY_MODULE_ENABLED - #include "stm32f4xx_hal_can_legacy.h" -#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f4xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_DSI_MODULE_ENABLED - #include "stm32f4xx_hal_dsi.h" -#endif /* HAL_DSI_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32f4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPDIFRX_MODULE_ENABLED - #include "stm32f4xx_hal_spdifrx.h" -#endif /* HAL_SPDIFRX_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0U) -#endif /* USE_FULL_ASSERT */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ diff --git a/examples/stm32_example/Inc/stm32f4xx_it.h b/examples/stm32_example/Inc/stm32f4xx_it.h deleted file mode 100644 index 7da1457..0000000 --- a/examples/stm32_example/Inc/stm32f4xx_it.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - ****************************************************************************** - * @file UART/UART_Printf/Inc/stm32f4xx_it.h - * @author MCD Application Team - * @brief This file contains the headers of the interrupt handlers. - ****************************************************************************** - * @attention - * - * Copyright (c) 2017 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_IT_H -#define __STM32F4xx_IT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -void NMI_Handler(void); -void HardFault_Handler(void); -void MemManage_Handler(void); -void BusFault_Handler(void); -void UsageFault_Handler(void); -void SVC_Handler(void); -void DebugMon_Handler(void); -void PendSV_Handler(void); -void SysTick_Handler(void); -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_IT_H */ diff --git a/examples/stm32_example/STM32F429ZITX_FLASH.ld b/examples/stm32_example/STM32F429ZITX_FLASH.ld deleted file mode 100644 index 33f3577..0000000 --- a/examples/stm32_example/STM32F429ZITX_FLASH.ld +++ /dev/null @@ -1,206 +0,0 @@ -/* -****************************************************************************** -** -** @file : LinkerScript.ld -** -** @author : Auto-generated by STM32CubeIDE -** -** @brief : Linker script for STM32F429ZITx Device from STM32F4 series -** 2048Kbytes ROM -** 64Kbytes CCMRAM -** 192Kbytes RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used -** -** Target : STMicroelectronics STM32 -** -** Distribution: The file is distributed as is, without any warranty -** of any kind. -** -****************************************************************************** -** @attention -** -** Copyright (c) 2022 STMicroelectronics. -** All rights reserved. -** -** This software is licensed under terms that can be found in the LICENSE file -** in the root directory of this software component. -** If no LICENSE file comes with this software, it is provided AS-IS. -** -****************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ - -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Memories definition */ -MEMORY -{ - CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K - ROM (rx) : ORIGIN = 0x08000000, LENGTH = 2048K -} - -/* Sections */ -SECTIONS -{ - /* The startup code into "ROM" Rom type memory */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >ROM - - /* The program code and other data into "ROM" Rom type memory */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >ROM - - /* Constant data into "ROM" Rom type memory */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >ROM - - .ARM.extab : { - . = ALIGN(4); - *(.ARM.extab* .gnu.linkonce.armextab.*) - . = ALIGN(4); - } >ROM - - .ARM : { - . = ALIGN(4); - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - . = ALIGN(4); - } >ROM - - .preinit_array : - { - . = ALIGN(4); - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - . = ALIGN(4); - } >ROM - - .init_array : - { - . = ALIGN(4); - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - . = ALIGN(4); - } >ROM - - .fini_array : - { - . = ALIGN(4); - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - . = ALIGN(4); - } >ROM - - /* Used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections into "RAM" Ram type memory */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - *(.RamFunc) /* .RamFunc sections */ - *(.RamFunc*) /* .RamFunc* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - - } >RAM AT> ROM - - _siccmram = LOADADDR(.ccmram); - - /* CCM-RAM section - * - * IMPORTANT NOTE! - * If initialized variables will be placed in this section, - * the startup code needs to be modified to copy the init-values. - */ - .ccmram : - { - . = ALIGN(4); - _sccmram = .; /* create a global symbol at ccmram start */ - *(.ccmram) - *(.ccmram*) - - . = ALIGN(4); - _eccmram = .; /* create a global symbol at ccmram end */ - } >CCMRAM AT> ROM - - /* Uninitialized data section into "RAM" Ram type memory */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the compiler libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/examples/stm32_example/Src/cryptography_tests.c b/examples/stm32_example/Src/cryptography_tests.c deleted file mode 100644 index adfb482..0000000 --- a/examples/stm32_example/Src/cryptography_tests.c +++ /dev/null @@ -1,409 +0,0 @@ - -/* At the moment, those are still exposed in libtropic */ -#include "ts_hkdf.h" -#include "ts_aesgcm.h" -#include "ts_sha256.h" -#include "ts_x25519.h" - -/* Purpose of this file is to provide quick way how to run all crypto related functions on a used devkit hardware and verify their outputs. - In a real world scenario, cryptography interfaces will be hidden to user. -*/ -#define FROMHEX_MAXLEN 512 - -const uint8_t *fromhex(const char *str) { - static uint8_t buf[FROMHEX_MAXLEN]; - size_t len = strlen(str) / 2; - if (len > FROMHEX_MAXLEN) len = FROMHEX_MAXLEN; - for (size_t i = 0; i < len; i++) { - uint8_t c = 0; - if (str[i * 2] >= '0' && str[i * 2] <= '9') c += (str[i * 2] - '0') << 4; - if ((str[i * 2] & ~0x20) >= 'A' && (str[i * 2] & ~0x20) <= 'F') - c += (10 + (str[i * 2] & ~0x20) - 'A') << 4; - if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') - c += (str[i * 2 + 1] - '0'); - if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F') - c += (10 + (str[i * 2 + 1] & ~0x20) - 'A'); - buf[i] = c; - } - return buf; -} - -struct { - char *key; - char *iv; - char *aad; - char *plaintext; - char *ciphertext; - char *tag; - } vectors[] = { - // Test case 1 - { - "00000000000000000000000000000000", - "000000000000000000000000", - "", - "", - "", - "58e2fccefa7e3061367f1d57a4e7455a", - }, - // Test case 2 - { - "00000000000000000000000000000000", - "000000000000000000000000", - "", - "00000000000000000000000000000000", - "0388dace60b6a392f328c2b971b2fe78", - "ab6e47d42cec13bdf53a67b21257bddf", - }, - // Test case 3 - { - "feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", - "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d5" - "14b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985", - "4d5c2af327cd64a62cf35abd2ba6fab4", - }, - // Test case 4 - { - "feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d5" - "14b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091", - "5bc94fbc3221a5db94fae95ae7121a47", - }, - // Test case 5 - { - "feffe9928665731c6d6a8f9467308308", - "cafebabefacedbad", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c74237380" - "6900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598", - "3612d2e79e3b0785561be14aaca2fccb", - }, - // Test case 6 - { - "feffe9928665731c6d6a8f9467308308", - "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0" - "c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4" - "a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5", - "619cc5aefffe0bfa462af43c1699d050", - }, - // Test case 7 - { - "000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "", - "", - "cd33b28ac773f74ba00ed1f312572435", - }, - // Test case 8 - { - "000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "00000000000000000000000000000000", - "98e7247c07f0fe411c267e4384b0f600", - "2ff58d80033927ab8ef4d4587514f0fb", - }, - // Test case 9 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "cafebabefacedbaddecaf888", - "", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", - "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d77" - "3d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256", - "9924a7c8587336bfb118024db8674a14", - }, - // Test case 10 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "cafebabefacedbaddecaf888", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d77" - "3d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710", - "2519498e80f1478f37ba55bd6d27618c", - }, - // Test case 11 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "cafebabefacedbad", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc" - "29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7", - "65dcc57fcf623a24094fcca40d3533f8", - }, - // Test case 12 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c", - "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0" - "c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e7" - "9012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b", - "dcf566ff291c25bbb8568fc3d376a6d9", - }, - // Test case 13 - { - "0000000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "", - "", - "530f8afbc74536b9a963b4f1c4cb738b", - }, - // Test case 14 - { - "0000000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000", - "", - "00000000000000000000000000000000", - "cea7403d4d606b6e074ec5d3baf39d18", - "d0d1c8a799996bf0265b98b5d48ab919", - }, - // Test case 15 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", - "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb0" - "8e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad", - "b094dac5d93471bdec1a502270e3cc6c", - }, - // Test case 16 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbaddecaf888", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb0" - "8e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662", - "76fc6ece0f4e1768cddf8853bb2d551b", - }, - // Test case 17 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "cafebabefacedbad", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb5" - "82d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f", - "3a337dbf46a792c45e454913fe2ea8f2", - }, - // Test case 18 - { - "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", - "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0" - "c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c" - "0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", - "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0" - "c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f", - "a44a8266ee1c8eb0c8b5d4cf5ae9f19a", - }, - }; - -int test_aesgcm() -{ - uint8_t iv[60] = {0}; - uint8_t aad[20] = {0}; - uint8_t msg[64] = {0}; - uint8_t tag[16] = {0}; - - for (uint32_t i=0; i < (sizeof(vectors)/sizeof(vectors[0])); i++) { - - size_t iv_len = strlen(vectors[i].iv) / 2; - memcpy(iv, fromhex(vectors[i].iv), iv_len); - size_t aad_len = strlen(vectors[i].aad) / 2; - memcpy(aad, fromhex(vectors[i].aad), aad_len); - size_t msg_len = strlen(vectors[i].plaintext) / 2; - memcpy(msg, fromhex(vectors[i].plaintext), msg_len); - size_t tag_len = strlen(vectors[i].tag) / 2; - - // Set key. - ts_aes_gcm_ctx_t ctx_enc = {0}; - int ret = ts_aesgcm_init_and_key( - &ctx_enc, /* the mode context */ - fromhex(vectors[i].key), /* the key value */ - strlen(vectors[i].key) / 2 /* and its length in bytes */ - ); - - ret = ts_aesgcm_encrypt( - &ctx_enc, /* the mode context */ - iv, /* the initialisation vector */ - iv_len, /* and its length in bytes */ - aad, /* the header buffer */ - aad_len, /* and its length in bytes */ - msg, /* the message buffer */ - msg_len, /* and its length in bytes */ - tag, /* the buffer for the tag */ - tag_len /* and its length in bytes */ - ); - - //memset(&ctx, 0, sizeof(ts_aes_gcm_ctx_t)); - if(RETURN_GOOD != ret) { - return 1; - } - //TEST_ASSERT_EQUAL(RETURN_GOOD, ret); - if ((msg_len > 0)) - { - if(memcmp(msg, fromhex(vectors[i].ciphertext), msg_len) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(msg, fromhex(vectors[i].ciphertext), msg_len); - } - if ((tag_len > 0)) - { - if(memcmp(tag, fromhex(vectors[i].tag), tag_len) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(tag, fromhex(vectors[i].tag), tag_len); - } - - ts_aes_gcm_ctx_t ctx_dec = {0}; - - ret = ts_aesgcm_init_and_key(&ctx_dec, - fromhex(vectors[i].key), /* the key value */ - strlen(vectors[i].key) / 2 /* and its length in bytes */ - ); - - ret = ts_aesgcm_decrypt( &ctx_dec, /* the mode context */ - iv, /* the initialisation vector */ - iv_len, /* and its length in bytes */ - aad, /* the header buffer */ - aad_len, /* and its length in bytes */ - msg, /* the message buffer */ - msg_len, /* and its length in bytes */ - tag, /* the buffer for the tag */ - tag_len); /* and its length in bytes */ - - - if(msg_len > 0) { - if(memcmp(fromhex(vectors[i].plaintext), msg, msg_len) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(fromhex(vectors[i].plaintext), msg, msg_len); - } - } - return 0; -} - -int test_hkdf() { - - uint8_t output_1[33] = {0}; - uint8_t output_2[32] = {0}; - // round 1, output_2 is not used - uint8_t protocol_name[32] = {'N','o','i','s','e','_','K','K','1','_','2','5','5','1','9','_','A','E','S','G','C','M','_','S','H','A','2','5','6',0x00,0x00,0x00}; - uint8_t s_s_1[32] = {0x3d,0x9c,0xf1,0x6d,0x28,0x96,0x11,0x5e,0x4e,0x6a,0x9f,0xce,0x07,0x10,0x39,0xd9,0xa2,0x06,0x80,0xd3,0x24,0xa6,0xd1,0x6d,0xcb,0x83,0x3c,0xd6,0xd5,0x85,0xdf,0x3b}; - ts_hkdf(protocol_name, 32, s_s_1, 32, 1, output_1, output_2); - uint8_t ck1[32] = {0x8e,0x5d,0xae,0xbc,0xbc,0xe7,0xa3,0x0d,0xd6,0x6e,0xb7,0x23,0x01,0x53,0x50,0xd9,0x05,0x7f,0x53,0xaf,0x0f,0x81,0xce,0x0d,0xae,0x51,0xda,0xf8,0x70,0x4e,0xca,0x1b}; - - if(memcmp(ck1, output_1, 32) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(ck1, output_1, 32); - // round 2, output_2 is not used - uint8_t s_s_2[32] = {0xdf,0xf8,0x1a,0xa2,0x04,0x78,0x5e,0x0b,0x53,0x28,0xfe,0xed,0x8d,0xec,0x02,0x0d,0xbb,0xcb,0xda,0xb3,0x07,0x67,0xdd,0x3b,0xb1,0xa6,0xc5,0x6c,0x93,0xcb,0x3a,0x13}; - ts_hkdf(ck1, 32, s_s_2, 32, 1, output_1, output_2); - uint8_t ck2[32] = {0x2f,0x5b,0xc4,0xcb,0xae,0xe1,0x00,0x4d,0x57,0x58,0x53,0x16,0xbc,0xa4,0x06,0x6e,0xac,0x66,0xa8,0xc0,0xe6,0x68,0x0a,0x46,0x97,0x2c,0xe3,0x91,0xa4,0x34,0x48,0x63}; - if(memcmp(ck2, output_1, 32) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(ck2, output_1, 32); - // round 3, output_2 is also used - uint8_t s_s_3[32] = {0xb9,0x1c,0x94,0x87,0x9c,0x54,0x09,0x09,0x6d,0x79,0x2d,0x2b,0x98,0xba,0xb0,0x11,0xbf,0x8e,0x49,0xbf,0x8f,0x8d,0x26,0x0b,0x90,0x85,0x1c,0x7e,0x75,0xa9,0xfb,0x6a}; - ts_hkdf(ck2, 32, s_s_3, 32, 2, output_1, output_2); - uint8_t ck3[32] = {0xa3,0xb3,0x38,0x0a,0x6f,0xf2,0xbb,0x64,0x03,0xc3,0x4f,0xec,0xa4,0x4b,0xf5,0xde,0xb2,0xed,0xc9,0x2f,0xfb,0x4c,0x1b,0xa6,0xcb,0x20,0xdc,0x97,0xb6,0xe2,0xc8,0x34}; - uint8_t kauth[32] = {0xa1,0x97,0x09,0x67,0x11,0xf5,0x8e,0x5d,0x10,0x4c,0xbf,0xfb,0xa7,0x16,0xa0,0x57,0x38,0x28,0x09,0x65,0x6f,0xa5,0xd7,0xfd,0x56,0x93,0x08,0x41,0xf8,0xef,0xf6,0x29}; - if(memcmp(ck3, output_1, 32) == 1) { - return 1; - } - if(memcmp(kauth, output_2, 32) == 1) { - return 1; - } - - //TEST_ASSERT_EQUAL_HEX8_ARRAY(ck3, output_1, 32); - //TEST_ASSERT_EQUAL_HEX8_ARRAY(kauth, output_2, 32); - // round 4, output_2 is also used - ts_hkdf(ck3, 32, (uint8_t *)"", 0, 2, output_1, output_2); - uint8_t kcmd[32] = {0x10,0xf3,0x29,0xf6,0x85,0xc3,0x44,0x25,0xa3,0x79,0x0e,0xdb,0xcf,0x42,0xa5,0x88,0xe8,0x87,0x64,0x07,0x73,0x87,0xe3,0x0e,0x57,0x58,0xbd,0xb1,0x9d,0x68,0x45,0xcb}; - uint8_t kres[32] = {0x32,0xb3,0x1d,0x65,0xad,0xf4,0xab,0x0e,0x2c,0xba,0xd8,0x0d,0xe9,0x1f,0xa4,0x66,0xf5,0x76,0x26,0x71,0x81,0x5a,0x75,0x04,0xdf,0x1c,0x32,0xaf,0xfe,0xba,0xaf,0x15}; - //TEST_ASSERT_EQUAL_HEX8_ARRAY(kcmd, output_1, 32); - //TEST_ASSERT_EQUAL_HEX8_ARRAY(kres, output_2, 32); - - if(memcmp(kcmd, output_1, 32) == 1) { - return 1; - } - if(memcmp(kres, output_2, 32) == 1) { - return 1; - } - - return 0; -} - -int test_sha256(void) { - - uint8_t protocol_name[32] = {'N','o','i','s','e','_','K','K','1','_','2','5','5','1','9','_','A','E','S','G','C','M','_','S','H','A','2','5','6'}; - uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; - ts_sha256_ctx_t ctx = {0}; - ts_sha256_init(&ctx); - ts_sha256_start(&ctx); - ts_sha256_update(&ctx, protocol_name, 29); - ts_sha256_finish(&ctx, hash); - uint8_t expected[] = {0x92,0x5b,0x44,0xac,0xed,0xc4,0x53,0x3b,0x48,0x42,0xa0,0x66,0x0d,0x81,0x5e,0x16,0x84,0x0a,0xee,0x64,0x63,0x28,0x0f,0x07,0xa8,0x28,0xe1,0x5d,0x07,0x0c,0x73,0x78}; - - if(memcmp(expected, hash, 32)) { - return 1; - } - return 0; -} - -// vectors taken from python model -int test_X25519() -{ - uint8_t priv[32] = {0x38,0xc9,0xd9,0xb1,0x79,0x11,0xde,0x26,0xed,0x81,0x2f,0x5c,0xc1,0x9c,0x00,0x29,0xe8,0xd0,0x16,0xbc,0xbc,0x60,0x78,0xbc,0x9d,0xb2,0xaf,0x33,0xf1,0x76,0x1e,0x4a}; - uint8_t pub[32] = {0x31,0x1b,0x62,0x48,0xaf,0x8d,0xab,0xec,0x5c,0xc8,0x1e,0xac,0x5b,0xf2,0x29,0x92,0x5f,0x6d,0x21,0x8a,0x12,0xe0,0x54,0x7f,0xb1,0x85,0x6e,0x01,0x5c,0xc7,0x6f,0x5d}; - uint8_t out[32] = {0}; - ts_X25519(priv, pub, out); - uint8_t expected[32] = {0xa9,0x3d,0xbd,0xb2,0x3e,0x5c,0x99,0xda,0x74,0x3e,0x20,0x3b,0xd3,0x91,0xaf,0x79,0xf2,0xb8,0x3f,0xb8,0xd0,0xfd,0x6e,0xc8,0x13,0x37,0x1c,0x71,0xf0,0x8f,0x2d,0x4d}; - if(memcmp(expected, out, 32) == 1) { - return 1; - } - //TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, out, 32); - - uint8_t priv2[32] = {0x38,0xc9,0xd9,0xb1,0x79,0x11,0xde,0x26,0xed,0x81,0x2f,0x5c,0xc1,0x9c,0x00,0x29,0xe8,0xd0,0x16,0xbc,0xbc,0x60,0x78,0xbc,0x9d,0xb2,0xaf,0x33,0xf1,0x76,0x1e,0x4a}; - uint8_t pub2[32] = {0x31,0x1b,0x62,0x48,0xaf,0x8d,0xab,0xec,0x5c,0xc8,0x1e,0xac,0x5b,0xf2,0x29,0x92,0x5f,0x6d,0x21,0x8a,0x12,0xe0,0x54,0x7f,0xb1,0x85,0x6e,0x01,0x5c,0xc7,0x6f,0x5d}; - uint8_t out2[32] = {0}; - ts_X25519(priv2, pub2, out2); - uint8_t expected2[32] = {0xa9,0x3d,0xbd,0xb2,0x3e,0x5c,0x99,0xda,0x74,0x3e,0x20,0x3b,0xd3,0x91,0xaf,0x79,0xf2,0xb8,0x3f,0xb8,0xd0,0xfd,0x6e,0xc8,0x13,0x37,0x1c,0x71,0xf0,0x8f,0x2d,0x4d}; - if(memcmp(expected2, out2, 32) == 1) { - return 1; - } - return 0; - //TEST_ASSERT_EQUAL_HEX8_ARRAY(expected2, out2, 32); -} - diff --git a/examples/stm32_example/Src/cryptography_tests.h b/examples/stm32_example/Src/cryptography_tests.h deleted file mode 100644 index b621761..0000000 --- a/examples/stm32_example/Src/cryptography_tests.h +++ /dev/null @@ -1,10 +0,0 @@ - -#ifndef CRYPTOGRAPHY_TESTS_H -#define CRYPTOGRAPHY_TESTS_H - -int test_aesgcm(); -int test_hkdf(); -int test_sha256(void); -int test_X25519(); - -#endif \ No newline at end of file diff --git a/examples/stm32_example/Src/main.c b/examples/stm32_example/Src/main.c deleted file mode 100644 index 3d7ec82..0000000 --- a/examples/stm32_example/Src/main.c +++ /dev/null @@ -1,614 +0,0 @@ -/** - ****************************************************************************** - * @file UART/UART_Printf/Src/main.c - * @author MCD Application Team - * @brief This example shows how to retarget the C library printf function - * to the UART. - ****************************************************************************** - * @attention - * - * Copyright (c) 2017 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "main.h" -#include "libtropic.h" -#include "cryptography_tests.h" - -#include "ed25519.h" -#include "ts_sha256.h" - -// Default initial Tropic handshake keys -#define PKEY_INDEX_BYTE 0 -#define SHiPRIV_BYTES {0xf0,0xc4,0xaa,0x04,0x8f,0x00,0x13,0xa0,0x96,0x84,0xdf,0x05,0xe8,0xa2,0x2e,0xf7,0x21,0x38,0x98,0x28,0x2b,0xa9,0x43,0x12,0xf3,0x13,0xdf,0x2d,0xce,0x8d,0x41,0x64}; -#define SHiPUB_BYTES {0x84,0x2f,0xe3,0x21,0xa8,0x24,0x74,0x08,0x37,0x37,0xff,0x2b,0x9b,0x88,0xa2,0xaf,0x42,0x44,0x2d,0xb0,0xd8,0xaa,0xcc,0x6d,0xc6,0x9e,0x99,0x53,0x33,0x44,0xb2,0x46}; - - -#define LOG_OUT(f_, ...) printf(f_, ##__VA_ARGS__) -#define LOG_OUT_INFO(f_, ...) printf("\t[INFO] "f_, ##__VA_ARGS__) -#define LOG_OUT_VALUE(f_, ...) printf("\t\t\t\t\t"f_, ##__VA_ARGS__) -#define LOG_OUT_LINE(f_, ...) printf("\t-------------------------------------------------------------------------------------------------------------\r\n"f_, ##__VA_ARGS__) - -void bytes_to_chars(uint8_t const *key, char *buffer, uint16_t len) -{ - uint16_t offset = 0; - memset(buffer, 0, len); - - for (size_t i = 0; i < len; i++) - { - offset += sprintf(buffer + offset, "%02X", key[i]); - } - sprintf(buffer + offset, "%c", '\0'); -} - - - -/** @addtogroup STM32F4xx_HAL_Examples - * @{ - */ - -/** @addtogroup UART_Printf - * @{ - */ - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -#define LOG_OUT(f_, ...) printf(f_, ##__VA_ARGS__) -#define NUM_OF_PING_CMDS 1 -/* Private variables ---------------------------------------------------------*/ - - -/* Private function prototypes -----------------------------------------------*/ -#ifdef __GNUC__ -/* With GCC, small printf (option LD Linker->Libraries->Small printf - set to 'Yes') calls __io_putchar() */ -#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) -#else -#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) -#endif /* __GNUC__ */ -static void SystemClock_Config(void); -static void Error_Handler(void); - -/* Private functions ---------------------------------------------------------*/ - -/* UART handle declaration */ -static UART_HandleTypeDef UartHandle; - -/** - * @brief Configures the UART peripheral - * Put the USART peripheral in the Asynchronous mode (UART Mode) - * UART configured as follows: - * - Word Length = 8 Bits (7 data bit + 1 parity bit) : - * BE CAREFUL : Program 7 data bits + 1 parity bit in PC HyperTerminal - * - Stop Bit = One Stop bit - * - Parity = NONE parity - * - BaudRate = 115200 baud - * - Hardware flow control disabled (RTS and CTS signals) - * - * @return HAL_StatusTypeDef - */ -static HAL_StatusTypeDef UART_Init(void) -{ - UartHandle.Instance = USARTx; - UartHandle.Init.BaudRate = 115200; - UartHandle.Init.WordLength = UART_WORDLENGTH_8B; - UartHandle.Init.StopBits = UART_STOPBITS_1; - UartHandle.Init.Parity = UART_PARITY_NONE; - UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; - UartHandle.Init.Mode = UART_MODE_TX_RX; - UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; - - if (HAL_UART_Init(&UartHandle) != HAL_OK) - { - return HAL_ERROR; - } - - return HAL_OK; -} - -/** - * @brief Retargets the C library printf function to the USART. - * @param None - * @retval None - */ -PUTCHAR_PROTOTYPE -{ - /* Place your implementation of fputc here */ - /* e.g. write a character to the USART3 and Loop until the end of transmission */ - HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, 0xFFFF); - - return ch; -} - - - -/** - * @brief Main program - * @param None - * @retval None - */ -int main(void) -{ - /* STM32F4xx HAL library initialization: - - Configure the Flash prefetch - - Systick timer is configured by default as source of time base, but user - can eventually implement his proper time base source (a general purpose - timer for example or other time source), keeping in mind that Time base - duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and - handled in milliseconds basis. - - Set NVIC Group Priority to 4 - - Low Level Initialization - */ - HAL_Init(); - /* Configure the system clock to 180 MHz */ - SystemClock_Config(); - /* Initialize BSP Led for LED2 */ - BSP_LED_Init(LED2); - - if(UART_Init() != HAL_OK) { - Error_Handler(); - } - - /************************************************************************************************************/ - /* Welcome banner */ - LOG_OUT("\r\n"); - LOG_OUT("\t\t======================================================================\r\n"); -#if HAL_UART - LOG_OUT("\t\t===== libtropic stm32 demo, running over UART against model ===\r\n"); -#elif HAL_SPI - LOG_OUT("\t\t===== libtropic stm32 demo, running over SPI against FPGA ===\r\n"); -#endif - LOG_OUT("\t\t======================================================================\r\n\n"); - - LOG_OUT_INFO("List all possible return values:\r\n\n"); - for(int i=0; iCPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ - #endif - /* Reset the RCC clock configuration to the default reset state ------------*/ - /* Set HSION bit */ - RCC->CR |= (uint32_t)0x00000001; - - /* Reset CFGR register */ - RCC->CFGR = 0x00000000; - - /* Reset HSEON, CSSON and PLLON bits */ - RCC->CR &= (uint32_t)0xFEF6FFFF; - - /* Reset PLLCFGR register */ - RCC->PLLCFGR = 0x24003010; - - /* Reset HSEBYP bit */ - RCC->CR &= (uint32_t)0xFFFBFFFF; - - /* Disable all interrupts */ - RCC->CIR = 0x00000000; - - - /* Configure the Vector Table location add offset address ------------------*/ -#ifdef VECT_TAB_SRAM - SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -#endif -} - -/** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value - * depends on the application requirements), user has to ensure that HSE_VALUE - * is same as the real frequency of the crystal used. Otherwise, this function - * may have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ - - /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N - SYSCLK = PLL_VCO / PLL_P - */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - - if (pllsource != 0) - { - /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - else - { - /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - /* Compute HCLK frequency --------------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK frequency */ - SystemCoreClock >>= tmp; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/examples/stm32_example/System/Startup/startup_stm32f429zitx.s b/examples/stm32_example/System/Startup/startup_stm32f429zitx.s deleted file mode 100644 index 89f8906..0000000 --- a/examples/stm32_example/System/Startup/startup_stm32f429zitx.s +++ /dev/null @@ -1,542 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32f429xx.s - * @author MCD Application Team - * @brief STM32F429xx Devices vector table for GCC based toolchains. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - * Copyright (c) 2017 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - ldr r0, =_sdata - ldr r1, =_edata - ldr r2, =_sidata - movs r3, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r4, [r2, r3] - str r4, [r0, r3] - adds r3, r3, #4 - -LoopCopyDataInit: - adds r4, r0, r3 - cmp r4, r1 - bcc CopyDataInit - -/* Zero fill the bss segment. */ - ldr r2, =_sbss - ldr r4, =_ebss - movs r3, #0 - b LoopFillZerobss - -FillZerobss: - str r3, [r2] - adds r2, r2, #4 - -LoopFillZerobss: - cmp r2, r4 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - -g_pfnVectors: - .word _estack - .word Reset_Handler - - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ - .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FMC_IRQHandler /* FMC */ - .word SDIO_IRQHandler /* SDIO */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* Reserved */ - .word HASH_RNG_IRQHandler /* Hash and Rng */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word SPI4_IRQHandler /* SPI4 */ - .word SPI5_IRQHandler /* SPI5 */ - .word SPI6_IRQHandler /* SPI6 */ - .word SAI1_IRQHandler /* SAI1 */ - .word LTDC_IRQHandler /* LTDC_IRQHandler */ - .word LTDC_ER_IRQHandler /* LTDC_ER_IRQHandler */ - .word DMA2D_IRQHandler /* DMA2D */ - - - .size g_pfnVectors, .-g_pfnVectors - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler - .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler - .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM11_IRQHandler - .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FMC_IRQHandler - .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDIO_IRQHandler - .thumb_set SDIO_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak ETH_IRQHandler - .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler - .thumb_set ETH_WKUP_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler - .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler - .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler - .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler - .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak HASH_RNG_IRQHandler - .thumb_set HASH_RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak SPI5_IRQHandler - .thumb_set SPI5_IRQHandler,Default_Handler - - .weak SPI6_IRQHandler - .thumb_set SPI6_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak LTDC_IRQHandler - .thumb_set LTDC_IRQHandler,Default_Handler - - .weak LTDC_ER_IRQHandler - .thumb_set LTDC_ER_IRQHandler,Default_Handler - - .weak DMA2D_IRQHandler - .thumb_set DMA2D_IRQHandler,Default_Handler diff --git a/examples/stm32_example/System/User/syscalls.c b/examples/stm32_example/System/User/syscalls.c deleted file mode 100644 index d190edf..0000000 --- a/examples/stm32_example/System/User/syscalls.c +++ /dev/null @@ -1,176 +0,0 @@ -/** - ****************************************************************************** - * @file syscalls.c - * @author Auto-generated by STM32CubeIDE - * @brief STM32CubeIDE Minimal System calls file - * - * For more information about which c-functions - * need which of these lowlevel functions - * please consult the Newlib libc-manual - ****************************************************************************** - * @attention - * - * Copyright (c) 2020-2023 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes */ -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Variables */ -extern int __io_putchar(int ch) __attribute__((weak)); -extern int __io_getchar(void) __attribute__((weak)); - - -char *__env[1] = { 0 }; -char **environ = __env; - - -/* Functions */ -void initialise_monitor_handles() -{ -} - -int _getpid(void) -{ - return 1; -} - -int _kill(int pid, int sig) -{ - (void)pid; - (void)sig; - errno = EINVAL; - return -1; -} - -void _exit (int status) -{ - _kill(status, -1); - while (1) {} /* Make sure we hang here */ -} - -__attribute__((weak)) int _read(int file, char *ptr, int len) -{ - (void)file; - int DataIdx; - - for (DataIdx = 0; DataIdx < len; DataIdx++) - { - *ptr++ = __io_getchar(); - } - - return len; -} - -__attribute__((weak)) int _write(int file, char *ptr, int len) -{ - (void)file; - int DataIdx; - - for (DataIdx = 0; DataIdx < len; DataIdx++) - { - __io_putchar(*ptr++); - } - return len; -} - -int _close(int file) -{ - (void)file; - return -1; -} - - -int _fstat(int file, struct stat *st) -{ - (void)file; - st->st_mode = S_IFCHR; - return 0; -} - -int _isatty(int file) -{ - (void)file; - return 1; -} - -int _lseek(int file, int ptr, int dir) -{ - (void)file; - (void)ptr; - (void)dir; - return 0; -} - -int _open(char *path, int flags, ...) -{ - (void)path; - (void)flags; - /* Pretend like we always fail */ - return -1; -} - -int _wait(int *status) -{ - (void)status; - errno = ECHILD; - return -1; -} - -int _unlink(char *name) -{ - (void)name; - errno = ENOENT; - return -1; -} - -int _times(struct tms *buf) -{ - (void)buf; - return -1; -} - -int _stat(char *file, struct stat *st) -{ - (void)file; - st->st_mode = S_IFCHR; - return 0; -} - -int _link(char *old, char *new) -{ - (void)old; - (void)new; - errno = EMLINK; - return -1; -} - -int _fork(void) -{ - errno = EAGAIN; - return -1; -} - -int _execve(char *name, char **argv, char **env) -{ - (void)name; - (void)argv; - (void)env; - errno = ENOMEM; - return -1; -} diff --git a/examples/stm32_example/System/User/sysmem.c b/examples/stm32_example/System/User/sysmem.c deleted file mode 100644 index 921ecef..0000000 --- a/examples/stm32_example/System/User/sysmem.c +++ /dev/null @@ -1,79 +0,0 @@ -/** - ****************************************************************************** - * @file sysmem.c - * @author Generated by STM32CubeIDE - * @brief STM32CubeIDE System Memory calls file - * - * For more information about which C functions - * need which of these lowlevel functions - * please consult the newlib libc manual - ****************************************************************************** - * @attention - * - * Copyright (c) 2023 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes */ -#include -#include - -/** - * Pointer to the current high watermark of the heap usage - */ -static uint8_t *__sbrk_heap_end = NULL; - -/** - * @brief _sbrk() allocates memory to the newlib heap and is used by malloc - * and others from the C library - * - * @verbatim - * ############################################################################ - * # .data # .bss # newlib heap # MSP stack # - * # # # # Reserved by _Min_Stack_Size # - * ############################################################################ - * ^-- RAM start ^-- _end _estack, RAM end --^ - * @endverbatim - * - * This implementation starts allocating at the '_end' linker symbol - * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack - * The implementation considers '_estack' linker symbol to be RAM end - * NOTE: If the MSP stack, at any point during execution, grows larger than the - * reserved size, please increase the '_Min_Stack_Size'. - * - * @param incr Memory size - * @return Pointer to allocated memory - */ -void *_sbrk(ptrdiff_t incr) -{ - extern uint8_t _end; /* Symbol defined in the linker script */ - extern uint8_t _estack; /* Symbol defined in the linker script */ - extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ - const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; - const uint8_t *max_heap = (uint8_t *)stack_limit; - uint8_t *prev_heap_end; - - /* Initialize heap end at first call */ - if (NULL == __sbrk_heap_end) - { - __sbrk_heap_end = &_end; - } - - /* Protect heap from growing into the reserved MSP stack */ - if (__sbrk_heap_end + incr > max_heap) - { - errno = ENOMEM; - return (void *)-1; - } - - prev_heap_end = __sbrk_heap_end; - __sbrk_heap_end += incr; - - return (void *)prev_heap_end; -} diff --git a/examples/stm32_example/readme.MD b/examples/stm32_example/readme.MD deleted file mode 100644 index 09db702..0000000 --- a/examples/stm32_example/readme.MD +++ /dev/null @@ -1,68 +0,0 @@ -# About - -This is a minimalistic example for NUCLEO-F439ZI devboard: - -* It expects SPI connection to a running TROPIC01 - chip, model or FPGA -* used SPI pins are: PE2 SCK, PE4 CS, PE5 MISO, PE6 MOSI -* Debug messages are transmitted over USB ACM, they can be received by opening a serial port - -## Dependencies - -* cmake -* arm-none-eabi-gcc -* openocd (check OPENOCD_CFG in CMakeLists.txt o set path to config file for your devboard) - -# How to compile and flash? - - Connect devboard and run in this folder: -``` -mkdir build -cd build -cmake .. -make flash -``` - -# Debugging - -## VS Code - -Dependencies: - -* cortex-debug extension -* arm-none-eabi-gdb - -Place this launch.json file into .vscode folder: - -``` -{ - "version": "0.2.0", - "configurations": [ - { - "type": "cortex-debug", - "request": "attach", - "name": "Debug (OpenOCD)", - "servertype": "openocd", - "cwd": "${workspaceRoot}", - //"preLaunchTask": "cargo build", - //"runToEntryPoint": "true", - "executable": "./examples/stm32_example/build/stm32_example.elf", - "device": "STM32F429ZI", - "configFiles": [ - "/usr/share/openocd/scripts/board/stm32f429discovery.cfg" - ], - // Commented setup is not working at the moment, but lets have it here anyway - //"svdFile": "${workspaceRoot}/.vscode/STM32F303.svd", - //"swoConfig": { - // "enabled": true, - // "cpuFrequency": 8000000, - // "swoFrequency": 2000000, - // "source": "probe", - // "decoders": [ - // { "type": "console", "label": "ITM", "port": 0 } - // ] - //} - } - ] -} - -``` diff --git a/examples/stm32_example/toolchain.cmake b/examples/stm32_example/toolchain.cmake deleted file mode 100644 index cddc644..0000000 --- a/examples/stm32_example/toolchain.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# Name of the target -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_SYSTEM_PROCESSOR cortex-m4) - -set(MCPU_FLAGS "-mthumb -mcpu=cortex-m4") -set(VFP_FLAGS "") - -# Toolchain settings -set(CMAKE_C_COMPILER arm-none-eabi-gcc) -set(CMAKE_CXX_COMPILER arm-none-eabi-g++) -set(AS arm-none-eabi-as) -set(AR arm-none-eabi-ar) -set(OBJCOPY arm-none-eabi-objcopy) -set(OBJDUMP arm-none-eabi-objdump) -set(SIZE arm-none-eabi-size) - -set(CMAKE_C_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -Wall -fno-builtin -g -std=gnu11 -fdata-sections -ffunction-sections" CACHE INTERNAL "c compiler flags") -set(CMAKE_CXX_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -Wall -fno-builtin -fdata-sections -ffunction-sections" CACHE INTERNAL "cxx compiler flags") -set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -ggdb3" CACHE INTERNAL "c debug compiler flags") -SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -ggdb3" CACHE INTERNAL "cxx debug compiler flags") -SET(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug compiler flags") - -SET(CMAKE_C_FLAGS_RELEASE "-O2 -g -ggdb3" CACHE INTERNAL "c release compiler flags") -SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -g -ggdb3" CACHE INTERNAL "cxx release compiler flags") -SET(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags") - -# omit -nostartfiles when using __libc_init_array -set(LD_FLAGS "-T ${LINKER_SCRIPT}") -set(CMAKE_EXE_LINKER_FLAGS "${MCPU_FLAGS} ${LD_FLAGS} -Wl,--gc-sections" CACHE INTERNAL "exe link flags") diff --git a/examples/unix_example/CMakeLists.txt b/examples/unix_example/CMakeLists.txt deleted file mode 100644 index 59ee47a..0000000 --- a/examples/unix_example/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -cmake_minimum_required(VERSION 3.21.0) - - -########################################################################### -# # -# Define project's name # -# # -########################################################################### - -project(unix_example LANGUAGES C) - -set(CMAKE_BUILD_TYPE Debug) - -########################################################################### -# # -# Configure libtropic for this exmaple # -# # -########################################################################### - -# This example is compiled for linux, so use unix hal functions: -set(TS_HAL_UNIX ON) -# Use trezor crypto as a source of backend cryptography code -set(TS_CRYPTO_TREZOR ON) - - -########################################################################### -# # -# Add path to libtropic's repository root folder # -# # -########################################################################### - -add_subdirectory(../../ "src") - - -########################################################################### -# # -# Building unix example # -# # -########################################################################### - -add_executable(main main.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../hal/spi/ts_l1_unix_tcp.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../hal/system/ts_random_unix.c) -target_compile_definitions(main PRIVATE USE_TS_CRYPTO) -target_link_libraries(main PUBLIC tropic) diff --git a/examples/unix_example/main.c b/examples/unix_example/main.c deleted file mode 100644 index f83c3a4..0000000 --- a/examples/unix_example/main.c +++ /dev/null @@ -1,372 +0,0 @@ -#include -#include -#include - -// This header is only thing needed to work with libtropic -#include "libtropic.h" - -// Some crypto is practical to have here, for example when application wants to hash a message or verify a signature -#include "ed25519.h" -#include "ts_sha256.h" - -// Default initial Tropic handshake keys -#define PKEY_INDEX_BYTE 0 -#define SHiPRIV_BYTES {0xf0,0xc4,0xaa,0x04,0x8f,0x00,0x13,0xa0,0x96,0x84,0xdf,0x05,0xe8,0xa2,0x2e,0xf7,0x21,0x38,0x98,0x28,0x2b,0xa9,0x43,0x12,0xf3,0x13,0xdf,0x2d,0xce,0x8d,0x41,0x64}; -#define SHiPUB_BYTES {0x84,0x2f,0xe3,0x21,0xa8,0x24,0x74,0x08,0x37,0x37,0xff,0x2b,0x9b,0x88,0xa2,0xaf,0x42,0x44,0x2d,0xb0,0xd8,0xaa,0xcc,0x6d,0xc6,0x9e,0x99,0x53,0x33,0x44,0xb2,0x46}; - - -#define LOG_OUT(f_, ...) printf(f_, ##__VA_ARGS__) -#define LOG_OUT_INFO(f_, ...) printf("\t[INFO] "f_, ##__VA_ARGS__) -#define LOG_OUT_VALUE(f_, ...) printf("\t\t\t\t\t"f_, ##__VA_ARGS__) -#define LOG_OUT_LINE(f_, ...) printf("\t-------------------------------------------------------------------------------------------------------------\r\n"f_, ##__VA_ARGS__) - -void bytes_to_chars(uint8_t const *key, char *buffer, uint16_t len) -{ - uint16_t offset = 0; - memset(buffer, 0, len); - - for (size_t i = 0; i < len; i++) - { - offset += sprintf(buffer + offset, "%02X", key[i]); - } - sprintf(buffer + offset, "%c", '\0'); -} - - -int main(void) -{ - /************************************************************************************************************/ - LOG_OUT("\r\n"); - LOG_OUT("\t\t======================================================================\r\n"); - LOG_OUT("\t\t===== libtropic Unix demo, running over TCP against model ===\r\n"); - LOG_OUT("\t\t======================================================================\r\n\n"); - LOG_OUT_INFO("List all possible return values:\r\n\n"); - for(int i=0; i + +#include "ed25519-donna/ed25519-donna.h" +#include "ed25519-donna/ed25519.h" +#include "ed25519-donna/ed25519-hash-custom.h" +#include "rand.h" +#include "memzero.h" +#include "lt_x25519.h" + +int lt_ed25519_sign_open(const uint8_t *msg, const uint16_t msg_len, const uint8_t *pubkey, const uint8_t *rs) +{ + return ed25519_sign_open(msg, msg_len, pubkey, rs); +} + +#endif diff --git a/hal/crypto/trezor_crypto/ts_trezor_sha256.c b/hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c similarity index 68% rename from hal/crypto/trezor_crypto/ts_trezor_sha256.c rename to hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c index 4cacafb..b0887b0 100644 --- a/hal/crypto/trezor_crypto/ts_trezor_sha256.c +++ b/hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c @@ -1,4 +1,4 @@ -#ifdef USE_TS_CRYPTO +#ifdef USE_TREZOR_CRYPTO #include #include #include @@ -7,33 +7,33 @@ #include "hasher.h" #include "sha2.h" #include "hmac.h" -#include "ts_sha256.h" +#include "lt_sha256.h" -void ts_sha256_init(void* ctx) +void lt_sha256_init(void* ctx) { Hasher *h = (Hasher *) ctx; memset(h, 0, sizeof(Hasher)); } -void ts_sha256_start(void *ctx) +void lt_sha256_start(void *ctx) { Hasher *h = (Hasher *) ctx; hasher_InitParam(h, HASHER_SHA2, NULL, 0); } -void ts_sha256_update(void *ctx, const uint8_t *input, size_t len) +void lt_sha256_update(void *ctx, const uint8_t *input, size_t len) { Hasher *h = (Hasher *) ctx; hasher_Update(h, input, len); } -void ts_sha256_finish(void * ctx, uint8_t *output) +void lt_sha256_finish(void * ctx, uint8_t *output) { Hasher *h = (Hasher *) ctx; hasher_Final(h, output); } -void ts_hmac_sha256( const uint8_t *key, size_t keylen, +void lt_hmac_sha256( const uint8_t *key, size_t keylen, const uint8_t *input, size_t ilen, uint8_t *output ) { diff --git a/hal/crypto/trezor_crypto/lt_crypto_trezor_x25519.c b/hal/crypto/trezor_crypto/lt_crypto_trezor_x25519.c new file mode 100644 index 0000000..094e2c7 --- /dev/null +++ b/hal/crypto/trezor_crypto/lt_crypto_trezor_x25519.c @@ -0,0 +1,21 @@ +#ifdef USE_TREZOR_CRYPTO +#include + +#include "ed25519-donna/ed25519-donna.h" +#include "ed25519-donna/ed25519.h" +#include "ed25519-donna/ed25519-hash-custom.h" +#include "rand.h" +#include "memzero.h" +#include "lt_x25519.h" + +void lt_X25519(const uint8_t *priv, const uint8_t *pub, uint8_t *secret) +{ + curve25519_scalarmult(secret, priv, pub); +} + +void lt_X25519_scalarmult(const uint8_t *sk, uint8_t *pk) +{ + curve25519_scalarmult_basepoint(pk,sk); +} + +#endif \ No newline at end of file diff --git a/hal/crypto/trezor_crypto/ts_trezor_x25519.c b/hal/crypto/trezor_crypto/ts_trezor_x25519.c deleted file mode 100644 index 427f8f5..0000000 --- a/hal/crypto/trezor_crypto/ts_trezor_x25519.c +++ /dev/null @@ -1,21 +0,0 @@ -#ifdef USE_TS_CRYPTO -#include - -#include "ed25519-donna.h" -#include "ed25519.h" -#include "ed25519-hash-custom.h" -#include "rand.h" -#include "memzero.h" -#include "ts_x25519.h" - -void ts_X25519(const uint8_t *priv, const uint8_t *pub, uint8_t *secret) -{ - curve25519_scalarmult(secret, priv, pub); -} - -void ts_X25519_scalarmult(const uint8_t *sk, uint8_t *pk) -{ - curve25519_scalarmult_basepoint(pk,sk); -} - -#endif \ No newline at end of file diff --git a/hal/port/stm32/lt_port_stm32.c b/hal/port/stm32/lt_port_stm32.c new file mode 100644 index 0000000..7eff79b --- /dev/null +++ b/hal/port/stm32/lt_port_stm32.c @@ -0,0 +1,373 @@ +#include +#include +#include "stm32f4xx_hal.h" +// Pin definitions are in main.h: +#include "main.h" + +#include "libtropic_common.h" +#include "libtropic_port.h" + +// Random number generator's handle +RNG_HandleTypeDef rng; + +lt_ret_t lt_port_random_bytes(uint32_t *buff, uint16_t len) { + + for(int i=0; i 0) { + ret = HAL_UART_Receive(&UartHandle, rx_buffer.PAYLOAD, rx_buffer.LENGTH, 0xFFFF); + if(ret != HAL_OK) { + return LT_L1_SPI_ERROR; + } + } + + if (rx_buffer.TAG == TAG_E_INVALID) + { + return LT_L1_SPI_ERROR; + } + // server does not know what to do with the sent tag + else if (rx_buffer.TAG == TAG_E_UNSUPPORTED) + { + return LT_L1_SPI_ERROR; + } + // RX tag and TX tag should be identical + else if (rx_buffer.TAG != tx_buffer.TAG) + { + return LT_L1_SPI_ERROR; + } + + return LT_OK; +} + +// This function simulates powering TROPIC01 ON +//static int lt_tropic01_power_on(void) +//{ +// tx_buffer.TAG = TAG_E_POWER_ON; +// return lt_communicate(NULL); +//} +// +// This function simulates powering TROPIC01 OFF +//static int lt_tropic01_power_off(void) +//{ +// tx_buffer.TAG = TAG_E_POWER_OFF; +// return lt_communicate(NULL); +//} + +static int lt_reset_target(void) +{ + tx_buffer.TAG = TAG_E_RESET_TARGET; + return lt_communicate(NULL); +} + +lt_ret_t lt_port_spi_csn_low(lt_handle_t *h) +{ + UNUSED(h); + ////LOG_OUT("-- Driving Chip Select to Low.\n"); + tx_buffer.TAG = TAG_E_SPI_DRIVE_CSN_LOW; + return lt_communicate(NULL); +} + +lt_ret_t lt_port_spi_csn_high(lt_handle_t *h) +{ + UNUSED(h); + ////LOG_OUT("-- Driving Chip Select to High.\n"); + tx_buffer.TAG = TAG_E_SPI_DRIVE_CSN_HIGH; + return lt_communicate(NULL); +} + +lt_ret_t lt_port_init(lt_handle_t *h) +{ + UNUSED(h); + + // RNG Init: + rng.Instance = RNG; + + if (HAL_RNG_Init(&rng) != HAL_OK) { + return LT_FAIL; + } + + // UART init: + // Enable clock for used uart + UART_MODEL_CLK_ENABLE(); + // UART configuration + UartHandle.Instance = UART_MODEL; + UartHandle.Init.BaudRate = 115200; + UartHandle.Init.WordLength = UART_WORDLENGTH_8B; + UartHandle.Init.StopBits = UART_STOPBILT_1; + UartHandle.Init.Parity = UART_PARITY_NONE; + UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + UartHandle.Init.Mode = UART_MODE_TX_RX; + UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&UartHandle) != HAL_OK) { + return LT_FAIL; + } + + // Empty buffers used to talk to model + memset(tx_buffer.BUFFER, 0, MAX_UART_BUFFER_LEN); + memset(rx_buffer.BUFFER, 0, MAX_UART_BUFFER_LEN); + lt_reset_target(); + + return LT_OK; +} + +lt_ret_t lt_port_deinit(lt_handle_t *h) +{ + UNUSED(h); + + if (HAL_RNG_DeInit(&rng) != HAL_OK) { + return LT_FAIL; + } + + if (HAL_UART_DeInit(&UartHandle) != HAL_OK) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_port_spi_transfer (lt_handle_t *h, uint8_t offset, uint16_t tx_data_length, uint32_t timeout) +{ + UNUSED(h); + + int status; + int tx_payload_length = tx_data_length; + int rx_payload_length = 0; + + tx_buffer.TAG = TAG_E_SPI_SEND; + tx_buffer.LENGTH = (uint16_t)tx_payload_length; + + // copy tx_data to tx payload + memcpy(&tx_buffer.PAYLOAD, h->l2_buff, tx_payload_length); + + status = lt_communicate(&tx_payload_length); + if (status != LT_OK) { + return status; + } + rx_payload_length = rx_buffer.LENGTH + MIN_UART_PAYLOAD_LEN; + + memcpy(h->l2_buff + offset, &rx_buffer.PAYLOAD, rx_payload_length); + + return LT_OK; +} + +lt_ret_t lt_port_delay(lt_handle_t *h, uint32_t ms) +{ + UNUSED(h); + + HAL_Delay(ms); + + return LT_OK; +} + +#else + + +#define LT_SPI_CS_BANK GPIOE +#define LT_SPI_CS_PIN GPIO_PIN_4 +#define LT_SPI_INSTANCE SPI4 + +// Use 1 here to enable SPI on FPGA board +#define FPGA_REMOTE 1 + +/* Most of this SPI code is taken from: + vendor/STM32CubeF4/Projects/STM32F429I-Discovery/Examples/SPI/SPI_FullDuplex_ComPolling/Src/main.c +*/ + +/* SPI handle declaration */ +SPI_HandleTypeDef SpiHandle; + +lt_ret_t lt_port_spi_csn_low(lt_handle_t *h) +{ + UNUSED(h); + + HAL_GPIO_WritePin(LT_SPI_CS_BANK, LT_SPI_CS_PIN, GPIO_PIN_RESET); + while(HAL_GPIO_ReadPin(LT_SPI_CS_BANK, LT_SPI_CS_PIN)) { + ; + } + + return LT_OK; +} + +lt_ret_t lt_port_spi_csn_high(lt_handle_t *h) +{ + UNUSED(h); + + HAL_GPIO_WritePin(LT_SPI_CS_BANK, LT_SPI_CS_PIN, GPIO_PIN_SET); + while(!HAL_GPIO_ReadPin(LT_SPI_CS_BANK, LT_SPI_CS_PIN)) { + ; + } + + return LT_OK; +} + +lt_ret_t lt_port_init(lt_handle_t *h) +{ + UNUSED(h); + + if (HAL_RNG_Init(&rng) != HAL_OK) { + return LT_FAIL; + } + + /* Set the SPI parameters */ + SpiHandle.Instance = LT_SPI_INSTANCE; + SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; + SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; + SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; + SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; + SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + //SpiHandle.Init.CRCPolynomial = 7; + SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; + SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; + SpiHandle.Init.NSS = SPI_NSS_HARD_OUTPUT; + SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE; + SpiHandle.Init.Mode = SPI_MODE_MASTER; + + if(HAL_SPI_Init(&SpiHandle) != HAL_OK) + { + return LT_FAIL; + } + + // GPIO for chip select: + GPIO_InitTypeDef GPIO_InitStruct = {0}; + __HAL_RCC_GPIOE_CLK_ENABLE(); + HAL_GPIO_WritePin(LT_SPI_CS_BANK, LT_SPI_CS_PIN, GPIO_PIN_SET); + GPIO_InitStruct.Pin = LT_SPI_CS_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + HAL_GPIO_Init(LT_SPI_CS_BANK, &GPIO_InitStruct); + + #ifdef FPGA_REMOTE + // Pin for controlling SPI access + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET); + HAL_Delay(100); + #endif + + return LT_OK; +} + +lt_ret_t lt_port_deinit(lt_handle_t *h) +{ + UNUSED(h); + + if (HAL_RNG_DeInit(&rng) != HAL_OK) { + return LT_FAIL; + } + + #ifdef FPGA_REMOTE + // Clear pin for controlling SPI access + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET); + HAL_Delay(100); + #endif + + HAL_SPI_MspDeInit(&SpiHandle); + + return LT_OK; +} + +lt_ret_t lt_port_spi_transfer(lt_handle_t *h, uint8_t offset, uint16_t tx_data_length, uint32_t timeout) +{ + if (offset + tx_data_length > LT_L1_LEN_MAX) { + return LT_L1_DATA_LEN_ERROR; + } + int ret = HAL_SPI_TransmitReceive(&SpiHandle, h->l2_buff + offset, h->l2_buff + offset, tx_data_length, timeout); + if(ret != HAL_OK) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_port_delay(lt_handle_t *h, uint32_t ms) +{ + UNUSED(h); + + HAL_Delay(ms); + + return LT_OK; +} + +#endif diff --git a/hal/spi/ts_l1_unix_tcp.c b/hal/port/unix/lt_port_unix.c similarity index 62% rename from hal/spi/ts_l1_unix_tcp.c rename to hal/port/unix/lt_port_unix.c index 5a4c31e..f3a4f3b 100644 --- a/hal/spi/ts_l1_unix_tcp.c +++ b/hal/port/unix/lt_port_unix.c @@ -1,5 +1,5 @@ ///////////////////////// -// C TCP client for communicating with the TROPIC01Model +// C TCP client for communicating with the TROPIC01 Model #include #include @@ -10,41 +10,36 @@ #include #include -#include "ts_common.h" -#include "ts_l1.h" +#include "libtropic_common.h" +#include "libtropic_port.h" -#define UNUSED(x) (void)(x) +#define TCP_ADDR "127.0.0.1" +#define TCP_PORT 28992 +//#define NDEBUG #ifdef NDEBUG -# define LOG_OUT(f_, ...) printf(f_, ##__VA_ARGS__) +# define LOG_OUT(f_, ...) printf("[TCP] "f_, ##__VA_ARGS__) # define LOG_ERR(f_, ...) fprintf(stderr, "ERROR: " f_, ##__VA_ARGS__) # define LOG_U8_ARRAY(arr, len) \ for (int i = 0; i < len; i++) \ { \ - LOG_OUT("%02x ", arr[i]); \ + printf("%02x ", arr[i]); \ } \ - LOG_OUT("\n"); + printf("\r\n"); #else # define LOG_OUT(...) # define LOG_ERR(...) # define LOG_U8_ARRAY(...) #endif -#define TCP_ADDR "127.0.0.1" -#define TCP_PORT 28992 -#define UINT8_SIZE 1 -#define UINT16_SIZE 2 -#define UINT32_SIZE 4 -#define UINT64_SIZE 8 - -#define MIN_BUFFER_LEN (UINT8_SIZE + UINT16_SIZE) -#define MAX_PAYLOAD_LEN 259 -#define MAX_BUFFER_LEN (MIN_BUFFER_LEN + MAX_PAYLOAD_LEN) +#define TCP_TAG_AND_LENGTH_SIZE (sizeof(uint8_t) + sizeof(uint16_t)) +#define MAX_PAYLOAD_LEN L2_MAX_FRAME_SIZE +#define MAX_BUFFER_LEN (TCP_TAG_AND_LENGTH_SIZE + MAX_PAYLOAD_LEN) #define TX_ATTEMPTS 3 #define RX_ATTEMPTS 3 -#define BUFFER_SIZE 1024 +#define MAX_RECV_SIZE (MAX_PAYLOAD_LEN + TCP_TAG_AND_LENGTH_SIZE) typedef struct { @@ -81,7 +76,8 @@ static buffer_s tx_buffer; // server socket static int socket_fd = -1; -static int ts_connect_to_server () + +static int lt_connect_to_server () { struct sockaddr_in server; @@ -90,7 +86,7 @@ static int ts_connect_to_server () if (socket_fd < 0) { LOG_ERR("Could not create socket: %s (%d).\n", strerror(errno), errno); - return 1; + return LT_FAIL; } LOG_OUT("Socket created.\n"); @@ -112,28 +108,18 @@ static int ts_connect_to_server () return 0; } -static int ts_send_all (int socket, uint8_t * buffer, size_t length) +static int lt_send_all (int socket, uint8_t *buffer, size_t length) { - // check length is strictly positive - if (length <= 0) - { - LOG_ERR("Parameter length is not striclty positive: %lu.\n", length); - return 1; - } - - int nb_bytes_sent; - int nb_bytes_sent_total = 0; - int nb_bytes_to_send = length; - uint8_t * ptr = buffer; + int nb_bytes_sent; + int nb_bytes_sent_total = 0; + int nb_bytes_to_send = length; + uint8_t *ptr = buffer; // attempt several times to send the data - for (int i = 0; i < TX_ATTEMPTS; i++) - { + for (int i = 0; i < TX_ATTEMPTS; i++) { LOG_OUT("Attempting to send data: attempt #%d.\n", i); - nb_bytes_sent = send(socket, ptr, nb_bytes_to_send, 0); - if (nb_bytes_sent < 1) - { + if (nb_bytes_sent <= 0) { LOG_ERR("Send failed: %s (%d).\n", strerror(errno), errno); return 1; } @@ -150,35 +136,33 @@ static int ts_send_all (int socket, uint8_t * buffer, size_t length) } // could not send all the data after several attempts - LOG_ERR("%d bytes sent instead of expected %lu ", nb_bytes_sent_total, - length); + LOG_ERR("%d bytes sent instead of expected %lu ", nb_bytes_sent_total, length); LOG_ERR("after %d attempts.\n", TX_ATTEMPTS); + return 1; } -static int ts_communicate (int * tx_payload_length_ptr, int * rx_payload_length_ptr) +static int lt_communicate (int *tx_payload_length_ptr, int *rx_payload_length_ptr) { - - int status; - int nb_bytes_received; - int nb_bytes_received_total = 0; - int nb_bytes_to_receive = MIN_BUFFER_LEN; - uint8_t * rx_ptr = rx_buffer.BUFFER; - + int status; + int nb_bytes_received; + int nb_bytes_received_total = 0; + int nb_bytes_to_receive = TCP_TAG_AND_LENGTH_SIZE; + uint8_t * rx_ptr = rx_buffer.BUFFER; // number of bytes to send - int nb_bytes_to_send = MIN_BUFFER_LEN; - if (tx_payload_length_ptr != NULL) - { + int nb_bytes_to_send = TCP_TAG_AND_LENGTH_SIZE; + + if (tx_payload_length_ptr != NULL) { nb_bytes_to_send += *tx_payload_length_ptr; } // update payload length field - tx_buffer.LENGTH = nb_bytes_to_send - MIN_BUFFER_LEN; + tx_buffer.LENGTH = nb_bytes_to_send - TCP_TAG_AND_LENGTH_SIZE; // send data LOG_U8_ARRAY(tx_buffer.BUFFER, nb_bytes_to_send); - status = ts_send_all(socket_fd, tx_buffer.BUFFER, nb_bytes_to_send); + status = lt_send_all(socket_fd, tx_buffer.BUFFER, nb_bytes_to_send); if (status != 0) { return status; @@ -186,51 +170,51 @@ static int ts_communicate (int * tx_payload_length_ptr, int * rx_payload_length_ // receive data LOG_OUT("- Receiving data from target.\n"); - nb_bytes_received = recv(socket_fd, rx_buffer.BUFFER, BUFFER_SIZE, 0); + nb_bytes_received = recv(socket_fd, rx_buffer.BUFFER, MAX_RECV_SIZE, 0); if (nb_bytes_received < 0) { LOG_ERR("Receive failed: %s (%d).\n", strerror(errno), errno); return 1; } + else if (nb_bytes_received < nb_bytes_to_receive) { LOG_ERR("At least %d bytes are expected: %d.\n", nb_bytes_to_receive, nb_bytes_received); return 1; } + LOG_OUT("Length field: %d.\n", rx_buffer.LENGTH); nb_bytes_to_receive += rx_buffer.LENGTH; nb_bytes_received_total += nb_bytes_received; - LOG_OUT("Received %d bytes out of %d expected.\n", nb_bytes_received_total, - nb_bytes_to_receive); + LOG_OUT("Received %d bytes out of %d expected.\n", nb_bytes_received_total, nb_bytes_to_receive); if (nb_bytes_received_total < nb_bytes_to_receive) { - rx_ptr += nb_bytes_received; for (int i = 0; i < RX_ATTEMPTS; i++) { LOG_OUT("Attempting to receive remaining bytes: attempt #%d.\n", i); - nb_bytes_received = - recv(socket_fd, rx_buffer.BUFFER, BUFFER_SIZE, 0); + nb_bytes_received = recv(socket_fd, rx_buffer.BUFFER, MAX_RECV_SIZE, 0); if (nb_bytes_received < 0) { LOG_ERR("Receive failed: %s (%d).\n", strerror(errno), errno); return 1; } + nb_bytes_received_total += nb_bytes_received; if (nb_bytes_received_total >= nb_bytes_to_receive) { - LOG_OUT("Received %d bytes in total.\n", - nb_bytes_received_total); + LOG_OUT("Received %d bytes in total.\n", nb_bytes_received_total); break; } rx_ptr += nb_bytes_received; } } + if (nb_bytes_received_total != nb_bytes_to_receive) { LOG_ERR("Received %d bytes in total instead of %d.\n", @@ -244,12 +228,14 @@ static int ts_communicate (int * tx_payload_length_ptr, int * rx_payload_length_ LOG_ERR("Tag %d is not known by the server.\n", tx_buffer.TAG); return 1; } + // server does not know what to do with the sent tag else if (rx_buffer.TAG == TAG_E_UNSUPPORTED) { LOG_ERR("Tag %d is not supported by the server.\n", tx_buffer.TAG); return 1; } + // RX tag and TX tag should be identical else if (rx_buffer.TAG != tx_buffer.TAG) { @@ -261,30 +247,32 @@ static int ts_communicate (int * tx_payload_length_ptr, int * rx_payload_length_ LOG_OUT("Rx tag and tx tag match: %d.\n", rx_buffer.TAG); if (rx_payload_length_ptr != NULL) { - *rx_payload_length_ptr = nb_bytes_received_total - MIN_BUFFER_LEN; + *rx_payload_length_ptr = nb_bytes_received_total - TCP_TAG_AND_LENGTH_SIZE; } - return 0; -} - -static int ts_tropic01_power_on(void) -{ - LOG_OUT("-- Powering on the TROPIC01 chip.\n"); - tx_buffer.TAG = TAG_E_POWER_ON; - return ts_communicate(NULL, NULL); -} -static int ts_tropic01_power_off(void) -{ - LOG_OUT("-- Powering off the TROPIC01 chip.\n"); - tx_buffer.TAG = TAG_E_POWER_OFF; - return ts_communicate(NULL, NULL); + return 0; } -static int ts_reset_target(void) +//static int lt_tropic01_power_on(void) +//{ +// LOG_OUT("-- Powering on the TROPIC01 chip.\n"); +// tx_buffer.TAG = TAG_E_POWER_ON; +// return lt_communicate(NULL, NULL); +//} +// +//static int lt_tropic01_power_off(void) +//{ +// LOG_OUT("-- Powering off the TROPIC01 chip.\n"); +// tx_buffer.TAG = TAG_E_POWER_OFF; +// return lt_communicate(NULL, NULL); +//} +// +static int lt_reset_target(void) { LOG_OUT("-- Resetting TROPIC01 target.\n"); tx_buffer.TAG = TAG_E_RESET_TARGET; - return ts_communicate(NULL, NULL); + + return lt_communicate(NULL, NULL); } static int server_connect(void) @@ -292,7 +280,7 @@ static int server_connect(void) bzero(tx_buffer.BUFFER, MAX_BUFFER_LEN); bzero(rx_buffer.BUFFER, MAX_BUFFER_LEN); - int ret = ts_connect_to_server(); + int ret = lt_connect_to_server(); if (ret != 0) { return ret; @@ -302,65 +290,62 @@ static int server_connect(void) static int server_disconnect(void) { + LOG_OUT("-- Server disconnect\n"); return close(socket_fd); } - -////////////////////////////////////////////////////////////////////// -// // -// ts_l1 HAL definitions: // -// // -////////////////////////////////////////////////////////////////////// - -ts_ret_t ts_l1_init(ts_handle_t *h) +lt_ret_t lt_port_init(lt_handle_t *h) { UNUSED(h); - memset(h, 0, sizeof(ts_handle_t)); + memset(h, 0, sizeof(lt_handle_t)); int ret = server_connect(); if(ret != 0) { - return TS_FAIL; - } - ret = ts_reset_target(); - if(ret != 0) { - return TS_FAIL; + return LT_FAIL; } - return TS_OK; + + lt_reset_target(); + + return LT_OK; } -ts_ret_t ts_l1_deinit(ts_handle_t *h) +lt_ret_t lt_port_deinit(lt_handle_t *h) { UNUSED(h); - return server_disconnect(); + if(server_disconnect() != 0) { + return LT_FAIL; + } + + return LT_OK; } -ts_ret_t ts_l1_spi_csn_low (ts_handle_t *h) +lt_ret_t lt_port_spi_csn_low (lt_handle_t *h) { UNUSED(h); LOG_OUT("-- Driving Chip Select to Low.\n"); tx_buffer.TAG = TAG_E_SPI_DRIVE_CSN_LOW; - return ts_communicate(NULL, NULL); + return lt_communicate(NULL, NULL); } -ts_ret_t ts_l1_spi_csn_high (ts_handle_t *h) +lt_ret_t lt_port_spi_csn_high (lt_handle_t *h) { UNUSED(h); LOG_OUT("-- Driving Chip Select to High.\n"); tx_buffer.TAG = TAG_E_SPI_DRIVE_CSN_HIGH; - return ts_communicate(NULL, NULL); + return lt_communicate(NULL, NULL); } -ts_ret_t ts_l1_spi_transfer (ts_handle_t *h, uint8_t offset, uint16_t tx_data_length, uint32_t timeout) +lt_ret_t lt_port_spi_transfer (lt_handle_t *h, uint8_t offset, uint16_t tx_data_length, uint32_t timeout) { UNUSED(h); UNUSED(timeout); - if (offset + tx_data_length > TS_L1_LEN_MAX) { - return TS_L1_DATA_LEN_ERROR; + if (offset + tx_data_length > LT_L1_LEN_MAX) { + return LT_L1_DATA_LEN_ERROR; } LOG_OUT("-- Sending data through SPI bus.\n"); - int status; + int tx_payload_length = tx_data_length; int rx_payload_length; @@ -368,32 +353,40 @@ ts_ret_t ts_l1_spi_transfer (ts_handle_t *h, uint8_t offset, uint16_t tx_data_le tx_buffer.LENGTH = (uint16_t)tx_payload_length; // copy tx_data to tx payload - for (int i = 0; i < tx_payload_length; i++) - { - *(tx_buffer.PAYLOAD + i) = *(h->l2_buff + i); - } + memcpy(&tx_buffer.PAYLOAD, h->l2_buff, tx_payload_length); - status = ts_communicate(&tx_payload_length, &rx_payload_length); + int status = lt_communicate(&tx_payload_length, &rx_payload_length); if (status != 0) { - return status; + return LT_FAIL; } - // copy rx payload to rx_data - for (int i = 0; i < rx_payload_length; i++) - { - *(h->l2_buff + i + offset) = *(rx_buffer.PAYLOAD + i); - } + memcpy(h->l2_buff + offset, &rx_buffer.PAYLOAD, rx_payload_length); - return 0; + return LT_OK; } -ts_ret_t ts_l1_delay (ts_handle_t *h, uint32_t wait_time_usecs) +lt_ret_t lt_port_delay (lt_handle_t *h, uint32_t wait_time_usecs) { UNUSED(h); LOG_OUT("-- Waiting for the target.\n"); + tx_buffer.TAG = TAG_E_WAIT; - int payload_length = UINT32_SIZE; - *(uint32_t *)(&tx_buffer.PAYLOAD) = wait_time_usecs; - return ts_communicate(&payload_length, NULL); + int payload_length = sizeof(uint32_t); + //*(uint32_t *)(&tx_buffer.PAYLOAD) = wait_time_usecs; + rx_buffer.PAYLOAD[0] = wait_time_usecs & 0x000000ff; + rx_buffer.PAYLOAD[1] = (wait_time_usecs & 0x0000ff00) >> 8; + rx_buffer.PAYLOAD[2] = (wait_time_usecs & 0x00ff0000) >> 16; + rx_buffer.PAYLOAD[3] = (wait_time_usecs & 0xff000000) >> 24; + + return lt_communicate(&payload_length, NULL); } + +lt_ret_t lt_port_random_bytes(uint32_t *buff, uint16_t len) { + + for(int i=0; i -#include "ts_common.h" -#include "ts_l1.h" - -#include "stm32f4xx_hal.h" - -#define TS_SPI_CS_BANK GPIOE -#define TS_SPI_CS_PIN GPIO_PIN_4 -#define TS_SPI_INSTANCE SPI4 - -// Use 1 here to enable SPI switching on FPGA board -#define FPGA_REMOTE 1 - -/* Most of this SPI code is taken from: - vendor/STM32CubeF4/Projects/STM32F429I-Discovery/Examples/SPI/SPI_FullDuplex_ComPolling/Src/main.c -*/ - -/* SPI handle declaration */ -SPI_HandleTypeDef SpiHandle; - -ts_ret_t ts_l1_spi_csn_low(ts_handle_t *h) -{ - UNUSED(h); - - HAL_GPIO_WritePin(TS_SPI_CS_BANK, TS_SPI_CS_PIN, GPIO_PIN_RESET); - while(HAL_GPIO_ReadPin(TS_SPI_CS_BANK, TS_SPI_CS_PIN)) { - ; - } - - return TS_OK; -} - -ts_ret_t ts_l1_spi_csn_high(ts_handle_t *h) -{ - UNUSED(h); - - HAL_GPIO_WritePin(TS_SPI_CS_BANK, TS_SPI_CS_PIN, GPIO_PIN_SET); - while(!HAL_GPIO_ReadPin(TS_SPI_CS_BANK, TS_SPI_CS_PIN)) { - ; - } - - return TS_OK; -} - - -ts_ret_t ts_l1_init(ts_handle_t *h) -{ - UNUSED(h); - - /* Set the SPI parameters */ - SpiHandle.Instance = TS_SPI_INSTANCE; - SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; - SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; - SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; - SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; - SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; - //SpiHandle.Init.CRCPolynomial = 7; - SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; - SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; - SpiHandle.Init.NSS = SPI_NSS_HARD_OUTPUT; - SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE; - SpiHandle.Init.Mode = SPI_MODE_MASTER; - - if(HAL_SPI_Init(&SpiHandle) != HAL_OK) - { - return TS_FAIL; - } - - // GPIO for chip select: - GPIO_InitTypeDef GPIO_InitStruct = {0}; - __HAL_RCC_GPIOE_CLK_ENABLE(); - HAL_GPIO_WritePin(TS_SPI_CS_BANK, TS_SPI_CS_PIN, GPIO_PIN_SET); - GPIO_InitStruct.Pin = TS_SPI_CS_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - HAL_GPIO_Init(TS_SPI_CS_BANK, &GPIO_InitStruct); - - #ifdef FPGA_REMOTE - // Pin for controlling SPI access - GPIO_InitStruct.Pin = GPIO_PIN_3; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET); - HAL_Delay(100); - #endif - - return TS_OK; -} - -ts_ret_t ts_l1_deinit(ts_handle_t *h) -{ - UNUSED(h); - - #ifdef FPGA_REMOTE - // Clear pin for controlling SPI access - GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = GPIO_PIN_3; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET); - HAL_Delay(100); - #endif - - HAL_SPI_MspDeInit(&SpiHandle); - - return TS_OK; -} - -ts_ret_t ts_l1_spi_transfer(ts_handle_t *h, uint8_t offset, uint16_t tx_data_length, uint32_t timeout) -{ - if (offset + tx_data_length > TS_L1_LEN_MAX) { - return TS_L1_DATA_LEN_ERROR; - } - int ret = HAL_SPI_TransmitReceive(&SpiHandle, h->l2_buff + offset, h->l2_buff + offset, tx_data_length, timeout); - if(ret != HAL_OK) { - return TS_L1_SPI_ERROR; - } - - return TS_OK; -} - - -ts_ret_t ts_l1_delay(ts_handle_t *h, uint32_t ms) -{ - UNUSED(h); - - if (ms > TS_L1_DELAY_MS_MAX) { - return TS_PARAM_ERR; - } - - HAL_Delay(ms); - - return TS_OK; -} diff --git a/hal/spi/ts_l1_stm32_uart.c b/hal/spi/ts_l1_stm32_uart.c deleted file mode 100644 index 9e92029..0000000 --- a/hal/spi/ts_l1_stm32_uart.c +++ /dev/null @@ -1,288 +0,0 @@ -#include - -#include "ts_common.h" -#include "ts_l1.h" - -#include "stm32f4xx_hal.h" - -////////////////////////////////////////////////////////////////////// -// // -// Definition for UART used to communicate with model // -// // -////////////////////////////////////////////////////////////////////// - -/* - Nucleo F439ZI, CN8 Connector: - _ _ - |_|_| - |_|_| - |_|_| - |_|_| - |_|_| TX (RX on serial adapter) - GND |_|_| RX (TX on serial adapter) - GND |_|_| - |_|_| -*/ - -#define UART_MODEL UART5 -#define UART_MODEL_CLK_ENABLE() __HAL_RCC_UART5_CLK_ENABLE(); -#define UART_MODEL_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() -#define UART_MODEL_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE() -#define UART_MODEL_FORCE_RESET() __HAL_RCC_UART5_FORCE_RESET() -#define UART_MODEL_RELEASE_RESET() __HAL_RCC_UART5_RELEASE_RESET() - -// Used pins -#define UART_MODEL_TX_PIN GPIO_PIN_12 -#define UART_MODEL_TX_GPIO_PORT GPIOC -#define UART_MODEL_TX_AF GPIO_AF8_UART5 -#define UART_MODEL_RX_PIN GPIO_PIN_2 -#define UART_MODEL_RX_GPIO_PORT GPIOD -#define UART_MODEL_RX_AF GPIO_AF8_UART5\ - -// #define LOG_OUT(f_, ...) printf(f_, ##__VA_ARGS__) - -////////////////////////////////////////////////////////////////////// -// // -// End of user setup // -// // -////////////////////////////////////////////////////////////////////// - - -// Uart transport layer defines -#define MIN_UART_PAYLOAD_LEN 3 -#define MAX_UART_BUFFER_LEN (MIN_UART_PAYLOAD_LEN + TS_L1_LEN_MAX) - -// This structure holds data transported over uart -typedef struct -{ - union - { - uint8_t BUFFER[MAX_UART_BUFFER_LEN]; - struct __attribute__((__packed__, __aligned__)) - { - uint8_t TAG; - uint16_t LENGTH; - uint8_t PAYLOAD[TS_L1_LEN_MAX]; - }; - }; -} buffer_s; - -// Possible values for TAG field -typedef enum -{ - TAG_E_SPI_DRIVE_CSN_LOW = 0x01, - TAG_E_SPI_DRIVE_CSN_HIGH = 0x02, - TAG_E_SPI_SEND = 0x03, - TAG_E_POWER_ON = 0x04, - TAG_E_POWER_OFF = 0x05, - TAG_E_WAIT = 0x06, - TAG_E_RESET_TARGET = 0x10, - TAG_E_INVALID = 0xfd, - TAG_E_UNSUPPORTED = 0xfe, -} tag_e; - -// Uart handle -static UART_HandleTypeDef UartHandle; -// reception buffer -static buffer_s rx_buffer; -// emission buffer -static buffer_s tx_buffer; - - -static int ts_communicate (int * tx_payload_length_ptr) -{ - int ret = HAL_ERROR; - - // number of bytes to send - int nb_bytes_to_send = MIN_UART_PAYLOAD_LEN; - if (tx_payload_length_ptr != NULL) - { - nb_bytes_to_send += *tx_payload_length_ptr; - } - - // update payload length field - tx_buffer.LENGTH = nb_bytes_to_send - MIN_UART_PAYLOAD_LEN; - - ret = HAL_UART_Transmit(&UartHandle, tx_buffer.BUFFER, nb_bytes_to_send, 0xFFF); - if(ret != HAL_OK) { - return TS_L1_SPI_ERROR; - } - - ret = HAL_UART_Receive(&UartHandle, rx_buffer.BUFFER, MIN_UART_PAYLOAD_LEN, 0xFFFF); - if(ret != HAL_OK) { - return TS_L1_SPI_ERROR; - } - - if (rx_buffer.LENGTH > 0) { - ret = HAL_UART_Receive(&UartHandle, rx_buffer.PAYLOAD, rx_buffer.LENGTH, 0xFFFF); - if(ret != HAL_OK) { - return TS_L1_SPI_ERROR; - } - } - - if (rx_buffer.TAG == TAG_E_INVALID) - { - return TS_L1_SPI_ERROR; - } - // server does not know what to do with the sent tag - else if (rx_buffer.TAG == TAG_E_UNSUPPORTED) - { - return TS_L1_SPI_ERROR; - } - // RX tag and TX tag should be identical - else if (rx_buffer.TAG != tx_buffer.TAG) - { - return TS_L1_SPI_ERROR; - } - - return TS_OK; -} - -//static int ts_tropic01_power_on(void) -//{ -// tx_buffer.TAG = TAG_E_POWER_ON; -// return ts_communicate(NULL); -//} -// -//static int ts_tropic01_power_off(void) -//{ -// tx_buffer.TAG = TAG_E_POWER_OFF; -// return ts_communicate(NULL); -//} - -static int ts_reset_target(void) -{ - tx_buffer.TAG = TAG_E_RESET_TARGET; - return ts_communicate(NULL); -} - -////////////////////////////////////////////////////////////////////// -// // -// ts_l1 HAL definitions: // -// // -////////////////////////////////////////////////////////////////////// - -ts_ret_t ts_l1_spi_csn_low(const ts_handle_t *h) -{ - UNUSED(h); - ////LOG_OUT("-- Driving Chip Select to Low.\n"); - tx_buffer.TAG = TAG_E_SPI_DRIVE_CSN_LOW; - return ts_communicate(NULL); -} - -ts_ret_t ts_l1_spi_csn_high(const ts_handle_t *h) -{ - UNUSED(h); - ////LOG_OUT("-- Driving Chip Select to High.\n"); - tx_buffer.TAG = TAG_E_SPI_DRIVE_CSN_HIGH; - return ts_communicate(NULL); -} - -ts_ret_t ts_l1_init(ts_handle_t *h) -{ - UNUSED(h); - - GPIO_InitTypeDef GPIO_InitStruct; - - // enable clock for gpio - UART_MODEL_TX_GPIO_CLK_ENABLE(); - UART_MODEL_RX_GPIO_CLK_ENABLE(); - // And enable clock for used uart - UART_MODEL_CLK_ENABLE(); - - // GPIO config: - // UART TX GPIO pin configuration - GPIO_InitStruct.Pin = UART_MODEL_TX_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = UART_MODEL_TX_AF; - - HAL_GPIO_Init(UART_MODEL_TX_GPIO_PORT, &GPIO_InitStruct); - - /* UART RX GPIO pin configuration */ - GPIO_InitStruct.Pin = UART_MODEL_RX_PIN; - GPIO_InitStruct.Alternate = UART_MODEL_RX_AF; - - HAL_GPIO_Init(UART_MODEL_RX_GPIO_PORT, &GPIO_InitStruct); - - bzero(tx_buffer.BUFFER, MAX_UART_BUFFER_LEN); - bzero(rx_buffer.BUFFER, MAX_UART_BUFFER_LEN); - - UartHandle.Instance = UART_MODEL; - UartHandle.Init.BaudRate = 115200; - UartHandle.Init.WordLength = UART_WORDLENGTH_8B; - UartHandle.Init.StopBits = UART_STOPBITS_1; - UartHandle.Init.Parity = UART_PARITY_NONE; - UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; - UartHandle.Init.Mode = UART_MODE_TX_RX; - UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; - - if (HAL_UART_Init(&UartHandle) != HAL_OK) { - return TS_L1_SPI_ERROR; - } - - ts_reset_target(); - - return TS_OK; -} - -ts_ret_t ts_l1_deinit(ts_handle_t *h) -{ - UNUSED(h); - - // Deinitialize serial port used as a transport layer for tropic chip - UART_MODEL_FORCE_RESET(); - UART_MODEL_RELEASE_RESET(); - - HAL_GPIO_DeInit(UART_MODEL_TX_GPIO_PORT, UART_MODEL_TX_PIN); - HAL_GPIO_DeInit(UART_MODEL_RX_GPIO_PORT, UART_MODEL_RX_PIN); - - return TS_OK; -} - -ts_ret_t ts_l1_spi_transfer(const ts_handle_t *h, const uint8_t * tx_data, uint8_t * rx_data, - uint16_t tx_data_length, uint32_t timeout) -{ - UNUSED(h); - // LOG_OUT("\r\n\tAhoj :)\r\n"); - int status; - int tx_payload_length = tx_data_length; - int rx_payload_length = 0; - - tx_buffer.TAG = TAG_E_SPI_SEND; - tx_buffer.LENGTH = (uint16_t)tx_payload_length; - - // copy tx_data to tx payload - for (int i = 0; i < tx_payload_length; i++) { - *(tx_buffer.PAYLOAD + i) = *(tx_data + i); - } - - status = ts_communicate(&tx_payload_length); - if (status != 0) { - return status; - } - rx_payload_length = rx_buffer.LENGTH + MIN_UART_PAYLOAD_LEN; - // LOG_OUT("\r\n\trx_payload_length: %d\r\n", rx_payload_length); - - - // copy rx payload to rx_data - for (int i = 0; i < rx_payload_length; i++) { - *(rx_data + i) = *(rx_buffer.PAYLOAD + i); - } - - return TS_OK; -} - - -ts_ret_t ts_l1_delay(const ts_handle_t *h, const uint32_t ms) -{ - UNUSED(h); - if (ms > TS_L1_DELAY_MS_MAX) { - return TS_PARAM_ERR; - } - - HAL_Delay(ms); - - return TS_OK; -} diff --git a/hal/system/ts_random_stm32.c b/hal/system/ts_random_stm32.c deleted file mode 100644 index 019ce59..0000000 --- a/hal/system/ts_random_stm32.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "ts_common.h" -#include "stdint.h" - -//#include -//#include -// TODO FAKE -ts_ret_t ts_random_bytes(uint8_t *buff, uint16_t len) { - - for(int i=0; i -#include - -ts_ret_t ts_random_bytes(uint8_t *buff, uint16_t len) { - - getrandom(buff, len, 0); - return TS_OK; -} - diff --git a/include/TROPIC01_configuration_objects.h b/include/TROPIC01_configuration_objects.h new file mode 100644 index 0000000..a46dcfb --- /dev/null +++ b/include/TROPIC01_configuration_objects.h @@ -0,0 +1,395 @@ +// Ordt 230321.02 autogenerated file +// Input: /projects/tropic01/work/avrba/tassic/doc/user_api/tropic01_configuration_objects.rdl +// Parms: /projects/tropic01/work/avrba/tassic/scripts/param_file +// Date: Tue Jul 16 13:19:30 CEST 2024 +// + +#ifndef __CONFIGURATION_OBJECTS_REGISTER_MAP__ +#define __CONFIGURATION_OBJECTS_REGISTER_MAP__ + +#include "bits.h" + + +/* CFG_START_UP register fields */ + +#define CONFIGURATION_OBJECTS_CFG_START_UP_MBIST_DIS_MASK BIT(1) +#define CONFIGURATION_OBJECTS_CFG_START_UP_MBIST_DIS_POS 1 + +#define CONFIGURATION_OBJECTS_CFG_START_UP_RNGTEST_DIS_MASK BIT(2) +#define CONFIGURATION_OBJECTS_CFG_START_UP_RNGTEST_DIS_POS 2 + +#define CONFIGURATION_OBJECTS_CFG_START_UP_MAINTENANCE_ENA_MASK BIT(3) +#define CONFIGURATION_OBJECTS_CFG_START_UP_MAINTENANCE_ENA_POS 3 + +#define CONFIGURATION_OBJECTS_CFG_START_UP_CPU_FW_VERIFY_DIS_MASK BIT(4) +#define CONFIGURATION_OBJECTS_CFG_START_UP_CPU_FW_VERIFY_DIS_POS 4 + +#define CONFIGURATION_OBJECTS_CFG_START_UP_SPECT_FW_VERIFY_DIS_MASK BIT(5) +#define CONFIGURATION_OBJECTS_CFG_START_UP_SPECT_FW_VERIFY_DIS_POS 5 + + +/* CFG_SLEEP_MODE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_SLEEP_MODE_EN_MASK BIT(0) +#define CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_SLEEP_MODE_EN_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_DEEP_SLEEP_MODE_EN_MASK BIT(1) +#define CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_DEEP_SLEEP_MODE_EN_POS 1 + + +/* CFG_SENSORS register fields */ + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PTRNG0_TEST_DIS_MASK BIT(0) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PTRNG0_TEST_DIS_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PTRNG1_TEST_DIS_MASK BIT(1) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PTRNG1_TEST_DIS_POS 1 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_OSCILLATOR_MON_DIS_MASK BIT(2) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_OSCILLATOR_MON_DIS_POS 2 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_SHIELD_DIS_MASK BIT(3) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_SHIELD_DIS_POS 3 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_VOLTAGE_MON_DIS_MASK BIT(4) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_VOLTAGE_MON_DIS_POS 4 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_GLITCH_DET_DIS_MASK BIT(5) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_GLITCH_DET_DIS_POS 5 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_TEMP_SENS_DIS_MASK BIT(6) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_TEMP_SENS_DIS_POS 6 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_LASER_DET_DIS_MASK BIT(7) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_LASER_DET_DIS_POS 7 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_EM_PULSE_DET_DIS_MASK BIT(8) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_EM_PULSE_DET_DIS_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_CPU_ALERT_DIS_MASK BIT(9) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_CPU_ALERT_DIS_POS 9 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PIN_VERIF_BIT_FLIP_DIS_MASK BIT(10) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PIN_VERIF_BIT_FLIP_DIS_POS 10 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_SCB_BIT_FLIP_DIS_MASK BIT(11) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_SCB_BIT_FLIP_DIS_POS 11 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_CPB_BIT_FLIP_DIS_MASK BIT(12) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_CPB_BIT_FLIP_DIS_POS 12 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_ECC_BIT_FLIP_DIS_MASK BIT(13) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_ECC_BIT_FLIP_DIS_POS 13 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_R_MEM_BIT_FLIP_DIS_MASK BIT(14) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_R_MEM_BIT_FLIP_DIS_POS 14 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_EKDB_BIT_FLIP_DIS_MASK BIT(15) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_EKDB_BIT_FLIP_DIS_POS 15 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_I_MEM_BIT_FLIP_DIS_MASK BIT(16) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_I_MEM_BIT_FLIP_DIS_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PLATFORM_BIT_FLIP_DIS_MASK BIT(17) +#define CONFIGURATION_OBJECTS_CFG_SENSORS_PLATFORM_BIT_FLIP_DIS_POS 17 + + +/* CFG_DEBUG register fields */ + +#define CONFIGURATION_OBJECTS_CFG_DEBUG_FW_LOG_EN_MASK BIT(0) +#define CONFIGURATION_OBJECTS_CFG_DEBUG_FW_LOG_EN_POS 0 + + +/* CFG_UAP_PAIRING_KEY_WRITE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_0_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_0_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_1_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_1_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_2_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_2_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_3_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_WRITE_PKEY_SLOT_3_POS 24 + + +/* CFG_UAP_PAIRING_KEY_READ register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_0_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_0_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_1_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_1_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_2_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_2_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_3_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_READ_PKEY_SLOT_3_POS 24 + + +/* CFG_UAP_PAIRING_KEY_INVALIDATE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_0_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_0_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_1_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_1_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_2_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_2_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_3_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_INVALIDATE_PKEY_SLOT_3_POS 24 + + +/* CFG_UAP_R_CONFIG_WRITE_ERASE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_WRITE_ERASE_R_CONFIG_WRITE_ERASE_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_WRITE_ERASE_R_CONFIG_WRITE_ERASE_POS 0 + + +/* CFG_UAP_R_CONFIG_READ register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ_R_CONFIG_READ_CFG_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ_R_CONFIG_READ_CFG_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ_R_CONFIG_READ_FUNC_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ_R_CONFIG_READ_FUNC_POS 8 + + +/* CFG_UAP_I_CONFIG_WRITE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE_I_CONFIG_WRITE_CFG_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE_I_CONFIG_WRITE_CFG_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE_I_CONFIG_WRITE_FUNC_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE_I_CONFIG_WRITE_FUNC_POS 8 + + +/* CFG_UAP_I_CONFIG_READ register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ_I_CONFIG_READ_CFG_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ_I_CONFIG_READ_CFG_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ_I_CONFIG_READ_FUNC_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ_I_CONFIG_READ_FUNC_POS 8 + + +/* CFG_UAP_PING register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_PING_PING_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_PING_PING_POS 0 + + +/* CFG_UAP_R_MEM_DATA_WRITE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_0_127_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_0_127_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_128_255_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_128_255_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_256_383_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_256_383_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_384_511_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_WRITE_UDATA_SLOT_384_511_POS 24 + + +/* CFG_UAP_R_MEM_DATA_READ register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_0_127_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_0_127_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_128_255_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_128_255_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_256_383_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_256_383_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_384_511_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_READ_UDATA_SLOT_384_511_POS 24 + + +/* CFG_UAP_R_MEM_DATA_ERASE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_0_127_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_0_127_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_128_255_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_128_255_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_256_383_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_256_383_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_384_511_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ERASE_UDATA_SLOT_384_511_POS 24 + + +/* CFG_UAP_RANDOM_VALUE_GET register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_RANDOM_VALUE_GET_RANDOM_VALUE_GET_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_RANDOM_VALUE_GET_RANDOM_VALUE_GET_POS 0 + + +/* CFG_UAP_ECC_KEY_GENERATE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_0_7_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_0_7_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_8_15_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_8_15_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_16_23_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_16_23_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_24_31_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_GEN_ECCKEY_SLOT_24_31_POS 24 + + +/* CFG_UAP_ECC_KEY_STORE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_0_7_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_0_7_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_8_15_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_8_15_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_16_23_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_16_23_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_24_31_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_STORE_ECCKEY_SLOT_24_31_POS 24 + + +/* CFG_UAP_ECC_KEY_READ register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_0_7_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_0_7_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_8_15_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_8_15_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_16_23_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_16_23_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_24_31_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_READ_ECCKEY_SLOT_24_31_POS 24 + + +/* CFG_UAP_ECC_KEY_ERASE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_0_7_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_0_7_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_8_15_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_8_15_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_16_23_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_16_23_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_24_31_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ERASE_ECCKEY_SLOT_24_31_POS 24 + + +/* CFG_UAP_ECDSA_SIGN register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_0_7_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_0_7_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_8_15_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_8_15_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_16_23_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_16_23_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_24_31_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ECDSA_ECCKEY_SLOT_24_31_POS 24 + + +/* CFG_UAP_EDDSA_SIGN register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_0_7_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_0_7_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_8_15_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_8_15_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_16_23_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_16_23_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_24_31_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_EDDSA_ECCKEY_SLOT_24_31_POS 24 + + +/* CFG_UAP_MCOUNTER_INIT register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_0_3_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_0_3_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_4_7_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_4_7_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_8_11_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_8_11_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_12_15_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_MCOUNTER_INIT_12_15_POS 24 + + +/* CFG_UAP_MCOUNTER_GET register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_0_3_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_0_3_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_4_7_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_4_7_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_8_11_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_8_11_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_12_15_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_MCOUNTER_GET_12_15_POS 24 + + +/* CFG_UAP_MCOUNTER_UPDATE register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_0_3_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_0_3_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_4_7_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_4_7_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_8_11_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_8_11_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_12_15_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_MCOUNTER_UPDATE_12_15_POS 24 + + +/* CFG_UAP_MAC_AND_DESTROY register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_0_31_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_0_31_POS 0 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_32_63_MASK GENMASK(15, 8) +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_32_63_POS 8 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_64_95_MASK GENMASK(23, 16) +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_64_95_POS 16 + +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_96_127_MASK GENMASK(31, 24) +#define CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_MACANDD_96_127_POS 24 + + +/* CFG_UAP_SERIAL_CODE_GET register fields */ + +#define CONFIGURATION_OBJECTS_CFG_UAP_SERIAL_CODE_GET_SERIAL_CODE_MASK GENMASK(7, 0) +#define CONFIGURATION_OBJECTS_CFG_UAP_SERIAL_CODE_GET_SERIAL_CODE_POS 0 + + +#endif + diff --git a/include/bits.h b/include/bits.h new file mode 100644 index 0000000..ced30ec --- /dev/null +++ b/include/bits.h @@ -0,0 +1,89 @@ +/**********************************************************************//** + * @file bits.h + * @author Ondrej Ille + * @brief Struct and function declarations for dealing with bit assignment. + * + * @license For the license see file LICENSE.txt file in the root directory + * of this source tree. + **************************************************************************/ + +#ifndef BITS_H +#define BITS_H + +#define BITS_PER_LONG 32 + +// ## allows token concatenation +// X = 1 and Y = 10 would return 110 +#define __AC(X,Y) (X##Y) +#define _AC(X,Y) __AC(X,Y) + +#define _U(x) (_AC(x, U)) +#define U(x) (_U(x)) + +#define BIT(nr) (1U << (nr)) + +#define BIT64(nr) (((u64)(1)) << ((u64)(nr))) + +// BIT defines a bit mask for the specified bit number from 0 to whatever fits into an unsigned long +// so BIT(10) should evaluate to decimal 1024 (which is binary 1 left shifted by 10 bits) + +#define GENMASK_INPUT_CHECK(h, l) 0 + +// h is high index, l is low index in a bitfield +// __GENMASK returns 32 bit number with 1s in the h-to-l field +// if h = 4 and l = 1, __GENMASK would return 00000000000000000000000000011110 +#define __GENMASK(h, l) \ + (((~U(0)) - (U(1) << (l)) + 1) & \ + (~U(0) >> (BITS_PER_LONG - 1 - (h)))) + +#define GENMASK(h, l) \ + (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l)) + +#define __bf_shf(x) (__builtin_ffsll(x) - 1) + +/* + * Example: + * + * #define REG_FIELD_A GENMASK(6, 0) + * #define REG_FIELD_B BIT(7) + * #define REG_FIELD_C GENMASK(15, 8) + * #define REG_FIELD_D GENMASK(31, 16) + * + * Get: + * a = FIELD_GET(REG_FIELD_A, reg); + * b = FIELD_GET(REG_FIELD_B, reg); + * + * Set: + * reg = FIELD_PREP(REG_FIELD_A, 1) | + * FIELD_PREP(REG_FIELD_B, 0) | + * FIELD_PREP(REG_FIELD_C, c) | + * FIELD_PREP(REG_FIELD_D, 0x40); + * + * Modify: + * FIELD_SET(reg, REG_FIELD_D, 0x40); + * + * Note: + * FIELD_GET and FIELD_PREP are R-value expressions. + * FIELD_SET is statement. + * "({" "})" braces were removed since they are non-ISO C. + */ + + +#define FIELD_GET(_mask, _reg) \ + ( \ + (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)) \ + ) + +#define FIELD_PREP(_mask, _val) \ + ( \ + ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask) \ + ) + +#define FIELD_SET(_reg, _mask, _val) \ + { \ + _reg &= ~_mask; \ + _reg |= FIELD_PREP(_mask, _val); \ + } + +#endif // ! BITS_H + diff --git a/include/libtropic.h b/include/libtropic.h index b7bc8ff..a83a202 100644 --- a/include/libtropic.h +++ b/include/libtropic.h @@ -1,80 +1,391 @@ -#ifndef TS_HOST_H -#define TS_HOST_H +#ifndef LT_LIBTROPIC_H +#define LT_LIBTROPIC_H /** -* @file libtropic.h -* @brief libtropic header file -* @author Tropic Square s.r.o. -*/ + * @defgroup libtropic_API libtropic API functions + * @brief Expected to be used by an application + * @details Dear users, please use this API. It contains all functions you need to interface with TROPIC01 device. + * @{ + */ + +/** + * @file libtropic.h + * @brief libtropic library main API header file + * @author Tropic Square s.r.o. + */ #include #include -#include -#include "ts_common.h" -#include "ts_l3.h" +#include "libtropic_common.h" +#include "TROPIC01_configuration_objects.h" +//--------------------------------------------------------------------------------------------------------------------// /** * @brief Initialize handle and transport layer * * @param h Device's handle - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_init(ts_handle_t *h); +lt_ret_t lt_init(lt_handle_t *h); +//--------------------------------------------------------------------------------------------------------------------// /** * @brief Deinitialize handle and transport layer * * @param h Device's handle - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_deinit(lt_handle_t *h); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Maximal size of certificate */ +#define LT_L2_GET_INFO_REQ_CERT_SIZE 512 + +/** + * @brief Get device's certificate + * + * @param h Device's handle + * @param cert Certificate's buffer + * @param max_len Length of certificate's buffer + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_get_info_cert(lt_handle_t *h, uint8_t *cert, const uint16_t max_len); + +//--------------------------------------------------------------------------------------------------------------------// +/** + * @brief Verify certificate chain and parse STPUB + * + * @param cert Certificate in DER format + * @param max_len Len of certificate buffer + * @param stpub TROPIC01 STPUB, unique for each device + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_cert_verify_and_parse(const uint8_t *cert, const uint16_t max_len, uint8_t *stpub); + +//--------------------------------------------------------------------------------------------------------------------// +#define LT_L2_GET_INFO_CHIP_ID_SIZE 128 +/** + * @brief Read TROPIC01's chip ID + * + * @param h Device's handle + * @param chip_id Buffer for CHIP ID bytes + * @param max_len Length of a buffer to store id in + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_get_info_chip_id(lt_handle_t *h, uint8_t *chip_id, const uint16_t max_len); + +//--------------------------------------------------------------------------------------------------------------------// +#define LT_L2_GET_INFO_RISCV_FW_SIZE 4 +/** + * @brief Read TROPIC01's RISCV firmware version + * + * @param h Device's handle + * @param ver Buffer for FW version bytes + * @param max_len Length of a buffer to store fw version in + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_get_info_riscv_fw_ver(lt_handle_t *h, uint8_t *ver, const uint16_t max_len); + +//--------------------------------------------------------------------------------------------------------------------// +#define LT_L2_GET_INFO_SPECT_FW_SIZE 4 +/** + * @brief Read TROPIC01's SPECT firmware version + * + * @param h Device's handle + * @param ver Buffer for SPECT version bytes + * @param max_len Length of a buffer to store fw version in + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_get_info_spect_fw_ver(lt_handle_t *h, uint8_t *ver, const uint16_t max_len); + +//--------------------------------------------------------------------------------------------------------------------// +#define LT_L2_GET_INFO_FW_HEADER_SIZE 512 +/** + * @brief Read TROPIC01's fw bank info + * + * @param h Device's handle + * @param header Buffer to store fw header bytes into + * @param max_len Length of a buffer + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_deinit(ts_handle_t *h); +lt_ret_t lt_get_info_fw_bank(lt_handle_t *h, uint8_t *header, const uint16_t max_len); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief PAiring key indexes corresponds to S_HiPub */ +typedef enum { + PAIRING_KEY_SLOT_INDEX_0, + PAIRING_KEY_SLOT_INDEX_1, + PAIRING_KEY_SLOT_INDEX_2, + PAIRING_KEY_SLOT_INDEX_3, +} pkey_index_t; /** - * @brief This function provides secure handshake functionality. After succesfull execution, gcm contexts in passed handle will have kcmd and kres keys set. From this point, device will accept L3 commands. + * @brief Establish encrypted session between TROPIC01 and host MCU * * @param h Device's handle * @param stpub STPUB from device's certificate * @param pkey_index Index of pairing public key * @param shipriv Secure host private key * @param shipub Secure host public key - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_session_start(lt_handle_t *h, const uint8_t *stpub, const pkey_index_t pkey_index, const uint8_t *shipriv, const uint8_t *shipub); + +//--------------------------------------------------------------------------------------------------------------------// +/** + * @brief Abort encrypted session between TROPIC01 and host MCU + * + * @param h Device's handle + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_handshake(ts_handle_t *h, const uint8_t *stpub, const uint8_t pkey_index, const uint8_t *shipriv, const uint8_t *shipub); +lt_ret_t lt_session_abort(lt_handle_t *h); + +//--------------------------------------------------------------------------------------------------------------------// +#define LT_L2_STARTUP_ID_REBOOT 0x01 +#define LT_L2_STARTUP_ID_MAINTENANCE 0x03 /** - * @brief Test secure session by exchanging a message with chip + * @brief Reboot TROPIC01 + * + * @param h Device's handle + * @param startup_id Startup ID + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_reboot(lt_handle_t *h, const uint8_t startup_id); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Maximal length of Ping command message */ +#define PING_LEN_MAX (L3_CMD_DATA_SIZE_MAX - L3_CMD_ID_SIZE) + +/** + * @brief Test secure session by exchanging a message with chip + * * * @param h Device's handle * @param msg_out Ping message going out * @param msg_in Ping message going in * @param len Length of ping message - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_ping(lt_handle_t *h, const uint8_t *msg_out, uint8_t *msg_in, const uint16_t len); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief ECC key slot indexes */ +typedef enum { + SH0PUB = 0, SH1PUB, SH2PUB, SH3PUB, +} pairing_key_slot_t; + +/** + * @brief Write pairing public key into TROPIC01's pairing key slot 0-3 + * + * @param h Device's handle + * @param pubkey 32B of pubkey + * @param slot Pairing key lot SH0PUB - SH3PUB + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_pairing_key_write(lt_handle_t *h, const uint8_t *pubkey, const uint8_t slot); + +//--------------------------------------------------------------------------------------------------------------------// +/** + * @brief Read pairing public key from TROPIC01's pairing key slot 0-3 + * + * @param h Device's handle + * @param pubkey 32B of pubkey + * @param slot Pairing key lot SH0PUB - SH3PUB + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_pairing_key_read(lt_handle_t *h, uint8_t *pubkey, const uint8_t slot); + +//--------------------------------------------------------------------------------------------------------------------// +/** + * @brief Invalidate pairing key in slo 0-3 + * + * @param h Device's handle + * @param slot Pairing key lot SH0PUB - SH3PUB + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_pairing_key_invalidate(lt_handle_t *h, const uint8_t slot); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief CONFIGURATION_OBJECTS_REGISTERS memory map */ +enum CONFIGURATION_OBJECTS_REGS { + CONFIGURATION_OBJECTS_CFG_START_UP_ADDR = 0X0, + CONFIGURATION_OBJECTS_CFG_SLEEP_MODE_ADDR = 0X4, + CONFIGURATION_OBJECTS_CFG_SENSORS_ADDR = 0X8, + CONFIGURATION_OBJECTS_CFG_DEBUG_ADDR = 0X10, + CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_WRITE_ADDR = 0X20, + CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_READ_ADDR = 0X24, + CONFIGURATION_OBJECTS_CFG_UAP_PAIRING_KEY_INVALIDATE_ADDR = 0X28, + CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_WRITE_ERASE_ADDR = 0X30, + CONFIGURATION_OBJECTS_CFG_UAP_R_CONFIG_READ_ADDR = 0X34, + CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_WRITE_ADDR = 0X40, + CONFIGURATION_OBJECTS_CFG_UAP_I_CONFIG_READ_ADDR = 0X44, + CONFIGURATION_OBJECTS_CFG_UAP_PING_ADDR = 0X100, + CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_WRITE_ADDR = 0X110, + CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_READ_ADDR = 0X114, + CONFIGURATION_OBJECTS_CFG_UAP_R_MEM_DATA_ERASE_ADDR = 0X118, + CONFIGURATION_OBJECTS_CFG_UAP_RANDOM_VALUE_GET_ADDR = 0X120, + CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_GENERATE_ADDR = 0X130, + CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_STORE_ADDR = 0X134, + CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_READ_ADDR = 0X138, + CONFIGURATION_OBJECTS_CFG_UAP_ECC_KEY_ERASE_ADDR = 0X13C, + CONFIGURATION_OBJECTS_CFG_UAP_ECDSA_SIGN_ADDR = 0X140, + CONFIGURATION_OBJECTS_CFG_UAP_EDDSA_SIGN_ADDR = 0X144, + CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_INIT_ADDR = 0X150, + CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_GET_ADDR = 0X154, + CONFIGURATION_OBJECTS_CFG_UAP_MCOUNTER_UPDATE_ADDR = 0X158, + CONFIGURATION_OBJECTS_CFG_UAP_MAC_AND_DESTROY_ADDR = 0X160, + CONFIGURATION_OBJECTS_CFG_UAP_SERIAL_CODE_GET_ADDR = 0X170 +}; + +/** + * @brief Write one configuration object + * + * @param h Device's handle + * @param addr Address of a config object + * @param obj Content to be written + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_ping(ts_handle_t *h, const uint8_t *msg_out, uint8_t *msg_in, const uint16_t len); +lt_ret_t lt_r_config_write(lt_handle_t *h, enum CONFIGURATION_OBJECTS_REGS addr, const uint32_t obj); /** - * @brief Get number of random bytes + * @brief Read one configuration object + * + * @param h Device's handle + * @param addr Address of a config object + * @param obj Variable to read content into + * @return LT_OK if success, otherwise returns other error code. + * + */ +lt_ret_t lt_r_config_read(lt_handle_t *h, const enum CONFIGURATION_OBJECTS_REGS addr, uint32_t *obj); + +/** + * @brief Erase the whole config space + * + * @param h Device's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_r_config_erase(lt_handle_t *h); + +/** + * @brief Write one I config object + * + * @param h Device's handle + * @param addr Address of a config object + * @param bit_index Index of bit to write from 1 to 0 + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_i_config_write(lt_handle_t *h, const enum CONFIGURATION_OBJECTS_REGS addr, const uint8_t bit_index); + +/** + * @brief Read one I config object + * + * @param h Device's handle + * @param addr Address of a config object + * @param obj Variable to read content into + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_i_config_read(lt_handle_t *h, const enum CONFIGURATION_OBJECTS_REGS addr, uint32_t *obj); + +//--------------------------------------------------------------------------------------------------------------------// +#define R_MEM_DATA_SIZE_MAX (444) +#define R_MEM_DATA_SLOT_MAX (511) +/** + * @brief Write bytes into a given slot of R MEMORY + * + * @param h Device's handle + * @param udata_slot Memory's slot to be written + * @param data Buffer of data to be written into R MEMORY slot + * @param size Size of data to be read + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_r_mem_data_write(lt_handle_t *h, const uint16_t udata_slot, uint8_t *data, const uint16_t size); + +//--------------------------------------------------------------------------------------------------------------------// +/** + * @brief Read bytes from a given slot of R MEMORY + * + * @param h Device's handle + * @param udata_slot Memory's slot to be read + * @param data Buffer to read data into + * @param size Size of data to be read + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_r_mem_data_read(lt_handle_t *h, const uint16_t udata_slot, uint8_t *data, const uint16_t size); + +//--------------------------------------------------------------------------------------------------------------------// +/** + * @brief Erase bytes from a given slot of R MEMORY + * + * @param h Device's handle + * @param udata_slot Memory's slot to be erased + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_r_mem_data_erase(lt_handle_t *h, const uint16_t udata_slot); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Maximum number of random bytes requested at once */ +#define RANDOM_VALUE_GET_LEN_MAX L2_CHUNK_MAX_DATA_SIZE + +/** + * @brief Get number of random bytes * * @param h Device's handle * @param buff Buffer * @param len Number of random bytes - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_random_get(ts_handle_t *h, uint8_t *buff, const uint16_t len); +lt_ret_t lt_random_get(lt_handle_t *h, uint8_t *buff, const uint16_t len); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief ECC key slot indexes */ +typedef enum { + ECC_SLOT_1 = 0, ECC_SLOT_2, ECC_SLOT_3, ECC_SLOT_4, + ECC_SLOT_5, ECC_SLOT_6, ECC_SLOT_7, ECC_SLOT_8, + ECC_SLOT_9, ECC_SLOT_10, ECC_SLOT_11, ECC_SLOT_12, + ECC_SLOT_13, ECC_SLOT_14, ECC_SLOT_15, ECC_SLOT_16, + ECC_SLOT_17, ECC_SLOT_18, ECC_SLOT_19, ECC_SLOT_20, + ECC_SLOT_21, ECC_SLOT_22, ECC_SLOT_23, ECC_SLOT_24, + ECC_SLOT_25, ECC_SLOT_26, ECC_SLOT_27, ECC_SLOT_28, + ECC_SLOT_29, ECC_SLOT_30, ECC_SLOT_31, ECC_SLOT_32, +} ecc_slot_t; + +/** @brief ECC key type */ +typedef enum { + CURVE_P256 = 1, + CURVE_ED25519 +} ecc_curve_type_t; + +/** @brief ECC key origin */ +typedef enum { + CURVE_GENERATED = 1, + CURVE_STORED +} ecc_key_origin_t; /** - * @brief Generate ECC key in the chip's ECC key slot + * @brief Generate ECC key in the device's ECC key slot * * @param h Device's handle - * @param slot Slot number ECC_SLOT_1 - ECC_SLOT_32 - * @param curve ECC curve L3_ECC_KEY_GENERATE_CURVE_ED25519 or L3_ECC_KEY_GENERATE_CURVE_P256 - * @return TS_OK if success, otherwise returns other error code. + * @param slot Slot number ecc_slot_t + * @param curve Type of ECC curve. Use L3_ECC_KEY_GENERATE_CURVE_ED25519 or L3_ECC_KEY_GENERATE_CURVE_P256 + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_ecc_key_generate(lt_handle_t *h, const ecc_slot_t slot, const ecc_curve_type_t curve); + +/** + * @brief Store ECC key in the device's ECC key slot + * + * @param h Device's handle + * @param slot Slot number ecc_slot_t + * @param curve Type of ECC curve. Use L3_ECC_KEY_GENERATE_CURVE_ED25519 or L3_ECC_KEY_GENERATE_CURVE_P256 + * @param key Key to store + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_ecc_key_generate(ts_handle_t *h, const uint8_t slot, const uint8_t curve); +lt_ret_t lt_ecc_key_store(lt_handle_t *h, const ecc_slot_t slot, const ecc_curve_type_t curve, const uint8_t *key); /** - * @brief + * @brief Read ECC public key corresponding to a private key in device's slot * * @param h Device's handle * @param slot Slot number ECC_SLOT_1 - ECC_SLOT_32 @@ -82,62 +393,88 @@ ts_ret_t ts_ecc_key_generate(ts_handle_t *h, const uint8_t slot, const uint8_t c * @param keylen Length of the key's buffer * @param curve Will be filled by curve byte * @param origin Will be filled by origin byte - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_ecc_key_read(ts_handle_t *h, const uint8_t slot, uint8_t *key, const int8_t keylen, uint8_t *curve, uint8_t *origin); +lt_ret_t lt_ecc_key_read(lt_handle_t *h, const ecc_slot_t slot, uint8_t *key, const uint8_t keylen, ecc_curve_type_t *curve, ecc_key_origin_t *origin); /** - * @brief Tropic EDDSA signs with ECC key + * @brief Erase ECC key from device's slot * * @param h Device's handle * @param slot Slot number ECC_SLOT_1 - ECC_SLOT_32 - * @param msg Buffer containing a message to sign, max length is 4096B - * @param msg_len Length of a message - * @param rs Buffer for storing a signature in a form of R and S bytes - * @param rs_len Length of rs buffer should be 64B - * @return TS_OK if success, otherwise returns other error code. - * + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_eddsa_sign(ts_handle_t *h, const uint8_t slot, const uint8_t *msg, const int16_t msg_len, uint8_t *rs, const int8_t rs_len); +lt_ret_t lt_ecc_key_erase(lt_handle_t *h, const ecc_slot_t slot); /** - * @brief + * @brief ECDSA sign message with a private key stored in TROPIC01 device * * @param h Device's handle - * @param slot Slot number ECC_SLOT_1 - ECC_SLOT_32 - * @param msg Buffer containing hash of a message - * @param msg_len Length of hash's buffer should be 32B + * @param slot Slot containing a private key, ECC_SLOT_1 - ECC_SLOT_32 + * @param msg_hash Buffer containing hash of a message + * @param msg_hash_len Length of hash's buffer should be 32B * @param rs Buffer for storing a signature in a form of R and S bytes * @param rs_len Length of rs buffer should be 64B - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_ecdsa_sign(ts_handle_t *h, const uint8_t slot, const uint8_t *msg_hash, const int16_t msg_hash_len, uint8_t *rs, const int8_t rs_len); +lt_ret_t lt_ecc_ecdsa_sign(lt_handle_t *h, const ecc_slot_t slot, const uint8_t *msg_hash, const uint16_t msg_hash_len, uint8_t *rs, const uint8_t rs_len); /** - * @brief Erase ECC key from chip-s slot + * @brief EdDSA sign message with a private key stored in TROPIC01 device * * @param h Device's handle - * @param slot Slot number ECC_SLOT_1 - ECC_SLOT_32 - * @return TS_OK if success, otherwise returns other error code. + * @param slot Slot containing a private key, ECC_SLOT_1 - ECC_SLOT_32 + * @param msg Buffer containing a message to sign, max length is 4096B + * @param msg_len Length of a message + * @param rs Buffer for storing a silt_r_mem_data_erasewise returns other error code. TODO info about other ret values + * */ -ts_ret_t ts_ecc_key_erase(ts_handle_t *h, const uint8_t slot); +lt_ret_t lt_ecc_eddsa_sign(lt_handle_t *h, const ecc_slot_t slot, const uint8_t *msg, const uint16_t msg_len, uint8_t *rs, const uint8_t rs_len); /** - * @brief Get device's certificate + * @brief EdDSA signature verify + * + * @param msg Message + * @param msg_len Length of message. Max length is 4095 + * @param pubkey Public key related to private key which signed the message + * @param rs Signature to be verified, in a form of R and S bytes + * @return LT_OK if success, otherwise returns other error code. TODO info about other ret values + * + */ +lt_ret_t lt_ecc_eddsa_sig_verify(const uint8_t *msg, const uint16_t msg_len, const uint8_t *pubkey, const uint8_t *rs); + +//--------------------------------------------------------------------------------------------------------------------// +/* + +MCounter_Init + +MCounter_Update + +MCounter_Get + +*/ + +//--------------------------------------------------------------------------------------------------------------------// +#define SERIAL_CODE_SIZE 32u + +/** + * @brief Get serial code field * * @param h Device's handle - * @param cert Certificate's buffer - * @param max_len Length of certificate's buffer - * @return TS_OK if success, otherwise returns other error code. + * @param serial_code Serial code bytes + * @param size Size of buffer to read into + * @return LT_OK if success, otherwise returns other error code. */ -ts_ret_t ts_get_info_cert(ts_handle_t *h, uint8_t *cert, const int16_t max_len); +lt_ret_t lt_serial_code_get(lt_handle_t *h, uint8_t *serial_code, const uint16_t size); -ts_ret_t ts_cert_verify_and_parse(const uint8_t *cert, const int16_t max_len, uint8_t *stpub); +/** + * @details Helper function for printing out name of returned value + * + * @param ret lt_ret_t returned type value + * @return const char* description of return value. + */ +const char *lt_ret_verbose(lt_ret_t ret); -// TODO -//ts_ret_t ts_get_info_chip_id(ts_handle_t *h, uint8_t chip_id, uint16_t max_len); -//ts_ret_t ts_get_info_riscv_fw_ver(ts_handle_t *h, uint8_t ver, uint16_t max_len); -//ts_ret_t ts_get_info_spect_fw_ver(ts_handle_t *h, uint8_t ver, uint16_t max_len); -//ts_ret_t ts_get_info_fw_bank(ts_handle_t *h, uint8_t fw_bank, uint16_t max_len); +/** @} */ // end of group_libtropic_API #endif diff --git a/include/libtropic_common.h b/include/libtropic_common.h new file mode 100644 index 0000000..c5ab2be --- /dev/null +++ b/include/libtropic_common.h @@ -0,0 +1,143 @@ +#ifndef LT_LIBTROPIC_COMMON_H +#define LT_LIBTROPIC_COMMON_H + +/** + * @file libtropic_common.h + * @brief Shared definitions and functions commonly used by more libtropic's layers + * @author Tropic Square s.r.o. + */ + +#include "stdint.h" + +/** Alias for unsigned 8 bit integer */ +typedef uint8_t u8; +/** Alias for unsigned 16 bit integer */ +typedef uint16_t u16; +/** Alias for unsigned 32 bit integer */ +typedef uint32_t u32; + +/** Macro to sanitize compiler warnings */ +#ifndef UNUSED +#define UNUSED(x) (void)(x) +#endif + +/** This particular value means that secure session was succesfully established and it is currently ON */ +#define SESSION_ON 0xA5A55A5A + +/** Size of l3 ID field */ +#define L3_ID_SIZE 1u +/** Size of l3 TAG field */ +#define L3_TAG_SIZE 16u +/** Size of IV */ +#define L3_IV_SIZE 12u + +/** Size of RES_SIZE field */ +#define L3_RES_SIZE_SIZE sizeof(uint16_t) +/** Size of l3 CMD_ID field */ +#define L3_CMD_ID_SIZE (1) +/** Maximal size of l3 RES/RSP DATA field */ +#define L3_CMD_DATA_SIZE_MAX (4097) + +/** TODO Maximal size of data field in one L2 transfer */ +#define L2_CHUNK_MAX_DATA_SIZE 252u +/** Maximal size of one l2 frame */ +#define L2_MAX_FRAME_SIZE (1 + 1 + L2_CHUNK_MAX_DATA_SIZE + 2) +/** Maximal number of data bytes in one L1 transfer */ +#define LT_L1_LEN_MIN 1 +/** Maximal number of data bytes in one L1 transfer */ +#define LT_L1_LEN_MAX (1 + 1 + 1 + L2_CHUNK_MAX_DATA_SIZE + 2) + +/** Maximum size of l3 ciphertext (or decrypted l3 packet) */ +#define L3_PACKET_MAX_SIZE (L3_CMD_ID_SIZE + L3_CMD_DATA_SIZE_MAX) +/** Max size of one unit of transport on l3 layer */ +#define L3_FRAME_MAX_SIZE (L3_RES_SIZE_SIZE + L3_PACKET_MAX_SIZE + L3_TAG_SIZE) + +/** Generic L3 command and result frame */ +struct __attribute__((packed)) lt_l3_gen_frame_t { + /** RES_SIZE or CMD_SIZE value */ + uint16_t cmd_size; + /** Command or result data including ID and TAG */ + uint8_t data[L3_FRAME_MAX_SIZE - L3_RES_SIZE_SIZE]; +}; + +/** + * @details This structure holds data related to one physical chip. + * Contains AESGCM contexts for encrypting and decrypting L3 commands, nonce and device void pointer, which can be used for passing arbitrary data. + */ +typedef struct lt_handle_t { + void *device; + uint32_t session; + uint8_t IV[12]; +#if USE_TREZOR_CRYPTO + uint8_t encrypt[352] __attribute__ ((aligned (16))); // Because sizeof(lt_aes_gcm_ctx_t) == 352; + uint8_t decrypt[352] __attribute__ ((aligned (16))); +#elif USE_MBEDTLS +#warning "Warning: MBED Tls is not implemented yet"; +#endif + uint8_t l2_buff [1 + L2_MAX_FRAME_SIZE]; + uint8_t l3_buff[L3_FRAME_MAX_SIZE]; +} lt_handle_t; + +/** Enum return type */ +typedef enum { + /** Operation was successful */ + LT_OK, + /** Operation was not succesfull */ + LT_FAIL, + /* Host no session */ + LT_HOST_NO_SESSION, + /** Some parameter was not accepted by function */ + LT_PARAM_ERR, + /** Error detected during cryptographic operation */ + LT_CRYPTO_ERR, + + /** Spi transfer returned error */ + LT_L1_SPI_ERROR, + /** Data does not have an expected length */ + LT_L1_DATA_LEN_ERROR, + /** Chip is in STARTUP mode */ + LT_L1_CHIP_STARTUP_MODE, + /** Chip is in ALARM mode */ + LT_L1_CHIP_ALARM_MODE, + /** Chip is BUSY - typically chip is still booting */ + LT_L1_CHIP_BUSY, + + /** Return values based on STATUS field */ + /** l2 response frame contains CRC error */ + LT_L2_IN_CRC_ERR, + /** There is more than one chunk to be expected for a current request */ + LT_L2_REQ_CONT, + /** There is more than one chunk to be received for a current response */ + LT_L2_RES_CONT, + /** There were an error during handshake establishing */ + LT_L2_HSK_ERR, + /** There is no secure session */ + LT_L2_NO_SESSION, + /** There were error during checking message authenticity */ + LT_L2_TAG_ERR, + /** l2 request contained crc error */ + LT_L2_CRC_ERR, + /** There were some other error */ + LT_L2_GEN_ERR, + /** Chip has no response to be transmitted */ + LT_L2_NO_RESP, + /** ID of last request is not known to TROPIC01 */ + LT_L2_UNKNOWN_REQ, + /** Returned status byte is not recognized at all */ + LT_L2_STATUS_NOT_RECOGNIZED, + /** L2 data does not have an expected length */ + LT_L2_DATA_LEN_ERROR, + + /** L3 command was received correctly*/ + LT_L3_OK, + /** L3 command was not received correctly */ + LT_L3_FAIL, + /** Current pairing keys are not authorized for execution of the last command */ + LT_L3_UNAUTHORIZED, + /** Received L3 command is invalid */ + LT_L3_INVALID_CMD, + /** L3 data does not have an expected length */ + LT_L3_DATA_LEN_ERROR, +} lt_ret_t; + +#endif diff --git a/include/libtropic_port.h b/include/libtropic_port.h new file mode 100644 index 0000000..0e65df9 --- /dev/null +++ b/include/libtropic_port.h @@ -0,0 +1,83 @@ +#ifndef LT_LIBTROPIC_PORT_H +#define LT_LIBTROPIC_PORT_H + +/** + * @defgroup group_port_functions Layer 1 port specific functions + * @brief Defined for each supported platform + * @details Function used by host platform during l1 operations. Check 'hal/port/' folder to see what is supported. + * + * @{ + */ + +/** + * @file libtropic_port.h + * @brief Header file with layer 1 interfaces which are defined based on host platform + * @author Tropic Square s.r.o. + */ + +#include "libtropic_common.h" + +/** + * @brief Platform defined init function. Init resources and set pins as needed. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise LT_FAIL. + */ +lt_ret_t lt_port_init(lt_handle_t *h); + +/** + * @brief Platform defined deinit function. Deinit resources and clear pins as needed. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_port_deinit(lt_handle_t *h); + +/** + * @brief Set chip select pin low, platform defined function. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_port_spi_csn_low(lt_handle_t *h); + +/** + * @brief Set chip select pin high, platform defined function. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_port_spi_csn_high(lt_handle_t *h); + +/** + * @brief Do l1 transfer, platform defined function. + * + * @param h Chip's handle + * @param tx_len The length of data to be transferred + * @param offset Offset in handle's internal buffer where incomming bytes should be stored into + * @param timeout Timeout + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_port_spi_transfer(lt_handle_t *h, uint8_t offset, uint16_t tx_len, uint32_t timeout); + +/** + * @brief Platform defined function for delay, specifies what host platform should do when libtropic's functions need some delay + * + * @param h Chip's handle + * @param ms Time to wait in miliseconds + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_port_delay(lt_handle_t *h, uint32_t ms); + +/** + * @brief Fill buffer with random bytes, platform defined function. + * + * @param buff Buffer to be filled + * @param len number of 32bit numbers + * @return lt_ret_t S_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_port_random_bytes(uint32_t *buff, uint16_t len); + +/** @} */ // end of group_port_functions + +#endif diff --git a/project.yml b/project.yml index cc18eaf..50dbbac 100755 --- a/project.yml +++ b/project.yml @@ -16,26 +16,26 @@ :paths: :test: - - +:tests/** - - -:tests/support + - +:tests/unit/** + - -:tests/unit/support :source: - ./include/* - ./src/** - ./vendor/trezor_crypto/** - ./hal/** :support: - - tests/support + - tests/unit/support :libraries: [] :defines: # in order to add common defines: # 1) remove the trailing [] from the :common: section # 2) add entries to the :common: section (e.g. :test: has TEST defined) - :common: &common_defines [] + :common: &common_defines [LIBT_DEBUG] :test: - *common_defines - TEST - - USE_TS_CRYPTO + - USE_TREZOR_CRYPTO :test_preprocess: - *common_defines - TEST @@ -47,6 +47,8 @@ :plugins: - :ignore - :callback + - :expect_any_args + - :array :treat_as: uint8: HEX8 uint16: HEX16 diff --git a/src/libtropic.c b/src/libtropic.c index 2f72bfc..73ad192 100644 --- a/src/libtropic.c +++ b/src/libtropic.c @@ -1,80 +1,308 @@ /** -* @file libtropic.c -* @brief Implementation of libtropic API -* @author Tropic Square s.r.o. -*/ + * @file libtropic.c + * @brief Implementation of libtropic API + * @author Tropic Square s.r.o. + */ #include #include #include #include -#include "ts_common.h" -#include "ts_random.h" -#include "ts_l1.h" -#include "ts_l2.h" -#include "ts_l3.h" -#include "ts_x25519.h" -#include "ts_hkdf.h" -#include "ts_sha256.h" -#include "ts_aesgcm.h" +#include "libtropic_common.h" +#include "libtropic_port.h" +#include "lt_random.h" +#include "lt_l1_port_wrap.h" +#include "lt_l1.h" +#include "lt_l2.h" +#include "lt_l2_api_structs.h" +#include "lt_l3.h" +#include "lt_l3_api_structs.h" +#include "lt_x25519.h" +#include "lt_ed25519.h" +#include "lt_hkdf.h" +#include "lt_sha256.h" +#include "lt_aesgcm.h" #include "libtropic.h" +#include "TROPIC01_configuration_objects.h" -ts_ret_t ts_init(ts_handle_t *h) +lt_ret_t lt_init(lt_handle_t *h) { if(!h) { - return TS_PARAM_ERR; + return LT_PARAM_ERR; } - ts_ret_t ret = ts_l1_init(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l1_init(h); + if(ret != LT_OK) { return ret; } - return TS_OK; + return LT_OK; } -ts_ret_t ts_deinit(ts_handle_t *h) +lt_ret_t lt_deinit(lt_handle_t *h) { if(!h) { - return TS_PARAM_ERR; + return LT_PARAM_ERR; } - ts_ret_t ret = ts_l1_deinit(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l1_deinit(h); + if(ret != LT_OK) { return ret; } - return TS_OK; + return LT_OK; } -ts_ret_t ts_handshake(ts_handle_t *h, const uint8_t *stpub, const uint8_t pkey_index, const uint8_t *shipriv, const uint8_t *shipub) +/** @brief Block index for data bytes 0-511 of the object */ +typedef enum { +LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_0_127, +LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_128_255, +LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_256_383, +LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_384_511, +} block_index_t; + +/** @brief The X.509 device certificate read from I-Memory and signed by Tropic Square (max length of 512B) */ +# define LT_L2_GET_INFO_REQ_OBJECT_ID_X509_CERTIFICATE 0 +/** @brief The chip ID - the chip silicon revision and unique device ID (max length of 128B) */ +# define LT_L2_GET_INFO_REQ_OBJECT_ID_CHIP_ID 1 +/** @brief The RISCV current running FW version (4 Bytes) */ +# define LT_L2_GET_INFO_REQ_OBJECT_ID_RISCV_FW_VERSION 2 +/** @brief The SPECT FW version (4 Bytes) */ +# define LT_L2_GET_INFO_REQ_OBJECT_ID_SPECT_FW_VERSION 4 +/** @brief The FW header read from the selected bank id (shown as an index). Supported only in Start-up mode */ +# define LT_L2_GET_INFO_REQ_OBJECT_ID_FW_BANK 176 + +lt_ret_t lt_get_info_cert(lt_handle_t *h, uint8_t *cert, const uint16_t max_len) { - if (!h || !shipriv || !shipub || (pkey_index > TS_L2_HANDSHAKE_REQ_PKEY_INDEX_PAIRING_KEY_SLOT_3)) { - return TS_PARAM_ERR; + if ( max_len < LT_L2_GET_INFO_REQ_CERT_SIZE + || !h + || !cert + ) { + return LT_PARAM_ERR; } + // Setup a request pointer to l2 buffer with request data + struct lt_l2_get_info_req_t* p_l2_req = (struct lt_l2_get_info_req_t*)&h->l2_buff; + // Setup a request pointer to l2 buffer with response data + struct lt_l2_get_info_rsp_t* p_l2_resp = (struct lt_l2_get_info_rsp_t*)&h->l2_buff; + + for(int8_t i=0; i<4; i++) { + // Fill l2 request buffer + p_l2_req->req_id = LT_L2_GET_INFO_REQ_ID; + p_l2_req->req_len = LT_L2_GET_INFO_REQ_LEN; + p_l2_req->obj_id = LT_L2_GET_INFO_REQ_OBJECT_ID_X509_CERTIFICATE; + + // LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_0_127 = 0, "i" is used + // LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_128_255 = 1, "i" is used + // LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_256_383 = 2, "i" is used + // LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_384_511 = 3, "i" is used + p_l2_req->block_index = i; + lt_ret_t ret = lt_l2_transfer(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if((LT_L2_GET_INFO_REQ_CERT_SIZE/4) != (p_l2_resp->rsp_len)) { + return LT_FAIL; + } + + memcpy(cert + i*128, ((struct lt_l2_get_info_rsp_t*)h->l2_buff)->data, 128); + } + + return LT_OK; +} + +lt_ret_t lt_cert_verify_and_parse(const uint8_t *cert, const uint16_t max_len, uint8_t *stpub) +{ + if( !cert + || !stpub + || (max_len > LT_L2_GET_INFO_REQ_CERT_SIZE) + ) { + return LT_PARAM_ERR; + } + + // TODO Verify + + /* TODO Improve this + Currently DER certificate is searched for "OBJECT IDENTIFIER curveX25519 (1 3 101 110)", + which is represented by four bytes: 0x65, 0x6e, 0x03 and 0x21 */ + for(int i = 0; i<(512-3); i++) { + if(cert[i] == 0x65 && cert[i+1] == 0x6e && cert[i+2] == 0x03 && cert[i+3] == 0x21) { + memcpy(stpub, cert + i + 5, 32); + return LT_OK; + } + } + + return LT_FAIL; +} + +lt_ret_t lt_get_info_chip_id(lt_handle_t *h, uint8_t *chip_id, const uint16_t max_len) +{ + if ( !h + || !chip_id + || max_len < LT_L2_GET_INFO_CHIP_ID_SIZE) { + return LT_PARAM_ERR; + } + + // Setup a request pointer to l2 buffer, which is placed in handle + struct lt_l2_get_info_req_t* p_l2_req = (struct lt_l2_get_info_req_t*)&h->l2_buff; + // Setup a request pointer to l2 buffer with response data + struct lt_l2_get_info_rsp_t* p_l2_resp = (struct lt_l2_get_info_rsp_t*)&h->l2_buff; + + p_l2_req->req_id = LT_L2_GET_INFO_REQ_ID; + p_l2_req->req_len = LT_L2_GET_INFO_REQ_LEN; + p_l2_req->obj_id = LT_L2_GET_INFO_REQ_OBJECT_ID_CHIP_ID; + p_l2_req->block_index = LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_0_127; + + lt_ret_t ret = lt_l2_transfer(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(128 != (p_l2_resp->rsp_len)) { + return LT_FAIL; + } + + memcpy(chip_id, ((struct lt_l2_get_info_rsp_t*)h->l2_buff)->data, 128); + + return LT_OK; +} + +lt_ret_t lt_get_info_riscv_fw_ver(lt_handle_t *h, uint8_t *ver, const uint16_t max_len) +{ + if ( !h + || !ver + || max_len < LT_L2_GET_INFO_RISCV_FW_SIZE + ) { + return LT_PARAM_ERR; + } + + // Setup a request pointer to l2 buffer, which is placed in handle + struct lt_l2_get_info_req_t* p_l2_req = (struct lt_l2_get_info_req_t*)&h->l2_buff; + // Setup a request pointer to l2 buffer with response data + struct lt_l2_get_info_rsp_t* p_l2_resp = (struct lt_l2_get_info_rsp_t*)&h->l2_buff; + + p_l2_req->req_id = LT_L2_GET_INFO_REQ_ID; + p_l2_req->req_len = LT_L2_GET_INFO_REQ_LEN; + p_l2_req->obj_id = LT_L2_GET_INFO_REQ_OBJECT_ID_RISCV_FW_VERSION; + p_l2_req->block_index = LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_0_127; + + lt_ret_t ret = lt_l2_transfer(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(LT_L2_GET_INFO_RISCV_FW_SIZE != (p_l2_resp->rsp_len)) { + return LT_FAIL; + } + + memcpy(ver, ((struct lt_l2_get_info_rsp_t*)h->l2_buff)->data, LT_L2_GET_INFO_RISCV_FW_SIZE); + + return LT_OK; +} + +lt_ret_t lt_get_info_spect_fw_ver(lt_handle_t *h, uint8_t *ver, const uint16_t max_len) +{ + if ( !h + || !ver + || max_len < LT_L2_GET_INFO_SPECT_FW_SIZE) { + return LT_PARAM_ERR; + } + + // Setup a request pointer to l2 buffer, which is placed in handle + struct lt_l2_get_info_req_t* p_l2_req = (struct lt_l2_get_info_req_t*)&h->l2_buff; + // Setup a request pointer to l2 buffer with response data + struct lt_l2_get_info_rsp_t* p_l2_resp = (struct lt_l2_get_info_rsp_t*)&h->l2_buff; + + p_l2_req->req_id = LT_L2_GET_INFO_REQ_ID; + p_l2_req->req_len = LT_L2_GET_INFO_REQ_LEN; + p_l2_req->obj_id = LT_L2_GET_INFO_REQ_OBJECT_ID_SPECT_FW_VERSION; + p_l2_req->block_index = LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_0_127; + + lt_ret_t ret = lt_l2_transfer(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(LT_L2_GET_INFO_SPECT_FW_SIZE != (p_l2_resp->rsp_len)) { + return LT_FAIL; + } + + memcpy(ver, ((struct lt_l2_get_info_rsp_t*)h->l2_buff)->data, LT_L2_GET_INFO_SPECT_FW_SIZE); + + return LT_OK; +} + +lt_ret_t lt_get_info_fw_bank(lt_handle_t *h, uint8_t *header, const uint16_t max_len) +{ + if ( !h + || !header + || max_len < LT_L2_GET_INFO_FW_HEADER_SIZE + ) { + return LT_PARAM_ERR; + } + + // Setup a request pointer to l2 buffer, which is placed in handle + struct lt_l2_get_info_req_t* p_l2_req = (struct lt_l2_get_info_req_t*)&h->l2_buff; + // Setup a request pointer to l2 buffer with response data + struct lt_l2_get_info_rsp_t* p_l2_resp = (struct lt_l2_get_info_rsp_t*)&h->l2_buff; + + p_l2_req->req_id = LT_L2_GET_INFO_REQ_ID; + p_l2_req->req_len = LT_L2_GET_INFO_REQ_LEN; + p_l2_req->obj_id = LT_L2_GET_INFO_REQ_OBJECT_ID_CHIP_ID; + p_l2_req->block_index = LT_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_0_127; + + lt_ret_t ret = lt_l2_transfer(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(128 != (p_l2_resp->rsp_len)) { + return LT_FAIL; + } + + memcpy(header, ((struct lt_l2_get_info_rsp_t*)h->l2_buff)->data, 128); //TODO specify and fix size of header + + return LT_OK; +} + +lt_ret_t lt_session_start(lt_handle_t *h, const uint8_t *stpub, const pkey_index_t pkey_index, const uint8_t *shipriv, const uint8_t *shipub) +{ + if ( !h + || !shipriv + || !shipub + || (pkey_index > PAIRING_KEY_SLOT_INDEX_3) + ) { + return LT_PARAM_ERR; + } + memset(h, 0, sizeof(lt_handle_t)); // Create ephemeral host keys uint8_t ehpriv[32]; uint8_t ehpub[32]; - ts_ret_t ret = ts_random_bytes(ehpriv, 32); - if(ret != TS_OK) { + lt_ret_t ret = lt_random_bytes((uint32_t*)ehpriv, 8); + if(ret != LT_OK) { return ret; } - ts_X25519_scalarmult(ehpriv, ehpub); + lt_X25519_scalarmult(ehpriv, ehpub); // Setup a request pointer to l2 buffer, which is placed in handle - struct l2_handshake_req_t* p_req = (struct l2_handshake_req_t*)h->l2_buff; + struct lt_l2_handshake_req_t* p_req = (struct lt_l2_handshake_req_t*)h->l2_buff; // Setup a response pointer to l2 buffer, which is placed in handle - struct l2_handshake_rsp_t* p_rsp = (struct l2_handshake_rsp_t*)h->l2_buff; + struct lt_l2_handshake_rsp_t* p_rsp = (struct lt_l2_handshake_rsp_t*)h->l2_buff; - p_req->req_id = L2_HANDSHAKE_REQ_ID; - p_req->req_len = L2_HANDSHAKE_REQ_LEN; + p_req->req_id = LT_L2_HANDSHAKE_REQ_ID; + p_req->req_len = LT_L2_HANDSHAKE_REQ_LEN; memcpy(p_req->e_hpub, ehpub, 32); p_req->pkey_index = pkey_index; - ret = ts_l2_transfer(h); - if(ret != TS_OK) { + ret = lt_l2_transfer(h); + if(ret != LT_OK) { return ret; } @@ -82,383 +310,992 @@ ts_ret_t ts_handshake(ts_handle_t *h, const uint8_t *stpub, const uint8_t pkey_i uint8_t protocol_name[32] = {'N','o','i','s','e','_','K','K','1','_','2','5','5','1','9','_','A','E','S','G','C','M','_','S','H','A','2','5','6',0x00,0x00,0x00}; uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; // h = SHA_256(protocol_name) - ts_sha256_ctx_t hctx = {0}; - - ts_sha256_init(&hctx); - ts_sha256_start(&hctx); - ts_sha256_update(&hctx, protocol_name, 32); - ts_sha256_finish(&hctx, hash); + lt_crypto_sha256_ctx_t hctx = {0}; + lt_sha256_init(&hctx); + lt_sha256_start(&hctx); + lt_sha256_update(&hctx, protocol_name, 32); + lt_sha256_finish(&hctx, hash); // h = SHA256(h||SHiPUB) - ts_sha256_start(&hctx); - ts_sha256_update(&hctx, hash, 32); - ts_sha256_update(&hctx, shipub, 32); - ts_sha256_finish(&hctx, hash); + lt_sha256_start(&hctx); + lt_sha256_update(&hctx, hash, 32); + lt_sha256_update(&hctx, shipub, 32); + lt_sha256_finish(&hctx, hash); // h = SHA256(h||STPUB) - ts_sha256_start(&hctx); - ts_sha256_update(&hctx, hash, 32); - ts_sha256_update(&hctx, stpub, 32); - ts_sha256_finish(&hctx, hash); + lt_sha256_start(&hctx); + lt_sha256_update(&hctx, hash, 32); + lt_sha256_update(&hctx, stpub, 32); + lt_sha256_finish(&hctx, hash); // h = SHA256(h||EHPUB) - ts_sha256_start(&hctx); - ts_sha256_update(&hctx, hash, 32); - ts_sha256_update(&hctx, ehpub, 32); - ts_sha256_finish(&hctx, hash); + lt_sha256_start(&hctx); + lt_sha256_update(&hctx, hash, 32); + lt_sha256_update(&hctx, ehpub, 32); + lt_sha256_finish(&hctx, hash); // h = SHA256(h||PKEY_INDEX) - ts_sha256_start(&hctx); - ts_sha256_update(&hctx, hash, 32); - ts_sha256_update(&hctx, &pkey_index, 1); - ts_sha256_finish(&hctx, hash); + lt_sha256_start(&hctx); + lt_sha256_update(&hctx, hash, 32); + lt_sha256_update(&hctx, (uint8_t*)&pkey_index, 1); + lt_sha256_finish(&hctx, hash); // h = SHA256(h||ETPUB) - ts_sha256_start(&hctx); - ts_sha256_update(&hctx, hash, 32); - ts_sha256_update(&hctx, p_rsp->e_tpub, 32); - ts_sha256_finish(&hctx, hash); + lt_sha256_start(&hctx); + lt_sha256_update(&hctx, hash, 32); + lt_sha256_update(&hctx, p_rsp->e_tpub, 32); + lt_sha256_finish(&hctx, hash); // ck = protocol_name uint8_t output_1[33] = {0}; uint8_t output_2[32] = {0}; // ck = HKDF (ck, X25519(EHPRIV, ETPUB), 1) uint8_t shared_secret[32] = {0}; - ts_X25519(ehpriv, p_rsp->e_tpub, shared_secret); - ts_hkdf(protocol_name, 32, shared_secret, 32, 1, output_1, output_2); + lt_X25519(ehpriv, p_rsp->e_tpub, shared_secret); + lt_hkdf(protocol_name, 32, shared_secret, 32, 1, output_1, output_2); // ck = HKDF (ck, X25519(SHiPRIV, ETPUB), 1) - ts_X25519(shipriv, p_rsp->e_tpub, shared_secret); - ts_hkdf(output_1, 32, shared_secret, 32, 1, output_1, output_2); + lt_X25519(shipriv, p_rsp->e_tpub, shared_secret); + lt_hkdf(output_1, 32, shared_secret, 32, 1, output_1, output_2); // ck, kAUTH = HKDF (ck, X25519(EHPRIV, STPUB), 2) - ts_X25519(ehpriv, stpub, shared_secret); + lt_X25519(ehpriv, stpub, shared_secret); uint8_t kauth[32] = {0}; - ts_hkdf(output_1, 32, shared_secret, 32, 2, output_1, kauth); + lt_hkdf(output_1, 32, shared_secret, 32, 2, output_1, kauth); // kCMD, kRES = HKDF (ck, emptystring, 2) uint8_t kcmd[32] = {0}; uint8_t kres[32] = {0}; - ts_hkdf(output_1, 32, (uint8_t*)"", 0, 2, kcmd, kres); + lt_hkdf(output_1, 32, (uint8_t*)"", 0, 2, kcmd, kres); + + ret = lt_aesgcm_init_and_key(&h->decrypt, kauth, 32); + if(ret != LT_OK) { + return LT_CRYPTO_ERR; + } + + ret = lt_aesgcm_decrypt(&h->decrypt, h->IV, 12u, hash, 32, (uint8_t*)"", 0, p_rsp->t_auth, 16u); + if(ret != LT_OK) { + return LT_CRYPTO_ERR; + } + + ret = lt_aesgcm_init_and_key(&h->encrypt, kcmd, 32); + if(ret != LT_OK) { + return LT_CRYPTO_ERR; + } + + ret = lt_aesgcm_init_and_key(&h->decrypt, kres, 32); + if(ret != LT_OK) { + return LT_CRYPTO_ERR; + } + + h->session = SESSION_ON; + //lt_l3_nonce_init(h); + // TODO create goto and clean keys here before leaving if something fails? + return LT_OK; +} - ret = ts_aesgcm_init_and_key(&h->decrypt, kauth, 32); - if(ret != RETURN_GOOD) { +lt_ret_t lt_session_abort(lt_handle_t *h) +{ + if ( !h + ) { + return LT_PARAM_ERR; + } + + // Setup a request pointer to l2 buffer, which is placed in handle + struct lt_l2_encrypted_session_abt_req_t* p_l2_req = (struct lt_l2_encrypted_session_abt_req_t*)&h->l2_buff; + // Setup a request pointer to l2 buffer with response data + struct lt_l2_encrypted_session_abt_rsp_t* p_l2_resp = (struct lt_l2_encrypted_session_abt_rsp_t*)&h->l2_buff; + + p_l2_req->req_id = LT_L2_ENCRYPTED_SESSION_ABT_REQ_ID; + p_l2_req->req_len = 0; + + lt_ret_t ret = lt_l2_transfer(h); + if(ret != LT_OK) { return ret; } - ret = ts_aesgcm_decrypt(&h->decrypt, h->IV, 12u, hash, 32, (uint8_t*)"", 0, p_rsp->t_auth, 16u); - if(ret != RETURN_GOOD) { + // Check incomming l3 length + if(0 != (p_l2_resp->rsp_len)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_reboot(lt_handle_t *h, const uint8_t startup_id) +{ + if ( !h + || ((startup_id != LT_L2_STARTUP_ID_REBOOT) && (startup_id != LT_L2_STARTUP_ID_MAINTENANCE)) + ) { + return LT_PARAM_ERR; + } + + // Setup a request pointer to l2 buffer, which is placed in handle + struct lt_l2_startup_req_t* p_l2_req = (struct lt_l2_startup_req_t*)&h->l2_buff; + // Setup a request pointer to l2 buffer with response data + struct lt_l2_startup_rsp_t* p_l2_resp = (struct lt_l2_startup_rsp_t*)&h->l2_buff; + + p_l2_req->req_id = LT_L2_STARTUP_REQ_ID; + p_l2_req->req_len = LT_L2_STARTUP_REQ_LEN; + p_l2_req->startup_id = startup_id; + + lt_ret_t ret = lt_l2_transfer(h); + if(ret != LT_OK) { return ret; } - ret = ts_aesgcm_init_and_key(&h->encrypt, kcmd, 32); - if(ret != RETURN_GOOD) { + // Check incomming l3 length + if(0 != (p_l2_resp->rsp_len)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_ping(lt_handle_t *h, const uint8_t *msg_out, uint8_t *msg_in, const uint16_t len) +{ + if( (len > PING_LEN_MAX) + || !h + || !msg_out + || !msg_in + ) { + return LT_PARAM_ERR; + } + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_ping_cmd_t* p_l3_cmd = (struct lt_l3_ping_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_ping_res_t* p_l3_res = (struct lt_l3_ping_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = len + 1; + p_l3_cmd->cmd_id = LT_L3_PING_CMD; + memcpy(p_l3_cmd->data, msg_out, len); + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - ret = ts_aesgcm_init_and_key(&h->decrypt, kres, 32); - if(ret != RETURN_GOOD) { + // Check incomming l3 length + if(len != (p_l3_res->res_size - 1)) + { + return LT_FAIL; + } + + memcpy(msg_in, p_l3_res->data, len); + + return LT_OK; +} + +lt_ret_t lt_pairing_key_write(lt_handle_t *h, const uint8_t *pubkey, const uint8_t slot) +{ + if( !h + || !pubkey + || (slot > 3) + ) { + return LT_PARAM_ERR; + } + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_pairing_key_write_cmd_t * p_l3_cmd = (struct lt_l3_pairing_key_write_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_pairing_key_write_res_t* p_l3_res = (struct lt_l3_pairing_key_write_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_PAIRING_KEY_WRITE_CMD_SIZE; + p_l3_cmd->cmd_id = LT_L3_PAIRING_KEY_WRITE_CMD; + p_l3_cmd->slot = slot; + memcpy(p_l3_cmd->key, pubkey, 32); + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - h->session = SESSION_ON; + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } - // TODO create goto and clean keys here before leaving if something fails - return TS_OK; + return LT_OK; } -ts_ret_t ts_ping(ts_handle_t *h, const uint8_t *msg_out, uint8_t *msg_in, const uint16_t len) +lt_ret_t lt_pairing_key_read(lt_handle_t *h, uint8_t *pubkey, const uint8_t slot) { + if( !h + || !pubkey + || (slot > 3) + ) { + return LT_PARAM_ERR; + } if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_pairing_key_read_cmd_t * p_l3_cmd = (struct lt_l3_pairing_key_read_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_pairing_key_read_res_t* p_l3_res = (struct lt_l3_pairing_key_read_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_PAIRING_KEY_READ_CMD_SIZE; + p_l3_cmd->cmd_id = LT_L3_PAIRING_KEY_READ_CMD; + p_l3_cmd->slot = slot; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(LT_L3_PAIRING_KEY_READ_RES_SIZE != (p_l3_res->res_size)) { + return LT_FAIL; + } + + memcpy(pubkey, p_l3_res->key, 32); + + return LT_OK; +} + +lt_ret_t lt_pairing_key_invalidate(lt_handle_t *h, const uint8_t slot) +{ + if( !h + || (slot > 3) + ) { + return LT_PARAM_ERR; } - if((len > L3_PING_MSG_MAX_LEN) || !h || !msg_out || !msg_in) { - return TS_PARAM_ERR; + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; } - // Pointer to access l3 buffer when it contains Ping command data - struct ts_l3_ping_cmd_t* p_l3_cmd = (struct ts_l3_ping_cmd_t*)&h->l3_buff; - // Pointer to access l3 buffer when it contains Ping result data. - struct ts_l3_ping_res_t* p_l3_res = (struct ts_l3_ping_res_t*)&h->l3_buff; + // Pointer to access l3 buffer when it contains command data + struct lt_l3_pairing_key_invalidate_cmd_t * p_l3_cmd = (struct lt_l3_pairing_key_invalidate_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_pairing_key_invalidate_res_t* p_l3_res = (struct lt_l3_pairing_key_invalidate_res_t*)&h->l3_buff; // Fill l3 buffer - p_l3_cmd->packet_size = len + 1; - p_l3_cmd->command = L3_PING_CMD_ID; - memcpy(p_l3_cmd->data, msg_out, len); + p_l3_cmd->cmd_size = LT_L3_PAIRING_KEY_INVALIDATE_CMD_SIZE; + p_l3_cmd->cmd_id = LT_L3_PAIRING_KEY_INVALIDATE_CMD; + // cmd data + p_l3_cmd->slot = slot; - ts_ret_t ret = ts_l3_cmd(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - if(len != (p_l3_res->packet_size - 1)) - { - return TS_FAIL; + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_r_config_write(lt_handle_t *h, enum CONFIGURATION_OBJECTS_REGS addr, const uint32_t obj) +{ + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + if(!h) { + return LT_PARAM_ERR; + } + + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_r_config_write_cmd_t* p_l3_cmd = (struct lt_l3_r_config_write_cmd_t*)&h->l3_buff; + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_r_config_write_res_t* p_l3_res = (struct lt_l3_r_config_write_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_R_CONFIG_WRITE_SIZE; + p_l3_cmd->command = LT_L3_R_CONFIG_WRITE; + p_l3_cmd->address = (uint16_t)addr; + p_l3_cmd->value = obj; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_r_config_read(lt_handle_t *h, const enum CONFIGURATION_OBJECTS_REGS addr, uint32_t *obj) +{ + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + if(!h) { + return LT_PARAM_ERR; } - memcpy(msg_in, (uint8_t*)&p_l3_res->data, p_l3_res->packet_size); + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_r_config_read_cmd_t* p_l3_cmd = (struct lt_l3_r_config_read_cmd_t*)&h->l3_buff; + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_r_config_read_res_t* p_l3_res = (struct lt_l3_r_config_read_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_R_CONFIG_READ_SIZE; + p_l3_cmd->command = LT_L3_R_CONFIG_READ; + p_l3_cmd->address = (uint16_t)addr; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(8 != (p_l3_res->res_size)) { + return LT_FAIL; + } - return TS_OK; + *obj = p_l3_res->value; + + return LT_OK; } -ts_ret_t ts_random_get(ts_handle_t *h, uint8_t *buff, const uint16_t len) +lt_ret_t lt_r_config_erase(lt_handle_t *h) { if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; + return LT_HOST_NO_SESSION; } - if((len > L3_RANDOM_VALUE_GET_LEN_MAX) || !h || !buff) { - return TS_PARAM_ERR; + if(!h) { + return LT_PARAM_ERR; } - // Pointer to access l3 buffer when it contains Ping command data - struct ts_l3_random_value_get_cmd_t* p_l3_cmd = (struct ts_l3_random_value_get_cmd_t*)&h->l3_buff; - // Pointer to access l3 buffer when it contains Ping result data. - struct ts_l3_random_value_get_res_t* p_l3_res = (struct ts_l3_random_value_get_res_t*)&h->l3_buff; + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_r_config_erase_cmd_t* p_l3_cmd = (struct lt_l3_r_config_erase_cmd_t*)&h->l3_buff; + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_r_config_erase_res_t* p_l3_res = (struct lt_l3_r_config_erase_res_t*)&h->l3_buff; // Fill l3 buffer - p_l3_cmd->packet_size = 0x02; - p_l3_cmd->command = TS_L3_RANDOM_VALUE_GET; + p_l3_cmd->cmd_size = LT_L3_R_CONFIG_ERASE_SIZE; + p_l3_cmd->command = LT_L3_R_CONFIG_ERASE; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_i_config_write(lt_handle_t *h, const enum CONFIGURATION_OBJECTS_REGS addr, const uint8_t bit_index) +{ + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + if(!h) { + return LT_PARAM_ERR; + } + + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_i_config_write_cmd_t* p_l3_cmd = (struct lt_l3_i_config_write_cmd_t*)&h->l3_buff; + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_i_config_write_res_t* p_l3_res = (struct lt_l3_i_config_write_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_I_CONFIG_WRITE_SIZE; + p_l3_cmd->command = LT_L3_I_CONFIG_WRITE; + p_l3_cmd->address = (uint16_t)addr; + p_l3_cmd->bit_index = bit_index; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_i_config_read(lt_handle_t *h, const enum CONFIGURATION_OBJECTS_REGS addr, uint32_t *obj) +{ + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + if(!h) { + return LT_PARAM_ERR; + } + + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_i_config_read_cmd_t* p_l3_cmd = (struct lt_l3_i_config_read_cmd_t*)&h->l3_buff; + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_i_config_read_res_t* p_l3_res = (struct lt_l3_i_config_read_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_I_CONFIG_READ_SIZE; + p_l3_cmd->command = LT_L3_I_CONFIG_READ; + p_l3_cmd->address = (uint16_t)addr; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(8 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + *obj = p_l3_res->value; + + return LT_OK; +} + +lt_ret_t lt_r_mem_data_write(lt_handle_t *h, const uint16_t udata_slot, uint8_t *data, const uint16_t size) +{ + if( !h + || !data + || size > R_MEM_DATA_SIZE_MAX + || (udata_slot > R_MEM_DATA_SLOT_MAX) + ) { + return LT_PARAM_ERR; + } + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_r_mem_data_write_cmd_t * p_l3_cmd = (struct lt_l3_r_mem_data_write_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_r_mem_data_write_res_t* p_l3_res = (struct lt_l3_r_mem_data_write_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = size + 4; + p_l3_cmd->cmd_id = LT_L3_R_MEM_DATA_WRITE_CMD; + p_l3_cmd->slot = udata_slot; + memcpy(p_l3_cmd->data, data, size); + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_r_mem_data_read(lt_handle_t *h, const uint16_t udata_slot, uint8_t *data, const uint16_t size) +{ + if( !h + || !data + || size > 444 + || (udata_slot > 511) + ) { + return LT_PARAM_ERR; + } + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_r_mem_data_read_cmd_t * p_l3_cmd = (struct lt_l3_r_mem_data_read_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_r_mem_data_read_res_t* p_l3_res = (struct lt_l3_r_mem_data_read_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_R_MEM_DATA_READ_CMD_SIZE; + p_l3_cmd->cmd_id = LT_L3_R_MEM_DATA_READ_CMD; + p_l3_cmd->slot = udata_slot; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(4 + size != (p_l3_res->res_size)) { + return LT_FAIL; + } + memcpy(data, p_l3_res->data, size); + + return LT_OK; +} + +lt_ret_t lt_r_mem_data_erase(lt_handle_t *h, const uint16_t udata_slot) +{ + if( !h + || (udata_slot > 511) + ) { + return LT_PARAM_ERR; + } + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_r_mem_data_erase_cmd_t * p_l3_cmd = (struct lt_l3_r_mem_data_erase_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_r_mem_data_erase_res_t* p_l3_res = (struct lt_l3_r_mem_data_erase_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_R_MEM_DATA_ERASE_CMD_SIZE; + p_l3_cmd->cmd_id = LT_L3_R_MEM_DATA_ERASE_CMD; + p_l3_cmd->slot = udata_slot; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_random_get(lt_handle_t *h, uint8_t *buff, const uint16_t len) +{ + if( (len > RANDOM_VALUE_GET_LEN_MAX) + || !h + || !buff + ) { + return LT_PARAM_ERR; + } + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_random_value_get_cmd_t* p_l3_cmd = (struct lt_l3_random_value_get_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_random_value_get_res_t* p_l3_res = (struct lt_l3_random_value_get_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_RANDOM_VALUE_GET_CMD_SIZE; + p_l3_cmd->cmd_id = LT_L3_RANDOM_VALUE_GET_CMD; p_l3_cmd->n_bytes = len; - ts_ret_t ret = ts_l3_cmd(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - if(len != (p_l3_res->packet_size - 1 - 3)) - { - return TS_FAIL; + // Check incomming l3 length + if(1 + len != (p_l3_res->res_size - 3)) { + return LT_FAIL; } - memcpy(buff, (uint8_t*)&p_l3_res->random_data, p_l3_res->packet_size); + memcpy(buff, p_l3_res->random_data, p_l3_res->res_size); - return TS_OK; + return LT_OK; } -ts_ret_t ts_ecc_key_generate(ts_handle_t *h, const uint8_t slot, const uint8_t curve) +lt_ret_t lt_ecc_key_generate(lt_handle_t *h, const ecc_slot_t slot, const ecc_curve_type_t curve) { + if( !h + || slot > LT_L3_ECC_KEY_GENERATE_SLOT_MAX + || slot < LT_L3_ECC_KEY_GENERATE_SLOT_MIN + || ((curve != CURVE_P256) && (curve != CURVE_ED25519)) + ) { + return LT_PARAM_ERR; + } if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; + return LT_HOST_NO_SESSION; + } + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_ecc_key_generate_cmd_t* p_l3_cmd = (struct lt_l3_ecc_key_generate_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_ecc_key_generate_res_t* p_l3_res = (struct lt_l3_ecc_key_generate_res_t*)&h->l3_buff; + + // Fill l3 buffer + p_l3_cmd->cmd_size = LT_L3_ECC_KEY_GENERATE_CMD_SIZE; + p_l3_cmd->cmd_id = LT_L3_ECC_KEY_GENERATE_CMD; + p_l3_cmd->slot = (uint8_t)slot; + p_l3_cmd->curve = (uint8_t)curve; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_ecc_key_store(lt_handle_t *h, const ecc_slot_t slot, const ecc_curve_type_t curve, const uint8_t *key) +{ + if( !h + || slot > LT_L3_ECC_KEY_GENERATE_SLOT_MAX + || slot < LT_L3_ECC_KEY_GENERATE_SLOT_MIN + || !curve + || !key + ) { + return LT_PARAM_ERR; } - if((slot < L3_ECC_KEY_GENERATE_SLOT_MIN) || (slot > L3_ECC_KEY_GENERATE_SLOT_MAX) || !h || ((curve != L3_ECC_KEY_GENERATE_CURVE_P256) && (curve != L3_ECC_KEY_GENERATE_CURVE_ED25519)) ){ - return TS_PARAM_ERR; + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; } - // Pointer to access l3 buffer when it contains Ping command data - struct ts_l3_ecc_key_generate_cmd_t* p_l3_cmd = (struct ts_l3_ecc_key_generate_cmd_t*)&h->l3_buff; - // Pointer to access l3 buffer when it contains Ping result data. - struct ts_l3_ecc_key_generate_res_t* p_l3_res = (struct ts_l3_ecc_key_generate_res_t*)&h->l3_buff; + // Pointer to access l3 buffer when it contains command data + struct lt_l3_ecc_key_store_cmd_t* p_l3_cmd = (struct lt_l3_ecc_key_store_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_ecc_key_store_res_t* p_l3_res = (struct lt_l3_ecc_key_store_res_t*)&h->l3_buff; // Fill l3 buffer - p_l3_cmd->packet_size = L3_ECC_KEY_GENERATE_CMD_LEN; - p_l3_cmd->command = TS_L3_ECC_KEY_GENERATE; + p_l3_cmd->cmd_size = LT_L3_ECC_KEY_STORE_CMD_SIZE; + p_l3_cmd->cmd_id= LT_L3_ECC_KEY_STORE_CMD; p_l3_cmd->slot = slot; p_l3_cmd->curve = curve; + memcpy(p_l3_cmd->key, key, 32); - ts_ret_t ret = ts_l3_cmd(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - if(0 != (p_l3_res->packet_size - 1)) - { - return TS_FAIL; + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; } - return TS_OK; + return LT_OK; } -ts_ret_t ts_ecc_key_read(ts_handle_t *h, const uint8_t slot, uint8_t *key, const int8_t keylen, uint8_t *curve, uint8_t *origin) +lt_ret_t lt_ecc_key_read(lt_handle_t *h, const ecc_slot_t slot, uint8_t *key, const uint8_t keylen, ecc_curve_type_t *curve, ecc_key_origin_t *origin) { - if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; + if( !h + || slot > LT_L3_ECC_KEY_GENERATE_SLOT_MAX + || slot < LT_L3_ECC_KEY_GENERATE_SLOT_MIN + || !key + || !curve + || !origin + ) { + return LT_PARAM_ERR; } - if((slot < L3_ECC_KEY_GENERATE_SLOT_MIN) || (slot > L3_ECC_KEY_GENERATE_SLOT_MAX) || !h) { - return TS_PARAM_ERR; + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; } if(keylen < 64) { - return TS_PARAM_ERR; + return LT_PARAM_ERR; } - // Pointer to access l3 buffer when it contains Ping command data - struct ts_l3_ecc_key_read_cmd_t* p_l3_cmd = (struct ts_l3_ecc_key_read_cmd_t*)&h->l3_buff; - // Pointer to access l3 buffer when it contains Ping result data. - struct ts_l3_ecc_key_read_res_t* p_l3_res = (struct ts_l3_ecc_key_read_res_t*)&h->l3_buff; + // Pointer to access l3 buffer when it contains command data + struct lt_l3_ecc_key_read_cmd_t* p_l3_cmd = (struct lt_l3_ecc_key_read_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_ecc_key_read_res_t* p_l3_res = (struct lt_l3_ecc_key_read_res_t*)&h->l3_buff; // Fill l3 buffer - p_l3_cmd->packet_size = 0x03; - p_l3_cmd->command= TS_L3_ECC_KEY_READ; + p_l3_cmd->cmd_size = LT_L3_ECC_KEY_READ_CMD_SIZE; + p_l3_cmd->cmd_id= LT_L3_ECC_KEY_READ_CMD; p_l3_cmd->slot = slot; - ts_ret_t ret = ts_l3_cmd(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } // Check incomming l3 length - if((p_l3_res->curve == TS_L3_ECC_KEY_READ_CURVE_ED25519) && ((p_l3_res->packet_size -1-1-1-13) != 32)) { - return TS_FAIL; + if((p_l3_res->curve == (uint8_t)CURVE_ED25519) && ((p_l3_res->res_size -1-1-1-13) != 32)) { + return LT_FAIL; } - if((p_l3_res->curve == TS_L3_ECC_KEY_READ_CURVE_P256) && ((p_l3_res->packet_size -1-1-1-13) != 64)) { - return TS_FAIL; + if((p_l3_res->curve == (uint8_t)CURVE_P256) && ((p_l3_res->res_size -1-1-1-13) != 64)) { + return LT_FAIL; } *curve = p_l3_res->curve; *origin = p_l3_res->origin; - memcpy(key, (uint8_t*)&p_l3_res->pub_key, p_l3_res->packet_size); - return TS_OK; + if((p_l3_res->curve == (uint8_t)CURVE_ED25519)) { + memcpy(key, p_l3_res->pub_key, 32); + } + if((p_l3_res->curve == (uint8_t)CURVE_P256)) { + memcpy(key, p_l3_res->pub_key, 64); + } + + return LT_OK; } -ts_ret_t ts_eddsa_sign(ts_handle_t *h, const uint8_t slot, const uint8_t *msg, const int16_t msg_len, uint8_t *rs, const int8_t rs_len) +lt_ret_t lt_ecc_key_erase(lt_handle_t *h, const ecc_slot_t slot) { - if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; + if( !h + || slot < LT_L3_ECC_KEY_GENERATE_SLOT_MIN + || slot > LT_L3_ECC_KEY_GENERATE_SLOT_MAX + ) { + return LT_PARAM_ERR; } - if(!h || !msg || !rs || rs_len < 64) { - return TS_PARAM_ERR; + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; } - // Pointer to access l3 buffer when it contains Ping command data - struct ts_l3_eddsa_sign_cmd_t* p_l3_cmd = (struct ts_l3_eddsa_sign_cmd_t*)&h->l3_buff; - // Pointer to access l3 buffer when it contains Ping result data. - struct ts_l3_eddsa_sign_res_t* p_l3_res = (struct ts_l3_eddsa_sign_res_t*)&h->l3_buff; + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_ecc_key_erase_cmd_t* p_l3_buff = (struct lt_l3_ecc_key_erase_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_ecc_key_erase_res_t* p_l3_res = (struct lt_l3_ecc_key_erase_res_t*)&h->l3_buff; // Fill l3 buffer - p_l3_cmd->packet_size = L3_EDDSA_SIGN_CMD_LEN + msg_len; - p_l3_cmd->command = TS_L3_EDDSA_SIGN; - p_l3_cmd->slot = slot; - memcpy(p_l3_cmd->msg, msg, msg_len + L3_EDDSA_SIGN_CMD_LEN); + p_l3_buff->cmd_size = LT_L3_ECC_KEY_ERASE_CMD_SIZE; + p_l3_buff->cmd_id = LT_L3_ECC_KEY_ERASE_CMD; + p_l3_buff->slot = slot; - ts_ret_t ret = ts_l3_cmd(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - memcpy(rs, (uint8_t*)&p_l3_res->r, 32); - memcpy(rs + 32, (uint8_t*)&p_l3_res->s, 32); + // Check incomming l3 length + if(1 != (p_l3_res->res_size)) { + return LT_FAIL; + } - return TS_OK; + return LT_OK; } -ts_ret_t ts_ecdsa_sign(ts_handle_t *h, const uint8_t slot, const uint8_t *msg_hash, const int16_t msg_hash_len, uint8_t *rs, const int8_t rs_len) +lt_ret_t lt_ecc_ecdsa_sign(lt_handle_t *h, const ecc_slot_t slot, const uint8_t *msg, const uint16_t msg_len, uint8_t *rs, const uint8_t rs_len) { - if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; + if( !h + || !msg + || !rs + || (msg_len > LT_L3_ECDSA_SIGN_MSG_LEN_MAX) || (rs_len < 64) + || slot < LT_L3_ECC_KEY_GENERATE_SLOT_MIN + || slot > LT_L3_ECC_KEY_GENERATE_SLOT_MAX + ) { + return LT_PARAM_ERR; } - if(!h || !msg_hash || !rs || (msg_hash_len < 32) || (rs_len < 64)) { - return TS_PARAM_ERR; + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; } - // Pointer to access l3 buffer when it contains Ping command data - struct ts_l3_ecdsa_sign_cmd_t* p_l3_cmd = (struct ts_l3_ecdsa_sign_cmd_t*)&h->l3_buff; - // Pointer to access l3 buffer when it contains Ping result data. - struct ts_l3_ecdsa_sign_res_t* p_l3_res = (struct ts_l3_ecdsa_sign_res_t*)&h->l3_buff; + // Prepare hash of a message + uint8_t msg_hash[32] = {0}; + lt_crypto_sha256_ctx_t hctx = {0}; + lt_sha256_init(&hctx); + lt_sha256_start(&hctx); + lt_sha256_update(&hctx, (uint8_t*)msg, msg_len); + lt_sha256_finish(&hctx, msg_hash); + + // Pointer to access l3 buffer when it contains command data + struct lt_l3_ecdsa_sign_cmd_t* p_l3_cmd = (struct lt_l3_ecdsa_sign_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_ecdsa_sign_res_t* p_l3_res = (struct lt_l3_ecdsa_sign_res_t*)&h->l3_buff; // Fill l3 buffer - p_l3_cmd->packet_size = 0x30; - p_l3_cmd->command= TS_L3_ECDSA_SIGN; + p_l3_cmd->cmd_size = LT_L3_ECDSA_SIGN_CMD_SIZE; + p_l3_cmd->cmd_id= LT_L3_ECDSA_SIGN; p_l3_cmd->slot = slot; memcpy(p_l3_cmd->msg_hash, msg_hash, 32); - ts_ret_t ret = ts_l3_cmd(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - memcpy(rs, (uint8_t*)&p_l3_res->r, 32); - memcpy(rs + 32, (uint8_t*)&p_l3_res->s, 32); + // Check incomming l3 length + if(0x50 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + memcpy(rs, p_l3_res->r, 32); + memcpy(rs + 32, p_l3_res->s, 32); - return TS_OK; + return LT_OK; } -ts_ret_t ts_ecc_key_erase(ts_handle_t *h, const uint8_t slot) +lt_ret_t lt_ecc_eddsa_sign(lt_handle_t *h, const ecc_slot_t slot, const uint8_t *msg, const uint16_t msg_len, uint8_t *rs, const uint8_t rs_len) { - if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; + if( !h + || !msg + || !rs + || rs_len < 64 + || ((msg_len < LT_L3_EDDSA_SIGN_MSG_LEN_MIN) | (msg_len > LT_L3_EDDSA_SIGN_MSG_LEN_MAX)) + || slot < LT_L3_ECC_KEY_GENERATE_SLOT_MIN + || slot > LT_L3_ECC_KEY_GENERATE_SLOT_MAX + ) { + return LT_PARAM_ERR; } - if((slot < L3_ECC_KEY_GENERATE_SLOT_MIN) || (slot > L3_ECC_KEY_GENERATE_SLOT_MAX) || !h) { - return TS_PARAM_ERR; + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; } - // Setup a pointer to l3 buffer, which is placed in handle - struct l3_frame_t* p_l3_buff = (struct l3_frame_t*)&h->l3_buff; + // Pointer to access l3 buffer when it contains command data + struct lt_l3_eddsa_sign_cmd_t* p_l3_cmd = (struct lt_l3_eddsa_sign_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_eddsa_sign_res_t* p_l3_res = (struct lt_l3_eddsa_sign_res_t*)&h->l3_buff; // Fill l3 buffer - p_l3_buff->packet_size = L3_ECC_KEY_ERASE_CMD_LEN; - p_l3_buff->data[0] = L3_ECC_KEY_ERASE_CMD_ID; - p_l3_buff->data[1] = slot; - p_l3_buff->data[2] = 0; + p_l3_cmd->cmd_size = LT_L3_EDDSA_SIGN_CMD_SIZE + msg_len; + p_l3_cmd->cmd_id = LT_L3_EDDSA_SIGN_CMD; + p_l3_cmd->slot = slot; + memcpy(p_l3_cmd->msg, msg, msg_len); - ts_ret_t ret = ts_l3_cmd(h); - if(ret != TS_OK) { + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { return ret; } - return TS_OK; + // Check incomming l3 length + if(0x50 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + memcpy(rs, p_l3_res->r, 32); + memcpy(rs + 32, p_l3_res->s, 32); + + return LT_OK; } -ts_ret_t ts_get_info_cert(ts_handle_t *h, uint8_t *cert, const int16_t max_len) +lt_ret_t lt_ecc_eddsa_sig_verify(const uint8_t *msg, const uint16_t msg_len, const uint8_t *pubkey, const uint8_t *rs) { - if (max_len < 512 || !h || !cert) { - return TS_FAIL; + if ( !msg + || msg_len < LT_L3_EDDSA_SIGN_MSG_LEN_MIN + || msg_len > LT_L3_EDDSA_SIGN_MSG_LEN_MAX + || !pubkey + || !rs + ) { + return LT_PARAM_ERR; } - // Setup a request pointer to l2 buffer, which is placed in handle - struct l2_get_info_req_t* p_l2_buff = (struct l2_get_info_req_t*)&h->l2_buff; - - for(int8_t i=0; i<4; i++) { - // Fill l2 request buffer - p_l2_buff->req_id = L2_GET_INFO_REQ_ID; - p_l2_buff->req_len = L2_GET_INFO_REQ_LEN; - p_l2_buff->obj_id = L2_GET_INFO_REQ_OBJ_ID_X509; - - // L2_GET_INFO_REQ_DATA_CHUNK_0_127 = 0, "i" is used - // L2_GET_INFO_REQ_DATA_CHUNK_128_255 = 1, "i" is used - // L2_GET_INFO_REQ_DATA_CHUNK_256_383 = 2, "i" is used - // L2_GET_INFO_REQ_DATA_CHUNK_384_511 = 3, "i" is used - p_l2_buff->block_index = i; - ts_ret_t ret = ts_l2_transfer(h); - if(ret != TS_OK) { - return ret; - } - memcpy(cert + i*128, ((struct l2_get_info_rsp_t*)h->l2_buff)->data, 128); + if (lt_ed25519_sign_open(msg, msg_len, pubkey, rs) != 0) { + return LT_FAIL; } - return TS_OK; + return LT_OK; } -ts_ret_t ts_cert_verify_and_parse(const uint8_t *cert, const int16_t max_len, uint8_t *stpub) +/* + +MCounter_Init + +MCounter_Update + +MCounter_Get + +*/ + +lt_ret_t lt_serial_code_get(lt_handle_t *h, uint8_t *serial_code, const uint16_t size) { - if(!cert || !stpub || (max_len > 512)) { - return TS_PARAM_ERR; + if( !h + || !serial_code + || size > SERIAL_CODE_SIZE + ) { + return LT_PARAM_ERR; + } + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; } - // TODO Verify + // Setup a pointer to l3 buffer, which is placed in handle + struct lt_l3_serial_data_get_cmd_t* p_l3_buff = (struct lt_l3_serial_data_get_cmd_t*)&h->l3_buff; + // Pointer to access l3 buffer with result data + struct lt_l3_serial_data_get_res_t* p_l3_res = (struct lt_l3_serial_data_get_res_t*)&h->l3_buff; - // TODO parse correctly, not like this: - #ifdef HOST_KEY_FPGA - memcpy(STPUB, cert+197, 32); - #else - memcpy(stpub, cert+188, 32); - #endif - - return TS_OK; -} - - -// TODO -//ts_ret_t ts_get_info_chip_id(ts_handle_t *h, uint8_t chip_id, uint16_t max_len) -//{ -// return TS_OK; -//} -//ts_ret_t ts_get_info_riscv_fw_ver(ts_handle_t *h, uint8_t ver, uint16_t max_len) -//{ -// return TS_OK; -//} -//ts_ret_t ts_get_info_spect_fw_ver(ts_handle_t *h, uint8_t ver, uint16_t max_len) -//{ -// return TS_OK; -//} -//ts_ret_t ts_get_info_fw_bank(ts_handle_t *h, uint8_t fw_bank, uint16_t max_len) -//{ -// return TS_OK; -//} -// + // Fill l3 buffer + p_l3_buff->cmd_size = LT_L3_SERIAL_DATA_GET_SIZE; + p_l3_buff->cmd_id = LT_L3_SERIAL_DATA_GET_CMD; + + lt_ret_t ret = lt_l3_cmd(h); + if(ret != LT_OK) { + return ret; + } + + // Check incomming l3 length + if(0x24 != (p_l3_res->res_size)) { + return LT_FAIL; + } + + memcpy(serial_code, p_l3_res->serial_code, SERIAL_CODE_SIZE); + + return LT_OK; +} + +const char *lt_ret_verbose(lt_ret_t ret) { + switch(ret) { + // Chip MODES + case LT_L1_CHIP_ALARM_MODE: + return "LT_L1_CHIP_ALARM_MODE"; + case LT_L1_CHIP_STARTUP_MODE: + return "LT_L1_CHIP_STARTUP_MODE"; + case LT_L1_CHIP_BUSY: + return "LT_L1_CHIP_BUSY"; + + // L1 + case LT_L1_SPI_ERROR: + return "LT_L1_SPI_ERROR"; + case LT_L1_DATA_LEN_ERROR: + return "LT_L1_DATA_LEN_ERROR"; + + // L2 + case LT_L2_IN_CRC_ERR: + return "LT_L2_IN_CRC_ERR"; + case LT_L2_REQ_CONT: + return "LT_L2_REQ_CONT"; + case LT_L2_RES_CONT: + return "LT_L2_RES_CONT"; + case LT_L2_HSK_ERR: + return "LT_L2_HSK_ERR"; + case LT_L2_NO_SESSION: + return "LT_L2_NO_SESSION"; + case LT_L2_TAG_ERR: + return "LT_L2_TAG_ERR"; + case LT_L2_CRC_ERR: + return "LT_L2_CRC_ERR"; + case LT_L2_GEN_ERR: + return "LT_L2_GEN_ERR"; + case LT_L2_NO_RESP: + return "LT_L2_NO_RESP"; + case LT_L2_UNKNOWN_REQ: + return "LT_L2_UNKNOWN_REQ"; + case LT_L2_STATUS_NOT_RECOGNIZED: + return "LT_L2_STATUS_NOT_RECOGNIZED"; + case LT_L2_DATA_LEN_ERROR: + return "LT_L2_DATA_LEN_ERROR"; + + // L3 + case LT_L3_OK: + return "LT_L3_OK"; + case LT_L3_FAIL: + return "LT_L3_FAIL"; + case LT_L3_UNAUTHORIZED: + return "LT_L3_UNAUTHORIZED"; + case LT_L3_INVALID_CMD: + return "LT_L3_INVALID_CMD"; + case LT_L3_DATA_LEN_ERROR: + return "LT_L3_DATA_LEN_ERROR"; + + // libtropic + case LT_HOST_NO_SESSION: + return "LT_HOST_NO_SESSION"; + case LT_OK: + return "LT_OK"; + case LT_FAIL: + return "LT_FAIL"; + case LT_PARAM_ERR: + return "LT_PARAM_ERR"; + case LT_CRYPTO_ERR: + return "LT_CRYPTO_ERR"; + + // Default + default: + return "FATAL ERROR, unknown return value"; + } +} diff --git a/src/ts_aesgcm.h b/src/lt_aesgcm.h similarity index 75% rename from src/ts_aesgcm.h rename to src/lt_aesgcm.h index 5ca8040..af7bb91 100644 --- a/src/ts_aesgcm.h +++ b/src/lt_aesgcm.h @@ -1,27 +1,25 @@ -#ifndef TS_AES_GCM_H -#define TS_AES_GCM_H +#ifndef LT_AES_GCM_H +#define LT_AES_GCM_H /** -* @file ts_aesgcm.h -* @brief AESGCM function declarations -* @author Tropic Square s.r.o. -*/ - -#include "aes.h" -#include "aesgcm.h" - -/** - * @brief - * + * @file lt_aesgcm.h + * @brief AESGCM function declarations + * @author Tropic Square s.r.o. */ -typedef struct ts_aes_gcm_ctx +#if USE_TREZOR_CRYPTO +#include "aes/aes.h" +#include "aes/aesgcm.h" +#endif + +/** AES-GCM context structure */ +typedef struct lt_crypto_aes_gcm_ctx { -#if USE_TS_CRYPTO +#if USE_TREZOR_CRYPTO gcm_ctx ctx; #elif USE_MBEDTLS #endif -} ts_aes_gcm_ctx_t; +} lt_crypto_aes_gcm_ctx_t; /** * @details This function initializes AES GCM context with keys @@ -29,9 +27,9 @@ typedef struct ts_aes_gcm_ctx * @param ctx AESGCM context structure * @param key The key value * @param key_len Length of key in bytes - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -int ts_aesgcm_init_and_key(void *ctx, +int lt_aesgcm_init_and_key(void *ctx, const uint8_t *key, uint32_t key_len); @@ -47,9 +45,9 @@ int ts_aesgcm_init_and_key(void *ctx, * @param msg_len Length of message in bytes * @param tag The tag buffer * @param tag_len Length of tag buffer in bytes - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -int ts_aesgcm_encrypt(void *ctx, +int lt_aesgcm_encrypt(void *ctx, const uint8_t *iv, uint32_t iv_len, const uint8_t *aad, @@ -71,9 +69,9 @@ int ts_aesgcm_encrypt(void *ctx, * @param msg_len Length of message in bytes * @param tag The tag buffer * @param tag_len Length of tag buffer in bytes - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -int ts_aesgcm_decrypt(void *ctx, +int lt_aesgcm_decrypt(void *ctx, const uint8_t *iv, uint32_t iv_len, const uint8_t *aad, @@ -87,8 +85,8 @@ int ts_aesgcm_decrypt(void *ctx, * @details This function clears AES GCM context * * @param ctx AESGCM context structure - * @return TS_OK if success, otherwise returns other error code. + * @return LT_OK if success, otherwise returns other error code. */ -int ts_aesgcm_end(void *ctx); +int lt_aesgcm_end(void *ctx); #endif diff --git a/src/ts_crc16.c b/src/lt_crc16.c similarity index 90% rename from src/ts_crc16.c rename to src/lt_crc16.c index 9c9c035..bb3a78f 100755 --- a/src/ts_crc16.c +++ b/src/lt_crc16.c @@ -1,10 +1,10 @@ /** -* @file ts_crc16.c -* @brief CRC16 functions are defined here -* @author Tropic Square s.r.o. -*/ + * @file lt_crc16.c + * @brief CRC16 functions definitions + * @author Tropic Square s.r.o. + */ -#include "ts_crc16.h" +#include "lt_crc16.h" /* Generator polynomial value used */ #define CRC16_POLYNOMIAL 0x8005 diff --git a/src/ts_crc16.h b/src/lt_crc16.h similarity index 61% rename from src/ts_crc16.h rename to src/lt_crc16.h index 8b618f0..a05eded 100755 --- a/src/ts_crc16.h +++ b/src/lt_crc16.h @@ -1,11 +1,11 @@ -#ifndef TS_CRC16_H -#define TS_CRC16_H +#ifndef LT_CRC16_H +#define LT_CRC16_H /** -* @file ts_crc16.h -* @brief CRC16 functions are defined here -* @author Tropic Square s.r.o. -*/ + * @file lt_crc16.h + * @brief CRC16 functions declarations + * @author Tropic Square s.r.o. + */ #include /** diff --git a/src/lt_ed25519.h b/src/lt_ed25519.h new file mode 100644 index 0000000..f3b27c0 --- /dev/null +++ b/src/lt_ed25519.h @@ -0,0 +1,14 @@ +#ifndef LT_ED25519_H +#define LT_ED25519_H + +/** + * @file lt_ed25519.h + * @brief ED25519 function declarations + * @author Tropic Square s.r.o. + */ + +#include "stdint.h" + +int lt_ed25519_sign_open(const uint8_t *msg, const uint16_t msg_len, const uint8_t *pubkey, const uint8_t *rs); + +#endif diff --git a/src/ts_hkdf.c b/src/lt_hkdf.c similarity index 58% rename from src/ts_hkdf.c rename to src/lt_hkdf.c index 159ace0..f202ee1 100644 --- a/src/ts_hkdf.c +++ b/src/lt_hkdf.c @@ -1,14 +1,14 @@ /** -* @file ts_hkdf.c -* @brief HKDF function definition -* @author Tropic Square s.r.o. -*/ + * @file lt_hkdf.c + * @brief HKDF functions definitions + * @author Tropic Square s.r.o. + */ #include #include -#if USE_TS_CRYPTO -#include "ts_hmac_sha256.h" +#if USE_TREZOR_CRYPTO +#include "lt_hmac_sha256.h" #include "hasher.h" #include "blake256.h" #include "blake2b.h" @@ -24,19 +24,19 @@ #define UNUSED(x) (void)(x) -void ts_hkdf(uint8_t *ck, uint32_t ck_size, uint8_t *input, uint32_t input_size, uint8_t nouts, uint8_t *output_1, uint8_t *output_2) +void lt_hkdf(uint8_t *ck, uint32_t ck_size, uint8_t *input, uint32_t input_size, uint8_t nouts, uint8_t *output_1, uint8_t *output_2) { UNUSED(nouts); uint8_t tmp[32] = {0}; uint8_t one = 0x01; - ts_hmac_sha256(ck, ck_size, input, input_size, tmp); - ts_hmac_sha256(tmp, 32, &one, 1, output_1); + lt_hmac_sha256(ck, ck_size, input, input_size, tmp); + lt_hmac_sha256(tmp, 32, &one, 1, output_1); uint8_t helper[33] = {0}; memcpy(helper, output_1, 32); helper[32] = 2; - ts_hmac_sha256(tmp, 32, helper, 33, output_2); + lt_hmac_sha256(tmp, 32, helper, 33, output_2); } diff --git a/src/ts_hkdf.h b/src/lt_hkdf.h similarity index 64% rename from src/ts_hkdf.h rename to src/lt_hkdf.h index bfc7a17..349fd8e 100644 --- a/src/ts_hkdf.h +++ b/src/lt_hkdf.h @@ -1,11 +1,11 @@ -#ifndef TS_HKDF_H -#define TS_HKDF_H +#ifndef LT_HKDF_H +#define LT_HKDF_H /** -* @file ts_hkdf.h -* @brief HKDF function declaration -* @author Tropic Square s.r.o. -*/ + * @file lt_hkdf.h + * @brief HKDF function declaration + * @author Tropic Square s.r.o. + */ #include #include @@ -14,13 +14,13 @@ * @details The HMAC key derivation function as described in datasheet * * @param ck CK parameter - * @param ck_len Length of CK parameter + * @param ck_size Length of CK parameter * @param input Input data * @param input_size Size of input data * @param nouts Number of outputs * @param output_1 Output data 1 * @param output_2 Output data 2 */ -void ts_hkdf(uint8_t *ck, uint32_t ck_size, uint8_t *input, uint32_t input_size, uint8_t nouts, uint8_t *output_1, uint8_t *output_2); +void lt_hkdf(uint8_t *ck, uint32_t ck_size, uint8_t *input, uint32_t input_size, uint8_t nouts, uint8_t *output_1, uint8_t *output_2); #endif diff --git a/src/ts_hmac_sha256.h b/src/lt_hmac_sha256.h similarity index 66% rename from src/ts_hmac_sha256.h rename to src/lt_hmac_sha256.h index ba1e19b..4e5f7b9 100644 --- a/src/ts_hmac_sha256.h +++ b/src/lt_hmac_sha256.h @@ -1,11 +1,11 @@ -#ifndef TS_HMAC_SHA256_H -#define TS_HMAC_SHA256_H +#ifndef LT_HMAC_SHA256_H +#define LT_HMAC_SHA256_H /** -* @file ts_hmac_sha256.h -* @brief HMAC SHA256 function declarations -* @author Tropic Square s.r.o. -*/ + * @file lt_hmac_sha256.h + * @brief HMAC SHA256 functions declarations + * @author Tropic Square s.r.o. + */ #include #include @@ -19,7 +19,7 @@ * @param ilen Length of data in input data buffer * @param output Output buffer */ -void ts_hmac_sha256( const uint8_t *key, size_t keylen, +void lt_hmac_sha256( const uint8_t *key, size_t keylen, const uint8_t *input, size_t ilen, uint8_t *output ); diff --git a/src/lt_l1.c b/src/lt_l1.c new file mode 100644 index 0000000..11d204f --- /dev/null +++ b/src/lt_l1.c @@ -0,0 +1,161 @@ +/** + * @file lt_l1.c + * @brief Layer 1 functions definitions + * @author Tropic Square s.r.o. + */ + + +#include +#include +#include + +#include "libtropic_common.h" +#include "lt_l1.h" +#include "lt_l1_port_wrap.h" + + +lt_ret_t lt_l1_read(lt_handle_t *h, const uint32_t max_len, const uint32_t timeout) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } + if ((timeout LT_L1_TIMEOUT_MS_MAX)) { + return LT_PARAM_ERR; + } + if ((max_len < LT_L1_LEN_MIN) | (max_len > LT_L1_LEN_MAX)) { + return LT_PARAM_ERR; + } +#endif + +#ifdef EXPERIMENTAL_SPI_UART + lt_l1_delay(h, 10); +#endif + + int max_tries = LT_L1_READ_MAX_TRIES; + + while(max_tries > 0) { + + max_tries--; + + h->l2_buff[0] = GET_INFO_REQ_ID; + + // Try to read CHIP_STATUS + lt_l1_spi_csn_low(h); +#ifdef EXPERIMENTAL_SPI_RASPBERRYPI + // store the byte which was initally in l2_buff + uint8_t store_byte = h->l2_buff[0]; + // put raspberry command byte there + h->l2_buff[0] = 0x00; + // do transmit of that one command + if (lt_l1_spi_transfer(h, 0, 1, timeout) != LT_OK) + { + lt_l1_spi_csn_high(h); + return LT_L1_SPI_ERROR; + } + // put previous byte back to buffer and continue as usually + h->l2_buff[0] = store_byte; +#endif + if (lt_l1_spi_transfer(h, 0, 1, timeout) != LT_OK) + { + lt_l1_spi_csn_high(h); + return LT_L1_SPI_ERROR; + } + + // Check ALARM bit of CHIP_STATUS + if (h->l2_buff[0] & CHIP_MODE_ALARM_bit) { + lt_l1_spi_csn_high(h); + return LT_L1_CHIP_ALARM_MODE; + } + // Check STARTUP bit of CHIP_STATUS + else if (h->l2_buff[0] & CHIP_MODE_STARTUP_bit) { + lt_l1_spi_csn_high(h); + return LT_L1_CHIP_STARTUP_MODE; + } + // Check READY bit of CHIP_STATUS + else if (h->l2_buff[0] & CHIP_MODE_READY_bit) { + // receive STATUS byte and length byte + if (lt_l1_spi_transfer(h, 1, 2, timeout) != LT_OK) //offset 1 + { + lt_l1_spi_csn_high(h); + return LT_L1_SPI_ERROR; + } + // TODO Better to read two bytes, not one. Then length. + // This function as it is now will return chip in alarm mode when + // spi wires are not connected (and therefore reading 0xff), but I want to get chip busy instead. + // Hotfix for fpga no resp handling: + if (h->l2_buff[1] == 0xff) { + lt_l1_spi_csn_high(h); + lt_l1_delay(h, LT_L1_READ_RETRY_DELAY); + continue; + } + + // Take length information and add 2B for crc bytes + uint16_t length = h->l2_buff[2] + 2; + if(length > (LT_L1_LEN_MAX - 2)) { + lt_l1_spi_csn_high(h); + return LT_L1_DATA_LEN_ERROR; + } + // Receive the rest of incomming bytes, including crc + if (lt_l1_spi_transfer(h, 3, length, timeout) != LT_OK) // offset 3 + { + lt_l1_spi_csn_high(h); + return LT_L1_SPI_ERROR; + } + lt_l1_spi_csn_high(h); + return LT_OK; + + // Chip status does not contain any special mode bit and also is not ready, + // try it again (until max_tries runs out) + } else { + lt_l1_spi_csn_high(h); + lt_l1_delay(h, LT_L1_READ_RETRY_DELAY); + } + } + + return LT_L1_CHIP_BUSY; +} + +lt_ret_t lt_l1_write(lt_handle_t *h, const uint16_t len, const uint32_t timeout) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } + if ((timeout LT_L1_TIMEOUT_MS_MAX)) { + return LT_PARAM_ERR; + } + if ((len < LT_L1_LEN_MIN) | (len > LT_L1_LEN_MAX)) { + return LT_PARAM_ERR; + } +#endif + +#ifdef EXPERIMENTAL_SPI_UART + lt_l1_delay(h, 10); +#endif + + lt_l1_spi_csn_low(h); +#ifdef EXPERIMENTAL_SPI_RASPBERRYPI + // store the byte which was initally in l2_buff + uint8_t store_byte = h->l2_buff[0]; + // put raspberry command byte there + h->l2_buff[0] = 0x01; + // do transmit of that one command + if (lt_l1_spi_transfer(h, 0, 1, timeout) != LT_OK) + { + lt_l1_spi_csn_high(h); + return LT_L1_SPI_ERROR; + } + // put previous byte back to buffer and continue as usually + h->l2_buff[0] = store_byte; +#endif + if (lt_l1_spi_transfer(h, 0, len, timeout) != LT_OK) + { + lt_l1_spi_csn_high(h); + return LT_L1_SPI_ERROR; + } + + lt_l1_spi_csn_high(h); + + return LT_OK; +} diff --git a/src/lt_l1.h b/src/lt_l1.h new file mode 100644 index 0000000..14cc539 --- /dev/null +++ b/src/lt_l1.h @@ -0,0 +1,68 @@ +#ifndef LT_L1_H +#define LT_L1_H + +/** + * @defgroup group_l1_functions Layer 1 functions + * @brief Used internally + * @details Function used internally by libtropic during l1 operation. + * + * @{ + */ + +/** + * @file lt_l1.h + * @brief Layer 1 functions declarations + * @author Tropic Square s.r.o. + */ + +#include "libtropic_common.h" + +/** This bit in CHIP_STATUS byte signalizes that chip is ready to accept requests */ +#define CHIP_MODE_READY_bit 0x01 +/** This bit in CHIP_STATUS byte signalizes that chip is in ALARM mode */ +#define CHIP_MODE_ALARM_bit 0x02 +/** This bit in CHIP_STATUS byte signalizes that chip is in STARTUP mode */ +#define CHIP_MODE_STARTUP_bit 0x04 + +/** Max number of GET_INFO requests when chip is not answering */ +#define LT_L1_READ_MAX_TRIES 50 // Increasing from 10 to 50 to cover SPI slave convertor behaviour. TODO put back to 10 in the future +/** Number of ms to wait between each GET_INFO request */ +#define LT_L1_READ_RETRY_DELAY 25 + +/** Minimal timeout when waiting for activity on SPI bus */ +#define LT_L1_TIMEOUT_MS_MIN 5 +/** Default timeout when waiting for activity on SPI bus */ +#define LT_L1_TIMEOUT_MS_DEFAULT 70 +/** Maximal timeout when waiting for activity on SPI bus */ +#define LT_L1_TIMEOUT_MS_MAX 150 + +/** Maximal delay in ms which can be used in delay funtion */ +#define LT_L1_DELAY_MS_MAX 500 + +/** Get info request's ID */ +#define GET_INFO_REQ_ID 0xAA + + +/** + * @brief Read data from Tropic chip into host platform + * + * @param h Chip's handle + * @param max_len Max len of receive buffer + * @param timeout Timeout - how long function will wait for response + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_read(lt_handle_t *h, const uint32_t max_len, const uint32_t timeout); + +/** + * @brief Write data from host platform into Tropic chip + * + * @param h Chip's handle + * @param len Length of data to send + * @param timeout Timeout + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_write(lt_handle_t *h, const uint16_t len, const uint32_t timeout); + +/** @} */ // end of group_l1_functions + +#endif diff --git a/src/lt_l1_port_wrap.c b/src/lt_l1_port_wrap.c new file mode 100644 index 0000000..fd837f7 --- /dev/null +++ b/src/lt_l1_port_wrap.c @@ -0,0 +1,81 @@ +/** + * @file lt_l1_port_wrap.c + * @brief Layer 1 functions definitions + * @author Tropic Square s.r.o. + */ + + +#include +#include +#include + +#include "libtropic_common.h" +#include "libtropic_port.h" + + +lt_ret_t lt_l1_init(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + + return lt_port_init(h); +} + +lt_ret_t lt_l1_deinit(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + + return lt_port_deinit(h); +} + + +lt_ret_t lt_l1_spi_csn_low(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + + return lt_port_spi_csn_low(h); +} + +lt_ret_t lt_l1_spi_csn_high(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + + return lt_port_spi_csn_high(h); +} + +lt_ret_t lt_l1_spi_transfer(lt_handle_t *h, uint8_t offset, uint16_t tx_len, uint32_t timeout) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + + return lt_port_spi_transfer(h, offset, tx_len, timeout); +} + +lt_ret_t lt_l1_delay(lt_handle_t *h, uint32_t ms) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + + return lt_port_delay(h, ms); +} diff --git a/src/lt_l1_port_wrap.h b/src/lt_l1_port_wrap.h new file mode 100644 index 0000000..85ed947 --- /dev/null +++ b/src/lt_l1_port_wrap.h @@ -0,0 +1,78 @@ +#ifndef LT_L1_PORT_WRAP_H +#define LT_L1_PORT_WRAP_H + +/** + * @defgroup group_l1_functions Layer 1 functions + * @brief Used internally + * @details Function used internally by libtropic during l1 operation. + * + * @{ + */ + +/** + * @file lt_l1.h + * @brief Layer 1 functions declarations + * @author Tropic Square s.r.o. + */ + +#include "libtropic_common.h" + + + +/** + * @brief Initialize handle and l1. This is wrapper for platform defined function. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_init(lt_handle_t *h); + +/** + * @brief Wipe handle and deinitialize l1. This is wrapper for platform defined function. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_deinit(lt_handle_t *h); + +/** + * @brief Sets chip select pin low. This is wrapper for platform defined function. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_spi_csn_low(lt_handle_t *h); + +/** + * @brief Set chip select pin high. This is wrapper for platform defined function. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_spi_csn_high(lt_handle_t *h); + +/** + * @brief Do l1 transfer. This is wrapper for platform defined function. + * + * @param h Chip's handle + * @param tx_len The length of data to be transferred + * @param offset Offset in handle's internal buffer where incomming bytes should be stored into + * @param timeout Timeout + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_spi_transfer(lt_handle_t *h, uint8_t offset, uint16_t tx_len, uint32_t timeout); + +/** + * @brief Platform's definition for delay, specifies what host + * platform should do when libtropic's functions need some delay. + * This is wrapper for platform defined function. + * + * @param h Chip's handle + * @param ms Time to wait in miliseconds + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l1_delay(lt_handle_t *h, uint32_t ms); + +/** @} */ // end of group_l1_functions + +#endif diff --git a/src/lt_l2.c b/src/lt_l2.c new file mode 100644 index 0000000..28ab2ff --- /dev/null +++ b/src/lt_l2.c @@ -0,0 +1,145 @@ +#include + +#include "libtropic_common.h" +#include "lt_crc16.h" +#include "lt_l1.h" +#include "lt_l2.h" +#include "lt_l2_frame_check.h" +#include "lt_l2_api_structs.h" + +/** + * @file lt_l2.c + * @brief Layer 2 functions definitions + * @author Tropic Square s.r.o. + */ + +/** Safety number - limit number of loops during l3 chunks reception. TROPIC01 divides data into 128B + * chunks, length of L3 buffer is (2 + 4096 + 16). + * Divided by typical chunk length: (2 + 4096 + 16) / 128 => 32, + * with a few added loops it is set to 42 + */ +#define MAX_LOOPS 42 + +lt_ret_t lt_l2_transfer(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + add_crc(h->l2_buff); + + uint8_t len = h->l2_buff[1]; + + int ret = lt_l1_write(h, len + 4, LT_L1_TIMEOUT_MS_DEFAULT); + if(ret != LT_OK) { + return ret; + } + + ret = lt_l1_read(h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT); + if(ret != LT_OK) { + return ret; + } + + ret = lt_l2_frame_check(h->l2_buff); + if(ret != LT_OK) { + return ret; + } + + return LT_OK; +} + +lt_ret_t lt_l2_encrypted_cmd(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + int ret = LT_FAIL; + + // Setup a request pointer to l2 buffer, which is placed in handle + struct lt_l2_encrypted_cmd_req_t *req = (struct lt_l2_encrypted_cmd_req_t*)h->l2_buff; + // Setup a response pointer to l2 buffer, which is placed in handle + struct lt_l2_encrypted_cmd_rsp_t *resp = (struct lt_l2_encrypted_cmd_rsp_t*)h->l2_buff; + + // SENDING PART + + struct lt_l3_gen_frame_t * p_frame = (struct lt_l3_gen_frame_t*)h->l3_buff; + // Calculate number of chunks to send. At least one chunk needs to be sent, therefore + 1 + uint16_t chunk_num = ((L3_RES_SIZE_SIZE + p_frame->cmd_size + L3_TAG_SIZE) / L2_CHUNK_MAX_DATA_SIZE) + 1; + // Calculate the length of the last + uint16_t chunk_last_len = ((L3_RES_SIZE_SIZE + p_frame->cmd_size + L3_TAG_SIZE) % L2_CHUNK_MAX_DATA_SIZE); + + // Split encrypted buffer into chunks and proceed them into l2 transfers: + for (int i=0; ireq_id = LT_L2_ENCRYPTED_CMD_REQ_ID; + // Update length based on whether actually processed chunk is the last one or not + if(i == (chunk_num - 1)) { + req->req_len = chunk_last_len; + } else { + req->req_len = L2_CHUNK_MAX_DATA_SIZE; + } + memcpy(req->body, (uint8_t*)&h->l3_buff + i*L2_CHUNK_MAX_DATA_SIZE, req->req_len); + + add_crc(req); + + // Send l2 request cointaining a chunk from l3 buff + ret = lt_l1_write(h, 2 + req->req_len + 2, LT_L1_TIMEOUT_MS_DEFAULT); + if(ret != LT_OK) { + return ret; + } + + // Read a response on this l2 request + ret = lt_l1_read(h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT); + if(ret != LT_OK) { + return ret; + } + + // Check status byte of this frame + ret = lt_l2_frame_check((uint8_t*)resp); + if(ret != LT_OK && ret != LT_L2_REQ_CONT) { + return ret; + } + } + + // RECEIVING PART + + // Position into l3 buffer where processed l2 chunk will be copied into + uint16_t offset = 0; + // Tropic can respond with various lengths of chunks, this loop should be limited + uint16_t loops = 0; + + do { + /* Get one l2 frame of a device's response */ + ret = lt_l1_read(h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT); + if(ret != LT_OK) { + return ret; + } + // Prevent overflow of l3 buffer + if (offset + resp->rsp_len > L3_FRAME_MAX_SIZE) { + return LT_L3_DATA_LEN_ERROR; + } + + // Check status byte of this frame + ret = lt_l2_frame_check((uint8_t*)resp); + switch (ret) { + case LT_L2_RES_CONT: + // Copy content of l2 into certain offset of l3 buffer + memcpy((uint8_t*)&h->l3_buff + offset, (struct l2_encrypted_rsp_t*)resp->body, resp->rsp_len); + offset += resp->rsp_len; + loops++; + break; + case LT_OK: + // This was last l2 frame of l3 packet, copy it and return + memcpy((uint8_t*)&h->l3_buff + offset, (struct l2_encrypted_rsp_t*)resp->body, resp->rsp_len); + return LT_OK; + default: + // Any other L2 packet's status is not expected + return ret; + } + } while (loops < MAX_LOOPS); + + return LT_FAIL; +} diff --git a/src/lt_l2.h b/src/lt_l2.h new file mode 100644 index 0000000..9b4a279 --- /dev/null +++ b/src/lt_l2.h @@ -0,0 +1,46 @@ +#ifndef LT_L2_H +#define LT_L2_H + +/** + * @defgroup group_l2_functions Layer 2 functions + * @brief Used internally + * @details Function used during l2 operation. + * + * @{ + */ + +/** + * @file lt_l2.h + * @brief Layer 2 functions declarations + * @author Tropic Square s.r.o. + */ + +#include "libtropic_common.h" + +/** + * @brief This function executes generic l2 request/respond. Prior calling this function, place + * request's data into handle's iternal l2 buffer, structures defined in lt_l2_api_structs.h migh help. + * Handle's internal buffer will contain response's when function returns TS_OK. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l2_transfer(lt_handle_t *h); + +/** + * @brief This function executes generic L3 command. It expects command's data to be correctly + * encrypted using keys created during previsously called lt_l2_handshake_req(). + * + * Prior calling this function, place + * command's data into handle's iternal l3 buffer, structures defined in lt_l3_api_structs.h migh help. + * Handle's internal l3 buffer will contain result's data when function returns TS_OK. + * + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l2_encrypted_cmd(lt_handle_t *h); + +/** @} */ // end of group_l2_functions + +#endif diff --git a/src/lt_l2_api_structs.h b/src/lt_l2_api_structs.h new file mode 100644 index 0000000..91c9807 --- /dev/null +++ b/src/lt_l2_api_structs.h @@ -0,0 +1,167 @@ +#ifndef LT_L2_API_H +#define LT_L2_API_H + +/** + * @file lt_l2_api_structs.h + * @brief API structures for layer 2 requests and responses + * @author Tropic Square s.r.o. + */ + +#include "libtropic_common.h" + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Request's ID */ +#define LT_L2_GET_INFO_REQ_ID 0x01 +/** @brief Length of this request */ +#define LT_L2_GET_INFO_REQ_LEN 0x02 + +/** This structure declares how "get info request" l2 frame is organized */ +struct lt_l2_get_info_req_t { + /** Request ID byte */ + u8 req_id; + /** Length byte */ + u8 req_len; + /** The Identifier of the requested object */ + u8 obj_id; + /** The index of the 128 Byte long block to request */ + u8 block_index; + /** Checksum */ + uint8_t crc[2]; +} __attribute__((__packed__)); + +/** This structure declares how "get info response" l2 frame is organized */ +struct lt_l2_get_info_rsp_t{ + /** CHIP_STATUS byte */ + u8 chip_status; + /** l2 status byte */ + u8 status; + /** Length of incomming data */ + u8 rsp_len; + /** The data content of the requested object block. */ + u8 data[128]; + /** Checksum */ + u8 crc[2]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Request's ID */ +#define LT_L2_HANDSHAKE_REQ_ID 0x02 +/** @brief Length of this request */ +#define LT_L2_HANDSHAKE_REQ_LEN 0x21 + +/** This structure declares how "handshake request" l2 frame is organized */ +struct lt_l2_handshake_req_t { + /** Request ID byte */ + u8 req_id; + /** Length byte */ + u8 req_len; + /** EHPUB key */ + uint8_t e_hpub[32]; + /** The index of corresponding pairing key */ + uint8_t pkey_index; + /** Checksum */ + uint8_t crc[2]; +} __attribute__((__packed__)); + +/** This structure declares how "handshake response" l2 frame is are organized */ +struct lt_l2_handshake_rsp_t{ + /** CHIP_STATUS byte */ + u8 chip_status; + /** l2 status byte */ + u8 status; + /** Length of incomming data */ + u8 rsp_len; + /** ETPUB comment */ + uint8_t e_tpub[32]; + /** T_AUTH comment */ + uint8_t t_auth[16]; + /** Checksum */ + u8 crc[2]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Request's ID */ +#define LT_L2_ENCRYPTED_CMD_REQ_ID 0x04 + +/** This structure declares how "encrypted cmd request" l2 frame is organized */ +struct lt_l2_encrypted_cmd_req_t { + /** Request ID byte */ + u8 req_id; + /** Length byte */ + u8 req_len; + /** Contains encrypted command */ + uint8_t body[L2_CHUNK_MAX_DATA_SIZE]; + /** Checksum */ + uint8_t crc[2]; +} __attribute__((__packed__)); + +/** This structure declares how "encrypted cmd response" l2 frame is organized */ +struct lt_l2_encrypted_cmd_rsp_t{ + /** CHIP_STATUS byte */ + u8 chip_status; + /** l2 status byte */ + u8 status; + /** Length of incomming data */ + u8 rsp_len; + /** Contains encrypted result */ + uint8_t body[L2_CHUNK_MAX_DATA_SIZE]; + /** Checksum */ + u8 crc[2]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Request's ID */ +#define LT_L2_ENCRYPTED_SESSION_ABT_REQ_ID 0x08 + +/** This structure declares how "encrypted_session_abt request" l2 frame is organized */ +struct lt_l2_encrypted_session_abt_req_t { + /** Request ID byte */ + u8 req_id; + /** Length byte */ + u8 req_len; + /** Checksum */ + uint8_t crc[2]; +} __attribute__((__packed__)); + +/** This structure declares how "encrypted_session_abt response" l2 frame is organized */ +struct lt_l2_encrypted_session_abt_rsp_t{ + /** CHIP_STATUS byte */ + u8 chip_status; + /** l2 status byte */ + u8 status; + /** Length of incomming data */ + u8 rsp_len; + /** Checksum */ + u8 crc[2]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Request's ID */ +#define LT_L2_STARTUP_REQ_ID 0xB3 +#define LT_L2_STARTUP_REQ_LEN 0x1 + +/** This structure declares how "startup_req request" l2 frame is organized */ +struct lt_l2_startup_req_t { + /** Request ID byte */ + u8 req_id; + /** Length byte */ + u8 req_len; + /** Length byte */ + u8 startup_id; + /** Checksum */ + uint8_t crc[2]; +} __attribute__((__packed__)); + +/** This structure declares how "startup_req response" l2 frame is organized */ +struct lt_l2_startup_rsp_t{ + /** CHIP_STATUS byte */ + u8 chip_status; + /** l2 status byte */ + u8 status; + /** Length of incomming data */ + u8 rsp_len; + /** Checksum */ + u8 crc[2]; +} __attribute__((__packed__)); + +#endif diff --git a/src/lt_l2_frame_check.c b/src/lt_l2_frame_check.c new file mode 100644 index 0000000..cc86bc5 --- /dev/null +++ b/src/lt_l2_frame_check.c @@ -0,0 +1,55 @@ +/** + * @file lt_l2_frame_check.c + * @brief Layer 2 frame check functions definitions + * @author Tropic Square s.r.o. + */ + +#include "libtropic_common.h" +#include "lt_crc16.h" +#include "lt_l2_frame_check.h" + +lt_ret_t lt_l2_frame_check(const uint8_t *frame) +{ +#ifdef LIBT_DEBUG + if(!frame) { + return LT_PARAM_ERR; + } +#endif + // Take status, len and crc values from incomming frame + uint8_t status = frame[1]; + uint8_t len = frame[2]; + uint16_t frame_crc = frame[len + 4] | frame[len + 3] << 8; + + switch (status) { + + // Valid frames, or crc errors in INCOMMING frames are handled here: + case L2_STATUS_REQUEST_OK: + case L2_STATUS_RESULT_OK: + if (frame_crc != crc16(frame+1, len + 2)) { + return LT_L2_IN_CRC_ERR; + } + return LT_OK; + + // L2 statuses returned by Tropic chip are handled here + case L2_STATUS_REQUEST_CONT: + return LT_L2_REQ_CONT; + case L2_STATUS_RESULT_CONT: + return LT_L2_RES_CONT; + case L2_STATUS_HSK_ERR: + return LT_L2_HSK_ERR; + case L2_STATUS_NO_SESSION: + return LT_L2_NO_SESSION; + case L2_STATUS_TAG_ERR: + return LT_L2_TAG_ERR; + case L2_STATUS_CRC_ERR: + return LT_L2_CRC_ERR; + case L2_STATUS_GEN_ERR: + return LT_L2_GEN_ERR; + case L2_STATUS_NO_RESP: + return LT_L2_NO_RESP; + case L2_STATUS_UNKNOWN_ERR: + return LT_L2_UNKNOWN_REQ; + default: + return LT_L2_STATUS_NOT_RECOGNIZED; + } +} \ No newline at end of file diff --git a/src/lt_l2_frame_check.h b/src/lt_l2_frame_check.h new file mode 100644 index 0000000..516555d --- /dev/null +++ b/src/lt_l2_frame_check.h @@ -0,0 +1,53 @@ +#ifndef LT_L2_FRAME_CHECK_H +#define LT_L2_FRAME_CHECK_H + +/** + * @defgroup group_l2_frame_check_functions Layer 2 frame check functions + * @brief Used internally + * @details Functions for L2 frame checking + * + * @{ + */ + +/** + * @file lt_l2_frame_check.h + * @brief Layer 2 frame check functions declarations + * @author Tropic Square s.r.o. + */ + +#include "libtropic_common.h" + +/** @brief STATUS field value */ +#define L2_STATUS_REQUEST_OK 0x01 +/** @brief STATUS field value */ +#define L2_STATUS_RESULT_OK 0x02 +/** @brief STATUS field value */ +#define L2_STATUS_REQUEST_CONT 0x03 +/** @brief STATUS field value */ +#define L2_STATUS_RESULT_CONT 0x04 +/** @brief STATUS field value */ +#define L2_STATUS_HSK_ERR 0x79 +/** @brief STATUS field value */ +#define L2_STATUS_NO_SESSION 0x7A +/** @brief STATUS field value */ +#define L2_STATUS_TAG_ERR 0x7B +/** @brief STATUS field value */ +#define L2_STATUS_CRC_ERR 0x7C +/** @brief STATUS field value */ +#define L2_STATUS_UNKNOWN_ERR 0x7E +/** @brief STATUS field value */ +#define L2_STATUS_GEN_ERR 0x7F +/** @brief STATUS field value */ +#define L2_STATUS_NO_RESP 0xFF + +/** + * @brief This function checks if incomming L2 frame is valid + * + * @param frame + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l2_frame_check(const uint8_t *frame); + +/** @} */ // end of group_l2_frame_check_functions + +#endif diff --git a/src/lt_l3.c b/src/lt_l3.c new file mode 100644 index 0000000..dafbd27 --- /dev/null +++ b/src/lt_l3.c @@ -0,0 +1,88 @@ +/** +* @file lt_l3.c +* @brief Layer 3 functions definitions +* @author Tropic Square s.r.o. +*/ + +#include +#include +#include + +#include "libtropic_common.h" +#include "lt_l1.h" +#include "lt_l2.h" +#include "lt_l3.h" +#include "lt_aesgcm.h" + +lt_ret_t lt_l3_nonce_init(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + memset(&h->IV,0,12); + return LT_OK; +} + +lt_ret_t lt_l3_nonce_increase(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + uint32_t nonce = (h->IV[3] << 24) | (h->IV[2] << 16) | (h->IV[1] << 8) | (h->IV[0]); + + nonce ++; + h->IV[3] = nonce >> 24; + h->IV[2] = (nonce & 0x00FF0000) >> 16; + h->IV[1] = (nonce & 0x0000FF00) >> 8; + h->IV[0] = (nonce & 0x000000FF); + + return LT_OK; +} + +lt_ret_t lt_l3_cmd(lt_handle_t *h) +{ +#ifdef LIBT_DEBUG + if(!h) { + return LT_PARAM_ERR; + } +#endif + if(h->session != SESSION_ON) { + return LT_HOST_NO_SESSION; + } + + struct lt_l3_gen_frame_t * p_frame = (struct lt_l3_gen_frame_t*)h->l3_buff; + + int ret = lt_aesgcm_encrypt(&h->encrypt, h->IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE); + if (ret != LT_OK) { + return ret; + } + + ret = lt_l2_encrypted_cmd(h); + if (ret != LT_OK) { + return ret; + } + + ret = lt_aesgcm_decrypt(&h->decrypt, h->IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE); + if (ret != LT_OK) { + return ret; + } + + switch (p_frame->data[0]) { + case L3_RESULT_FAIL: + return LT_L3_FAIL; + case L3_RESULT_UNAUTHORIZED: + lt_l3_nonce_increase(h); + return LT_L3_UNAUTHORIZED; + case L3_RESULT_INVALID_CMD: + return LT_L3_INVALID_CMD; + case L3_RESULT_OK: + lt_l3_nonce_increase(h); + return LT_OK; + default: + return LT_FAIL; + } +} diff --git a/src/lt_l3.h b/src/lt_l3.h new file mode 100644 index 0000000..67a1ae4 --- /dev/null +++ b/src/lt_l3.h @@ -0,0 +1,57 @@ +#ifndef LT_L3_H +#define LT_L3_H + +/** + * @defgroup group_l3_functions Layer 3 functions + * @brief Used internally + * @details Function used during l3 operation. + * + * @{ + */ + +/** +* @file lt_l3.h +* @brief Layer 3 functions declarations +* @author Tropic Square s.r.o. +*/ + +#include "libtropic_common.h" + +/** @brief L3 RESULT field Value */ +#define L3_RESULT_OK 0xC3u +/** @brief L3 RESULT field Value */ +#define L3_RESULT_FAIL 0x3Cu +/** @brief L3 RESULT field Value */ +#define L3_RESULT_UNAUTHORIZED 0x01u +/** @brief L3 RESULT field Value */ +#define L3_RESULT_INVALID_CMD 0x02u + +/** + * @details Initializes nonce in handle to 0. This function is used during secure handshake. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l3_nonce_init(lt_handle_t *h); + +/** + * @details Increases by one nonce stored in handle. This function is called after successfull + * reception of L3 response. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l3_nonce_increase(lt_handle_t *h); + +/** + * @details Perform l3 encrypted command operation. It takes handle's l3 buffer containing l3 command + * and after successfull execution handle's l3 buffer contains l3 result. + * + * @param h Chip's handle + * @return LT_OK if success, otherwise returns other error code. + */ +lt_ret_t lt_l3_cmd(lt_handle_t *h); + +/** @} */ // end of group_l3_functions + +#endif diff --git a/src/lt_l3_api_structs.h b/src/lt_l3_api_structs.h new file mode 100644 index 0000000..8737615 --- /dev/null +++ b/src/lt_l3_api_structs.h @@ -0,0 +1,641 @@ +#ifndef LT_L3_API_H +#define LT_L3_API_H + +/** +* @file lt_l3_api_structs.h +* @brief API structures for layer 3 commands and results +* @author Tropic Square s.r.o. +*/ + +#include "libtropic_common.h" + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_PING_CMD 0x01 + +/** This structure declares how "Ping command" l3 packet is organized */ +struct lt_l3_ping_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** Data transferred from host into chip */ + u8 data[4096]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "Ping result" l3 packet is organized */ +struct lt_l3_ping_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** Data transferred from chip into host */ + u8 data[4096]; + /* L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_PAIRING_KEY_WRITE_CMD 0x10u +#define LT_L3_PAIRING_KEY_WRITE_CMD_SIZE 0x24u + +struct lt_l3_pairing_key_write_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** Pairing key slot */ + u16 slot; + /** Padding */ + u8 padding; + /** Pairing key bytes */ + u8 key[32]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +struct lt_l3_pairing_key_write_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_PAIRING_KEY_READ_CMD 0x11u +#define LT_L3_PAIRING_KEY_READ_CMD_SIZE 0x3u + +struct lt_l3_pairing_key_read_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** Pairing key slot */ + u16 slot; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +#define LT_L3_PAIRING_KEY_READ_RES_SIZE 0x24u +struct lt_l3_pairing_key_read_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + + u8 padding[3]; + u8 key[32]; + + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_PAIRING_KEY_INVALIDATE_CMD 0x12u +#define LT_L3_PAIRING_KEY_INVALIDATE_CMD_SIZE 0x3u + +struct lt_l3_pairing_key_invalidate_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** Pairing key slot */ + u16 slot; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +struct lt_l3_pairing_key_invalidate_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_R_CONFIG_WRITE 0x20 +/** @brief Command length */ +#define LT_L3_R_CONFIG_WRITE_SIZE 0x8u + +/** */ +struct lt_l3_r_config_write_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 command; + /** CO offset address */ + u16 address; + /** Padding */ + u8 padding; + /** */ + u32 value; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** */ +struct lt_l3_r_config_write_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_R_CONFIG_READ 0x21 +/** @brief Command length */ +#define LT_L3_R_CONFIG_READ_SIZE 0x3u + +/** */ +struct lt_l3_r_config_read_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 command; + /** CO offset address */ + u16 address; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** */ +struct lt_l3_r_config_read_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** Padding */ + u8 padding[3]; + /** Value */ + u32 value; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_R_CONFIG_ERASE 0x22 +/** @brief Command length */ +#define LT_L3_R_CONFIG_ERASE_SIZE 0x1u + +/** */ +struct lt_l3_r_config_erase_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 command; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** */ +struct lt_l3_r_config_erase_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_I_CONFIG_WRITE 0x30 +/** @brief Command length */ +#define LT_L3_I_CONFIG_WRITE_SIZE 0x4u + +/** */ +struct lt_l3_i_config_write_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 command; + /** CO offset address */ + u16 address; + /** Padding */ + u8 bit_index; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** */ +struct lt_l3_i_config_write_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_I_CONFIG_READ 0x31 +/** @brief Command length */ +#define LT_L3_I_CONFIG_READ_SIZE 0x3u + +/** */ +struct lt_l3_i_config_read_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 command; + /** CO offset address */ + u16 address; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** */ +struct lt_l3_i_config_read_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** Padding */ + u8 padding[3]; + /** Value */ + u32 value; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_R_MEM_DATA_WRITE_CMD 0x40u +//#define LT_L3_R_MEM_DATA_WRITE_CMD_SIZE 0x3u + +struct lt_l3_r_mem_data_write_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** Pairing key slot */ + u16 slot; + u8 padding; + u8 data[444]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +struct lt_l3_r_mem_data_write_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_R_MEM_DATA_READ_CMD 0x41u +#define LT_L3_R_MEM_DATA_READ_CMD_SIZE 0x3u + +struct lt_l3_r_mem_data_read_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** Pairing key slot */ + u16 slot; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +struct lt_l3_r_mem_data_read_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + u8 padding[3]; + u8 data[444]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_R_MEM_DATA_ERASE_CMD 0x42u +#define LT_L3_R_MEM_DATA_ERASE_CMD_SIZE 0x3u + +struct lt_l3_r_mem_data_erase_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** Pairing key slot */ + u16 slot; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +struct lt_l3_r_mem_data_erase_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_RANDOM_VALUE_GET_CMD 0x50 +/** @brief Command length */ +#define LT_L3_RANDOM_VALUE_GET_CMD_SIZE 2 + +/** This structure declares how "random value get command" l3 packet is organized */ +struct lt_l3_random_value_get_cmd_t { + /* L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** The number of random bytes to get */ + u8 n_bytes; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "random value get result" l3 packet is organized */ +struct lt_l3_random_value_get_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** The padding by dummy data */ + u8 padding[3]; + /** The random data from TRNG2 in the number of bytes specified in the N_BYTES L3 Field */ + u8 random_data[255]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief ECC_Key_generate command ID */ +#define LT_L3_ECC_KEY_GENERATE_CMD 0x60 +/** @brief ECC_Key_generate command size */ +#define LT_L3_ECC_KEY_GENERATE_CMD_SIZE 0x04u +/** @brief ECC_Key_generate min slot number */ +#define LT_L3_ECC_KEY_GENERATE_SLOT_MIN 0 +/** @brief ECC_Key_generate max slot number */ +#define LT_L3_ECC_KEY_GENERATE_SLOT_MAX 31 + +/** This structure declares how "ECC key generate command" l3 packet is organized */ +struct lt_l3_ecc_key_generate_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** The slot to write the generated key. Valid values are 0 - 31 */ + u16 slot; + /** The Elliptic Curve the key is generated from */ + u8 curve; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "ECC key generate result" l3 packet is organized */ +struct lt_l3_ecc_key_generate_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief ECC_Key_store command ID */ +#define LT_L3_ECC_KEY_STORE_CMD 0x61 +/** @brief ECC_Key_store command size */ +#define LT_L3_ECC_KEY_STORE_CMD_SIZE 0x30u +/** This structure declares how "ECC key store command" l3 packet is organized */ +struct lt_l3_ecc_key_store_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** The slot to write the store key. Valid values are 0 - 31 */ + u16 slot; + /** The Elliptic Curve the key is store from */ + u8 curve; + /** Padding */ + u8 padding[12]; + /** Key to store */ + u8 key[32]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "ECC key store result" l3 packet is organized */ +struct lt_l3_ecc_key_store_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_ECC_KEY_READ_CMD 0x62 +/** @brief Command length */ +#define LT_L3_ECC_KEY_READ_CMD_SIZE 0x03 + +/** This structure declares how "ECC key read command" l3 packet is organized */ +struct lt_l3_ecc_key_read_cmd_t { + /**L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** ECC Key slot */ + u16 slot; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "ECC key read result" l3 packet is organized */ +struct lt_l3_ecc_key_read_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** Elliptic Curve */ + u8 curve; + /** The origin of the key */ + u8 origin; + /** Padding */ + u8 padding[13]; + /** The public key from the ECC Key slot as specified in the SLOT L3 Field */ + u8 pub_key[64]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_ECC_KEY_ERASE_CMD 0x63u +/** @brief Command length */ +#define LT_L3_ECC_KEY_ERASE_CMD_SIZE 0x03u + +/** This structure declares how "EC key erase command" l3 packet is organized */ +struct lt_l3_ecc_key_erase_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** ECC Key slot */ + u16 slot; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "EC key erase result" l3 packet is organized */ +struct lt_l3_ecc_key_erase_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_ECDSA_SIGN 0x70 +/** @brief Command length */ +#define LT_L3_ECDSA_SIGN_CMD_SIZE 0x30u +/** TODO Max length of message to be signed with ECDSA */ +#define LT_L3_ECDSA_SIGN_MSG_LEN_MAX (4096 - L3_CMD_ID_SIZE) + +/** This structure declares how "ECDSA sign command" l3 packet is organized */ +struct lt_l3_ecdsa_sign_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** ECC Key slot */ + u16 slot; + /** Padding */ + u8 padding[13]; + /** Message to sign */ + u8 msg_hash[32]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "ECDSA sign result" l3 packet is organized */ +struct lt_l3_ecdsa_sign_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** Padding */ + u8 padding[15]; + /** EdDSA signature - The R part */ + u8 r[32]; + /** EdDSA signature - The S part */ + u8 s[32]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_EDDSA_SIGN_CMD 0x71 +/** @brief Command length */ +#define LT_L3_EDDSA_SIGN_CMD_SIZE 0x10u +/** Minimal length of message to be signed with EdDSA */ +#define LT_L3_EDDSA_SIGN_MSG_LEN_MIN 0x01 +/** Maximal length of message to be signed with EdDSA */ +#define LT_L3_EDDSA_SIGN_MSG_LEN_MAX 4096 + +/** This structure declares how "EdDSA sign command" l3 packet is organized */ +struct lt_l3_eddsa_sign_cmd_t { + /** L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** ECC Key slot */ + u16 slot; + /** Padding */ + u8 padding[13]; + /** Message to sign */ + u8 msg[4096]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "EdDSA sign result" l3 packet is organized */ +struct lt_l3_eddsa_sign_res_t{ + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** Padding */ + u8 padding[15]; + /** EdDSA signature - The R part */ + u8 r[32]; + /** EdDSA signature - The S part */ + u8 s[32]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +//--------------------------------------------------------------------------------------------------------------------// +/* + +MCounter_Init + +MCounter_Update + +MCounter_Get + +*/ + +//--------------------------------------------------------------------------------------------------------------------// +/** @brief Command ID */ +#define LT_L3_SERIAL_DATA_GET_CMD 0xa0 +/** @brief Command length */ +#define LT_L3_SERIAL_DATA_GET_SIZE 0x01 + +/** This structure declares how "Serial data get command" l3 packet is organized */ +struct lt_l3_serial_data_get_cmd_t { + /**L3 packet size */ + u16 cmd_size; + /** L3 Command Identifier */ + u8 cmd_id; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +/** This structure declares how "Serial data get result" l3 packet is organized */ +struct lt_l3_serial_data_get_res_t { + /** L3 packet size */ + u16 res_size; + /** L3 Result status indication */ + u8 result; + /** Padding */ + u8 padding[3]; + /** Serial code data */ + u8 serial_code[32]; + /** L3 tag */ + u8 tag[16]; +} __attribute__((__packed__)); + +#endif diff --git a/src/lt_random.c b/src/lt_random.c new file mode 100644 index 0000000..38f3f9d --- /dev/null +++ b/src/lt_random.c @@ -0,0 +1,19 @@ +/** +* @file lt_random.c +* @brief Definitions of functions related to random number generator +* @author Tropic Square s.r.o. +*/ + +#include "libtropic_common.h" +#include "libtropic_port.h" + + +lt_ret_t lt_random_bytes(uint32_t *buff, uint16_t len) +{ +#ifdef LIBT_DEBUG + if(!buff) { + return LT_PARAM_ERR; + } +#endif + return lt_port_random_bytes(buff, len); +} diff --git a/src/lt_random.h b/src/lt_random.h new file mode 100644 index 0000000..5eaf640 --- /dev/null +++ b/src/lt_random.h @@ -0,0 +1,23 @@ + +#ifndef LT_RANDOM_H +#define LT_RANDOM_H + +/** +* @file lt_random.h +* @brief Declarations of functions related to random number generator +* @author Tropic Square s.r.o. +*/ + +#include "libtropic_common.h" + + +/** + * @brief Get random bytes in a form of 32bit numbers. This is wrapper for platform defined function. + * + * @param buff Buffer to be filled + * @param len number of 32bit numbers + * @return lt_ret_t + */ +lt_ret_t lt_random_bytes(uint32_t *buff, uint16_t len); + +#endif diff --git a/src/ts_sha256.h b/src/lt_sha256.h similarity index 61% rename from src/ts_sha256.h rename to src/lt_sha256.h index 88d9352..ea02994 100644 --- a/src/ts_sha256.h +++ b/src/lt_sha256.h @@ -1,41 +1,39 @@ -#ifndef TS_SHA256_H -#define TS_SHA256_H +#ifndef LT_SHA256_H +#define LT_SHA256_H /** -* @file ts_sha256.h -* @brief SHA256 function declarations +* @file lt_sha256.h +* @brief SHA256 functions declarations * @author Tropic Square s.r.o. */ #include #include +/** Length of sha256 digest */ #define SHA256_DIGEST_LENGTH 32 -/** - * @brief - * - */ -typedef struct ts_sha256_ctx +/** sha256 context structure */ +typedef struct lt_crypto_sha256_ctx { #ifdef USE_MBEDTLS uint32_t space[32]; -#elif USE_TS_CRYPTO +#elif USE_TREZOR_CRYPTO uint32_t space[256]; // mbedtls is ok with 32. TODO how big is Hasher struct #endif -} ts_sha256_ctx_t; +} lt_crypto_sha256_ctx_t; /** * @details This function initializes hash context * @param ctx Hash context */ -void ts_sha256_init(void* ctx); +void lt_sha256_init(void* ctx); /** * @details This function starts hash context * @param ctx */ -void ts_sha256_start(void *ctx); +void lt_sha256_start(void *ctx); /** * @details This function add data to hashing context @@ -43,13 +41,13 @@ void ts_sha256_start(void *ctx); * @param input Input data * @param len Length of input data */ -void ts_sha256_update(void *ctx, const uint8_t *input, size_t len); +void lt_sha256_update(void *ctx, const uint8_t *input, size_t len); /** * @brief This function finalizes hashing and outputs a digest * @param ctx Hash context * @param output Hash digest */ -void ts_sha256_finish(void * ctx, uint8_t *output); +void lt_sha256_finish(void * ctx, uint8_t *output); #endif diff --git a/src/ts_x25519.h b/src/lt_x25519.h similarity index 62% rename from src/ts_x25519.h rename to src/lt_x25519.h index 0f9a386..684e765 100644 --- a/src/ts_x25519.h +++ b/src/lt_x25519.h @@ -1,9 +1,9 @@ -#ifndef TS_X25519_H -#define TS_X25519_H +#ifndef LT_X25519_H +#define LT_X25519_H /** -* @file ts_x25519.h -* @brief X25519 function declarations +* @file lt_x25519.h +* @brief X25519 functiosn declarations * @author Tropic Square s.r.o. */ @@ -15,7 +15,7 @@ * @param pub Public key 32B long * @param secret Shared secret 32B long */ -void ts_X25519(const uint8_t *priv, const uint8_t *pub, uint8_t *secret); +void lt_X25519(const uint8_t *priv, const uint8_t *pub, uint8_t *secret); /** * @brief X25519 scalar multiplication with a base point @@ -23,6 +23,6 @@ void ts_X25519(const uint8_t *priv, const uint8_t *pub, uint8_t *secret); * @param sk Secret key * @param pk Public key */ -void ts_X25519_scalarmult(const uint8_t *sk, uint8_t *pk); +void lt_X25519_scalarmult(const uint8_t *sk, uint8_t *pk); #endif diff --git a/src/ts_common.c b/src/ts_common.c deleted file mode 100644 index 9b11678..0000000 --- a/src/ts_common.c +++ /dev/null @@ -1,77 +0,0 @@ -/** -* @file ts_common.c -* @brief Shared definitions and functions commonly used by more layers -* @author Tropic Square s.r.o. -*/ - -#include "ts_common.h" - -/** - * @brief Returns more verbose description of ts return value - * - * @param error ts_ret_t value - * @return const char* - */ -const char *ts_ret_verbose(ts_ret_t ret) { - switch(ret) { - // Chip MODES - case TS_L1_CHIP_ALARM_MODE: - return "TS_L1_CHIP_ALARM_MODE"; - case TS_L1_CHIP_STARTUP_MODE: - return "TS_L1_CHIP_STARTUP_MODE"; - case TS_L1_CHIP_BUSY: - return "TS_L1_CHIP_BUSY"; - - // L1 - case TS_L1_SPI_ERROR: - return "TS_L1_SPI_ERROR"; - case TS_L1_DATA_LEN_ERROR: - return "TS_L1_DATA_LEN_ERROR"; - - // L2 - case TS_L2_IN_CRC_ERR: - return "TS_L2_IN_CRC_ERR"; - case TS_L2_REQ_CONT: - return "TS_L2_REQ_CONT"; - case TS_L2_RES_CONT: - return "TS_L2_RES_CONT"; - case TS_L2_HSK_ERR: - return "TS_L2_HSK_ERR"; - case TS_L2_NO_SESSION: - return "TS_L2_NO_SESSION"; - case TS_L2_TAG_ERR: - return "TS_L2_TAG_ERR"; - case TS_L2_CRC_ERR: - return "TS_L2_CRC_ERR"; - case TS_L2_GEN_ERR: - return "TS_L2_GEN_ERR"; - case TS_L2_NO_RESP: - return "TS_L2_NO_RESP"; - case TS_L2_UNKNOWN_REQ: - return "TS_L2_UNKNOWN_REQ"; - - // L3 - case TS_L3_OK: - return "TS_L3_OK"; - case TS_L3_FAIL: - return "TS_L3_FAIL"; - case TS_L3_UNAUTHORIZED: - return "TS_L3_UNAUTHORIZED"; - case TS_L3_INVALID_CMD: - return "TS_L3_INVALID_CMD"; - - // libtropic - case TS_HOST_NO_SESSION: - return "TS_HOST_NO_SESSION"; - case TS_OK: - return "TS_OK"; - case TS_FAIL: - return "TS_FAIL"; - case TS_PARAM_ERR: - return "TS_PARAM_ERR"; - - // Default - default: - return "UNKNOWN return value"; - } -} diff --git a/src/ts_common.h b/src/ts_common.h deleted file mode 100644 index 289da8a..0000000 --- a/src/ts_common.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef TS_COMMON_H -#define TS_COMMON_H - -/** -* @file ts_common.h -* @brief Shared definitions and functions commonly used by more layers -* @author Tropic Square s.r.o. -*/ - -#include "stdint.h" -#include "ts_aesgcm.h" - -typedef uint8_t u8; -typedef uint16_t u16; - -#define UNUSED(x) (void)(x) - -#define SESSION_ON 0xAA55AA55 -#define SESSION_OFF 0x00000000 - -#define L3_ID_SIZE 1u -#define L3_TAG_SIZE 16u -#define L3_KEY_SIZE 32u -#define L3_IV_SIZE 12u - -#define L3_PACKET_SIZE_SIZE sizeof(uint16_t) -#define L3_CMD_ID_SIZE (1) -#define L3_CMD_DATA_SIZE (4095) - -/** Maximal size of data field in one L2 transfer */ -#define L2_CHUNK_MAX_DATA_SIZE 252u -#define L2_CHUNK_MAX_FRAME_SIZE (1 + 1 + L2_CHUNK_MAX_DATA_SIZE + 2) -/** Maximal number of data bytes in one L1 transfer */ -#define TS_L1_LEN_MIN 1 -/** Maximal number of data bytes in one L1 transfer */ -#define TS_L1_LEN_MAX (1 + 1 + 1 + L2_CHUNK_MAX_DATA_SIZE + 2) - -/** Maximum size of l3 ciphertext (or decrypted l3 packet) */ -#define L3_PACKET_MAX_SIZE (L3_CMD_ID_SIZE + L3_CMD_DATA_SIZE) -/** Max size of one unit of transport on l3 layer */ -#define L3_FRAME_MAX_SIZE (L3_PACKET_SIZE_SIZE + L3_PACKET_MAX_SIZE + L3_TAG_SIZE) - -/** - * @details L3 command and result packet - */ -struct __attribute__((packed)) l3_frame_t{ - uint16_t packet_size; /** RES_SIZE or CMD_SIZE value */ - uint8_t data[L3_FRAME_MAX_SIZE - L3_PACKET_SIZE_SIZE]; /** Command or result data including ID and TAG */ -}; - -/** - * @details This structure holds data related to one physical chip. - * Contains AESGCM contexts for encrypting and decrypting L3 commands, nonce and device void pointer, which can be used for passing arbitrary data. - */ -typedef struct ts_handle_t { - void *device; - uint32_t session; - uint8_t IV[12]; - ts_aes_gcm_ctx_t encrypt; - ts_aes_gcm_ctx_t decrypt; - uint8_t l2_buff [1 + L2_CHUNK_MAX_FRAME_SIZE]; - uint8_t l3_buff[L3_FRAME_MAX_SIZE]; -} ts_handle_t; - -/** - * @brief Enum return type - */ -typedef enum { - /** Operation was successful */ - TS_OK, - /** Operation was not succesfull */ - TS_FAIL, - /** Some parameter was not accepted by function */ - TS_PARAM_ERR, - - /** Spi transfer returned error */ - TS_L1_SPI_ERROR, - /** Data does not have an expected length */ - TS_L1_DATA_LEN_ERROR, - /** Chip is in STARTUP mode */ - TS_L1_CHIP_STARTUP_MODE, - /** Chip is in ALARM mode */ - TS_L1_CHIP_ALARM_MODE, - /** Chip is BUSY - typically chip is still booting */ - TS_L1_CHIP_BUSY, - - /** Return values based on STATUS field */ - /** Indicates that there are more l2 frames to be received */ - TS_L2_IN_CRC_ERR, - TS_L2_REQ_CONT, - TS_L2_RES_CONT, - TS_L2_HSK_ERR, - TS_L2_NO_SESSION, - TS_L2_TAG_ERR, - TS_L2_CRC_ERR, - TS_L2_GEN_ERR, - TS_L2_NO_RESP, - TS_L2_UNKNOWN_REQ, - /** L2 data does not have an expected length */ - TS_L2_DATA_LEN_ERROR, - - /* L3 */ - TS_L3_OK, - TS_L3_FAIL, - TS_L3_UNAUTHORIZED, - TS_L3_INVALID_CMD, - - /* Host */ - TS_HOST_NO_SESSION, -} ts_ret_t; - -/** - * @details Helper function for printing out error's associated name - * - * @param error ts_ret_t error type - * @return const char* name of error. - */ -const char *ts_ret_verbose(ts_ret_t ret); - - -#endif diff --git a/src/ts_l1.c b/src/ts_l1.c deleted file mode 100644 index a39d76b..0000000 --- a/src/ts_l1.c +++ /dev/null @@ -1,173 +0,0 @@ -/** -* @file -* @author Tropic Square s.r.o. -* @version 0.1 -* -* -* @brief DESCRIPTION -* -*/ - -#include -#include -#include - -#include "ts_common.h" -#include "ts_l1.h" - - -#if ((TS_HAL_UNIX == 0) && (TS_HAL_STM32_SPI == 0) && (TS_HAL_STM32_UART == 0) && (TEST == 0)) // && other platforms here -#pragma message("Provide own implementation for: ts_l1_init()") -#pragma message("Provide own implementation for: ts_l1_deinit()") -#pragma message("Provide own implementation for: ts_l1_spi_transfer()") -#pragma message("Provide own implementation for: ts_l1_spi_csn_low()") -#pragma message("Provide own implementation for: ts_l1_spi_csn_high()") -#pragma message("Provide own implementation for: ts_l1_delay()") - -__attribute__((weak)) ts_ret_t ts_l1_init(ts_handle_t *h) -{ - UNUSED(h); - return TS_FAIL; -} - -__attribute__((weak)) ts_ret_t ts_l1_deinit(ts_handle_t *h) -{ - UNUSED(h); - return TS_FAIL; -} - -__attribute__((weak)) ts_ret_t ts_l1_spi_transfer(ts_handle_t *h, uint8_t offset, uint16_t tx_len, uint32_t timeout) -{ - UNUSED(h); - UNUSED(offset); - UNUSED(tx_len); - UNUSED(timeout); - return TS_FAIL; -} - -__attribute__((weak)) ts_ret_t ts_l1_spi_csn_low(ts_handle_t *h) -{ - UNUSED(h); - return TS_FAIL; -} - -__attribute__((weak)) ts_ret_t ts_l1_spi_csn_high (ts_handle_t *h) -{ - UNUSED(h); - return TS_FAIL; -} -__attribute__((weak)) ts_ret_t ts_l1_delay(ts_handle_t *h, uint32_t ms) { - UNUSED(ms); - UNUSED(h); - return TS_FAIL; -} - -#endif - -ts_ret_t ts_l1_read(ts_handle_t *h, const uint32_t max_len, const uint32_t timeout) -{ - if (!h) { - return TS_PARAM_ERR; - } - if ((timeout TS_L1_TIMEOUT_MS_MAX)) { - return TS_PARAM_ERR; - } - if ((max_len < TS_L1_LEN_MIN) | (max_len > TS_L1_LEN_MAX)) { - return TS_PARAM_ERR; - } - - int max_tries = TS_L1_READ_MAX_TRIES; - - while(max_tries > 0) { - - max_tries--; - - h->l2_buff[0] = GET_INFO_REQ_ID; - - // Try to read CHIP_STATUS - ts_l1_spi_csn_low(h); - if (ts_l1_spi_transfer(h, 0, 1, timeout) != 0) - { - ts_l1_spi_csn_high(h); - return TS_L1_SPI_ERROR; - } - - // Check ALARM bit of CHIP_STATUS - if (h->l2_buff[0] & CHIP_MODE_ALARM_mask) { - ts_l1_spi_csn_high(h); - return TS_L1_CHIP_ALARM_MODE; - } - // Check STARTUP bit of CHIP_STATUS - else if (h->l2_buff[0] & CHIP_MODE_STARTUP_mask) { - ts_l1_spi_csn_high(h); - return TS_L1_CHIP_STARTUP_MODE; - } - // Check READY bit of CHIP_STATUS - else if (h->l2_buff[0] & CHIP_MODE_READY_mask) { - // receive STATUS byte and length byte - if (ts_l1_spi_transfer(h, 1, 2, timeout) != 0) //offset 1 - { - ts_l1_spi_csn_high(h); - return TS_L1_SPI_ERROR; - } - // TODO Better to read two bytes, not one. Then length. - // This function as it is now will return chip in alarm mode when - // spi wires are not connected (and therefore reading 0xff), but I want to get chip busy instead. - // Hotfix for fpga no resp handling: - if (h->l2_buff[1] == 0xff) { - ts_l1_spi_csn_high(h); - ts_l1_delay(h, TS_L1_READ_RETRY_DELAY); - continue; - } - - // Take length information and add 2B for crc bytes - uint16_t length = h->l2_buff[2] + 2; - if(length > (TS_L1_LEN_MAX - 2)) { - ts_l1_spi_csn_high(h); - return TS_L1_DATA_LEN_ERROR; - } - // Receive the rest of incomming bytes, including crc - if (ts_l1_spi_transfer(h, 3, length, timeout) != 0) // offset 3 - { - ts_l1_spi_csn_high(h); - return TS_L1_SPI_ERROR; - } - ts_l1_spi_csn_high(h); - return TS_OK; - - // Chip status does not contain any special mode bit and also is not ready, - // try it again (until max_tries runs out) - } else { - ts_l1_spi_csn_high(h); - ts_l1_delay(h, TS_L1_READ_RETRY_DELAY); - } - - } - - return TS_L1_CHIP_BUSY; -} - -ts_ret_t ts_l1_write(ts_handle_t *h, const uint16_t len, const uint32_t timeout) -{ - if (!h) { - return TS_PARAM_ERR; - } - if ((timeout TS_L1_TIMEOUT_MS_MAX)) { - return TS_PARAM_ERR; - } - if ((len < TS_L1_LEN_MIN) | (len > TS_L1_LEN_MAX)) { - return TS_PARAM_ERR; - } - - ts_l1_spi_csn_low(h); - - if (ts_l1_spi_transfer(h, 0, len, timeout) != 0) - { - ts_l1_spi_csn_high(h); - return TS_L1_SPI_ERROR; - } - - ts_l1_spi_csn_high(h); - - return TS_OK; -} diff --git a/src/ts_l1.h b/src/ts_l1.h deleted file mode 100644 index d4d1be3..0000000 --- a/src/ts_l1.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef TS_L1_H -#define TS_L1_H - -/** -* @file ts_l1.h -* @brief Layer 1 interfaces -* @author Tropic Square s.r.o. -*/ - -#include "ts_common.h" - -#define CHIP_MODE_READY_mask 0x01 -#define CHIP_MODE_ALARM_mask 0x02 -#define CHIP_MODE_STARTUP_mask 0x04 - -#define TS_L1_READ_MAX_TRIES 10 -#define TS_L1_READ_RETRY_DELAY 25 - -#define TS_L1_TIMEOUT_MS_MIN 5 -#define TS_L1_TIMEOUT_MS_DEFAULT 70 -#define TS_L1_TIMEOUT_MS_MAX 150 -#define TS_L1_DELAY_MS_MAX 500 - -#define GET_INFO_REQ_ID 0xAA - -/** - * @brief Set chip select pin low - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_spi_csn_low(ts_handle_t *h); - -/** - * @brief Set chip select pin high - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_spi_csn_high(ts_handle_t *h); - -/** - * @brief Do l1 transfer - * - * @param h Chip's handle - * @param tx_len The length of data to be transferred - * @param timeout Timeout - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_spi_transfer(ts_handle_t *h, uint8_t offset, uint16_t tx_len, uint32_t timeout); - -/** - * @brief Platform agonostic init function, configurable during build. Check libtropic's documentation for more info about platform configuration. - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_init(ts_handle_t *h); - -/** - * @brief Platform agonostic deinit function, configurable during build. Check libtropic's documentation for more info about platform configuration. - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_deinit(ts_handle_t *h); - -/** - * @brief Read data from Tropic chip into host platform - * - * @param h Chip's handle - * @param max_len Max len of receive buffer - * @param timeout Timeout - how long function will wait for response - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_read(ts_handle_t *h, const uint32_t max_len, const uint32_t timeout); - -/** - * @brief Write data from host platform into Tropic chip - * - * @param h Chip's handle - * @param len Length of data to send - * @param timeout Timeout - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_write(ts_handle_t *h, const uint16_t len, const uint32_t timeout); - -/** - * @brief Platform's definition for delay, specifies what host platform should do when libtropic's functions need some delay - * - * @param h Chip's handle - * @param ms Time to wait in miliseconds - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l1_delay(ts_handle_t *h, uint32_t ms); - -#endif diff --git a/src/ts_l2.c b/src/ts_l2.c deleted file mode 100644 index 5adaaca..0000000 --- a/src/ts_l2.c +++ /dev/null @@ -1,182 +0,0 @@ -#include - -#include "ts_common.h" -#include "ts_crc16.h" -#include "ts_l1.h" -#include "ts_l2.h" - -/** -* @file ts_l2.c -* @brief Layer 2 interfaces -* @author Tropic Square s.r.o. -*/ - -/** Safety number - limit number of loops during l3 chunks reception. TROPIC01 divides data into 128B - * chunks, length of L3 buffer is (2 + 4096 + 16). - * Divided by typical chunk length: (2 + 4096 + 16) / 128 => 32, - * with a few added loops it is set to 42 - */ -#define MAX_LOOPS 42 - -ts_ret_t ts_l2_frame_check(const uint8_t *frame) -{ - if(!frame) { - return TS_PARAM_ERR; - } - - // Take status, len and crc values from incomming frame - uint8_t status = frame[1]; - uint8_t len = frame[2]; - uint16_t frame_crc = frame[len + 4] | frame[len + 3] << 8; - - switch (status) { - - // Valid frames, or crc errors in INCOMMING frames are handled here: - case L2_STATUS_REQUEST_OK: - case L2_STATUS_RESULT_OK: - if (frame_crc != crc16(frame+1, len + 2)) { - return TS_L2_IN_CRC_ERR; - } - return TS_OK; - - // L2 statuses returned by Tropic chip are handled here - case L2_STATUS_REQUEST_CONT: - return TS_L2_REQ_CONT; - case L2_STATUS_RESULT_CONT: - return TS_L2_RES_CONT; - case L2_STATUS_HSK_ERR: - return TS_L2_HSK_ERR; - case L2_STATUS_NO_SESSION: - return TS_L2_NO_SESSION; - case L2_STATUS_TAG_ERR: - return TS_L2_TAG_ERR; - case L2_STATUS_CRC_ERR: - return TS_L2_CRC_ERR; - case L2_STATUS_GEN_ERR: - return TS_L2_GEN_ERR; - case L2_STATUS_NO_RESP: - return TS_L2_NO_RESP; - case L2_STATUS_UNKNOWN_ERR: - return TS_L2_UNKNOWN_REQ; - default: - return TS_FAIL; - } -} - -ts_ret_t ts_l2_transfer(ts_handle_t *h) -{ - if(!h) { - return TS_PARAM_ERR; - } - - add_crc(h->l2_buff); - - uint8_t len = h->l2_buff[1]; - - int ret = ts_l1_write(h, len + 4, TS_L1_TIMEOUT_MS_DEFAULT); - if(ret != TS_OK) { - return ret; - } - - ret = ts_l1_read(h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT); - if(ret != TS_OK) { - return ret; - } - - ret = ts_l2_frame_check(h->l2_buff); - if(ret != TS_OK) { - return ret; - } - - return TS_OK; -} - -ts_ret_t ts_l2_encrypted_cmd(ts_handle_t *h) -{ - int ret = TS_FAIL; - - // Setup a request pointer to l2 buffer, which is placed in handle - struct l2_encrypted_req_t *req = (struct l2_encrypted_req_t*)h->l2_buff; - // Setup a response pointer to l2 buffer, which is placed in handle - struct l2_encrypted_rsp_t *resp = (struct l2_encrypted_rsp_t*)h->l2_buff; - - // SENDING PART - - struct l3_frame_t * p_frame = (struct l3_frame_t*)h->l3_buff; - // Calculate number of chunks to send. At least one chunk needs to be sent, therefore + 1 - uint16_t chunk_num = ((L3_PACKET_SIZE_SIZE + p_frame->packet_size + L3_TAG_SIZE) / L2_CHUNK_MAX_DATA_SIZE) + 1; - // Calculate the length of the last - uint16_t chunk_last_len = ((L3_PACKET_SIZE_SIZE + p_frame->packet_size + L3_TAG_SIZE) % L2_CHUNK_MAX_DATA_SIZE); - - // Split encrypted buffer into chunks and proceed them into l2 transfers: - for (int i=0; ireq_id = L2_ENCRYPTED_CMD_REQ_ID; - // Update length based on whether actually processed chunk is the last one or not - if(i == (chunk_num - 1)) { - req->req_len = chunk_last_len; - } else { - req->req_len = L2_CHUNK_MAX_DATA_SIZE; - } - memcpy(req->body, (uint8_t*)&h->l3_buff + i*L2_CHUNK_MAX_DATA_SIZE, req->req_len); - - add_crc(req); - - // Send l2 request cointaining a chunk from l3 buff - ret = ts_l1_write(h, 2 + req->req_len + 2, TS_L1_TIMEOUT_MS_DEFAULT); - if(ret != TS_OK) { - return ret; - } - - // Read a response on this l2 request - ret = ts_l1_read(h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT); - if(ret != TS_OK) { - return ret; - } - - // Check status byte of this frame - ret = ts_l2_frame_check((uint8_t*)resp); - if(ret != TS_OK && ret != TS_L2_REQ_CONT) { - return ret; - } - } - - // RECEIVING PART - - // Position into l3 buffer where processed l2 chunk will be copied into - uint16_t offset = 0; - // Tropic can respond with various lengths of chunks, this loop should be limited - uint16_t loops = 0; - - do { - // Get one l2 frame of a chip's response - ret = ts_l1_read(h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT); - if(ret != TS_OK) { - return ret; - } - // Prevent overflow of l3 buffer - if (offset + resp->resp_len > L3_FRAME_MAX_SIZE) { - return TS_L2_DATA_LEN_ERROR; - } - - // Check status byte of this frame - ret = ts_l2_frame_check((uint8_t*)resp); - switch (ret) { - case TS_L2_RES_CONT: - // Copy content of l2 into certain offset of l3 buffer - memcpy((uint8_t*)&h->l3_buff + offset, (struct l2_encrypted_rsp_t*)resp->body, resp->resp_len); - offset += resp->resp_len; - loops++; - break; - case TS_OK: - // This was last l2 frame of l3 packet, copy it and return - memcpy((uint8_t*)&h->l3_buff + offset, (struct l2_encrypted_rsp_t*)resp->body, resp->resp_len); - return TS_OK; - default: - // Any other L2 packet's status is not expected - return ret; - } - } while (loops < MAX_LOOPS); - - return TS_FAIL; -} diff --git a/src/ts_l2.h b/src/ts_l2.h deleted file mode 100644 index a481cd9..0000000 --- a/src/ts_l2.h +++ /dev/null @@ -1,239 +0,0 @@ -#ifndef TS_L2_H -#define TS_L2_H - -/** -* @file ts_l2.h -* @brief Layer 2 interfaces -* @author Tropic Square s.r.o. -*/ - -#include "ts_common.h" - -/** Chip status READY bit mask. If CHIP_STATUS byte contains this bit, chip is ready. */ -#define CHIP_STATUS_READY 0x01 -/** Chip status ALARM bit mask. If CHIP_STATUS byte contains this bit, chip is in ALARM mode. */ -#define CHIP_STATUS_ALARM 0x02 -/** Chip status START bit mask. If CHIP_STATUS byte contains this bit, chip is in START mode. */ -#define CHIP_STATUS_START 0x04 - - -// L2 Requests -/** "Get_info" request */ -#define L2_GET_INFO_REQ_ID 0x01 -#define L2_GET_INFO_REQ_LEN 0x02 - -/** Handshake_Req request */ -#define L2_HANDSHAKE_REQ_ID 0x02 -#define L2_HANDSHAKE_REQ_LEN 0x21 - -/** Encrypted_Cmd_Req request */ -#define L2_ENCRYPTED_CMD_REQ_ID 0x04 - - - - -/** STATUS field value */ -#define L2_STATUS_REQUEST_OK 0x01 -/** STATUS field value */ -#define L2_STATUS_RESULT_OK 0x02 -/** STATUS field value */ -#define L2_STATUS_REQUEST_CONT 0x03 -/** STATUS field value */ -#define L2_STATUS_RESULT_CONT 0x04 -/** STATUS field value */ -#define L2_STATUS_HSK_ERR 0x79 -/** STATUS field value */ -#define L2_STATUS_NO_SESSION 0x7A -/** STATUS field value */ -#define L2_STATUS_TAG_ERR 0x7B -/** STATUS field value */ -#define L2_STATUS_CRC_ERR 0x7C -/** STATUS field value */ -#define L2_STATUS_UNKNOWN_ERR 0x7E -/** STATUS field value */ -#define L2_STATUS_GEN_ERR 0x7F -/** STATUS field value */ -#define L2_STATUS_NO_RESP 0xFF - - - -/** Get_Info_Req */ -#define L2_GET_INFO_REQ_OBJ_ID_X509 0x00 -#define L2_GET_INFO_REQ_OBJ_ID_CHIP_ID 0x01 -#define L2_GET_INFO_REQ_OBJ_ID_RISCV_FW_VERSION 0x02 -#define L2_GET_INFO_REQ_OBJ_ID_SPECT_FW_VERSION 0x04 -#define L2_GET_INFO_REQ_OBJ_ID_FW_BANK 0xb0 - -#define L2_GET_INFO_REQ_DATA_CHUNK_0_127 0x00 -#define L2_GET_INFO_REQ_DATA_CHUNK_128_255 0x01 -#define L2_GET_INFO_REQ_DATA_CHUNK_256_383 0x02 -#define L2_GET_INFO_REQ_DATA_CHUNK_384_511 0x03 - -#define L2_GET_INFO_REQ_LEN_MAX 128 - - -/** - * @defgroup get_info_req_group get_info - * Request to execute a Secure Channel Handshake and establish a new Secure Channel Session (TROPIC01 moves to Secure Channel Mode). - * @{ - */ - -/** - * @brief Command ID - */ -#define TS_L2_GET_INFO_REQ 0x01 - -struct l2_get_info_req_t { - /* - * Request ID byte - */ - u8 req_id; - - /* - * Length byte - */ - u8 req_len; - - /* - The Identifier of the requested object. - */ - # define TS_L2_GET_INFO_REQ_OBJECT_ID_X509_CERTIFICATE 0 // The X.509 chip certificate read from I-Memory and signed by Tropic Square (max length of 512B). - # define TS_L2_GET_INFO_REQ_OBJECT_ID_CHIP_ID 1 // The chip ID - the chip silicon revision and unique device ID (max length of 128B). - # define TS_L2_GET_INFO_REQ_OBJECT_ID_RISCV_FW_VERSION 2 // The RISCV current running FW version (4 Bytes) - # define TS_L2_GET_INFO_REQ_OBJECT_ID_SPECT_FW_VERSION 4 // The SPECT FW version (4 Bytes) - # define TS_L2_GET_INFO_REQ_OBJECT_ID_FW_BANK 176 // The FW header read from the selected bank id (shown as an index). Supported only in Start-up mode. - u8 obj_id; - - /* - The index of the 128 Byte long block to request - */ - # define TS_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_0_127 0 // Request for data bytes 0-127 of the object. - # define TS_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_128_255 1 // Request for data bytes 128-255 of the object (only needed for the X.509 certificate). - # define TS_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_256_383 2 // Request for data bytes 128-383 of object (only needed for the X.509 certificate). - # define TS_L2_GET_INFO_REQ_BLOCK_INDEX_DATA_CHUNK_384_511 3 // Request for data bytes 384-511 of object (only needed for the X.509 certificate). - u8 block_index; - - /* - * Checksum - */ - uint8_t crc[2]; -} __attribute__((__packed__)); - - -struct l2_get_info_rsp_t{ - /* - * CHIP_STATUS byte - */ - u8 chip_status; - - /* - * l2 status byte - */ - u8 status; - - /* - * Length of incomming data - */ - u8 rsp_len; - - /* - * The data content of the requested object block. - */ - u8 data[128]; - - /* - * Checksum - */ - u8 crc[2]; -} __attribute__((__packed__)); - - -/** @} */ // end of get_info_req_group - - -/** - * @brief Corresponds to $S_{H0Pub}$. - */ -# define TS_L2_HANDSHAKE_REQ_PKEY_INDEX_PAIRING_KEY_SLOT_0 0 -/** - * @brief Corresponds to $S_{H1Pub}$. - */ -# define TS_L2_HANDSHAKE_REQ_PKEY_INDEX_PAIRING_KEY_SLOT_1 1 -/** - * @brief Corresponds to $S_{H2Pub}$. - */ -# define TS_L2_HANDSHAKE_REQ_PKEY_INDEX_PAIRING_KEY_SLOT_2 2 -/** - * @brief Corresponds to $S_{H3Pub}$. - */ -# define TS_L2_HANDSHAKE_REQ_PKEY_INDEX_PAIRING_KEY_SLOT_3 3 - -/** - * @details Handshake_Req request object - */ -struct l2_handshake_req_t{ - uint8_t req_id; - uint8_t req_len; - uint8_t e_hpub[32]; - uint8_t pkey_index; - uint8_t crc[2]; -}__attribute__((packed)); - -/** - * @details Handshake_Req response object - */ -struct l2_handshake_rsp_t{ - uint8_t chip_status; - uint8_t status; - uint8_t rsp_len; - uint8_t e_tpub[32]; - uint8_t t_auth[16]; - uint8_t crc[2]; -}__attribute__((packed)); - -/** - * @details L2 data frame going from host into chip - */ -struct l2_encrypted_req_t { - uint8_t req_id; - uint8_t req_len; - uint8_t body[L2_CHUNK_MAX_DATA_SIZE]; - uint8_t crc[2]; -}__attribute__((packed)); - -/** - * @details L2 data frame going into host from chip - */ -struct l2_encrypted_rsp_t { - uint8_t chip_status; - uint8_t status; - uint8_t resp_len; - uint8_t body[L2_CHUNK_MAX_DATA_SIZE]; - uint8_t crc[2]; -}__attribute__((packed)); - -/** - * @brief This function checks if incomming L2 frame is valid - * - * @param frame - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l2_frame_check(const uint8_t *frame); - -/** - * @brief - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l2_transfer(ts_handle_t *h); - -/** - * @brief This function executes generic L3 command. It expects command's data correctly encrypted using keys created during previsously called ts_l2_handshake_req() - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l2_encrypted_cmd(ts_handle_t *h); - -#endif diff --git a/src/ts_l3.c b/src/ts_l3.c deleted file mode 100644 index a696bc5..0000000 --- a/src/ts_l3.c +++ /dev/null @@ -1,83 +0,0 @@ -/** -* @file ts_l3.c -* @brief This file contains interfaces related to layer 3. -* @author Tropic Square s.r.o. -*/ - -#include -#include -#include - -#include "ts_common.h" -#include "ts_l1.h" -#include "ts_l2.h" -#include "ts_l3.h" -#include "ts_aesgcm.h" - -ts_ret_t ts_l3_nonce_init(ts_handle_t *h) -{ - if(!h) { - return TS_PARAM_ERR; - } - - memset(&h->IV,0,12); - return TS_OK; -} - -ts_ret_t ts_l3_nonce_increase(ts_handle_t *h) -{ - if(!h) { - return TS_PARAM_ERR; - } - - uint32_t nonce = (h->IV[3] << 24) | (h->IV[2] << 16) | (h->IV[1] << 8) | (h->IV[0]); - - nonce ++; - h->IV[3] = nonce >> 24; - h->IV[2] = (nonce & 0x00FF0000) >> 16; - h->IV[1] = (nonce & 0x0000FF00) >> 8; - h->IV[0] = (nonce & 0x000000FF); - - return TS_OK; -} - -ts_ret_t ts_l3_cmd(ts_handle_t *h) -{ - if(!h) { - return TS_PARAM_ERR; - } - if(h->session != SESSION_ON) { - return TS_HOST_NO_SESSION; - } - - struct l3_frame_t * p_frame = (struct l3_frame_t*)h->l3_buff; - - int ret = ts_aesgcm_encrypt(&h->encrypt, h->IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE); - if (ret != RETURN_GOOD) { - return ret; - } - - ret = ts_l2_encrypted_cmd(h); - if (ret != TS_OK) { - return ret; - } - - ret = ts_aesgcm_decrypt(&h->decrypt, h->IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE); - if (ret != RETURN_GOOD) { - return ret; - } - - switch (p_frame->data[0]) { - case L3_RESULT_FAIL: - return TS_L3_FAIL; - case L3_RESULT_UNAUTHORIZED: - return TS_L3_UNAUTHORIZED; - case L3_RESULT_INVALID_CMD: - return TS_L3_INVALID_CMD; - case L3_RESULT_OK: - ts_l3_nonce_increase(h); - return TS_OK; - default: - return TS_FAIL; - } -} diff --git a/src/ts_l3.h b/src/ts_l3.h deleted file mode 100644 index 111ea2f..0000000 --- a/src/ts_l3.h +++ /dev/null @@ -1,555 +0,0 @@ -#ifndef TS_L3_H -#define TS_L3_H - -/** -* @file ts_l3.h -* @brief This file contains interfaces related to layer 3. -* @author Tropic Square s.r.o. -*/ - -#include "ts_common.h" -#include "ts_l2.h" - -/** L3 RESULT field Value */ -#define L3_RESULT_OK 0xC3u -/** L3 RESULT field Value */ -#define L3_RESULT_FAIL 0x3Cu -/** L3 RESULT field Value */ -#define L3_RESULT_UNAUTHORIZED 0x01u -/** L3 RESULT field Value */ -#define L3_RESULT_INVALID_CMD 0x02u - - -// L3 Commands -/** "Ping" command */ -//#define L3_PING_CMD_ID 0x01u -// len min? -#define L3_PING_MSG_MAX_LEN L3_CMD_DATA_SIZE - -/** "Random_Value_Get" command */ -//#define L3_RANDOM_VALUE_GET_CMD_ID 0x50u -#define L3_RANDOM_VALUE_GET_LEN_MIN 0x00u -#define L3_RANDOM_VALUE_GET_LEN_MAX L2_CHUNK_MAX_DATA_SIZE - -/** "ECC_Key_Generate" command */ -//#define L3_ECC_KEY_GENERATE_CMD_ID 0x60u -#define L3_ECC_KEY_GENERATE_CMD_LEN 0x04u -#define L3_ECC_KEY_GENERATE_SLOT_MIN 0x01u -#define L3_ECC_KEY_GENERATE_SLOT_MAX 0x20u -#define L3_ECC_KEY_GENERATE_CURVE_P256 0x01u -#define L3_ECC_KEY_GENERATE_CURVE_ED25519 0x02u - -/** "ECC_Key_Read" command */ -//#define L3_ECC_KEY_READ_CMD_ID 0x62u - -/** "ECDSA_Sign" command */ -#define L3_ECDSA_SIGN_CMD_ID 0x70u -#define L3_ECDSA_SIGN_CMD_LEN 0x30u -#define L3_ECDSA_SIGN_MSG_LEN 0x20u - -/** "EDDSA_Sign" command */ -//#define L3_EDDSA_SIGN_CMD_ID 0x71u -#define L3_EDDSA_SIGN_CMD_LEN 0x10u -#define L3_EDDSA_SIGN_MSG_LEN_MIN 0x01u -#define L3_EDDSA_SIGN_MSG_LEN_MAX 4096u - -/** "ECC_Key_Erase" command */ -#define L3_ECC_KEY_ERASE_CMD_ID 0x63u -#define L3_ECC_KEY_ERASE_CMD_LEN 0x03u - - -/** - * @defgroup l3_ping - * Comment: ping command - * @{ - */ - -/** - * @brief Command ID - */ -#define L3_PING_CMD_ID 0x01 - -struct ts_l3_ping_cmd_t { - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Command Identifier - */ - u8 command; - - /** - * < Data transferred from host into chip - */ - u8 data[4096]; - - /** - * < L3 tag - */ - u8 tag[16]; - -} __attribute__((__packed__)); - - -struct ts_l3_ping_res_t{ - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Result status indication - */ - u8 result; - - /** - * < Data transferred from chip into host - */ - u8 data[4096]; - - /** - * < L3 tag - */ - u8 tag[16]; -} __attribute__((__packed__)); - - -/** @} */ // end of l3_ping - - -/** - * @defgroup l3_random_value_get - * Comment: Random value get - * @{ - */ - -/** - * @brief Command ID - */ -#define TS_L3_RANDOM_VALUE_GET 0x50 - -struct ts_l3_random_value_get_cmd_t { - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Command Identifier - */ - u8 command; - - /** - * < The number of random bytes to get - */ - u8 n_bytes; - - /** - * < L3 tag - */ - u8 tag[16]; - -} __attribute__((__packed__)); - - -struct ts_l3_random_value_get_res_t{ - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Result status indication - */ - u8 result; - - /** - * < The padding by dummy data - */ - u8 padding[3]; - - /** - * < The random data from TRNG2 in the number of bytes specified in the N_BYTES L3 Field - */ - u8 random_data[255]; - - /** - * < L3 tag - */ - u8 tag[16]; -} __attribute__((__packed__)); - - -/** @} */ // end of l3_random_value_get - - - -/** - * @defgroup ecc_key_generate - * Comment: ECC key generate - * @{ - */ - -/** - * @brief Command ID - */ -#define TS_L3_ECC_KEY_GENERATE 0x60 - -struct ts_l3_ecc_key_generate_cmd_t { - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Command Identifier - */ - u8 command; - - /** - * < The slot to write the generated key. Valid values are 0 - 31 - */ - #define ECC_SLOT_1 1 - #define ECC_SLOT_2 2 - #define ECC_SLOT_3 3 - #define ECC_SLOT_4 4 - #define ECC_SLOT_5 5 - #define ECC_SLOT_6 6 - #define ECC_SLOT_7 7 - #define ECC_SLOT_8 8 - #define ECC_SLOT_9 9 - #define ECC_SLOT_10 10 - #define ECC_SLOT_11 11 - #define ECC_SLOT_12 12 - #define ECC_SLOT_13 13 - #define ECC_SLOT_14 14 - #define ECC_SLOT_15 15 - #define ECC_SLOT_16 16 - #define ECC_SLOT_17 17 - #define ECC_SLOT_18 18 - #define ECC_SLOT_19 19 - #define ECC_SLOT_20 20 - #define ECC_SLOT_21 21 - #define ECC_SLOT_22 22 - #define ECC_SLOT_23 23 - #define ECC_SLOT_24 24 - #define ECC_SLOT_25 25 - #define ECC_SLOT_26 26 - #define ECC_SLOT_27 27 - #define ECC_SLOT_28 28 - #define ECC_SLOT_29 29 - #define ECC_SLOT_30 30 - #define ECC_SLOT_31 31 - #define ECC_SLOT_32 32 - u16 slot; - - /** - * < The Elliptic Curve the key is generated from - */ - # define TS_L3_ECC_KEY_GENERATE_CURVE_P256 1 // P256 Curve - 64-byte long public key. - # define TS_L3_ECC_KEY_GENERATE_CURVE_ED25519 2 // Ed25519 Curve - 32-byte long public key. - u8 curve; - - /** - * < L3 tag - */ - u8 tag[16]; - -} __attribute__((__packed__)); - - -struct ts_l3_ecc_key_generate_res_t{ - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Result status indication - */ - u8 result; - - /** - * < L3 tag - */ - u8 tag[16]; -} __attribute__((__packed__)); - - -/** @} */ // end of ecc_key_generate - - - -/** - * @defgroup ecc_key_read - * Comment: Read ECC key - * @{ - */ - -/** - * @brief Command ID - */ -#define TS_L3_ECC_KEY_READ 0x62 - -struct ts_l3_ecc_key_read_cmd_t { - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Command Identifier - */ - u8 command; - - /** - * < ECC Key slot - */ - u16 slot; - - /** - * < L3 tag - */ - u8 tag[16]; - -} __attribute__((__packed__)); - - -struct ts_l3_ecc_key_read_res_t{ - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Result status indication - */ - u8 result; - - /** - * < Elliptic Curve - */ - # define TS_L3_ECC_KEY_READ_CURVE_P256 1 // P256 Curve - 64-byte long public key. - # define TS_L3_ECC_KEY_READ_CURVE_ED25519 2 // Ed25519 Curve - 32-byte long public key. - u8 curve; - - /** - * < The origin of the key - */ - # define TS_L3_ECC_KEY_READ_ORIGIN_ECC_KEY_GENERATE 1 // The key is from key generation on the device. - # define TS_L3_ECC_KEY_READ_ORIGIN_ECC_KEY_STORE 2 // The key is from key storage in the device. - u8 origin; - - /** - * < Padding - */ - u8 padding[13]; - - /** - * < The public key from the ECC Key slot as specified in the SLOT L3 Field - */ - u8 pub_key[64]; - - /** - * < L3 tag - */ - u8 tag[16]; -} __attribute__((__packed__)); - - -/** @} */ // end of ecc_key_read - - - -/** - * @defgroup eddsa_sign - * Comment: Sign with EDDSA key - * @{ - */ - -/** - * @brief Command ID - */ -#define TS_L3_EDDSA_SIGN 0x71 - -struct ts_l3_eddsa_sign_cmd_t { - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Command Identifier - */ - u8 command; - - /** - * < ECC Key slot - */ - u16 slot; - - /** - * < Padding - */ - u8 padding[13]; - - /** - * < Message to sign - */ - u8 msg[4096]; - - /** - * < L3 tag - */ - u8 tag[16]; - -} __attribute__((__packed__)); - - -struct ts_l3_eddsa_sign_res_t{ - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Result status indication - */ - u8 result; - - /** - * < Padding - */ - u8 padding[15]; - - /** - * < EdDSA signature - The R part - */ - u8 r[32]; - - /** - * < EdDSA signature - The S part - */ - u8 s[32]; - - /** - * < L3 tag - */ - u8 tag[16]; -} __attribute__((__packed__)); - - -/** @} */ // end of eddsa_sign - - - -/** - * @defgroup ecdsa_sign - * Comment: Sign with ECDSA key - * @{ - */ - -/** - * @brief Command ID - */ -#define TS_L3_ECDSA_SIGN 0x70 - -struct ts_l3_ecdsa_sign_cmd_t { - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Command Identifier - */ - u8 command; - - /** - * < ECC Key slot - */ - u16 slot; - - /** - * < Padding - */ - u8 padding[13]; - - /** - * < Message to sign - */ - u8 msg_hash[32]; - - /** - * < L3 tag - */ - u8 tag[16]; - -} __attribute__((__packed__)); - - -struct ts_l3_ecdsa_sign_res_t{ - /** - * < L3 packet size - */ - u16 packet_size; - - /** - * < L3 Result status indication - */ - u8 result; - - /** - * < Padding - */ - u8 padding[15]; - - /** - * < EdDSA signature - The R part - */ - u8 r[32]; - - /** - * < EdDSA signature - The S part - */ - u8 s[32]; - - /** - * < L3 tag - */ - u8 tag[16]; -} __attribute__((__packed__)); - - -/** @} */ // end of ecdsa_sign - - - - -/** - * @details Initializes nonce in handle to 0. This function is used during secure handshake. - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l3_nonce_init(ts_handle_t *h); - -/** - * @details Increases by one nonce stored in handle. This function is used after successfull reception of L3 response. - * , uint16_t cmd_len, - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l3_nonce_increase(ts_handle_t *h); - -/** - * @details Perform l3 encrypted command operation. - * - * @param h Chip's handle - * @return TS_OK if success, otherwise returns other error code. - */ -ts_ret_t ts_l3_cmd(ts_handle_t *h); - -#endif diff --git a/src/ts_random.c b/src/ts_random.c deleted file mode 100644 index d204187..0000000 --- a/src/ts_random.c +++ /dev/null @@ -1,19 +0,0 @@ -/** -* @file ts_random.c -* @brief API for providing random numbers from host platform RNG. Weak function, which is meant to be defined in platform HAL file. -* @author Tropic Square s.r.o. -*/ - -#include "stdint.h" -#include "ts_common.h" - -#if ((TS_HAL_UNIX == 0) && (TS_HAL_STM32_SPI == 0) && (TS_HAL_STM32_UART == 0) && (TEST == 0)) // && other platforms here -#pragma message("Provide own implementation for: ts_random_bytes()") - -__attribute__((weak)) ts_ret_t ts_random_bytes(uint8_t *buff, uint16_t len) { - UNUSED(buff); - UNUSED(len); - return TS_FAIL; -} - -#endif diff --git a/src/ts_random.h b/src/ts_random.h deleted file mode 100644 index 16f26ab..0000000 --- a/src/ts_random.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TS_RANDOM_H -#define TS_RANDOM_H - -/** -* @file ts_random.h -* @brief API for providing random numbers from host platform RNG -* @author Tropic Square s.r.o. -*/ - -#include "stdint.h" -#include "ts_common.h" - -/** - * @brief Get a number of random bytes from the host platform RNG - * - * @param buff Buffer to be filled with random bytes - * @param len Number of random bytes - * @return ts_ret_t TS_OK if all went OK, or other return value. - */ -ts_ret_t ts_random_bytes(uint8_t *buff, uint16_t len); - -#endif diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt new file mode 100644 index 0000000..6c37e46 --- /dev/null +++ b/tests/integration/CMakeLists.txt @@ -0,0 +1,72 @@ +cmake_minimum_required(VERSION 3.21.0) + + +########################################################################### +# # +# Paths and setup # +# # +########################################################################### + +#set(CMAKE_BUILD_TYPE Debug) + +set(PATH_TREZOR_CRYPTO "../../vendor/trezor_crypto/") +set(PATH_LIBTROPIC "../../") + +# Libtropic related setup +# Use trezor crypto as a source of backend cryptography code +set(USE_TREZOR_CRYPTO ON) + +########################################################################### +# # +# Define project's name # +# # +########################################################################### + +project(libtropic_unix_example + VERSION 0.1.0 + DESCRIPTION "Example of libtropic's usage in Unix environment" + LANGUAGES C) + + +########################################################################### +# # +# Sources # +# # +########################################################################### + +add_executable(integration_tests main.c + ${CMAKE_CURRENT_SOURCE_DIR}/${PATH_LIBTROPIC}hal/port/unix/lt_port_unix.c + ${CMAKE_CURRENT_SOURCE_DIR}/${PATH_LIBTROPIC}examples/hw_wallet/hw_wallet.c +) +target_include_directories(integration_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/${PATH_LIBTROPIC}examples/hw_wallet/) + +########################################################################### +# # +# Add executable and set definitions # +# # +########################################################################### + +if(USE_TREZOR_CRYPTO) + target_compile_definitions(integration_tests PRIVATE USE_TREZOR_CRYPTO) +endif() + + +########################################################################### +# # +# Add libtropic # +# # +########################################################################### + +# Add path to libtropic's repository root folder +add_subdirectory(${PATH_LIBTROPIC} "libtropic") + +# Customize libtropic's compilation +target_compile_options(tropic PRIVATE -Wall) +target_compile_options(tropic PRIVATE -ffunction-sections -fdata-sections) +target_compile_options(tropic PRIVATE -Wno-implicit-function-declaration) + +# Customize trezor_crypto library compilation: +target_compile_definitions(trezor_crypto PRIVATE USE_INSECURE_PRNG) + +target_link_options(integration_tests PRIVATE -Wl,--gc-sections) +target_link_libraries(integration_tests PRIVATE tropic) diff --git a/tests/integration/integration_tests.md b/tests/integration/integration_tests.md new file mode 100644 index 0000000..7a23cd0 --- /dev/null +++ b/tests/integration/integration_tests.md @@ -0,0 +1,44 @@ +# Integration tests + +This code is meant to be compiled under Unix and all tests here are running against TROPIC01's emulation model, that means no chip or external hardware is needed. + +## Model of TROPIC01 + +To start a model, follow readme in [its](https://github.com/tropicsquare/ts-tvl) repository. + +Don't forget to provide model with config file, keys and chip's certificate as is described [here](https://github.com/tropicsquare/ts-tvl?tab=readme-ov-file#configuration-file)! + + + +## Compile integration tests + +Keep the model running in its own terminal, open a new terminal and compile integration tests: + +``` +$ cd tests/integration_tests/ +$ mkdir build +$ cd build +$ cmake .. +$ make +``` + +Compilation shouldn't take long, for compiling in debug mode replace `cmake ..` with `cmake -DCMAKE_BUILD_TYPE=Debug ..` (this will allow to step through with a debugger) + + +## Run it all together + +While model is still running in first terminal, execute integration tests: + +``` +./build/integration_test +``` + +## How it works? + +Both processes will talk to each other through TCP socket 127.0.0.1:28992. + +*Note: During tests against model, SPI layer between libtropic and model is emulated through TCP connection. +Model responses are exactly the same as from physical TROPIC01 chip.* + +*Note2: Restarting the model is equivalent to plugging a fresh TROPIC01 straight out factory* + diff --git a/tests/integration/main.c b/tests/integration/main.c new file mode 100644 index 0000000..031cf64 --- /dev/null +++ b/tests/integration/main.c @@ -0,0 +1,13 @@ + + +#include +#include "string.h" + +#include "hw_wallet.h" + +// Code can be found in examples/hw/wallet/ +int main(void) +{ + int x = tropic01_hw_wallet_example(); + return x; +} \ No newline at end of file diff --git a/tests/support/support_ts_l1.h b/tests/support/support_ts_l1.h deleted file mode 100644 index 3ebd413..0000000 --- a/tests/support/support_ts_l1.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef TS_L1_H -#define TS_L1_H - -/** -* @file ts_l1.h -* @brief Testing support for l1 unit tests. Following functions will be mocked up by cmock, because normally they are platform defined. -* @author Tropic Square s.r.o. -*/ - -#include "ts_common.h" - -#define CHIP_MODE_READY_mask 0x01 -#define CHIP_MODE_ALARM_mask 0x02 -#define CHIP_MODE_STARTUP_mask 0x04 - -#define TS_L1_READ_MAX_TRIES 10 - -#define TS_L1_TIMEOUT_MS_MIN 5 -#define TS_L1_TIMEOUT_MS_DEFAULT 70 -#define TS_L1_TIMEOUT_MS_MAX 150 -#define TS_L1_DELAY_MS_MAX 500 - -// Support function definition - definition will be mocked up by cmock -ts_ret_t ts_l1_spi_csn_low(const ts_handle_t *h); - -// Support function definition - definition will be mocked up by cmock -ts_ret_t ts_l1_spi_csn_high(const ts_handle_t *h); - -// Support function definition - definition will be mocked up by cmock -ts_ret_t ts_l1_spi_transfer(ts_handle_t *h, uint8_t offset, uint16_t tx_len, uint32_t timeout); - -// Support function definition - definition will be mocked up by cmock -ts_ret_t ts_l1_init(ts_handle_t *h); - -// Support function definition - definition will be mocked up by cmock -ts_ret_t ts_l1_deinit(ts_handle_t *h); - -// Support function definition - definition will be mocked up by cmock -ts_ret_t ts_l1_delay(const ts_handle_t *h, const uint32_t ms); - -#endif diff --git a/tests/test_ts_common.c b/tests/test_ts_common.c deleted file mode 100644 index dab999a..0000000 --- a/tests/test_ts_common.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "unity.h" - -#include "ts_common.h" - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_status___correct() -{ - TEST_ASSERT_EQUAL_STRING("TS_OK", ts_ret_verbose(TS_OK)); - TEST_ASSERT_EQUAL_STRING("TS_FAIL", ts_ret_verbose(TS_FAIL)); - TEST_ASSERT_EQUAL_STRING("TS_PARAM_ERR", ts_ret_verbose(TS_PARAM_ERR)); - TEST_ASSERT_EQUAL_STRING("TS_L1_SPI_ERROR", ts_ret_verbose(TS_L1_SPI_ERROR)); - TEST_ASSERT_EQUAL_STRING("TS_L1_DATA_LEN_ERROR", ts_ret_verbose(TS_L1_DATA_LEN_ERROR)); - TEST_ASSERT_EQUAL_STRING("TS_L1_CHIP_STARTUP_MODE", ts_ret_verbose(TS_L1_CHIP_STARTUP_MODE)); - TEST_ASSERT_EQUAL_STRING("TS_L1_CHIP_ALARM_MODE", ts_ret_verbose(TS_L1_CHIP_ALARM_MODE)); - TEST_ASSERT_EQUAL_STRING("TS_L1_CHIP_BUSY", ts_ret_verbose(TS_L1_CHIP_BUSY)); - TEST_ASSERT_EQUAL_STRING("TS_L2_IN_CRC_ERR", ts_ret_verbose(TS_L2_IN_CRC_ERR)); - TEST_ASSERT_EQUAL_STRING("TS_L2_REQ_CONT", ts_ret_verbose(TS_L2_REQ_CONT)); - TEST_ASSERT_EQUAL_STRING("TS_L2_RES_CONT", ts_ret_verbose(TS_L2_RES_CONT)); - TEST_ASSERT_EQUAL_STRING("TS_L2_HSK_ERR", ts_ret_verbose(TS_L2_HSK_ERR)); - TEST_ASSERT_EQUAL_STRING("TS_L2_NO_SESSION", ts_ret_verbose(TS_L2_NO_SESSION)); - TEST_ASSERT_EQUAL_STRING("TS_L2_TAG_ERR", ts_ret_verbose(TS_L2_TAG_ERR)); - TEST_ASSERT_EQUAL_STRING("TS_L2_CRC_ERR", ts_ret_verbose(TS_L2_CRC_ERR)); - TEST_ASSERT_EQUAL_STRING("TS_L2_GEN_ERR", ts_ret_verbose(TS_L2_GEN_ERR)); - TEST_ASSERT_EQUAL_STRING("TS_L2_NO_RESP", ts_ret_verbose(TS_L2_NO_RESP)); - TEST_ASSERT_EQUAL_STRING("TS_L2_UNKNOWN_REQ", ts_ret_verbose(TS_L2_UNKNOWN_REQ)); - TEST_ASSERT_EQUAL_STRING("TS_L3_FAIL", ts_ret_verbose(TS_L3_FAIL)); - TEST_ASSERT_EQUAL_STRING("TS_L3_OK", ts_ret_verbose(TS_L3_OK)); - TEST_ASSERT_EQUAL_STRING("TS_L3_UNAUTHORIZED", ts_ret_verbose(TS_L3_UNAUTHORIZED)); - TEST_ASSERT_EQUAL_STRING("TS_L3_INVALID_CMD", ts_ret_verbose(TS_L3_INVALID_CMD)); - TEST_ASSERT_EQUAL_STRING("TS_HOST_NO_SESSION", ts_ret_verbose(TS_HOST_NO_SESSION)); - TEST_ASSERT_EQUAL_STRING("UNKNOWN return value", ts_ret_verbose(99)); -} diff --git a/tests/test_ts_l1.c b/tests/test_ts_l1.c deleted file mode 100644 index 1b9fe37..0000000 --- a/tests/test_ts_l1.c +++ /dev/null @@ -1,85 +0,0 @@ - -#include "unity.h" - -#include "ts_common.h" -#include "ts_l1.h" - -#include "mock_support_ts_l1.h" - - -#define SOME_UNUSED_DEFAULT_BYTE 0xfe - - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -//------------------------------------------------------------------------// -// Used to force l2_buff[0] to contain zeroed busy bit -static ts_ret_t callback_CHIP_BUSY(ts_handle_t* h, uint8_t offset, uint16_t tx_len, uint32_t timeout, int cmock_num_calls) { - h->l2_buff[0] = 0; - return TS_OK; -} -void test_ts_l1_read___CHIP_BUSY() -{ - ts_handle_t h = {0}; - - for(int i=0; i< TS_L1_READ_MAX_TRIES; i++) { - ts_l1_spi_csn_low_ExpectAndReturn(&h, TS_OK); - ts_l1_spi_transfer_StubWithCallback(callback_CHIP_BUSY); - ts_l1_spi_csn_high_ExpectAndReturn(&h, TS_OK); - ts_l1_delay_ExpectAndReturn(&h, TS_L1_READ_RETRY_DELAY, TS_OK); - } - TEST_ASSERT_EQUAL(TS_L1_CHIP_BUSY, ts_l1_read(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -//------------------------------------------------------------------------// -// SPI error during transfer -void test_ts_l1_read___TS_L1_SPI_ERROR() -{ - ts_handle_t h = {0}; - - ts_l1_spi_csn_low_ExpectAndReturn(&h, TS_OK); - ts_l1_spi_transfer_ExpectAndReturn(&h, 0, 1, TS_L1_TIMEOUT_MS_DEFAULT, TS_FAIL); - ts_l1_spi_csn_high_ExpectAndReturn(&h, TS_OK); - - TEST_ASSERT_EQUAL(TS_L1_SPI_ERROR, ts_l1_read(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -//------------------------------------------------------------------------// -// Used to force l2_buff[0] to contain ALARM bit -static ts_ret_t callback_TS_L1_CHIP_ALARM_MOD(ts_handle_t* h, uint8_t offset, uint16_t tx_len, uint32_t timeout, int cmock_num_calls) { - h->l2_buff[0] = CHIP_MODE_ALARM_mask; - return TS_OK; -} -void test_ts_l1_read___TS_L1_CHIP_ALARM_MODE() -{ - ts_handle_t h = {0}; - - ts_l1_spi_csn_low_ExpectAndReturn(&h, TS_OK); - ts_l1_spi_transfer_StubWithCallback(callback_TS_L1_CHIP_ALARM_MOD); - ts_l1_spi_csn_high_ExpectAndReturn(&h, TS_OK); - - TEST_ASSERT_EQUAL(TS_L1_CHIP_ALARM_MODE, ts_l1_read(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -//------------------------------------------------------------------------// -// Used to force l2_buff[0] to contain STARTUP bit -static ts_ret_t callback_TS_L1_CHIP_STARTUP_MODE(ts_handle_t* h, uint8_t offset, uint16_t tx_len, uint32_t timeout, int cmock_num_calls) { - h->l2_buff[0] = CHIP_MODE_STARTUP_mask; - return TS_OK; -} -void test_ts_l1_read___TS_L1_CHIP_STARTUP_MODE() -{ - ts_handle_t h = {0}; - - ts_l1_spi_csn_low_ExpectAndReturn(&h, TS_OK); - ts_l1_spi_transfer_StubWithCallback(callback_TS_L1_CHIP_STARTUP_MODE); - ts_l1_spi_csn_high_ExpectAndReturn(&h, TS_OK); - - TEST_ASSERT_EQUAL(TS_L1_CHIP_STARTUP_MODE, ts_l1_read(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT)); -} diff --git a/tests/test_ts_l1_input_params.c b/tests/test_ts_l1_input_params.c deleted file mode 100644 index 1743095..0000000 --- a/tests/test_ts_l1_input_params.c +++ /dev/null @@ -1,88 +0,0 @@ - -#include "unity.h" - -#include "ts_common.h" - -#include "ts_l1.h" -#include "mock_support_ts_l1.h" -#include "mock_ts_l2.h" - - -#define SOME_UNUSED_DEFAULT_BYTE 0xfe - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - - -void test_ts_l1_read___NULL_h() -{ - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_read(NULL, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -void test_ts_l1_read___invalid_max_len_smaller() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_read(&h, TS_L1_LEN_MIN-1, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -void test_ts_l1_read___invalid_max_len_bigger() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_read(&h, TS_L1_LEN_MAX+1, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -void test_ts_l1_read___invalid_timeout_smaller() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_read(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_MIN-1)); -} - -void test_ts_l1_read___invalid_timeout_bigger() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_read(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_MAX+1)); -} - -//--------------------------------------------------------------------------------------------------------------------- -void test_ts_l1_write___NULL_h() -{ - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_write(NULL, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -void test_ts_l1_write___invalid_len_smaller() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_write(&h, TS_L1_LEN_MIN-1, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -void test_ts_l1_write___invalid_len_bigger() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_write(&h, TS_L1_LEN_MAX+1, TS_L1_TIMEOUT_MS_DEFAULT)); -} - -void test_ts_l1_write___invalid_timeout_smaller() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_write(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_MIN-1)); -} - -void test_ts_l1_write___invalid_timeout_bigger() -{ - ts_handle_t h = {0}; - - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l1_write(&h, TS_L1_LEN_MAX, TS_L1_TIMEOUT_MS_MAX+1)); -} diff --git a/tests/test_ts_l2.c b/tests/test_ts_l2.c deleted file mode 100644 index 1c96971..0000000 --- a/tests/test_ts_l2.c +++ /dev/null @@ -1,139 +0,0 @@ - -#include "unity.h" - -#include "ts_common.h" -#include "ts_l2.h" - -#include "mock_ts_l1.h" -#include "mock_ts_crc16.h" - - -// Unknown byte, rubbish -#define INVALID_BYTE 0xfe - -/* -[ ] pridat popis erroru do verbose output funkce -*/ - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -static uint8_t test_data[] = {0x00, - 0x00, - 0x80, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0x2e,0x4e}; - - -// Check function's return value on correct frame -void test_ts_l2_frame_check___CHIP_STATUS_READY__TS_OK() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_RESULT_OK; - crc16_IgnoreAndReturn(0x2e4e); - TEST_ASSERT_EQUAL(TS_OK, ts_l2_frame_check(test_data)); -} - -/* Check what function returns when frame looks valid (from first two bytes), but frame's CRC check fails. -This may happen when payload is altered during transmission */ -void test_ts_l2_frame_check___CHIP_STATUS_READY__TS_CRC_ERR() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_REQUEST_OK; - crc16_IgnoreAndReturn(0xdead); - TEST_ASSERT_EQUAL(TS_L2_IN_CRC_ERR, ts_l2_frame_check(test_data)); -} - -/* Check what function returns when frame looks valid (from first two bytes), but frame's CRC check fails. -This may happen when payload is altered during transmission */ -void test_ts_l2_frame_check___CHIP_STATUS_READY__TS_CRC_ERR_2() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_RESULT_OK; - crc16_IgnoreAndReturn(0xdead); - TEST_ASSERT_EQUAL(TS_L2_IN_CRC_ERR, ts_l2_frame_check(test_data)); -} - -// Test various other return values -void test_ts_l2_frame_check___TS_L2_REQ_CONT() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_REQUEST_CONT; - TEST_ASSERT_EQUAL(TS_L2_REQ_CONT, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_RES_CONT() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_RESULT_CONT; - TEST_ASSERT_EQUAL(TS_L2_RES_CONT, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_HSK_ERR() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_HSK_ERR; - TEST_ASSERT_EQUAL(TS_L2_HSK_ERR, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_NO_SESSION() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_NO_SESSION; - TEST_ASSERT_EQUAL(TS_L2_NO_SESSION, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_TAG_ERR() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_TAG_ERR; - TEST_ASSERT_EQUAL(TS_L2_TAG_ERR, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_CRC_ERR() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_CRC_ERR; - TEST_ASSERT_EQUAL(TS_L2_CRC_ERR, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_GEN_ERR() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_GEN_ERR; - TEST_ASSERT_EQUAL(TS_L2_GEN_ERR, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_NO_RESP() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_NO_RESP; - TEST_ASSERT_EQUAL(TS_L2_NO_RESP, ts_l2_frame_check(test_data)); -} - -void test_ts_l2_frame_check___TS_L2_UNKNOWN_REQ() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = L2_STATUS_UNKNOWN_ERR; - TEST_ASSERT_EQUAL(TS_L2_UNKNOWN_REQ, ts_l2_frame_check(test_data)); -} - -// Test default behaviour when second byte is not recognized by parser -void test_ts_l2_frame_check___TS_FAIL() -{ - test_data[0] = CHIP_STATUS_READY; - test_data[1] = INVALID_BYTE; - TEST_ASSERT_EQUAL(TS_FAIL, ts_l2_frame_check(test_data)); -} diff --git a/tests/test_ts_l2_input_params.c b/tests/test_ts_l2_input_params.c deleted file mode 100644 index c284dcf..0000000 --- a/tests/test_ts_l2_input_params.c +++ /dev/null @@ -1,28 +0,0 @@ - -#include "unity.h" - -#include "ts_common.h" -#include "ts_l2.h" - -#include "mock_ts_l1.h" -#include "mock_ts_crc16.h" - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -//---------------------------------------------------------------------- -void test_ts_l2_frame_check___NULL_frame() -{ - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l2_frame_check(NULL)); -} - -//---------------------------------------------------------------------- -void test_ts_l2_transfer___NULL_h() -{ - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ts_l2_transfer(NULL)); -} diff --git a/tests/test_ts_l3.c b/tests/test_ts_l3.c deleted file mode 100644 index 246e0b5..0000000 --- a/tests/test_ts_l3.c +++ /dev/null @@ -1,127 +0,0 @@ - -#include "unity.h" -#include "string.h" - -#include "ts_common.h" -#include "ts_l3.h" - -#include "mock_ts_l2.h" -#include "mock_ts_aesgcm.h" - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_ts_l3_nonce_init___correct() -{ - ts_handle_t handle = {0}; - memset(handle.IV, 0xff, 12); - - uint8_t expected_1[12] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; - TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_1, handle.IV, 12); - - int ret = ts_l3_nonce_init(&handle); - TEST_ASSERT_EQUAL(TS_OK, ret); - - uint8_t expected_2[12] = {0}; - TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_2, handle.IV, 12); -} - -void test_ts_l3_nonce_increase___correct() -{ - ts_handle_t handle = {0}; - - for(int i=0;i<0xfffe;i++) { - int ret = ts_l3_nonce_increase(&handle); - TEST_ASSERT_EQUAL(TS_OK, ret); - } - - TEST_ASSERT_EQUAL(0xfe, handle.IV[0]); - TEST_ASSERT_EQUAL(0xff, handle.IV[1]); - // TODO test higher bytes as well, but this takes some time - //TEST_ASSERT_EQUAL(0xff, h.IV[9]); - //TEST_ASSERT_EQUAL(0xff, h.IV[8]); -} - -void test_ts_l3_cmd___fail_when_no_session() -{ - ts_handle_t handle = {0}; - - int ret = ts_l3_cmd(&handle); - TEST_ASSERT_EQUAL(TS_HOST_NO_SESSION, ret); -} - -void test_ts_l3_cmd___fail_during_ts_aesgcm_encrypt() -{ - ts_handle_t h = {0}; - h.session = SESSION_ON; - - struct l3_frame_t * p_frame = (struct l3_frame_t*)&h.l3_buff; - ts_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE,RETURN_ERROR); - - int ret = ts_l3_cmd(&h); - TEST_ASSERT_EQUAL(RETURN_ERROR, ret); -} - -void test_ts_l3_cmd___fail_during_ts_l2_encrypted_cmd() -{ - ts_handle_t h = {0}; - h.session = SESSION_ON; - - struct l3_frame_t * p_frame = (struct l3_frame_t*)&h.l3_buff; - ts_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE,RETURN_GOOD); - - ts_l2_encrypted_cmd_ExpectAndReturn(&h, TS_FAIL); - - - int ret = ts_l3_cmd(&h); - TEST_ASSERT_EQUAL(TS_FAIL, ret); -} - -void test_ts_l3_cmd___fail_during_ts_aesgcm_decrypt() -{ - ts_handle_t h = {0}; - h.session = SESSION_ON; - - struct l3_frame_t * p_frame = (struct l3_frame_t*)&h.l3_buff; - ts_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE,RETURN_GOOD); - - ts_l2_encrypted_cmd_ExpectAndReturn(&h, TS_OK); - - ts_aesgcm_decrypt_ExpectAndReturn(&h.decrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE,RETURN_ERROR); - - - int ret = ts_l3_cmd(&h); - TEST_ASSERT_EQUAL(RETURN_ERROR, ret); -} - -void test_ts_l3_cmd___test_all_l3_results() -{ - // Note: correct execution is tested at the end - uint8_t results[] = {L3_RESULT_FAIL, L3_RESULT_UNAUTHORIZED, L3_RESULT_INVALID_CMD, 0x99, L3_RESULT_OK}; - uint8_t returned[] = {TS_L3_FAIL, TS_L3_UNAUTHORIZED, TS_L3_INVALID_CMD, TS_FAIL, TS_OK}; - for (int i=0; i<5;i++) { - ts_handle_t h = {0}; - h.session = SESSION_ON; - - struct l3_frame_t * p_frame = (struct l3_frame_t*)&h.l3_buff; - ts_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE,RETURN_GOOD); - - ts_l2_encrypted_cmd_ExpectAndReturn(&h, TS_OK); - - ts_aesgcm_decrypt_ExpectAndReturn(&h.decrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->packet_size, p_frame->data + p_frame->packet_size, L3_TAG_SIZE,RETURN_GOOD); - - p_frame->data[0] = results[i]; - - if(i == 4) { - ts_l3_nonce_increase(&h); - } - - int ret = ts_l3_cmd(&h); - TEST_ASSERT_EQUAL(returned[i], ret); - } -} diff --git a/tests/test_ts_l3_input_params.c b/tests/test_ts_l3_input_params.c deleted file mode 100644 index 821f7c2..0000000 --- a/tests/test_ts_l3_input_params.c +++ /dev/null @@ -1,35 +0,0 @@ - -#include "unity.h" -#include "string.h" - -#include "ts_common.h" -#include "ts_l3.h" - -#include "mock_ts_l2.h" -#include "mock_ts_aesgcm.h" - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_ts_l3_nonce_init___NULL_h() -{ - ts_ret_t ret = ts_l3_nonce_init(NULL); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} - -void test_ts_l3_nonce_increase___NULL_h() -{ - ts_ret_t ret = ts_l3_nonce_increase(NULL); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} - -void test_ts_l3_cmd___NULL_h() -{ - int ret = ts_l3_cmd(NULL); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} diff --git a/tests/test_ts_libtropic_input_params.c b/tests/test_ts_libtropic_input_params.c deleted file mode 100644 index 4a23913..0000000 --- a/tests/test_ts_libtropic_input_params.c +++ /dev/null @@ -1,125 +0,0 @@ - -#include "unity.h" -#include "string.h" - -#include "ts_common.h" -#include "libtropic.h" - -#include "mock_ts_l1.h" -#include "mock_ts_l2.h" -#include "mock_ts_l3.h" -#include "mock_ts_random.h" -#include "mock_ts_x25519.h" -#include "mock_ts_hkdf.h" -#include "mock_ts_sha256.h" -#include "mock_ts_aesgcm.h" - - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -// ts_init() -void test_ts_init___invalid_handle() -{ - int ret = ts_init(NULL); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} - -void test_ts_init___error_during_ts_l1_init() -{ - ts_handle_t h = {0}; - - ts_l1_init_ExpectAndReturn(&h, TS_FAIL); - - ts_ret_t ret = ts_init(&h); - TEST_ASSERT_EQUAL(TS_FAIL, ret); -} - -void test_ts_init___correct() -{ - ts_handle_t h = {0}; - - ts_l1_init_ExpectAndReturn(&h, TS_OK); - - ts_ret_t ret = ts_init(&h); - TEST_ASSERT_EQUAL(TS_OK, ret); -} - -// ts_deinit() - -void test_ts_deinit___invalid_handle() -{ - int ret = ts_deinit(NULL); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} - -void test_ts_deinit___error_during_ts_l1_deinit() -{ - ts_handle_t h = {0}; - - ts_l1_deinit_ExpectAndReturn(&h, TS_FAIL); - - ts_ret_t ret = ts_deinit(&h); - TEST_ASSERT_EQUAL(TS_FAIL, ret); -} - -void test_ts_deinit___correct() -{ - ts_handle_t h = {0}; - - ts_l1_deinit_ExpectAndReturn(&h, TS_OK); - - ts_ret_t ret = ts_deinit(&h); - TEST_ASSERT_EQUAL(TS_OK, ret); -} - - -// ts_handshake() - -void test_ts_handshake___invalid_handle() -{ uint8_t pkey_index = 1; - uint8_t shipriv[] = {0x80,0x02,0xc5,0xa3,0xff,0x46,0xa2,0x09,0x4e,0x4e,0x71,0xf3,0xc8,0xe3,0xdd,0x79,0xec,0x5c,0x1c,0xcd,0xb0,0x40,0xbb,0xcf,0x6f,0x64,0x9d,0x49,0xe9,0x1d,0x9c,0x53}; - uint8_t shipub[] = {0x83,0xc3,0x36,0x3c,0xff,0x27,0x47,0xb7,0xf7,0xeb,0x19,0x85,0x17,0x63,0x1a,0x71,0x54,0x76,0xb4,0xfe,0x22,0x46,0x01,0x45,0x89,0xc3,0xac,0x11,0x8b,0xb8,0x9e,0x51}; - uint8_t stpub[] = {0}; - int ret = ts_handshake(NULL, stpub, pkey_index, shipriv, shipub); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} - -void test_ts_handshake___invalid_pkey_index() -{ - ts_handle_t handle = {0}; - uint8_t pkey_index = 5; - uint8_t shipriv[] = {0x80,0x02,0xc5,0xa3,0xff,0x46,0xa2,0x09,0x4e,0x4e,0x71,0xf3,0xc8,0xe3,0xdd,0x79,0xec,0x5c,0x1c,0xcd,0xb0,0x40,0xbb,0xcf,0x6f,0x64,0x9d,0x49,0xe9,0x1d,0x9c,0x53}; - uint8_t shipub[] = {0x83,0xc3,0x36,0x3c,0xff,0x27,0x47,0xb7,0xf7,0xeb,0x19,0x85,0x17,0x63,0x1a,0x71,0x54,0x76,0xb4,0xfe,0x22,0x46,0x01,0x45,0x89,0xc3,0xac,0x11,0x8b,0xb8,0x9e,0x51}; - uint8_t stpub[] = {0}; - - int ret = ts_handshake(&handle, stpub, pkey_index, shipriv, shipub); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} - -void test_ts_handshake___invalid_shipriv() -{ - ts_handle_t handle = {0}; - uint8_t pkey_index = 5; - uint8_t shipub[] = {0x83,0xc3,0x36,0x3c,0xff,0x27,0x47,0xb7,0xf7,0xeb,0x19,0x85,0x17,0x63,0x1a,0x71,0x54,0x76,0xb4,0xfe,0x22,0x46,0x01,0x45,0x89,0xc3,0xac,0x11,0x8b,0xb8,0x9e,0x51}; - uint8_t stpub[] = {0}; - - int ret = ts_handshake(&handle, stpub, pkey_index, NULL, shipub); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} - -void test_ts_handshake___invalid_shipub() -{ - ts_handle_t handle = {0}; - uint8_t pkey_index = 5; - uint8_t shipriv[] = {0x80,0x02,0xc5,0xa3,0xff,0x46,0xa2,0x09,0x4e,0x4e,0x71,0xf3,0xc8,0xe3,0xdd,0x79,0xec,0x5c,0x1c,0xcd,0xb0,0x40,0xbb,0xcf,0x6f,0x64,0x9d,0x49,0xe9,0x1d,0x9c,0x53}; - uint8_t stpub[] = {0}; - - int ret = ts_handshake(&handle, stpub, pkey_index, shipriv, NULL); - TEST_ASSERT_EQUAL(TS_PARAM_ERR, ret); -} diff --git a/tests/support/.gitkeep b/tests/unit/support/.gitkeep similarity index 100% rename from tests/support/.gitkeep rename to tests/unit/support/.gitkeep diff --git a/tests/unit/test_libtropic.c b/tests/unit/test_libtropic.c new file mode 100644 index 0000000..f90eafe --- /dev/null +++ b/tests/unit/test_libtropic.c @@ -0,0 +1,894 @@ + +#include "unity.h" +#include "string.h" +#include "time.h" + +#include "libtropic_common.h" +#include "libtropic.h" +#include "lt_l2_api_structs.h" +#include "lt_l3_api_structs.h" + +#include "mock_lt_random.h" +#include "mock_lt_l1_port_wrap.h" +#include "mock_lt_l1.h" +#include "mock_lt_l2.h" +#include "mock_lt_l3.h" +#include "mock_lt_x25519.h" +#include "mock_lt_ed25519.h" +#include "mock_lt_hkdf.h" +#include "mock_lt_sha256.h" +#include "mock_lt_aesgcm.h" + +void setUp(void) +{ + char buffer[100]; + #ifdef RNG_SEED + srand(RNG_SEED); + #else + time_t seed = time(NULL); + // Using this approach, because in our version of Unity there's no TEST_PRINTF yet. + // Also, raw printf is worse solution (without additional debug msgs, such as line). + snprintf(buffer, sizeof(buffer), "Using random seed: %ld\n", seed); + TEST_MESSAGE(buffer); + srand((unsigned int)seed); + #endif +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------- + +// Test if function returns LT_FAIL when l1 init failed +void test_lt_init___error_during_lt_l1_init() +{ + lt_handle_t h = {0}; + + lt_l1_init_ExpectAndReturn(&h, LT_FAIL); + + lt_ret_t ret = lt_init(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Test if function returns LT_OK when all went correctly +void test_lt_init___correct() +{ + lt_handle_t h = {0}; + + lt_l1_init_ExpectAndReturn(&h, LT_OK); + + lt_ret_t ret = lt_init(&h); + TEST_ASSERT_EQUAL(LT_OK, ret); +} + +//--------------------------------------------------------------------- + +// Test if function returns LT_FAIL when l1 deinit failed +void test_lt_deinit___error_during_lt_l1_deinit() +{ + lt_handle_t h = {0}; + + lt_l1_deinit_ExpectAndReturn(&h, LT_FAIL); + + lt_ret_t ret = lt_deinit(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Test if function returns LT_OK when all went correctly +void test_lt_deinit___correct() +{ + lt_handle_t h = {0}; + + lt_l1_deinit_ExpectAndReturn(&h, LT_OK); + + lt_ret_t ret = lt_deinit(&h); + TEST_ASSERT_EQUAL(LT_OK, ret); +} + +//--------------------------------------------------------------------- + +void test_lt_ping__no_session() +{ + lt_handle_t h = {0}; + h.session = 0; + + uint8_t msg_out = 1; + uint8_t msg_in = 0; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_ping(&h, &msg_out, &msg_in, 1)); +} + +void test_lt_ping__l3_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t msg_out, msg_in; + + lt_ret_t rets[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL}; + for (size_t i = 0; i < (sizeof(rets)/sizeof(rets[0])); i++) { + lt_l3_cmd_ExpectAndReturn(&h, rets[i]); + TEST_ASSERT_EQUAL(rets[i], lt_ping(&h, &msg_out, &msg_in, 0)); + } +} + +uint16_t lt_ping_cmd_size_inject_value; + +lt_ret_t callback_lt_ping_lt_l3_cmd(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_ping_res_t* p_l3_res = (struct lt_l3_ping_res_t*)&h->l3_buff; + p_l3_res->res_size = lt_ping_cmd_size_inject_value; + + return LT_OK; +} + +void test_lt_ping__len_mismatch() +{ + const int msg_max_size = 200; + uint8_t msg_out[msg_max_size], msg_in[msg_max_size]; + int rand_size, rand_len_offset; + + lt_handle_t h = {0}; + h.session = SESSION_ON; + + for (int i = 0; i < 25; i++) { + rand_size = rand() % msg_max_size; + rand_len_offset = rand() % (msg_max_size - rand_size); + if (rand_len_offset == 1) { + rand_len_offset++; + } + + lt_ping_cmd_size_inject_value = (uint16_t)rand_size; + + // Packet size for both cmd and res has the same position, so + // it would be overwritten by "p_l3_cmd->cmd_size = len + 1;", + // so we need to modify the value inside the callback. + lt_l3_cmd_StubWithCallback(callback_lt_ping_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_FAIL, lt_ping(&h, msg_out, msg_in, (uint16_t)(rand_size + rand_len_offset))); + } +} + +void test_lt_ping__correct() +{ + const int msg_max_size = 200; + uint8_t msg_out[200], msg_in[200]; + + lt_handle_t h = {0}; + h.session = SESSION_ON; + + // Because packet size position is shared by both cmd and res, + // it will already be set correctly by "p_l3_cmd->cmd_size = len + 1;". + lt_l3_cmd_ExpectAndReturn(&h, LT_OK); + TEST_ASSERT_EQUAL(LT_OK, lt_ping(&h, msg_out, msg_in, (uint16_t)(rand() % msg_max_size))); +} + +//--------------------------------------------------------------------- + +void test_lt_pairing_key_write__no_session() +{ + lt_handle_t h = {0}; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_pairing_key_write(&h, pubkey, slot)); +} + +void test_lt_pairing_key_write__l3_cmd_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + lt_l3_cmd_ExpectAndReturn(&h, LT_FAIL); + TEST_ASSERT_EQUAL(LT_FAIL, lt_pairing_key_write(&h, pubkey, slot)); +} + +// // // // +lt_ret_t callback_lt_pairing_key_write(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_pairing_key_write_res_t* p_l3_res = (struct lt_l3_pairing_key_write_res_t*)&h->l3_buff; + p_l3_res->res_size = 100; + + return LT_OK; +} + +void test_lt_pairing_key_write__len_mismatch() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + lt_l3_cmd_Stub(callback_lt_pairing_key_write); + + TEST_ASSERT_EQUAL(LT_FAIL, lt_pairing_key_write(&h, pubkey, slot)); +} + +lt_ret_t callback2_lt_pairing_key_write(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_pairing_key_write_res_t* p_l3_res = (struct lt_l3_pairing_key_write_res_t*)&h->l3_buff; + p_l3_res->res_size = 1; + + return LT_OK; +} + +void test_lt_pairing_key_write__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + lt_l3_cmd_Stub(callback2_lt_pairing_key_write); + + TEST_ASSERT_EQUAL(LT_OK, lt_pairing_key_write(&h, pubkey, slot)); +} + +//--------------------------------------------------------------------- + +void test_lt_pairing_key_read__no_session() +{ + lt_handle_t h = {0}; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_pairing_key_read(&h, pubkey, slot)); +} + + +void test_lt_pairing_key_read__l3_cmd_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + lt_l3_cmd_ExpectAndReturn(&h, LT_FAIL); + + TEST_ASSERT_EQUAL(LT_FAIL, lt_pairing_key_read(&h, pubkey, slot)); +} + +// // // // +lt_ret_t callback_lt_pairing_key_read(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_pairing_key_read_res_t* p_l3_res = (struct lt_l3_pairing_key_read_res_t*)&h->l3_buff; + p_l3_res->res_size = 100; + + return LT_OK; +} + +void test_lt_pairing_key_read__len_mismatch() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + lt_l3_cmd_Stub(callback_lt_pairing_key_read); + + TEST_ASSERT_EQUAL(LT_FAIL, lt_pairing_key_read(&h, pubkey, slot)); +} + +lt_ret_t callback2_lt_pairing_key_read(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_pairing_key_read_res_t* p_l3_res = (struct lt_l3_pairing_key_read_res_t*)&h->l3_buff; + p_l3_res->res_size = LT_L3_PAIRING_KEY_READ_RES_SIZE; + + return LT_OK; +} + +void test_lt_pairing_key_read__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + lt_l3_cmd_Stub(callback2_lt_pairing_key_read); + + TEST_ASSERT_EQUAL(LT_OK, lt_pairing_key_read(&h, pubkey, slot)); +} + +//--------------------------------------------------------------------- + +void test_lt_pairing_key_invalidate__no_session() +{ + lt_handle_t h = {0}; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_pairing_key_invalidate(&h, slot)); +} + +void test_lt_pairing_key_invalidate__l3_cmd_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + lt_l3_cmd_ExpectAndReturn(&h, LT_FAIL); + + TEST_ASSERT_EQUAL(LT_FAIL, lt_pairing_key_invalidate(&h, slot)); +} + + +lt_ret_t callback_lt_pairing_key_invalidate(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_pairing_key_read_res_t* p_l3_res = (struct lt_l3_pairing_key_read_res_t*)&h->l3_buff; + p_l3_res->res_size = 100; + + return LT_OK; +} + +void test_lt_pairing_key_invalidate__len_mismatch() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + lt_l3_cmd_Stub(callback_lt_pairing_key_invalidate); + + TEST_ASSERT_EQUAL(LT_FAIL, lt_pairing_key_invalidate(&h, slot)); +} + +lt_ret_t callback2_lt_pairing_key_invalidate(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_pairing_key_read_res_t* p_l3_res = (struct lt_l3_pairing_key_read_res_t*)&h->l3_buff; + p_l3_res->res_size = 1; + + return LT_OK; +} + +void test_lt_pairing_key_invalidate__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + lt_l3_cmd_Stub(callback2_lt_pairing_key_invalidate); + + TEST_ASSERT_EQUAL(LT_OK, lt_pairing_key_invalidate(&h, slot)); +} + + + + +//--------------------------------------------------------------------- +void test_lt_r_mem_data_write__no_session() +{ + lt_handle_t h = {0}; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_r_mem_data_write(&h, udata_slot, udata, size)); +} + +//--------------------------------------------------------------------- +void test_lt_r_mem_data_read__no_session() +{ + lt_handle_t h = {0}; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_r_mem_data_read(&h, udata_slot, udata, size)); +} + +//--------------------------------------------------------------------- +void test_lt_r_mem_data_erase__no_session() +{ + lt_handle_t h = {0}; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_r_mem_data_erase(&h, udata_slot)); +} + +//--------------------------------------------------------------------- + +void test_lt_random_get__no_session() +{ + uint8_t buff[200]; + lt_handle_t h = {0}; + h.session = 0; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_random_get(&h, buff, sizeof(buff))); +} + +void test_lt_random_get__l3_fail() +{ + uint8_t buff[10]; + lt_handle_t h = {0}; + h.session = SESSION_ON; + + lt_ret_t rets[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL}; + for (size_t i = 0; i < 4; i++) { + lt_l3_cmd_ExpectAndReturn(&h, rets[i]); + TEST_ASSERT_EQUAL(rets[i], lt_random_get(&h, buff, sizeof(buff))); + } +} + +uint16_t lt_random_get_cmd_size_inject_value; + +lt_ret_t callback_lt_random_get_lt_l3_cmd(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_random_value_get_res_t* p_l3_res = (struct lt_l3_random_value_get_res_t*)&h->l3_buff; + p_l3_res->res_size = lt_random_get_cmd_size_inject_value; + + return LT_OK; +} + +void test_lt_random_get__len_mismatch() +{ + const int buff_max_size = 200; + uint8_t buff[buff_max_size]; + int rand_size, rand_len_offset; + + lt_handle_t h = {0}; + h.session = SESSION_ON; + + for (int i = 0; i < 25; i++) { + rand_size = rand() % buff_max_size; + rand_len_offset = rand() % (buff_max_size - rand_size); + if (rand_len_offset == 4) { + rand_len_offset++; + } + + lt_random_get_cmd_size_inject_value = (uint16_t)rand_size; + + lt_l3_cmd_Stub(callback_lt_random_get_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_FAIL, lt_random_get(&h, buff, (uint16_t)(rand_size + rand_len_offset))); + } +} + +void test_lt_random_get__correct() +{ + const int buff_max_size = 200; + uint8_t buff[200]; + int cmd_size; + + lt_handle_t h = {0}; + h.session = SESSION_ON; + + // Making this at least 4 to not underflow in cmd_size - 4. + cmd_size = (rand() % (buff_max_size - 4)) + 4; + + // No correct value will be set for us as in ping, so injecting again... + lt_random_get_cmd_size_inject_value = (uint16_t)cmd_size; + lt_l3_cmd_Stub(callback_lt_random_get_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_OK, lt_random_get(&h, buff, (uint16_t)(cmd_size - 4))); +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_key_generate__no_session() +{ + lt_handle_t h = {0}; + h.session = 0; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_ecc_key_generate(&h, ECC_SLOT_1, CURVE_ED25519)); + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_ecc_key_generate(&h, ECC_SLOT_1, CURVE_P256)); +} + +void test_lt_ecc_key_generate__l3_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + lt_ret_t rets[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL}; + for (size_t i = 0; i < 4; i++) { + lt_l3_cmd_ExpectAndReturn(&h, rets[i]); + TEST_ASSERT_EQUAL(rets[i], lt_ecc_key_generate(&h, ECC_SLOT_1, CURVE_ED25519)); + } +} + +uint16_t lt_ecc_key_generate_cmd_size_inject_value; + +lt_ret_t callback_lt_ecc_key_generate_lt_l3_cmd(lt_handle_t *h, int __attribute__((unused)) cmock_num_calls) +{ + struct lt_l3_ecc_key_generate_res_t* p_l3_res = (struct lt_l3_ecc_key_generate_res_t*)&h->l3_buff; + p_l3_res->res_size = lt_ecc_key_generate_cmd_size_inject_value; + + return LT_OK; +} + +void test_lt_ecc_key_generate__cmd_size_mismatch() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + lt_random_get_cmd_size_inject_value = 0; + lt_l3_cmd_Stub(callback_lt_random_get_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_FAIL, lt_ecc_key_generate(&h, ECC_SLOT_1, CURVE_ED25519)); + + lt_random_get_cmd_size_inject_value = 2; + lt_l3_cmd_Stub(callback_lt_random_get_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_FAIL, lt_ecc_key_generate(&h, ECC_SLOT_1, CURVE_ED25519)); + + lt_random_get_cmd_size_inject_value = (uint16_t)((rand() % (L3_PACKET_MAX_SIZE - 2)) + 2); + lt_l3_cmd_Stub(callback_lt_random_get_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_FAIL, lt_ecc_key_generate(&h, ECC_SLOT_1, CURVE_ED25519)); +} + +void test_lt_ecc_key_generate__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + lt_random_get_cmd_size_inject_value = 1; + lt_l3_cmd_Stub(callback_lt_random_get_lt_l3_cmd); + + for (ecc_slot_t slot = ECC_SLOT_1; slot < ECC_SLOT_32; slot++) { + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_key_generate(&h, slot, CURVE_ED25519)); + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_key_generate(&h, slot, CURVE_P256)); + } +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_key_read__no_session() +{ + lt_handle_t h = {0}; + h.session = 0; + + uint8_t key[64]; + ecc_curve_type_t curve; + ecc_key_origin_t origin; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_ecc_key_read(&h, ECC_SLOT_1, key, sizeof(key), &curve, &origin)); +} + +void test_lt_ecc_key_read__l3_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t key[64] = {0}; + ecc_curve_type_t curve = 0; + ecc_key_origin_t origin = 0; + + lt_ret_t rets[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL}; + for (size_t i = 0; i < (sizeof(rets)/sizeof(rets[0])); i++) { + lt_l3_cmd_ExpectAndReturn(&h, rets[i]); + TEST_ASSERT_EQUAL(rets[i], lt_ecc_key_read(&h, ECC_SLOT_1, key, sizeof(key), &curve, &origin)); + } +} + +uint16_t lt_ecc_key_read_cmd_size_inject_value; +ecc_curve_type_t lt_ecc_key_read_curve_inject_value; + +lt_ret_t callback_lt_ecc_key_read_lt_l3_cmd(lt_handle_t *h, int cmock_num_calls) +{ + struct lt_l3_ecc_key_read_res_t* p_l3_res = (struct lt_l3_ecc_key_read_res_t*)&h->l3_buff; + + p_l3_res->res_size = lt_ecc_key_read_cmd_size_inject_value; + p_l3_res->curve = lt_ecc_key_read_curve_inject_value; + + return LT_OK; +} + +void test_lt_ecc_key_read__ed25519_size_mismatch() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t key[64] = {0}; + ecc_curve_type_t curve; + ecc_key_origin_t origin; + + lt_l3_cmd_Stub(callback_lt_ecc_key_read_lt_l3_cmd); + + for (int i = 0; i < 25; i++) { + lt_ecc_key_read_cmd_size_inject_value = (uint16_t)(rand() % L3_PACKET_MAX_SIZE); + + if (lt_ecc_key_read_cmd_size_inject_value != 48) { // skip correct value + lt_ecc_key_read_curve_inject_value = CURVE_ED25519; + TEST_ASSERT_EQUAL(LT_FAIL, lt_ecc_key_read(&h, ECC_SLOT_1, key, sizeof(key), &curve, &origin)); + } + + if (lt_ecc_key_read_cmd_size_inject_value != 80) { // skip correct value + lt_ecc_key_read_curve_inject_value = CURVE_P256; + TEST_ASSERT_EQUAL(LT_FAIL, lt_ecc_key_read(&h, ECC_SLOT_1, key, sizeof(key), &curve, &origin)); + } + } +} + +void test_lt_ecc_key_read__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t key[64] = {0}; + ecc_curve_type_t curve; + ecc_key_origin_t origin; + + lt_l3_cmd_Stub(callback_lt_ecc_key_read_lt_l3_cmd); + + lt_ecc_key_read_cmd_size_inject_value = 48; + lt_ecc_key_read_curve_inject_value = CURVE_ED25519; + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_key_read(&h, ECC_SLOT_1, key, sizeof(key), &curve, &origin)); + + lt_ecc_key_read_cmd_size_inject_value = 80; + lt_ecc_key_read_curve_inject_value = CURVE_P256; + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_key_read(&h, ECC_SLOT_1, key, sizeof(key), &curve, &origin)); +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_eddsa_sign__no_session() +{ + lt_handle_t h = {0}; + h.session = 0; + + uint8_t msg[10] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_ecc_eddsa_sign(&h, ECC_SLOT_1, msg, sizeof(msg), rs, sizeof(rs))); +} + +void test_lt_ecc_eddsa_sign__l3_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t msg[10] = {0}; + uint8_t rs[64] = {0}; + + lt_ret_t rets[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL}; + for (size_t i = 0; i < (sizeof(rets)/sizeof(rets[0])); i++) { + lt_l3_cmd_ExpectAndReturn(&h, rets[i]); + TEST_ASSERT_EQUAL(rets[i], lt_ecc_eddsa_sign(&h, ECC_SLOT_1, msg, sizeof(msg), rs, sizeof(rs))); + } +} + +lt_ret_t callback_lt_ecc_eddsa_sign_lt_l3_cmd(lt_handle_t *h, int cmock_num_calls) +{ + struct lt_l3_eddsa_sign_res_t* p_l3_res = (struct lt_l3_eddsa_sign_res_t*)&h->l3_buff; + + p_l3_res->res_size = 0x50; + + return LT_OK; +} + +void test_lt_ecc_eddsa_sign__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t msg[10] = {0}; + uint8_t rs[64] = {0}; + + lt_l3_cmd_Stub(callback_lt_ecc_eddsa_sign_lt_l3_cmd); + + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_eddsa_sign(&h, ECC_SLOT_1, msg, sizeof(msg), rs, sizeof(rs))); +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_ecdsa_sign__no_session() +{ + lt_handle_t h = {0}; + h.session = 0; + + uint8_t msg[10] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_ecc_ecdsa_sign(&h, ECC_SLOT_1, msg, sizeof(msg), rs, sizeof(rs))); +} + +void test_lt_ecc_ecdsa_sign__l3_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t msg[10] = {0}; + uint8_t rs[64] = {0}; + lt_crypto_sha256_ctx_t hctx = {0}; + uint8_t msg_hash[32] = {0}; + + lt_ret_t rets[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL}; + for (size_t i = 0; i < (sizeof(rets)/sizeof(rets[0])); i++) { + lt_sha256_init_Expect(&hctx); + lt_sha256_start_Expect(&hctx); + lt_sha256_update_Expect(&hctx, msg, sizeof(msg)); + lt_sha256_finish_Expect(&hctx, msg_hash); + lt_l3_cmd_ExpectAndReturn(&h, rets[i]); + TEST_ASSERT_EQUAL(rets[i], lt_ecc_ecdsa_sign(&h, ECC_SLOT_1, msg, sizeof(msg), rs, sizeof(rs))); + } +} + +lt_ret_t callback_lt_ecc_ecdsa_sign_lt_l3_cmd(lt_handle_t *h, int cmock_num_calls) +{ + struct lt_l3_eddsa_sign_res_t* p_l3_res = (struct lt_l3_eddsa_sign_res_t*)&h->l3_buff; + + p_l3_res->res_size = 0x50; + + return LT_OK; +} + +void test_lt_ecc_ecdsa_sign__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t msg[10] = {0}; + uint8_t rs[64] = {0}; + lt_crypto_sha256_ctx_t hctx = {0}; + uint8_t msg_hash[32] = {0}; + + lt_sha256_init_Expect(&hctx); + lt_sha256_start_Expect(&hctx); + lt_sha256_update_Expect(&hctx, msg, sizeof(msg)); + lt_sha256_finish_Expect(&hctx, msg_hash); + lt_l3_cmd_Stub(callback_lt_ecc_ecdsa_sign_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_ecdsa_sign(&h, ECC_SLOT_1, msg, sizeof(msg), rs, sizeof(rs))); +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_eddsa_sig_verify__fail() +{ + uint8_t msg[10]= {0}; + uint8_t pubkey[64]= {0}; + uint8_t rs[64] = {0}; + + lt_ed25519_sign_open_ExpectAndReturn(msg, sizeof(msg), pubkey, rs, 1); + TEST_ASSERT_EQUAL(LT_FAIL, lt_ecc_eddsa_sig_verify(msg, sizeof(msg), pubkey, rs)); +} + +void test_lt_ecc_eddsa_sig_verify__correct() +{ + uint8_t msg[10] = {0}; + uint8_t pubkey[64] = {0}; + uint8_t rs[64] = {0}; + + lt_ed25519_sign_open_ExpectAndReturn(msg, sizeof(msg), pubkey, rs, 0); + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_eddsa_sig_verify(msg, sizeof(msg), pubkey, rs)); +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_key_erase__no_session() +{ + lt_handle_t h = {0}; + h.session = 0; + + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, lt_ecc_key_erase(&h, ECC_SLOT_1)); +} + +void test_lt_ecc_key_erase__l3_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + lt_ret_t rets[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL}; + for (size_t i = 0; i < (sizeof(rets)/sizeof(rets[0])); i++) { + lt_l3_cmd_ExpectAndReturn(&h, rets[i]); + TEST_ASSERT_EQUAL(rets[i], lt_ecc_key_erase(&h, ECC_SLOT_1)); + } +} + +lt_ret_t callback_lt_ecc_key_erase_lt_l3_cmd(lt_handle_t *h, int cmock_num_calls) +{ + struct lt_l3_eddsa_sign_res_t* p_l3_res = (struct lt_l3_eddsa_sign_res_t*)&h->l3_buff; + + p_l3_res->res_size = 1; + + return LT_OK; +} + +void test_lt_ecc_key_erase__correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + lt_l3_cmd_Stub(callback_lt_ecc_key_erase_lt_l3_cmd); + TEST_ASSERT_EQUAL(LT_OK, lt_ecc_key_erase(&h, ECC_SLOT_1)); +} + +//--------------------------------------------------------------------- + +lt_ret_t callback1_lt_get_info_cert_lt_l2_transfer(lt_handle_t *h, int cmock_num_calls) +{ + struct lt_l2_get_info_rsp_t* p_l2_rsp = (struct lt_l2_get_info_rsp_t*)&h->l2_buff; + + p_l2_rsp->rsp_len = 128; + + switch(cmock_num_calls) { + case 0: + return LT_L1_SPI_ERROR; + + case 1: + return LT_OK; + case 2: + return LT_L1_SPI_ERROR; + + case 3: + return LT_OK; + case 4: + return LT_OK; + case 5: + return LT_L1_SPI_ERROR; + + case 6: + return LT_OK; + case 7: + return LT_OK; + case 8: + return LT_OK; + case 9: + return LT_L1_SPI_ERROR; + + default: + return 100; + } +} + +void test_lt_get_info_cert__l2_fail() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t cert[LT_L2_GET_INFO_REQ_CERT_SIZE]; + + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_get_info_cert(&h, cert, sizeof(cert))); + + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_get_info_cert(&h, cert, sizeof(cert))); + + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_get_info_cert(&h, cert, sizeof(cert))); + + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + lt_l2_transfer_StubWithCallback(callback1_lt_get_info_cert_lt_l2_transfer); + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_get_info_cert(&h, cert, sizeof(cert))); +} + +lt_ret_t callback2_lt_get_info_cert_lt_l2_transfer(lt_handle_t *h, int cmock_num_calls) +{ + struct lt_l2_get_info_rsp_t* p_l2_rsp = (struct lt_l2_get_info_rsp_t*)&h->l2_buff; + + p_l2_rsp->rsp_len = 128; + + switch(cmock_num_calls) { + case 0: + return LT_OK; + case 1: + return LT_OK; + case 2: + return LT_OK; + case 3: + return LT_OK; + default: + return 100; + } +} + +void test_lt_get_info_cert__l2_correct() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + uint8_t cert[LT_L2_GET_INFO_REQ_CERT_SIZE]; + + for (int i = 0; i < 4; i++) { + lt_l2_transfer_StubWithCallback(callback2_lt_get_info_cert_lt_l2_transfer); + } + TEST_ASSERT_EQUAL(LT_OK, lt_get_info_cert(&h, cert, sizeof(cert))); +} + +//--------------------------------------------------------------------- \ No newline at end of file diff --git a/tests/test_ts_crc.c b/tests/unit/test_lt_crc.c similarity index 66% rename from tests/test_ts_crc.c rename to tests/unit/test_lt_crc.c index eb38f81..0facfe8 100644 --- a/tests/test_ts_crc.c +++ b/tests/unit/test_lt_crc.c @@ -1,5 +1,5 @@ #include "unity.h" -#include "ts_crc16.h" +#include "lt_crc16.h" void setUp(void) { @@ -9,6 +9,8 @@ void tearDown(void) { } +//--------------------------------------------------------------------------------------------------------------------- +// Test if crc function calculate known crc bytes void test_crc16___correct() { uint8_t data[6] = {0x01, 0x02, 0x01, 0x01, 0, 0}; @@ -17,6 +19,7 @@ void test_crc16___correct() TEST_ASSERT_EQUAL_HEX16(0x2e12, crc); } +//--------------------------------------------------------------------------------------------------------------------- // Prepare (uint8_t*)req as this {0x01, 0x02, 0x01, 0x01, 0x00, 0x00}; // And test if function fills crc bytes instead of last two null bytes void test_add_crc___correct() diff --git a/tests/unit/test_lt_l1.c b/tests/unit/test_lt_l1.c new file mode 100644 index 0000000..13902fa --- /dev/null +++ b/tests/unit/test_lt_l1.c @@ -0,0 +1,283 @@ + +#include "unity.h" + +#include "libtropic_common.h" +#include "lt_l1.h" + +#include "mock_lt_l1_port_wrap.h" + + +#define SOME_UNUSED_DEFAULT_BYTE 0xfe + +#define L2_BUFF_WHEN_NOT_LT_L1_DATA_LEN_ERROR 0 + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +// TESTING CALLBACK: +// Used to force l2_buff[0] to contain zeroed busy bit +static lt_ret_t callback_CHIP_BUSY(lt_handle_t* h, uint8_t offset, uint16_t tx_len, uint32_t timeout, + int cmock_num_calls) { + h->l2_buff[0] = 0; + return LT_OK; +} + +// Test if lt_l1_read() function returns LT_L1_CHIP_BUSY when transferred chip status byte has READY bit == 0 +void test_lt_l1_read___CHIP_BUSY() +{ + lt_handle_t h = {0}; + + for(int i=0; i< LT_L1_READ_MAX_TRIES; i++) { + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_CHIP_BUSY); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + lt_l1_delay_ExpectAndReturn(&h, LT_L1_READ_RETRY_DELAY, LT_OK); + } + TEST_ASSERT_EQUAL(LT_L1_CHIP_BUSY, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test if lt_l1_read() function returns LT_L1_SPI_ERROR if spi transfer returns LT_FAIL +void test_lt_l1_read___LT_L1_SPI_ERROR() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_ExpectAndReturn(&h, 0, 1, LT_L1_TIMEOUT_MS_DEFAULT, LT_FAIL); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// TESTING CALLBACK: +// Used to force l2_buff[0] to contain ALARM bit +static lt_ret_t callback_LT_L1_CHIP_ALARM_MOD(lt_handle_t* h, uint8_t offset, uint16_t tx_len, + uint32_t timeout, int cmock_num_calls) { + h->l2_buff[0] = CHIP_MODE_ALARM_bit; + return LT_OK; +} + +// Test if function returns LT_L1_CHIP_ALARM_MODE when transferred chip status byte has ALARM bit == 1 +void test_lt_l1_read___LT_L1_CHIP_ALARM_MODE() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_LT_L1_CHIP_ALARM_MOD); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_L1_CHIP_ALARM_MODE, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// TESTING CALLBACK: +// Used to force l2_buff[0] to contain STARTUP bit +static lt_ret_t callback_LT_L1_CHIP_STARTUP_MODE(lt_handle_t* h, uint8_t offset, uint16_t tx_len, + uint32_t timeout, int cmock_num_calls) { + h->l2_buff[0] = CHIP_MODE_STARTUP_bit; + return LT_OK; +} + +// Test if function returns LT_L1_CHIP_STARTUP_MODE when transferred chip status byte has STARTUP bit == 1 +void test_lt_l1_read___LT_L1_CHIP_STARTUP_MODE() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_LT_L1_CHIP_STARTUP_MODE); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_L1_CHIP_STARTUP_MODE, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// TESTING CALLBACK: +// Used to force transfer function to return LT_FAIL during second transfer +static lt_ret_t callback_CHIP_MODE_READY_bit(lt_handle_t* h, uint8_t offset, uint16_t tx_len, + uint32_t timeout, int cmock_num_calls) +{ + if(cmock_num_calls == 0) { + h->l2_buff[0] = CHIP_MODE_READY_bit; + return LT_OK; + } + if(cmock_num_calls == 1) { + return LT_FAIL; + } + + // Just in case, return some invalid number: + return 0xfefe; +} + +// Test if function returns LT_L1_SPI_ERROR if chip is in ready mode and lt_l1_spi_transfer() fails +void test_lt_l1_read___CHIP_MODE_READY_LT_L1_SPI_ERROR() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_CHIP_MODE_READY_bit); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// TESTING CALLBACK: +// Used to force values into response buffer, so fpga looks busy and resp handling is always called +static lt_ret_t callback_CHIP_MODE_READY_fpga_no_resp(lt_handle_t* h, uint8_t offset, uint16_t tx_len, + uint32_t timeout, int cmock_num_calls) +{ + if(cmock_num_calls % 2 == 0) { + h->l2_buff[0] = CHIP_MODE_READY_bit; + return LT_OK; + } + if(cmock_num_calls % 2 == 1) { + h->l2_buff[1] = 0xff; + return LT_OK; + } + + // Just in case, return some invalid number: + return 0xfefe; +} + +// Test if function returns LT_L1_CHIP_BUSY when chip status is ready and lt_handle_t.l2_buff[1] == 0xff +void test_lt_l1_read___CHIP_MODE_READY_fpga_no_resp() +{ + lt_handle_t h = {0}; + + for(int i=0; i< LT_L1_READ_MAX_TRIES; i++) { + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_CHIP_MODE_READY_fpga_no_resp); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + lt_l1_delay_ExpectAndReturn(&h, LT_L1_READ_RETRY_DELAY, LT_OK); + } + TEST_ASSERT_EQUAL(LT_L1_CHIP_BUSY, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// TESTING CALLBACK: +// Used to force values into buffer so LT_L1_LEN_MAX is returned +static lt_ret_t callback_CHIP_MODE_READY_LT_L1_DATA_LEN_ERROR(lt_handle_t* h, uint8_t offset, + uint16_t tx_len, uint32_t timeout, + int cmock_num_calls) +{ + if(cmock_num_calls == 0) { + h->l2_buff[0] = CHIP_MODE_READY_bit; + return LT_OK; + } + if(cmock_num_calls == 1) { + h->l2_buff[1] = 0; + h->l2_buff[2] = LT_L1_LEN_MAX - 2; + return LT_OK; + } + + // Just in case, return some invalid number: + return 0xfefe; +} + +// Test if function returns LT_L1_DATA_LEN_ERROR if chip is in ready mode but tries to send longer l2 data frame +void test_lt_l1_read___CHIP_MODE_READY_LT_L1_DATA_LEN_ERROR() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_CHIP_MODE_READY_LT_L1_DATA_LEN_ERROR); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_L1_DATA_LEN_ERROR, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// TESTING CALLBACK: +// Used to force values so second LT_L1_SPI_ERROR is returned +static lt_ret_t callback_CHIP_MODE_READY_LT_L1_SPI_ERROR_2(lt_handle_t* h, uint8_t offset, uint16_t tx_len, + uint32_t timeout, int cmock_num_calls) +{ + if(cmock_num_calls == 0) { + h->l2_buff[0] = CHIP_MODE_READY_bit; + return LT_OK; + } + if(cmock_num_calls == 1) { + h->l2_buff[1] = 0; + h->l2_buff[2] = L2_BUFF_WHEN_NOT_LT_L1_DATA_LEN_ERROR; + return LT_OK; + } + if(cmock_num_calls == 2) { + return LT_FAIL; + } + + // Just in case, return some invalid number: + return 0xfefe; +} + +// Test if function returns LT_L1_SPI_ERROR when reception of the rest of incoming bytes fails +void test_lt_l1_read___CHIP_MODE_READY_LT_L1_SPI_ERROR_2() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_CHIP_MODE_READY_LT_L1_SPI_ERROR_2); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// TESTING CALLBACK: +// Used to force values so LT_OK is returned +static lt_ret_t callback_CHIP_MODE_READY_LT_OK(lt_handle_t* h, uint8_t offset, uint16_t tx_len, + uint32_t timeout, int cmock_num_calls) +{ + if(cmock_num_calls == 0) { + h->l2_buff[0] = CHIP_MODE_READY_bit; + return LT_OK; + } + if(cmock_num_calls == 1) { + h->l2_buff[1] = 0; + h->l2_buff[2] = L2_BUFF_WHEN_NOT_LT_L1_DATA_LEN_ERROR; + return LT_OK; + } + if(cmock_num_calls == 2) { + return LT_OK; + } + + // Just in case, return some invalid number: + return 0xfefe; +} + +// Test if function returns LT_OK when execution is correct +void test_lt_l1_read___CHIP_MODE_READY_LT_OK() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_StubWithCallback(callback_CHIP_MODE_READY_LT_OK); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_OK, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test LT_L1_SPI_ERROR return value during write +void test_lt_l1_write___LT_L1_SPI_ERROR() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_ExpectAndReturn(&h, 0, 1, LT_L1_TIMEOUT_MS_DEFAULT, LT_FAIL); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l1_write(&h, 1, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test LT_OK return value +void test_lt_l1_write___LT_OK() +{ + lt_handle_t h = {0}; + + lt_l1_spi_csn_low_ExpectAndReturn(&h, LT_OK); + lt_l1_spi_transfer_ExpectAndReturn(&h, 0, 1, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + TEST_ASSERT_EQUAL(LT_OK, lt_l1_write(&h, 1, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +//--------------------------------------------------------------------------------------------------------------------- diff --git a/tests/unit/test_lt_l1_input_params.c b/tests/unit/test_lt_l1_input_params.c new file mode 100644 index 0000000..9ba18f1 --- /dev/null +++ b/tests/unit/test_lt_l1_input_params.c @@ -0,0 +1,97 @@ + +#include "unity.h" + +#include "libtropic_common.h" + +#include "lt_l1.h" +#include "mock_lt_l1_port_wrap.h" + + +#define SOME_UNUSED_DEFAULT_BYTE 0xfe + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_read___NULL_h() +{ + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_read(NULL, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_read___invalid_max_len_smaller() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_read(&h, LT_L1_LEN_MIN-1, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_read___invalid_max_len_bigger() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_read(&h, LT_L1_LEN_MAX+1, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_read___invalid_timeout_smaller() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_MIN-1)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_read___invalid_timeout_bigger() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_read(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_MAX+1)); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_write___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_write(NULL, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_write___invalid_len_smaller() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_write(&h, LT_L1_LEN_MIN-1, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_write___invalid_len_bigger() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_write(&h, LT_L1_LEN_MAX+1, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_write___invalid_timeout_smaller() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_write(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_MIN-1)); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_write___invalid_timeout_bigger() +{ + lt_handle_t h = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_write(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_MAX+1)); +} diff --git a/tests/unit/test_lt_l1_port_wrap.c b/tests/unit/test_lt_l1_port_wrap.c new file mode 100644 index 0000000..f171e5e --- /dev/null +++ b/tests/unit/test_lt_l1_port_wrap.c @@ -0,0 +1,155 @@ +#include "unity.h" + +#include "libtropic_common.h" +#include "lt_l1_port_wrap.h" +#include "lt_l1.h" + +#include "mock_libtropic_port.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +// Check that function lt_l1_init() returns LT_FAIL when lt_port_init() function returns LT_FAIL +void test_lt_l1_init___lt_port_init__LT_FAIL() +{ + lt_handle_t h = {0}; + + lt_port_init_ExpectAndReturn(&h, LT_FAIL); + + lt_ret_t ret = lt_l1_init(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Check that function lt_l1_init() returns LT_OK when lt_port_init() function returns LT_OK +void test_lt_l1_init____lt_port_init__LT_OK() +{ + lt_handle_t h = {0}; + + lt_port_init_ExpectAndReturn(&h, LT_OK); + + lt_ret_t ret = lt_l1_init(&h); + TEST_ASSERT_EQUAL(LT_OK, ret); +} + +// Check that function lt_l1_deinit() returns LT_FAIL when lt_port_deinit() function returns LT_FAIL +void test_lt_l1_deinit___lt_port_deinit__LT_FAIL() +{ + lt_handle_t h = {0}; + + lt_port_deinit_ExpectAndReturn(&h, LT_FAIL); + + lt_ret_t ret = lt_l1_deinit(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +void test_lt_l1_deinit___lt_port_deinit__LT_OK() +{ + lt_handle_t h = {0}; + + lt_port_deinit_ExpectAndReturn(&h, LT_OK); + + lt_ret_t ret = lt_l1_deinit(&h); + TEST_ASSERT_EQUAL(LT_OK, ret); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Check that function lt_l1_spi_csn_low() returns LT_FAIL when lt_port_spi_csn_low() function returns LT_FAIL +void test_lt_l1_spi_csn_low___lt_port_spi_csn_low__LT_FAIL() +{ + lt_handle_t h = {0}; + + lt_port_spi_csn_low_ExpectAndReturn(&h, LT_FAIL); + + lt_ret_t ret = lt_l1_spi_csn_low(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Check that function lt_l1_spi_csn_low() returns LT_OK when lt_port_spi_csn_low() function returns LT_OK +void test_lt_l1_spi_csn_low___lt_port_spi_csn_low__LT_OK() +{ + lt_handle_t h = {0}; + + lt_port_spi_csn_low_ExpectAndReturn(&h, LT_OK); + + lt_ret_t ret = lt_l1_spi_csn_low(&h); + TEST_ASSERT_EQUAL(LT_OK, ret); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Check that function lt_l1_spi_csn_high() returns LT_FAIL when lt_port_spi_csn_high() function returns LT_FAIL +void test_lt_l1_spi_csn_high___lt_port_spi_csn_high__LT_FAIL() +{ + lt_handle_t h = {0}; + + lt_port_spi_csn_high_ExpectAndReturn(&h, LT_FAIL); + + lt_ret_t ret = lt_l1_spi_csn_high(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Check that function lt_l1_spi_csn_high() returns LT_OK when lt_port_spi_csn_high() function returns LT_OK +void test_lt_l1_spi_csn_high___lt_port_spi_csn_high__LT_OK() +{ + lt_handle_t h = {0}; + + lt_port_spi_csn_high_ExpectAndReturn(&h, LT_OK); + + lt_ret_t ret = lt_l1_spi_csn_high(&h); + TEST_ASSERT_EQUAL(LT_OK, ret); +} + + + + + +//--------------------------------------------------------------------------------------------------------------------- +// Check that function lt_l1_spi_transfer() returns LT_L1_DATA_LEN_ERROR when lt_port_spi_transfer() function returns LT_L1_DATA_LEN_ERROR +void test_lt_l1_spi_transfer___lt_port_spi_transfer__LT_L1_DATA_LEN_ERROR() +{ + lt_handle_t h = {0}; + + lt_port_spi_transfer_ExpectAndReturn(&h, 1, 1, LT_L1_TIMEOUT_MS_DEFAULT, LT_L1_DATA_LEN_ERROR); + + lt_ret_t ret = lt_l1_spi_transfer(&h, 1, 1, LT_L1_TIMEOUT_MS_DEFAULT); + TEST_ASSERT_EQUAL(LT_L1_DATA_LEN_ERROR, ret); +} + +// Check that function lt_l1_spi_transfer() returns LT_FAIL when lt_port_spi_transfer() function returns LT_FAIL +void test_lt_l1_spi_transfer___lt_port_spi_transfer__LT_FAIL() +{ + lt_handle_t h = {0}; + + lt_port_spi_transfer_ExpectAndReturn(&h, 1, 1, LT_L1_TIMEOUT_MS_DEFAULT, LT_FAIL); + + lt_ret_t ret = lt_l1_spi_transfer(&h, 1, 1, LT_L1_TIMEOUT_MS_DEFAULT); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Check that function lt_l1_spi_transfer() returns LT_OK when lt_port_spi_transfer() function returns LT_OK +void test_lt_l1_spi_transfer___lt_port_spi_transfer__LT_OK() +{ + lt_handle_t h = {0}; + + lt_port_spi_transfer_ExpectAndReturn(&h, 1, 1, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + + lt_ret_t ret = lt_l1_spi_transfer(&h, 1, 1, LT_L1_TIMEOUT_MS_DEFAULT); + TEST_ASSERT_EQUAL(LT_OK, ret); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Check that function lt_l1_delay() returns LT_OK when lt_port_delay() function returns LT_OK +void test_lt_l1_delay___lt_port_delay__LT_OK() +{ + lt_handle_t h = {0}; + + lt_port_delay_ExpectAndReturn(&h, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + + lt_ret_t ret = lt_l1_delay(&h, LT_L1_TIMEOUT_MS_DEFAULT); + TEST_ASSERT_EQUAL(LT_OK, ret); +} \ No newline at end of file diff --git a/tests/unit/test_lt_l1_port_wrap_input_parameters.c b/tests/unit/test_lt_l1_port_wrap_input_parameters.c new file mode 100644 index 0000000..3e29c82 --- /dev/null +++ b/tests/unit/test_lt_l1_port_wrap_input_parameters.c @@ -0,0 +1,57 @@ +#include "unity.h" + +#include "libtropic_common.h" +#include "lt_l1_port_wrap.h" +#include "lt_l1.h" + +#include "mock_libtropic_port.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_init___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_init(NULL)); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_deinit___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_deinit(NULL)); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_spi_csn_low___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_spi_csn_low(NULL)); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_spi_csn_high___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_spi_csn_high(NULL)); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_spi_transfer___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_spi_transfer(NULL, 1, 1, LT_L1_TIMEOUT_MS_DEFAULT)); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l1_delay___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l1_delay(NULL, LT_L1_TIMEOUT_MS_DEFAULT)); +} \ No newline at end of file diff --git a/tests/unit/test_lt_l2.c b/tests/unit/test_lt_l2.c new file mode 100644 index 0000000..e871221 --- /dev/null +++ b/tests/unit/test_lt_l2.c @@ -0,0 +1,213 @@ + +#include "unity.h" + +#include "libtropic_common.h" +#include "lt_l2.h" +#include "lt_l2_api_structs.h" + +#include "mock_lt_l1.h" +#include "mock_lt_l2_frame_check.h" +#include "mock_lt_crc16.h" + + +/* +[ ] pridat popis erroru do verbose output funkce +*/ + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_lt_l2_transfer__fail_during_l1_write() +{ + lt_handle_t h = {0}; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_L1_SPI_ERROR); + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l2_transfer(&h)); +} + +void test_lt_l2_transfer__fail_during_l1_read() +{ + lt_handle_t h = {0}; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_L1_SPI_ERROR); + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l2_transfer(&h)); +} + +void test_lt_l2_transfer__fail_during_frame_check() +{ + lt_handle_t h = {0}; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_L2_IN_CRC_ERR); + + TEST_ASSERT_EQUAL(LT_L2_IN_CRC_ERR, lt_l2_transfer(&h)); +} + +void test_lt_l2_transfer__correct() +{ + lt_handle_t h = {0}; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_OK); + + TEST_ASSERT_EQUAL(LT_OK, lt_l2_transfer(&h)); +} + +//-------------------------------------------------------------------------------------------------- + +void test_lt_l2_encrypted_cmd__l1_write_fail() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_L1_SPI_ERROR); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l2_encrypted_cmd(&h)); +} + +void test_lt_l2_encrypted_cmd__l1_read_fail() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_L1_SPI_ERROR); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l2_encrypted_cmd(&h)); +} + +void test_lt_l2_encrypted_cmd__frame_check_fail() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_L2_IN_CRC_ERR); + + TEST_ASSERT_EQUAL(LT_L2_IN_CRC_ERR, lt_l2_encrypted_cmd(&h)); +} + +// Test two chunk long packet, throw an error on the second chunk. +void test_lt_l2_encrypted_cmd__multiple_chunks() +{ + lt_handle_t h = {0}; + + struct lt_l3_gen_frame_t * p_frame = (struct lt_l3_gen_frame_t*)h.l3_buff; + p_frame->cmd_size = L2_CHUNK_MAX_DATA_SIZE * 2; + + add_crc_Ignore(); + lt_l1_write_ExpectAndReturn(&h, L2_CHUNK_MAX_DATA_SIZE + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_L2_REQ_CONT); + + lt_l1_write_ExpectAndReturn(&h, L2_CHUNK_MAX_DATA_SIZE + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_L1_SPI_ERROR); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l2_encrypted_cmd(&h)); +} + +void test_lt_l2_encrypted_cmd__recv_lt_l1_read_fail() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_L1_SPI_ERROR); + + TEST_ASSERT_EQUAL(LT_L1_SPI_ERROR, lt_l2_encrypted_cmd(&h)); +} + +lt_ret_t test_lt_l2_encrypted_cmd__overflow_callback(const uint8_t *frame, int cmock_num_calls) +{ + if (cmock_num_calls > 0) { + struct lt_l2_encrypted_cmd_rsp_t* resp = (struct lt_l2_encrypted_cmd_rsp_t*) frame; + resp->rsp_len = 255; + return LT_L2_RES_CONT; + } else { + return LT_OK; + } + +} + +// This is kinda tricky. resp->rsp_len is unsigned 8bit int => max value cannot be larger +// than L3_FRAME_MAX_SIZE, so overflow cannot be triggered by a callback. So, we need to +// trigger this by making offset larger. +void test_lt_l2_encrypted_cmd__recv_overflow() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_Stub(test_lt_l2_encrypted_cmd__overflow_callback); + lt_l1_read_IgnoreAndReturn(LT_OK); + + TEST_ASSERT_EQUAL(LT_L3_DATA_LEN_ERROR, lt_l2_encrypted_cmd(&h)); +} + +void test_lt_l2_encrypted_cmd__recv_last_frame() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_OK); + + TEST_ASSERT_EQUAL(LT_OK, lt_l2_encrypted_cmd(&h)); +} + +void test_lt_l2_encrypted_cmd__recv_frame_err() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_L2_IN_CRC_ERR); + + TEST_ASSERT_EQUAL(LT_L2_IN_CRC_ERR, lt_l2_encrypted_cmd(&h)); +} + +void test_lt_l2_encrypted_cmd__loop_overflow() +{ + lt_handle_t h = {0}; + int chunk_len = L3_RES_SIZE_SIZE + L3_TAG_SIZE; + + add_crc_Expect(h.l2_buff); + lt_l1_write_ExpectAndReturn(&h, chunk_len + 4, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_OK); + + for (int i = 0; i < 42; i++) { + lt_l1_read_ExpectAndReturn(&h, LT_L1_LEN_MAX, LT_L1_TIMEOUT_MS_DEFAULT, LT_OK); + lt_l2_frame_check_ExpectAndReturn(h.l2_buff, LT_L2_RES_CONT); + } + + TEST_ASSERT_EQUAL(LT_FAIL, lt_l2_encrypted_cmd(&h)); +} diff --git a/tests/unit/test_lt_l2_frame_check.c b/tests/unit/test_lt_l2_frame_check.c new file mode 100644 index 0000000..d62b426 --- /dev/null +++ b/tests/unit/test_lt_l2_frame_check.c @@ -0,0 +1,129 @@ + +#include "unity.h" + +#include "libtropic_common.h" +#include "lt_l2_frame_check.h" + +#include "mock_lt_l1.h" +#include "mock_lt_crc16.h" + + +// Unknown byte, rubbish +#define INVALID_BYTE 0xfe + +/* +[ ] pridat popis erroru do verbose output funkce +*/ + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +static uint8_t test_data[] = {0x00, + 0x00, + 0x80, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x2e,0x4e}; + + +// Check function's return value on correct frame +void test_lt_l2_frame_check___CHIP_STATUS_READY__LT_OK() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_RESULT_OK; + crc16_IgnoreAndReturn(0x2e4e); + TEST_ASSERT_EQUAL(LT_OK, lt_l2_frame_check(test_data)); +} + +/* Check what function returns when frame looks valid (from first two bytes), but frame's CRC check fails. +This may happen when payload is altered during transmission */ +void test_lt_l2_frame_check___CHIP_STATUS_READY__LT_CRC_ERR() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_REQUEST_OK; + crc16_IgnoreAndReturn(0xdead); + TEST_ASSERT_EQUAL(LT_L2_IN_CRC_ERR, lt_l2_frame_check(test_data)); +} + +// Test various other return values +void test_lt_l2_frame_check___LT_L2_REQ_CONT() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_REQUEST_CONT; + TEST_ASSERT_EQUAL(LT_L2_REQ_CONT, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_RES_CONT() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_RESULT_CONT; + TEST_ASSERT_EQUAL(LT_L2_RES_CONT, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_HSK_ERR() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_HSK_ERR; + TEST_ASSERT_EQUAL(LT_L2_HSK_ERR, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_NO_SESSION() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_NO_SESSION; + TEST_ASSERT_EQUAL(LT_L2_NO_SESSION, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_TAG_ERR() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_TAG_ERR; + TEST_ASSERT_EQUAL(LT_L2_TAG_ERR, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_CRC_ERR() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_CRC_ERR; + TEST_ASSERT_EQUAL(LT_L2_CRC_ERR, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_GEN_ERR() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_GEN_ERR; + TEST_ASSERT_EQUAL(LT_L2_GEN_ERR, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_NO_RESP() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_NO_RESP; + TEST_ASSERT_EQUAL(LT_L2_NO_RESP, lt_l2_frame_check(test_data)); +} + +void test_lt_l2_frame_check___LT_L2_UNKNOWN_REQ() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = L2_STATUS_UNKNOWN_ERR; + TEST_ASSERT_EQUAL(LT_L2_UNKNOWN_REQ, lt_l2_frame_check(test_data)); +} + +// Test default behaviour when second byte is not recognized by parser +void test_lt_l2_frame_check___LT_FAIL() +{ + test_data[0] = CHIP_MODE_READY_bit; + test_data[1] = INVALID_BYTE; + TEST_ASSERT_EQUAL(LT_L2_STATUS_NOT_RECOGNIZED, lt_l2_frame_check(test_data)); +} diff --git a/tests/unit/test_lt_l2_frame_check_input_params.c b/tests/unit/test_lt_l2_frame_check_input_params.c new file mode 100644 index 0000000..92ede46 --- /dev/null +++ b/tests/unit/test_lt_l2_frame_check_input_params.c @@ -0,0 +1,21 @@ + +#include "unity.h" + +#include "libtropic_common.h" +#include "lt_crc16.h" +#include "lt_l2_frame_check.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +//---------------------------------------------------------------------- +// Test if function returns expected error on non valid input parameter +void test_lt_l2_frame_check___NULL_frame() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l2_frame_check(NULL)); +} \ No newline at end of file diff --git a/tests/unit/test_lt_l2_input_params.c b/tests/unit/test_lt_l2_input_params.c new file mode 100644 index 0000000..76d50ac --- /dev/null +++ b/tests/unit/test_lt_l2_input_params.c @@ -0,0 +1,31 @@ + +#include "unity.h" + +#include "libtropic_common.h" +#include "lt_l2_frame_check.h" +#include "lt_l2.h" + +#include "mock_lt_l1.h" +#include "mock_lt_crc16.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +//---------------------------------------------------------------------- +// Test if function returns expected error on non valid input parameter +void test_lt_l2_transfer___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l2_transfer(NULL)); +} + +//---------------------------------------------------------------------- +// Test if function returns expected error on non valid input parameter +void test_lt_l2_encrypted_cmd___NULL_h() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_l2_encrypted_cmd(NULL)); +} diff --git a/tests/unit/test_lt_l3.c b/tests/unit/test_lt_l3.c new file mode 100644 index 0000000..325a75b --- /dev/null +++ b/tests/unit/test_lt_l3.c @@ -0,0 +1,134 @@ + +#include "unity.h" +#include "string.h" + +#include "libtropic_common.h" +#include "lt_l3.h" + +#include "mock_lt_l2.h" +#include "mock_lt_aesgcm.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +// Test correct nonce initialization +void test_lt_l3_nonce_init___correct() +{ + lt_handle_t handle = {0}; + memset(handle.IV, 0xff, 12); + + uint8_t expected_1[12] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_1, handle.IV, 12); + + int ret = lt_l3_nonce_init(&handle); + TEST_ASSERT_EQUAL(LT_OK, ret); + + uint8_t expected_2[12] = {0}; + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_2, handle.IV, 12); +} + +// Test if nonce increases correctly +void test_lt_l3_nonce_increase___correct() +{ + lt_handle_t handle = {0}; + + for(int i=0;i<0xfffe;i++) { + int ret = lt_l3_nonce_increase(&handle); + TEST_ASSERT_EQUAL(LT_OK, ret); + } + + TEST_ASSERT_EQUAL(0xfe, handle.IV[0]); + TEST_ASSERT_EQUAL(0xff, handle.IV[1]); + // TODO test higher bytes as well, but this takes some time + //TEST_ASSERT_EQUAL(0xff, h.IV[9]); + //TEST_ASSERT_EQUAL(0xff, h.IV[8]); +} + +// Test if lt_l3_cmd() fails when secure session is not active +void test_lt_l3_cmd___fail_when_no_session() +{ + lt_handle_t handle = {0}; + + int ret = lt_l3_cmd(&handle); + TEST_ASSERT_EQUAL(LT_HOST_NO_SESSION, ret); +} + +// Test if lt_l3_cmd() returns LT_FAIL, if some error happens during aesgcm encrypt operations +void test_lt_l3_cmd___fail_during_lt_aesgcm_encrypt() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + struct lt_l3_gen_frame_t * p_frame = (struct lt_l3_gen_frame_t*)&h.l3_buff; + lt_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE,LT_FAIL); + + int ret = lt_l3_cmd(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Test if lt_l3_cmd() returns LT_FAIL, if some error happens during l2 exchange +void test_lt_l3_cmd___fail_during_lt_l2_encrypted_cmd() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + struct lt_l3_gen_frame_t * p_frame = (struct lt_l3_gen_frame_t*)&h.l3_buff; + lt_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE,LT_OK); + + lt_l2_encrypted_cmd_ExpectAndReturn(&h, LT_FAIL); + + + int ret = lt_l3_cmd(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Test if lt_l3_cmd() returns LT_FAIL, if some error happens during aesgcm decrypt operations +void test_lt_l3_cmd___fail_during_lt_aesgcm_decrypt() +{ + lt_handle_t h = {0}; + h.session = SESSION_ON; + + struct lt_l3_gen_frame_t * p_frame = (struct lt_l3_gen_frame_t*)&h.l3_buff; + lt_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE,LT_OK); + + lt_l2_encrypted_cmd_ExpectAndReturn(&h, LT_OK); + + lt_aesgcm_decrypt_ExpectAndReturn(&h.decrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE,LT_FAIL); + + + int ret = lt_l3_cmd(&h); + TEST_ASSERT_EQUAL(LT_FAIL, ret); +} + +// Test that all possible L3_IDs are correctly parsed in lt_l3cmd() function and that they are propagated to upper layers +void test_lt_l3_cmd___test_all_l3_results() +{ + // Note: correct execution is tested at the end + uint8_t results[] = {L3_RESULT_FAIL, L3_RESULT_UNAUTHORIZED, L3_RESULT_INVALID_CMD, 0x99, L3_RESULT_OK}; + uint8_t returned[] = {LT_L3_FAIL, LT_L3_UNAUTHORIZED, LT_L3_INVALID_CMD, LT_FAIL, LT_OK}; + for (int i=0; i<5;i++) { + lt_handle_t h = {0}; + h.session = SESSION_ON; + + struct lt_l3_gen_frame_t * p_frame = (struct lt_l3_gen_frame_t*)&h.l3_buff; + lt_aesgcm_encrypt_ExpectAndReturn(&h.encrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE,LT_OK); + + lt_l2_encrypted_cmd_ExpectAndReturn(&h, LT_OK); + + lt_aesgcm_decrypt_ExpectAndReturn(&h.decrypt, h.IV, L3_IV_SIZE, (uint8_t *)"", 0, p_frame->data, p_frame->cmd_size, p_frame->data + p_frame->cmd_size, L3_TAG_SIZE,LT_OK); + + p_frame->data[0] = results[i]; + + if(i == 4) { + lt_l3_nonce_increase(&h); + } + + int ret = lt_l3_cmd(&h); + TEST_ASSERT_EQUAL(returned[i], ret); + } +} diff --git a/tests/unit/test_lt_l3_input_params.c b/tests/unit/test_lt_l3_input_params.c new file mode 100644 index 0000000..d5ba093 --- /dev/null +++ b/tests/unit/test_lt_l3_input_params.c @@ -0,0 +1,38 @@ + +#include "unity.h" +#include "string.h" + +#include "libtropic_common.h" +#include "lt_l3.h" + +#include "mock_lt_l2.h" +#include "mock_lt_aesgcm.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l3_nonce_init___NULL_h() +{ + lt_ret_t ret = lt_l3_nonce_init(NULL); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l3_nonce_increase___NULL_h() +{ + lt_ret_t ret = lt_l3_nonce_increase(NULL); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_l3_cmd___NULL_h() +{ + int ret = lt_l3_cmd(NULL); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} diff --git a/tests/unit/test_lt_libtropic_handshake.c b/tests/unit/test_lt_libtropic_handshake.c new file mode 100644 index 0000000..ea619a1 --- /dev/null +++ b/tests/unit/test_lt_libtropic_handshake.c @@ -0,0 +1,181 @@ + +#include "unity.h" +#include "string.h" + +#include "libtropic_common.h" +#include "libtropic.h" +#include "lt_l2_api_structs.h" + +#include "mock_lt_random.h" +#include "mock_lt_l1_port_wrap.h" +#include "mock_lt_l1.h" +#include "mock_lt_l2.h" +#include "mock_lt_l3.h" +#include "mock_lt_x25519.h" +#include "mock_lt_ed25519.h" +#include "mock_lt_hkdf.h" +#include "mock_lt_sha256.h" +#include "mock_lt_aesgcm.h" + +void setUp(void) +{ + +} + +void tearDown(void) +{ +} + +void mock_all_sha256() +{ + // Static needed, because data here are used after function return for comparison + // by CMock. + static lt_crypto_sha256_ctx_t hctx = {0}; + static uint8_t protocol_name[32] = {'N','o','i','s','e','_','K','K','1','_','2','5','5','1','9','_','A','E','S','G','C','M','_','S','H','A','2','5','6',0x00,0x00,0x00}; + static uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; + + // hctx is useful to check, because we need it blank (zeroed) + lt_sha256_init_Expect(&hctx); + for (int i = 0; i < 6; i++) { + lt_sha256_start_Expect(&hctx); + if (i > 0) { + lt_sha256_update_Expect(&hctx, hash, 32); + lt_sha256_update_ExpectAnyArgs(); // not interested in exact pointer addresses + } else { + lt_sha256_update_ExpectWithArray(&hctx, SHA256_DIGEST_LENGTH, protocol_name, 32, 32); + } + lt_sha256_finish_Expect(&hctx, hash); + } + + for (int i = 0; i < 3; i++) { + lt_X25519_ExpectAnyArgs(); + lt_hkdf_ExpectAnyArgs(); + } + lt_hkdf_ExpectAnyArgs(); +} + +void test_lt_session_start__random_bytes_error() +{ + lt_handle_t h = {0}; + uint8_t stpub = 0; + uint8_t shipriv = 0; + uint8_t shipub = 0; + + lt_random_bytes_ExpectAnyArgsAndReturn(LT_FAIL); + TEST_ASSERT_EQUAL(lt_session_start(&h, &stpub, 0, &shipriv, &shipub), LT_FAIL); +} + +void test_lt_session_start__l2_transfer_error() +{ + lt_handle_t h = {0}; + uint8_t stpub = 0; + uint8_t shipriv = 0; + uint8_t shipub = 0; + + lt_random_bytes_ExpectAnyArgsAndReturn(LT_OK); + lt_X25519_scalarmult_ExpectAnyArgs(); + lt_l2_transfer_ExpectAndReturn(&h, LT_FAIL); + + TEST_ASSERT_EQUAL(lt_session_start(&h, &stpub, 0, &shipriv, &shipub), LT_FAIL); +} + +void test_lt_session_start__lt_aesgcm_init_error() +{ + lt_handle_t h = {0}; + uint8_t stpub = 0; + uint8_t shipriv = 0; + uint8_t shipub = 0; + pkey_index_t pkey_index = 0; + + + lt_random_bytes_ExpectAnyArgsAndReturn(LT_OK); + lt_X25519_scalarmult_ExpectAnyArgs(); + lt_l2_transfer_ExpectAndReturn(&h, LT_OK); + mock_all_sha256(); + + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_FAIL); + + TEST_ASSERT_EQUAL(lt_session_start(&h, &stpub, pkey_index, &shipriv, &shipub), LT_CRYPTO_ERR); +} + +void test_lt_session_start__lt_aesgcm_decrypt_error() +{ + lt_handle_t h = {0}; + uint8_t stpub = 0; + uint8_t shipriv = 0; + uint8_t shipub = 0; + pkey_index_t pkey_index = 0; + + + lt_random_bytes_ExpectAnyArgsAndReturn(LT_OK); + lt_X25519_scalarmult_ExpectAnyArgs(); + lt_l2_transfer_ExpectAndReturn(&h, LT_OK); + mock_all_sha256(); + + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_decrypt_ExpectAnyArgsAndReturn(LT_FAIL); + + TEST_ASSERT_EQUAL(lt_session_start(&h, &stpub, pkey_index, &shipriv, &shipub), LT_CRYPTO_ERR); +} + +void test_lt_session_start__lt_aesgcm_2nd_init_error() +{ + lt_handle_t h = {0}; + uint8_t stpub = 0; + uint8_t shipriv = 0; + uint8_t shipub = 0; + pkey_index_t pkey_index = 0; + + lt_random_bytes_ExpectAnyArgsAndReturn(LT_OK); + lt_X25519_scalarmult_ExpectAnyArgs(); + lt_l2_transfer_ExpectAndReturn(&h, LT_OK); + mock_all_sha256(); + + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_decrypt_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_FAIL); + + TEST_ASSERT_EQUAL(lt_session_start(&h, &stpub, pkey_index, &shipriv, &shipub), LT_CRYPTO_ERR); +} + +void test_lt_session_start__lt_aesgcm_3rd_init_error() +{ + lt_handle_t h = {0}; + uint8_t stpub = 0; + uint8_t shipriv = 0; + uint8_t shipub = 0; + pkey_index_t pkey_index = 0; + + lt_random_bytes_ExpectAnyArgsAndReturn(LT_OK); + lt_X25519_scalarmult_ExpectAnyArgs(); + lt_l2_transfer_ExpectAndReturn(&h, LT_OK); + mock_all_sha256(); + + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_decrypt_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_FAIL); + + TEST_ASSERT_EQUAL(lt_session_start(&h, &stpub, pkey_index, &shipriv, &shipub), LT_CRYPTO_ERR); +} + +void test_lt_session_start__correct() +{ + lt_handle_t h = {0}; + uint8_t stpub = 0; + uint8_t shipriv = 0; + uint8_t shipub = 0; + pkey_index_t pkey_index = 0; + + lt_random_bytes_ExpectAnyArgsAndReturn(LT_OK); + lt_X25519_scalarmult_ExpectAnyArgs(); + lt_l2_transfer_ExpectAndReturn(&h, LT_OK); + mock_all_sha256(); + + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_decrypt_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_OK); + lt_aesgcm_init_and_key_ExpectAnyArgsAndReturn(LT_OK); + + TEST_ASSERT_EQUAL(lt_session_start(&h, &stpub, pkey_index, &shipriv, &shipub), LT_OK); +} \ No newline at end of file diff --git a/tests/unit/test_lt_libtropic_input_params.c b/tests/unit/test_lt_libtropic_input_params.c new file mode 100644 index 0000000..a8e73d3 --- /dev/null +++ b/tests/unit/test_lt_libtropic_input_params.c @@ -0,0 +1,716 @@ +#include "unity.h" +#include "string.h" +#include "time.h" + +#include "libtropic_common.h" +#include "libtropic.h" +#include "lt_l3_api_structs.h" + +#include "mock_lt_random.h" +#include "mock_lt_l1_port_wrap.h" +#include "mock_lt_l1.h" +#include "mock_lt_l2.h" +#include "mock_lt_l3.h" +#include "mock_lt_x25519.h" +#include "mock_lt_ed25519.h" +#include "mock_lt_hkdf.h" +#include "mock_lt_sha256.h" +#include "mock_lt_aesgcm.h" + + +void setUp(void) +{ + char buffer[100] = {0}; + #ifdef RNG_SEED + srand(RNG_SEED); + #else + time_t seed = time(NULL); + // Using this approach, because in our version of Unity there's no TEST_PRINTF yet. + // Also, raw printf is worse solution (without additional debug msgs, such as line). + snprintf(buffer, sizeof(buffer), "Using random seed: %lu\n", seed); + TEST_MESSAGE(buffer); + srand(seed); + #endif +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_init___invalid_handle() +{ + int ret = lt_init(NULL); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +//--------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_deinit___invalid_handle() +{ + int ret = lt_deinit(NULL); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +//--------------------------------------------------------------------- +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_session_start___invalid_handle() +{ uint8_t pkey_index = 1; + uint8_t shipriv[] = {0x80,0x02,0xc5,0xa3,0xff,0x46,0xa2,0x09,0x4e,0x4e,0x71,0xf3,0xc8,0xe3,0xdd,0x79,0xec,0x5c,0x1c,0xcd,0xb0,0x40,0xbb,0xcf,0x6f,0x64,0x9d,0x49,0xe9,0x1d,0x9c,0x53}; + uint8_t shipub[] = {0x83,0xc3,0x36,0x3c,0xff,0x27,0x47,0xb7,0xf7,0xeb,0x19,0x85,0x17,0x63,0x1a,0x71,0x54,0x76,0xb4,0xfe,0x22,0x46,0x01,0x45,0x89,0xc3,0xac,0x11,0x8b,0xb8,0x9e,0x51}; + uint8_t stpub[] = {0}; + int ret = lt_session_start(NULL, stpub, pkey_index, shipriv, shipub); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_session_start___invalid_pkey_index() +{ + lt_handle_t handle = {0}; + uint8_t pkey_index = 5; + uint8_t shipriv[] = {0x80,0x02,0xc5,0xa3,0xff,0x46,0xa2,0x09,0x4e,0x4e,0x71,0xf3,0xc8,0xe3,0xdd,0x79,0xec,0x5c,0x1c,0xcd,0xb0,0x40,0xbb,0xcf,0x6f,0x64,0x9d,0x49,0xe9,0x1d,0x9c,0x53}; + uint8_t shipub[] = {0x83,0xc3,0x36,0x3c,0xff,0x27,0x47,0xb7,0xf7,0xeb,0x19,0x85,0x17,0x63,0x1a,0x71,0x54,0x76,0xb4,0xfe,0x22,0x46,0x01,0x45,0x89,0xc3,0xac,0x11,0x8b,0xb8,0x9e,0x51}; + uint8_t stpub[] = {0}; + + int ret = lt_session_start(&handle, stpub, pkey_index, shipriv, shipub); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_session_start___invalid_shipriv() +{ + lt_handle_t handle = {0}; + uint8_t pkey_index = 5; + uint8_t shipub[] = {0x83,0xc3,0x36,0x3c,0xff,0x27,0x47,0xb7,0xf7,0xeb,0x19,0x85,0x17,0x63,0x1a,0x71,0x54,0x76,0xb4,0xfe,0x22,0x46,0x01,0x45,0x89,0xc3,0xac,0x11,0x8b,0xb8,0x9e,0x51}; + uint8_t stpub[] = {0}; + + int ret = lt_session_start(&handle, stpub, pkey_index, NULL, shipub); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +// Test if function returns LT_PARAM_ERR on non valid input parameter +void test_lt_session_start___invalid_shipub() +{ + lt_handle_t handle = {0}; + uint8_t pkey_index = 5; + uint8_t shipriv[] = {0x80,0x02,0xc5,0xa3,0xff,0x46,0xa2,0x09,0x4e,0x4e,0x71,0xf3,0xc8,0xe3,0xdd,0x79,0xec,0x5c,0x1c,0xcd,0xb0,0x40,0xbb,0xcf,0x6f,0x64,0x9d,0x49,0xe9,0x1d,0x9c,0x53}; + uint8_t stpub[] = {0}; + + int ret = lt_session_start(&handle, stpub, pkey_index, shipriv, NULL); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, ret); +} + +//--------------------------------------------------------------------- +void test_lt_ping__invalid_handle() +{ + uint8_t msg_out = 0; + uint8_t msg_in = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ping(NULL, &msg_out, &msg_in, 0)); +} + +void test_lt_ping__invalid_msg_out() +{ + lt_handle_t h; + h.session = SESSION_ON; + uint8_t msg_in; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ping(&h, NULL, &msg_in, 0)); +} + +void test_lt_ping__invalid_msg_in() +{ + lt_handle_t h; + h.session = SESSION_ON; + uint8_t msg_out = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ping(&h, &msg_out, NULL, 0)); +} + +void test_lt_ping__invalid_len() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg_out, msg_in; + uint16_t len; + + for (int i = 0; i < 25; i++) { + len = PING_LEN_MAX + 1; + len += rand() % (UINT16_MAX - len); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ping(&h, &msg_out, &msg_in, len)); + } +} + +//--------------------------------------------------------------------- +void test_lt_pairing_key_write__invalid_handle() +{ + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_write(NULL, pubkey, slot)); +} + +void test_lt_pairing_key_write__invalid_pubkey() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_write(&h, NULL, slot)); +} + + +void test_lt_pairing_key_write__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_write(&h, pubkey, 4)); +} + +//--------------------------------------------------------------------- +void test_lt_pairing_key_read__invalid_handle() +{ + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_read(NULL, pubkey, slot)); +} + +void test_lt_pairing_key_read__invalid_pubkey() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_read(&h, NULL, slot)); +} + + +void test_lt_pairing_key_read__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t pubkey[32] = {0}; + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_read(&h, pubkey, 4)); +} + + +//--------------------------------------------------------------------- +void test_lt_pairing_key_invalidate__invalid_handle() +{ + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_invalidate(NULL, slot)); +} + +void test_lt_pairing_key_invalidate__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t slot = 0; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_pairing_key_invalidate(&h, 4)); +} + +//--------------------------------------------------------------------- +void test_lt_r_mem_data_write__invalid_handle() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_write(NULL, udata_slot, udata, size)); +} + +void test_lt_r_mem_data_write__invalid_udata_slot() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_write(&h, 512, udata, size)); +} + +void test_lt_r_mem_data_write__invalid_udata() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_write(&h, 0, NULL, size)); +} + +void test_lt_r_mem_data_write__invalid_size() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_write(&h, udata_slot, udata, 445)); +} + + +//--------------------------------------------------------------------- +void test_lt_r_mem_data_read__invalid_handle() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_read(NULL, udata_slot, udata, size)); +} + +void test_lt_r_mem_data_read__invalid_udata_slot() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_read(&h, 512, udata, size)); +} + +void test_lt_r_mem_data_read__invalid_udata() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_read(&h, 0, NULL, size)); +} + +void test_lt_r_mem_data_read__invalid_size() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_read(&h, udata_slot, udata, 445)); +} + +//--------------------------------------------------------------------- +void test_lt_r_mem_data_erase__invalid_handle() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_erase(NULL, udata_slot)); +} + +void test_lt_r_mem_data_erase__invalid_udata_slot() +{ + lt_handle_t h; + uint16_t udata_slot; + uint8_t udata[100]; + uint16_t size; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_r_mem_data_erase(&h, 512)); +} + +//--------------------------------------------------------------------- +void test_lt_random_get__invalid_handle() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_random_get(NULL, (uint8_t*)"", 0)); +} + +void test_lt_random_get__invalid_buff() +{ + lt_handle_t h; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_random_get(&h, NULL, 0)); +} + +void test_lt_random_get__invalid_len() +{ + lt_handle_t h; + uint16_t len; + + h.session = SESSION_ON; + + for (int i = 0; i < 25; i++) { + len = RANDOM_VALUE_GET_LEN_MAX + 1; + len += rand() % (UINT16_MAX - len); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_random_get(&h, (uint8_t*)"", len)); + } +} + + +//--------------------------------------------------------------------- +void test_lt_ecc_key_generate__invalid_handle() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_generate(NULL, ECC_SLOT_1, CURVE_ED25519)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_generate(NULL, ECC_SLOT_1, CURVE_P256)); +} + +void test_lt_ecc_key_generate__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_generate(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MIN - 1, CURVE_ED25519)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_generate(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MAX + 1, CURVE_ED25519)); +} + +void test_lt_ecc_key_generate__invalid_curve() +{ + lt_handle_t h; + h.session = SESSION_ON; + + // Test random values. + int curve; + for (int i = 0; i < 25; i++) { + curve = rand(); + if (curve != CURVE_ED25519 && curve != CURVE_P256) { + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_generate(&h, ECC_SLOT_1, curve)); + } + } + + // Test top and lower bound. + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_generate(&h, ECC_SLOT_1, 0)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_generate(&h, ECC_SLOT_1, 3)); +} + +//--------------------------------------------------------------------- +void test_lt_ecc_key_read__invalid_handle() +{ + ecc_curve_type_t curve; + ecc_key_origin_t origin; + uint8_t key[64]; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_read(NULL, ECC_SLOT_1, key, 64, &curve, &origin)); +} + +void test_lt_ecc_key_read__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + ecc_curve_type_t curve; + ecc_key_origin_t origin; + uint8_t key[64]; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_read(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MIN - 1, key, 64, &curve, &origin)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_read(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MAX + 1, key, 64, &curve, &origin)); +} + +void test_lt_ecc_key_read__invalid_key() +{ + lt_handle_t h; + h.session = SESSION_ON; + + ecc_curve_type_t curve; + ecc_key_origin_t origin; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_read(&h, ECC_SLOT_1, NULL, 64, &curve, &origin)); +} + +void test_lt_ecc_key_read__invalid_key_len() +{ + lt_handle_t h; + h.session = SESSION_ON; + + ecc_curve_type_t curve; + ecc_key_origin_t origin; + uint8_t key[64]; + + for (int i = 0; i < 25; i++) { + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_read(&h, ECC_SLOT_1, key, rand() % 64, &curve, &origin)); + } +} + +void test_lt_ecc_key_read__invalid_curve() +{ + lt_handle_t h; + h.session = SESSION_ON; + + ecc_key_origin_t origin; + uint8_t key[64]; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_read(&h, ECC_SLOT_1, key, 64, NULL, &origin)); +} + +void test_lt_ecc_key_read__invalid_origin() +{ + lt_handle_t h; + h.session = SESSION_ON; + + ecc_curve_type_t curve; + uint8_t key[64]; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_read(&h, ECC_SLOT_1, key, 64, &curve, NULL)); +} + +//--------------------------------------------------------------------- +void test_lt_ecc_eddsa_sign__invalid_handle() +{ + uint8_t msg[1] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(NULL, ECC_SLOT_1, msg, 1, rs, 64)); +} + +void test_lt_ecc_eddsa_sign__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[1] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MIN - 1, msg, 1, rs, 64)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MAX + 1, msg, 1, rs, 64)); +} + +void test_lt_ecc_eddsa_sign__invalid_msg() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t rs[64]; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(&h, ECC_SLOT_1, NULL, 1, rs, 64)); +} + +void test_lt_ecc_eddsa_sign__invalid_msg_len() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[LT_L3_EDDSA_SIGN_MSG_LEN_MAX + 1] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(&h, ECC_SLOT_1, msg, LT_L3_EDDSA_SIGN_MSG_LEN_MAX + 1, rs, 64)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(&h, ECC_SLOT_1, msg, LT_L3_EDDSA_SIGN_MSG_LEN_MIN - 1, rs, 64)); +} + +void test_lt_ecc_eddsa_sign__invalid_rs() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[1] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(&h, ECC_SLOT_1, msg, 1, NULL, 64)); +} + +void test_lt_ecc_eddsa_sign__invalid_rs_len() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[1] = {0}; + uint8_t rs[64] = {0}; + + for (int i = 0; i < 25; i++) { + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sign(&h, ECC_SLOT_1, msg, 1, rs, rand() % 64)); + } +} + +//--------------------------------------------------------------------- +void test_lt_ecc_ecdsa_sign__invalid_handle() +{ + uint8_t msg[1] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_ecdsa_sign(NULL, ECC_SLOT_1, msg, 1, rs, 64)); +} + +void test_lt_ecc_ecdsa_sign__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[1] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_ecdsa_sign(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MIN - 1, msg, 1, rs, 64)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_ecdsa_sign(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MAX + 1, msg, 1, rs, 64)); +} + +void test_lt_ecc_ecdsa_sign__invalid_msg() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_ecdsa_sign(&h, ECC_SLOT_1, NULL, 1, rs, 64)); +} + +void test_lt_ecc_ecdsa_sign__invalid_msg_len() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[LT_L3_ECDSA_SIGN_MSG_LEN_MAX + 1] = {0}; + uint8_t rs[64] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_ecdsa_sign(&h, ECC_SLOT_1, msg, LT_L3_ECDSA_SIGN_MSG_LEN_MAX + 1, rs, 64)); +} + +void test_lt_ecc_ecdsa_sign__invalid_rs() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[1] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_ecdsa_sign(&h, ECC_SLOT_1, msg, 1, NULL, 64)); +} + +void test_lt_ecc_ecdsa_sign__invalid_rs_len() +{ + lt_handle_t h; + h.session = SESSION_ON; + + uint8_t msg[1] = {0}; + uint8_t rs[64] = {0}; + + for (int i = 0; i < 25; i++) { + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_ecdsa_sign(&h, ECC_SLOT_1, msg, 1, rs, rand() % 64)); + } +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_eddsa_sig_verify__invalid_msg() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sig_verify(NULL, LT_L3_EDDSA_SIGN_MSG_LEN_MIN, (uint8_t*)"", (uint8_t*)"")); +} + +void test_lt_ecc_eddsa_sig_verify__invalid_msg_len() +{ + uint8_t msg[LT_L3_EDDSA_SIGN_MSG_LEN_MAX + 1]; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sig_verify((uint8_t*)"", 0, (uint8_t*)"", (uint8_t*)"")); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sig_verify(msg, sizeof(msg), (uint8_t*)"", (uint8_t*)"")); +} + +void test_lt_ecc_eddsa_sig_verify__invalid_pubkey() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sig_verify((uint8_t*)"", 1, NULL, (uint8_t*)"")); +} + +void test_lt_ecc_eddsa_sig_verify__invalid_rs() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_eddsa_sig_verify((uint8_t*)"", 1, (uint8_t*)"", NULL)); +} + +//--------------------------------------------------------------------- + +void test_lt_ecc_key_erase__invalid_handle() +{ + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_erase(NULL, ECC_SLOT_1)); +} + +void test_lt_ecc_key_erase__invalid_slot() +{ + lt_handle_t h; + h.session = SESSION_ON; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_erase(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MIN - 1)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_ecc_key_erase(&h, LT_L3_ECC_KEY_GENERATE_SLOT_MAX + 1)); +} + +//--------------------------------------------------------------------- + +void test_lt_get_info_cert__invalid_handle() +{ + uint8_t cert[LT_L2_GET_INFO_REQ_CERT_SIZE]; + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_get_info_cert(NULL, cert, LT_L2_GET_INFO_REQ_CERT_SIZE)); +} + +void test_lt_get_info_cert__invalid_cert() +{ + lt_handle_t h; + h.session = SESSION_ON; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_get_info_cert(&h, NULL, LT_L2_GET_INFO_REQ_CERT_SIZE)); +} + +void test_lt_get_info_cert__invalid_cert_len() +{ + lt_handle_t h; + uint8_t cert[LT_L2_GET_INFO_REQ_CERT_SIZE]; + + h.session = SESSION_ON; + + for (int i = 0; i < 25; i++) { + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_get_info_cert(&h, cert, rand() % LT_L2_GET_INFO_REQ_CERT_SIZE)); + } +} + +//--------------------------------------------------------------------- +void test_lt_cert_verify_and_parse__invalid_cert() +{ + uint8_t stpub[] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_cert_verify_and_parse(NULL, LT_L2_GET_INFO_REQ_CERT_SIZE, stpub)); +} + +void test_lt_cert_verify_and_parse__invalid_len() +{ + uint8_t dummy_cert[1024] = {0}; + uint8_t stpub[] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_cert_verify_and_parse(dummy_cert, LT_L2_GET_INFO_REQ_CERT_SIZE + 1, stpub)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_cert_verify_and_parse(dummy_cert, LT_L2_GET_INFO_REQ_CERT_SIZE + 500, stpub)); + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_cert_verify_and_parse(dummy_cert, LT_L2_GET_INFO_REQ_CERT_SIZE + 1000, stpub)); +} + +void test_lt_cert_verify_and_parse__invalid_stpub() +{ + uint8_t dummy_cert[LT_L2_GET_INFO_REQ_CERT_SIZE] = {0}; + + TEST_ASSERT_EQUAL(LT_PARAM_ERR, lt_cert_verify_and_parse(dummy_cert, LT_L2_GET_INFO_REQ_CERT_SIZE, NULL)); +} + +//--------------------------------------------------------------------- + +// Test that all return values can be displayed as a string (for better debug) +void test_lt_ret_verbose() +{ + TEST_ASSERT_EQUAL_STRING("LT_L1_CHIP_STARTUP_MODE", lt_ret_verbose(LT_L1_CHIP_STARTUP_MODE)); + TEST_ASSERT_EQUAL_STRING("LT_L1_CHIP_ALARM_MODE", lt_ret_verbose(LT_L1_CHIP_ALARM_MODE)); + TEST_ASSERT_EQUAL_STRING("LT_L1_CHIP_BUSY", lt_ret_verbose(LT_L1_CHIP_BUSY)); + + TEST_ASSERT_EQUAL_STRING("LT_L1_SPI_ERROR", lt_ret_verbose(LT_L1_SPI_ERROR)); + TEST_ASSERT_EQUAL_STRING("LT_L1_DATA_LEN_ERROR", lt_ret_verbose(LT_L1_DATA_LEN_ERROR)); + + TEST_ASSERT_EQUAL_STRING("LT_L2_IN_CRC_ERR", lt_ret_verbose(LT_L2_IN_CRC_ERR)); + TEST_ASSERT_EQUAL_STRING("LT_L2_REQ_CONT", lt_ret_verbose(LT_L2_REQ_CONT)); + TEST_ASSERT_EQUAL_STRING("LT_L2_RES_CONT", lt_ret_verbose(LT_L2_RES_CONT)); + TEST_ASSERT_EQUAL_STRING("LT_L2_HSK_ERR", lt_ret_verbose(LT_L2_HSK_ERR)); + TEST_ASSERT_EQUAL_STRING("LT_L2_NO_SESSION", lt_ret_verbose(LT_L2_NO_SESSION)); + TEST_ASSERT_EQUAL_STRING("LT_L2_TAG_ERR", lt_ret_verbose(LT_L2_TAG_ERR)); + TEST_ASSERT_EQUAL_STRING("LT_L2_CRC_ERR", lt_ret_verbose(LT_L2_CRC_ERR)); + TEST_ASSERT_EQUAL_STRING("LT_L2_GEN_ERR", lt_ret_verbose(LT_L2_GEN_ERR)); + TEST_ASSERT_EQUAL_STRING("LT_L2_NO_RESP", lt_ret_verbose(LT_L2_NO_RESP)); + TEST_ASSERT_EQUAL_STRING("LT_L2_UNKNOWN_REQ", lt_ret_verbose(LT_L2_UNKNOWN_REQ)); + TEST_ASSERT_EQUAL_STRING("LT_L2_DATA_LEN_ERROR", lt_ret_verbose(LT_L2_DATA_LEN_ERROR)); + TEST_ASSERT_EQUAL_STRING("LT_L2_STATUS_NOT_RECOGNIZED", lt_ret_verbose(LT_L2_STATUS_NOT_RECOGNIZED)); + + TEST_ASSERT_EQUAL_STRING("LT_L3_OK", lt_ret_verbose(LT_L3_OK)); + TEST_ASSERT_EQUAL_STRING("LT_L3_FAIL", lt_ret_verbose(LT_L3_FAIL)); + TEST_ASSERT_EQUAL_STRING("LT_L3_UNAUTHORIZED", lt_ret_verbose(LT_L3_UNAUTHORIZED)); + TEST_ASSERT_EQUAL_STRING("LT_L3_INVALID_CMD", lt_ret_verbose(LT_L3_INVALID_CMD)); + TEST_ASSERT_EQUAL_STRING("LT_L3_DATA_LEN_ERROR", lt_ret_verbose(LT_L3_DATA_LEN_ERROR)); + + TEST_ASSERT_EQUAL_STRING("LT_HOST_NO_SESSION", lt_ret_verbose(LT_HOST_NO_SESSION)); + TEST_ASSERT_EQUAL_STRING("LT_OK", lt_ret_verbose(LT_OK)); + TEST_ASSERT_EQUAL_STRING("LT_FAIL", lt_ret_verbose(LT_FAIL)); + TEST_ASSERT_EQUAL_STRING("LT_PARAM_ERR", lt_ret_verbose(LT_PARAM_ERR)); + + TEST_ASSERT_EQUAL_STRING("FATAL ERROR, unknown return value", lt_ret_verbose(99)); +} \ No newline at end of file diff --git a/ts_sw_setup.yml b/ts_sw_setup.yml index 242e7f2..239ac8d 100644 --- a/ts_sw_setup.yml +++ b/ts_sw_setup.yml @@ -1,8 +1,16 @@ # This file is for internal use only +# Documentation and Latex +texlive 2022 +doxygen 1.10.0 + +# RISC-V tools openocd v0.11.0 cmake 3.23.2 cppcheck 2.6 -ts-python-env 0.4 -texlive 2022 -doxygen 1.10.0 + +# Python environment packages +ts-python-env 0.5 + +# Tropic flow tools +ts-latex-lib v0.19 diff --git a/vendor/STM32CubeF4 b/vendor/STM32CubeF4 deleted file mode 160000 index d7cb2bb..0000000 --- a/vendor/STM32CubeF4 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d7cb2bb74395b7f27e137da8adb5ad25f0aa0e78 diff --git a/vendor/trezor_crypto/CMakeLists.txt b/vendor/trezor_crypto/CMakeLists.txt index d7356f3..d84b0f2 100644 --- a/vendor/trezor_crypto/CMakeLists.txt +++ b/vendor/trezor_crypto/CMakeLists.txt @@ -1,10 +1,6 @@ cmake_minimum_required(VERSION 3.21.0) -project(trezor_crypto - LANGUAGES C) - - set(TREZOR_CRYPTO_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/aes/aesgcm.c ${CMAKE_CURRENT_SOURCE_DIR}/aes/aesccm.c @@ -37,19 +33,6 @@ set(TREZOR_CRYPTO_SRCS add_library(trezor_crypto ${TREZOR_CRYPTO_SRCS}) -target_include_directories(trezor_crypto PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/ - ${CMAKE_CURRENT_SOURCE_DIR}/aes/ - ${CMAKE_CURRENT_SOURCE_DIR}/ed25519-donna/ - ) - -target_link_directories(trezor_crypto PUBLIC +target_include_directories(trezor_crypto PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ - ${CMAKE_CURRENT_SOURCE_DIR}/aes/ - ${CMAKE_CURRENT_SOURCE_DIR}/ed25519-donna/ ) - -target_compile_definitions(trezor_crypto PRIVATE - USE_INSECURE_PRNG - AES_VAR - )