From 3a142cb575cf16e4388469cc39deb8cacf7c368c Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 10 Jun 2026 17:30:00 +0200 Subject: [PATCH] Make trust region board invariant. Signed-off-by: Pol Henarejos --- cmake/trusted.cmake | 242 +++++++++++++++++++++++++++++ config/rp2350/ld/trusted_region.ld | 32 ++++ config/rp2350/ld/trusted_state.ld | 29 ++++ picokeys_sdk_import.cmake | 98 ++---------- src/main.c | 2 + src/rescue.c | 14 +- src/trusted.c | 28 ++-- src/trusted.h | 15 +- src/trusted_mem.c | 130 ++++++++++++++++ src/trusted_pico_sha256.c | 196 +++++++++++++++++++++++ 10 files changed, 685 insertions(+), 101 deletions(-) create mode 100644 cmake/trusted.cmake create mode 100644 config/rp2350/ld/trusted_region.ld create mode 100644 config/rp2350/ld/trusted_state.ld create mode 100644 src/trusted_mem.c create mode 100644 src/trusted_pico_sha256.c diff --git a/cmake/trusted.cmake b/cmake/trusted.cmake new file mode 100644 index 0000000..c0e5a34 --- /dev/null +++ b/cmake/trusted.cmake @@ -0,0 +1,242 @@ +include_guard(GLOBAL) + +macro(picokeys_init_trusted_config) + set(PICOKEYS_TRUSTED_REGION_FLASH_BASE "0x100B0000" CACHE STRING "Fixed flash base for the trusted measurement region on Pico firmware builds") + set(PICOKEYS_TRUSTED_STATE_RAM_BASE "0x20070000" CACHE STRING "Fixed RAM base for trusted writable state on Pico firmware builds") + + if(CMAKE_C_COMPILER) + set(PICOKEYS_LIBGCC_QUERY_ARGS -print-libgcc-file-name) + if(PICO_RP2350) + set(PICOKEYS_LIBGCC_QUERY_ARGS + -mthumb + -march=armv8-m.main+fp + -mfloat-abi=softfp + -print-libgcc-file-name + ) + endif() + execute_process( + COMMAND ${CMAKE_C_COMPILER} ${PICOKEYS_LIBGCC_QUERY_ARGS} + OUTPUT_VARIABLE PICOKEYS_LIBGCC + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + + set(TRUSTED_MBEDTLS_HELPER_SOURCES + ${CMAKE_CURRENT_LIST_DIR}/src/trusted_mem.c + ) +endmacro() + +function(configure_picokeys_mbedtls_target target_name) + target_sources(${target_name} PRIVATE ${TRUSTED_MBEDTLS_HELPER_SOURCES}) + target_compile_definitions(${target_name} PRIVATE + MBEDTLS_PLATFORM_ZEROIZE_ALT + memset=picokeys_trusted_memset + memcpy=picokeys_trusted_memcpy + memmove=picokeys_trusted_memmove + memcmp=picokeys_trusted_memcmp + ) + target_compile_options(${target_name} PRIVATE -fno-builtin) +endfunction() + +function(configure_picokeys_trusted_mbedtls_target target_name) + target_sources(${target_name} PRIVATE ${TRUSTED_MBEDTLS_HELPER_SOURCES}) + target_compile_definitions(${target_name} PRIVATE + MBEDTLS_PLATFORM_ZEROIZE_ALT + memset=picokeys_trusted_memset + memcpy=picokeys_trusted_memcpy + memmove=picokeys_trusted_memmove + memcmp=picokeys_trusted_memcmp + strlen=picokeys_trusted_strlen + strncmp=picokeys_trusted_strncmp + strncpy=picokeys_trusted_strncpy + strchr=picokeys_trusted_strchr + calloc=picokeys_trusted_calloc + free=picokeys_trusted_free + at_the_end_of_time=picokeys_trusted_at_the_end_of_time + pico_sha256_lock=picokeys_trusted_pico_sha256_lock + pico_sha256_unlock=picokeys_trusted_pico_sha256_unlock + pico_sha256_cleanup=picokeys_trusted_pico_sha256_cleanup + pico_sha256_try_start=picokeys_trusted_pico_sha256_try_start + pico_sha256_start_blocking_until=picokeys_trusted_pico_sha256_start_blocking_until + pico_sha256_update=picokeys_trusted_pico_sha256_update + pico_sha256_update_blocking=picokeys_trusted_pico_sha256_update_blocking + pico_sha256_finish=picokeys_trusted_pico_sha256_finish + ) + target_compile_options(${target_name} PRIVATE + -fno-builtin + -ffunction-sections + -fdata-sections + ) + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${target_name} PRIVATE + -fno-tree-loop-distribute-patterns + ) + endif() +endfunction() + +macro(picokeys_setup_trusted_mbedtls) + if(NOT SKIP_MBEDTLS_FOR_OPENSSL_EMULATION) + if(NOT ESP_PLATFORM) + if(PICO_PLATFORM AND NOT ENABLE_EMULATION) + add_library(trusted_mbedtls_build STATIC ${MBEDTLS_SOURCES}) + target_include_directories(trusted_mbedtls_build SYSTEM PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/include + ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/library + ) + configure_picokeys_trusted_mbedtls_target(trusted_mbedtls_build) + set(TRUSTED_MBEDTLS_ARCHIVE ${CMAKE_CURRENT_BINARY_DIR}/libtrusted_mbedtls.a) + set(TRUSTED_LIBGCC_DIR ${CMAKE_CURRENT_BINARY_DIR}/trusted_libgcc) + add_custom_command( + OUTPUT ${TRUSTED_MBEDTLS_ARCHIVE} + COMMAND ${CMAKE_COMMAND} -E rm -f ${TRUSTED_MBEDTLS_ARCHIVE} + COMMAND ${CMAKE_COMMAND} -E rm -rf ${TRUSTED_LIBGCC_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${TRUSTED_LIBGCC_DIR} + COMMAND ${CMAKE_OBJCOPY} + --prefix-alloc-sections=.trusted + --redefine-sym memset=picokeys_trusted_memset + --redefine-sym mbedtls_sha256_init=picokeys_trusted_sha256_init + --redefine-sym mbedtls_sha256_free=picokeys_trusted_sha256_free + --redefine-sym mbedtls_sha256_starts=picokeys_trusted_sha256_starts + --redefine-sym mbedtls_sha256_update=picokeys_trusted_sha256_update + --redefine-sym mbedtls_sha256_finish=picokeys_trusted_sha256_finish + --redefine-sym mbedtls_sha256_clone=picokeys_trusted_sha256_clone + --redefine-sym __aeabi_uldivmod=picokeys_trusted___aeabi_uldivmod + $ + ${TRUSTED_MBEDTLS_ARCHIVE} + COMMAND ${CMAKE_COMMAND} -E chdir ${TRUSTED_LIBGCC_DIR} + ${CMAKE_AR} x ${PICOKEYS_LIBGCC} + _aeabi_uldivmod.o + _udivmoddi4.o + _dvmd_tls.o + COMMAND ${CMAKE_OBJCOPY} + --prefix-alloc-sections=.trusted + --redefine-sym __aeabi_uldivmod=picokeys_trusted___aeabi_uldivmod + --redefine-sym __udivmoddi4=picokeys_trusted___udivmoddi4 + --redefine-sym __aeabi_idiv0=picokeys_trusted___aeabi_idiv0 + ${TRUSTED_LIBGCC_DIR}/_aeabi_uldivmod.o + ${TRUSTED_LIBGCC_DIR}/_aeabi_uldivmod.trusted.o + COMMAND ${CMAKE_OBJCOPY} + --prefix-alloc-sections=.trusted + --redefine-sym __udivmoddi4=picokeys_trusted___udivmoddi4 + ${TRUSTED_LIBGCC_DIR}/_udivmoddi4.o + ${TRUSTED_LIBGCC_DIR}/_udivmoddi4.trusted.o + COMMAND ${CMAKE_OBJCOPY} + --prefix-alloc-sections=.trusted + --redefine-sym __aeabi_idiv0=picokeys_trusted___aeabi_idiv0 + ${TRUSTED_LIBGCC_DIR}/_dvmd_tls.o + ${TRUSTED_LIBGCC_DIR}/_dvmd_tls.trusted.o + COMMAND ${CMAKE_AR} q ${TRUSTED_MBEDTLS_ARCHIVE} + ${TRUSTED_LIBGCC_DIR}/_aeabi_uldivmod.trusted.o + ${TRUSTED_LIBGCC_DIR}/_udivmoddi4.trusted.o + ${TRUSTED_LIBGCC_DIR}/_dvmd_tls.trusted.o + COMMAND ${CMAKE_RANLIB} ${TRUSTED_MBEDTLS_ARCHIVE} + DEPENDS trusted_mbedtls_build + VERBATIM + ) + add_custom_target(trusted_mbedtls_archive DEPENDS ${TRUSTED_MBEDTLS_ARCHIVE}) + add_library(trusted_mbedtls STATIC IMPORTED GLOBAL) + add_dependencies(trusted_mbedtls trusted_mbedtls_archive) + set_target_properties(trusted_mbedtls PROPERTIES + IMPORTED_LOCATION ${TRUSTED_MBEDTLS_ARCHIVE} + ) + elseif(ENABLE_EMULATION AND NOT MSVC) + set(TRUSTED_REGION_EMBED_INPUT + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}mbedtls${CMAKE_STATIC_LIBRARY_SUFFIX} + ) + if(APPLE) + set(PICOKEYS_TRUSTED_SECTION_DIRECTIVE ".section __DATA,__trusted_region,regular,no_dead_strip") + set(PICOKEYS_TRUSTED_START_SYM "___trusted_start") + set(PICOKEYS_TRUSTED_END_SYM "___trusted_end") + set(PICOKEYS_TRUSTED_LOAD_START_SYM "___trusted_load_start") + set(PICOKEYS_TRUSTED_LOAD_END_SYM "___trusted_load_end") + else() + set(PICOKEYS_TRUSTED_SECTION_DIRECTIVE ".section .trusted_region,\"a\",@progbits") + set(PICOKEYS_TRUSTED_START_SYM "__trusted_start") + set(PICOKEYS_TRUSTED_END_SYM "__trusted_end") + set(PICOKEYS_TRUSTED_LOAD_START_SYM "__trusted_load_start") + set(PICOKEYS_TRUSTED_LOAD_END_SYM "__trusted_load_end") + endif() + set(TRUSTED_REGION_EMBED_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/trusted_region_embed.S) + configure_file( + ${CMAKE_CURRENT_LIST_DIR}/src/trusted_region_embed.in.S + ${TRUSTED_REGION_EMBED_SOURCE} + @ONLY + ) + endif() + elseif(ESP_PLATFORM) + add_library(trusted_mbedtls_payload STATIC ${MBEDTLS_SOURCES}) + target_include_directories(trusted_mbedtls_payload + SYSTEM PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/include + ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/library + ) + configure_picokeys_mbedtls_target(trusted_mbedtls_payload) + set(TRUSTED_REGION_EMBED_INPUT + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}trusted_mbedtls_payload${CMAKE_STATIC_LIBRARY_SUFFIX} + ) + set(PICOKEYS_TRUSTED_SECTION_DIRECTIVE ".section .rodata.trusted_region,\"a\",@progbits") + set(PICOKEYS_TRUSTED_START_SYM "__trusted_start") + set(PICOKEYS_TRUSTED_END_SYM "__trusted_end") + set(PICOKEYS_TRUSTED_LOAD_START_SYM "__trusted_load_start") + set(PICOKEYS_TRUSTED_LOAD_END_SYM "__trusted_load_end") + set(TRUSTED_REGION_EMBED_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/trusted_region_embed.S) + configure_file( + ${CMAKE_CURRENT_LIST_DIR}/src/trusted_region_embed.in.S + ${TRUSTED_REGION_EMBED_SOURCE} + @ONLY + ) + endif() + endif() +endmacro() + +macro(picokeys_configure_trusted_support_sources) + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/src/trusted_mem.c PROPERTIES + COMPILE_OPTIONS "-fno-builtin;-fno-tree-loop-distribute-patterns" + ) + else() + set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/src/trusted_mem.c PROPERTIES + COMPILE_OPTIONS "-fno-builtin" + ) + endif() + if(DEFINED TRUSTED_REGION_EMBED_SOURCE) + set_source_files_properties(${TRUSTED_REGION_EMBED_SOURCE} PROPERTIES + OBJECT_DEPENDS "${TRUSTED_REGION_EMBED_INPUT}" + ) + list(APPEND PICOKEYS_SOURCES + ${TRUSTED_REGION_EMBED_SOURCE} + ) + endif() +endmacro() + +macro(picokeys_configure_rp2350_trusted) + if(TARGET trusted_mbedtls_build) + target_include_directories(trusted_mbedtls_build PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/config/rp2350/alt + ) + target_sources(trusted_mbedtls_build PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/config/rp2350/alt/sha256_alt.c + ${CMAKE_CURRENT_LIST_DIR}/src/trusted_pico_sha256.c + ) + target_link_libraries(trusted_mbedtls_build PRIVATE + pico_sha256_headers + pico_bootrom_headers + pico_time_headers + ) + endif() +endmacro() + +macro(picokeys_link_trusted_region target_name) + if(TARGET trusted_mbedtls) + target_link_libraries(${target_name} PRIVATE trusted_mbedtls) + target_link_options(${target_name} PRIVATE + "LINKER:--defsym=__trusted_region_fixed_base=${PICOKEYS_TRUSTED_REGION_FLASH_BASE}" + "LINKER:-T,${CMAKE_CURRENT_LIST_DIR}/config/rp2350/ld/trusted_region.ld" + "LINKER:-T,${CMAKE_CURRENT_LIST_DIR}/config/rp2350/ld/trusted_state.ld" + ) + set_property(TARGET ${target_name} APPEND PROPERTY LINK_DEPENDS + ${CMAKE_CURRENT_LIST_DIR}/config/rp2350/ld/trusted_region.ld + ${CMAKE_CURRENT_LIST_DIR}/config/rp2350/ld/trusted_state.ld + ) + endif() +endmacro() diff --git a/config/rp2350/ld/trusted_region.ld b/config/rp2350/ld/trusted_region.ld new file mode 100644 index 0000000..3a45dcb --- /dev/null +++ b/config/rp2350/ld/trusted_region.ld @@ -0,0 +1,32 @@ +SECTIONS +{ + __trusted_region_min_flash_base = ALIGN(LOADADDR(.flash_end) + SIZEOF(.flash_end), 16); + __trusted_region_flash_base = DEFINED(__trusted_region_fixed_base) ? + __trusted_region_fixed_base : + __trusted_region_min_flash_base; + + .trusted_region __trusted_region_flash_base : + { + . = ALIGN(16); + __trusted_start = .; + + libtrusted_mbedtls.a:(.trusted.text .trusted.text.* .trusted.gnu.linkonce.t.*) + + . = ALIGN(16); + libtrusted_mbedtls.a:(.trusted.rodata .trusted.rodata.* .trusted.srodata .trusted.srodata.* .trusted.gnu.linkonce.r.*) + + . = ALIGN(16); + __trusted_end = .; + } + + __trusted_load_start = LOADADDR(.trusted_region); + __trusted_load_end = LOADADDR(.trusted_region) + SIZEOF(.trusted_region); + __flash_binary_end = __trusted_end; +} + +ASSERT(__trusted_end >= __trusted_start, "trusted region symbols are invalid") +ASSERT(!DEFINED(__trusted_region_fixed_base) || + (__trusted_region_fixed_base >= __trusted_region_min_flash_base), + "PICOKEYS_TRUSTED_REGION_FLASH_BASE is below the end of the regular flash image") + +INSERT AFTER .flash_end; diff --git a/config/rp2350/ld/trusted_state.ld b/config/rp2350/ld/trusted_state.ld new file mode 100644 index 0000000..17b9b00 --- /dev/null +++ b/config/rp2350/ld/trusted_state.ld @@ -0,0 +1,29 @@ +SECTIONS +{ + __trusted_state_ram_base = DEFINED(__trusted_state_fixed_base) ? + __trusted_state_fixed_base : + 0x20070000; + .trusted_data __trusted_state_ram_base : AT (ALIGN(__trusted_load_end, 16)) + { + . = ALIGN(16); + __trusted_data_start = .; + libtrusted_mbedtls.a:(.trusted.data .trusted.data.*) + . = ALIGN(16); + __trusted_data_end = .; + } + __trusted_data_load_start = LOADADDR(.trusted_data); + __trusted_data_load_end = LOADADDR(.trusted_data) + SIZEOF(.trusted_data); + .trusted_bss ALIGN(__trusted_data_end, 16) (NOLOAD) : + { + . = ALIGN(16); + __trusted_bss_start = .; + libtrusted_mbedtls.a:(.trusted.bss .trusted.bss.*) + . = ALIGN(16); + __trusted_bss_end = .; + } +} +ASSERT(__trusted_bss_end >= __trusted_data_start, "trusted state symbols are invalid") +ASSERT(__trusted_state_ram_base >= 0x20000000, "trusted state RAM base is below RP2350 SRAM") +ASSERT(__trusted_bss_end <= 0x20080000, "trusted state exceeds RP2350 main SRAM window") +INSERT AFTER .trusted_region; + diff --git a/picokeys_sdk_import.cmake b/picokeys_sdk_import.cmake index 0da0530..99a1da4 100644 --- a/picokeys_sdk_import.cmake +++ b/picokeys_sdk_import.cmake @@ -81,6 +81,8 @@ if(NOT DEFINED ENABLE_EMULATION) endif() include(${CMAKE_CURRENT_LIST_DIR}/cmake/openssl.cmake) include(${CMAKE_CURRENT_LIST_DIR}/cmake/build_helpers.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/cmake/trusted.cmake) +picokeys_init_trusted_config() option(ENABLE_DELAYED_BOOT "Enable/disable delayed boot" OFF) configure_bool_option( @@ -455,49 +457,11 @@ endif() if(NOT ESP_PLATFORM) if(NOT SKIP_MBEDTLS_FOR_OPENSSL_EMULATION) add_library(mbedtls STATIC ${MBEDTLS_SOURCES}) - target_include_directories(mbedtls SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/include) - - if(PICO_PLATFORM AND NOT ENABLE_EMULATION) - set(TRUSTED_MBEDTLS_ARCHIVE ${CMAKE_CURRENT_BINARY_DIR}/libtrusted_mbedtls.a) - add_custom_command( - OUTPUT ${TRUSTED_MBEDTLS_ARCHIVE} - COMMAND ${CMAKE_COMMAND} -E rm -f ${TRUSTED_MBEDTLS_ARCHIVE} - COMMAND ${CMAKE_OBJCOPY} --prefix-alloc-sections=.trusted $ ${TRUSTED_MBEDTLS_ARCHIVE} - DEPENDS mbedtls - VERBATIM - ) - add_custom_target(trusted_mbedtls_archive DEPENDS ${TRUSTED_MBEDTLS_ARCHIVE}) - add_library(trusted_mbedtls STATIC IMPORTED GLOBAL) - add_dependencies(trusted_mbedtls trusted_mbedtls_archive) - set_target_properties(trusted_mbedtls PROPERTIES - IMPORTED_LOCATION ${TRUSTED_MBEDTLS_ARCHIVE} - ) - add_compile_definitions(PICOKEYS_HAS_TRUSTED_REGION=1) - elseif(ENABLE_EMULATION AND NOT MSVC) - set(TRUSTED_REGION_EMBED_INPUT - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}mbedtls${CMAKE_STATIC_LIBRARY_SUFFIX} - ) - if(APPLE) - set(PICOKEYS_TRUSTED_SECTION_DIRECTIVE ".section __DATA,__trusted_region,regular,no_dead_strip") - set(PICOKEYS_TRUSTED_START_SYM "___trusted_start") - set(PICOKEYS_TRUSTED_END_SYM "___trusted_end") - set(PICOKEYS_TRUSTED_LOAD_START_SYM "___trusted_load_start") - set(PICOKEYS_TRUSTED_LOAD_END_SYM "___trusted_load_end") - else() - set(PICOKEYS_TRUSTED_SECTION_DIRECTIVE ".section .trusted_region,\"a\",@progbits") - set(PICOKEYS_TRUSTED_START_SYM "__trusted_start") - set(PICOKEYS_TRUSTED_END_SYM "__trusted_end") - set(PICOKEYS_TRUSTED_LOAD_START_SYM "__trusted_load_start") - set(PICOKEYS_TRUSTED_LOAD_END_SYM "__trusted_load_end") - endif() - set(TRUSTED_REGION_EMBED_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/trusted_region_embed.S) - configure_file( - ${CMAKE_CURRENT_LIST_DIR}/src/trusted_region_embed.in.S - ${TRUSTED_REGION_EMBED_SOURCE} - @ONLY - ) - add_compile_definitions(PICOKEYS_HAS_TRUSTED_REGION=1) - endif() + target_include_directories(mbedtls SYSTEM PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/include + ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/library + ) + configure_picokeys_mbedtls_target(mbedtls) endif() if(ENABLE_LIBCVC) add_library(libcvc STATIC ${LIBCVC_SOURCES}) @@ -517,29 +481,7 @@ if(NOT ESP_PLATFORM) endif() endif() -if(ESP_PLATFORM AND NOT SKIP_MBEDTLS_FOR_OPENSSL_EMULATION) - add_library(trusted_mbedtls_payload STATIC ${MBEDTLS_SOURCES}) - target_include_directories(trusted_mbedtls_payload - SYSTEM PRIVATE - ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/include - ${CMAKE_CURRENT_LIST_DIR}/third-party/mbedtls/library - ) - set(TRUSTED_REGION_EMBED_INPUT - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}trusted_mbedtls_payload${CMAKE_STATIC_LIBRARY_SUFFIX} - ) - set(PICOKEYS_TRUSTED_SECTION_DIRECTIVE ".section .rodata.trusted_region,\"a\",@progbits") - set(PICOKEYS_TRUSTED_START_SYM "__trusted_start") - set(PICOKEYS_TRUSTED_END_SYM "__trusted_end") - set(PICOKEYS_TRUSTED_LOAD_START_SYM "__trusted_load_start") - set(PICOKEYS_TRUSTED_LOAD_END_SYM "__trusted_load_end") - set(TRUSTED_REGION_EMBED_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/trusted_region_embed.S) - configure_file( - ${CMAKE_CURRENT_LIST_DIR}/src/trusted_region_embed.in.S - ${TRUSTED_REGION_EMBED_SOURCE} - @ONLY - ) - add_compile_definitions(PICOKEYS_HAS_TRUSTED_REGION=1) -endif() +picokeys_setup_trusted_mbedtls() if(PICO_PLATFORM) list(APPEND LIBRARIES @@ -614,14 +556,7 @@ else() ${CMAKE_CURRENT_LIST_DIR}/src/fs/mman.c ) endif() -if(DEFINED TRUSTED_REGION_EMBED_SOURCE) - set_source_files_properties(${TRUSTED_REGION_EMBED_SOURCE} PROPERTIES - OBJECT_DEPENDS "${TRUSTED_REGION_EMBED_INPUT}" - ) - list(APPEND PICOKEYS_SOURCES - ${TRUSTED_REGION_EMBED_SOURCE} - ) -endif() +picokeys_configure_trusted_support_sources() if(ENABLE_EMULATION) if(APPLE) @@ -760,6 +695,7 @@ if(PICO_RP2350) ) target_link_libraries(mbedtls PRIVATE pico_sha256_headers) endif() + picokeys_configure_rp2350_trusted() list(APPEND PICOKEYS_SOURCES ${CMAKE_CURRENT_LIST_DIR}/config/rp2350/alt/sha256_alt.c ) @@ -772,19 +708,7 @@ if(NOT TARGET picokeys_sdk) if(PICO_PLATFORM) pico_add_library(picokeys_sdk) - if(TARGET trusted_mbedtls) - target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE - "-Wl,--whole-archive" - trusted_mbedtls - "-Wl,--no-whole-archive" - ) - target_link_options(${CMAKE_PROJECT_NAME} PRIVATE - "LINKER:-T,${CMAKE_CURRENT_LIST_DIR}/../trusted_region.ld" - ) - set_property(TARGET ${CMAKE_PROJECT_NAME} APPEND PROPERTY LINK_DEPENDS - ${CMAKE_CURRENT_LIST_DIR}/../trusted_region.ld - ) - endif() + picokeys_link_trusted_region(${CMAKE_PROJECT_NAME}) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ${LIBRARIES}) else() add_impl_library(picokeys_sdk) diff --git a/src/main.c b/src/main.c index 89385c7..7f74ee2 100644 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,7 @@ #include "pico_time.h" #include "serial.h" #include "mbedtls/sha256.h" +#include "trusted.h" app_t apps[16]; uint8_t num_apps = 0; @@ -152,6 +153,7 @@ int app_main(void) { #else int main(void) { #endif + trusted_region_init(); serial_init(); #ifndef ENABLE_EMULATION diff --git a/src/rescue.c b/src/rescue.c index e13a4d6..b70bd96 100644 --- a/src/rescue.c +++ b/src/rescue.c @@ -31,7 +31,7 @@ #include "random.h" #include "crypto_utils.h" #include "usb.h" - +#include "trusted.h" #ifdef PICO_PLATFORM extern char __flash_binary_start; @@ -352,6 +352,18 @@ static int cmd_read(void) { res_APDU_size += put_uint32_be((uint32_t)tv_sec, res_APDU); } } + else if (p1 == 0x5) { // GET TRUST DIGEST + uint8_t digest[32]; + int ret = trusted_region_sha256(digest); + if (ret != PICOKEYS_OK) { + return SW_EXEC_ERROR(); + } + memcpy(res_APDU, digest, 32); + res_APDU_size = 32; + } + else { + return SW_INCORRECT_P1P2(); + } return SW_OK(); } diff --git a/src/trusted.c b/src/trusted.c index f333257..46e7e08 100644 --- a/src/trusted.c +++ b/src/trusted.c @@ -17,8 +17,24 @@ #include "trusted.h" +#include +#include + #include "mbedtls/sha256.h" +extern void picokeys_trusted_set_allocators(void *(*calloc_impl)(size_t, size_t), + void (*free_impl)(void *)); +extern void picokeys_trusted_set_memops(picokeys_trusted_memset_fn memset_impl, + picokeys_trusted_memcpy_fn memcpy_impl, + picokeys_trusted_memmove_fn memmove_impl, + picokeys_trusted_memcmp_fn memcmp_impl, + picokeys_trusted_strlen_fn strlen_impl, + picokeys_trusted_strncmp_fn strncmp_impl, + picokeys_trusted_strncpy_fn strncpy_impl, + picokeys_trusted_strchr_fn strchr_impl, + picokeys_trusted_calloc_fn calloc_impl, + picokeys_trusted_free_fn free_impl); + const uint8_t *trusted_region_start(void) { return __trusted_start; } @@ -27,20 +43,14 @@ const uint8_t *trusted_region_end(void) { return __trusted_end; } -const uint8_t *trusted_region_load_start(void) { - return __trusted_start; -} - -const uint8_t *trusted_region_load_end(void) { - return __trusted_end; -} - size_t trusted_region_size(void) { return (size_t)(__trusted_end - __trusted_start); } void trusted_region_init(void) { - /* The trusted measurement is always taken from its flash image range. */ + picokeys_trusted_set_memops(memset, memcpy, memmove, memcmp, + strlen, strncmp, strncpy, + strchr, calloc, free); } int trusted_region_sha256(uint8_t out[32]) { diff --git a/src/trusted.h b/src/trusted.h index d3d9534..5d9cd54 100644 --- a/src/trusted.h +++ b/src/trusted.h @@ -23,16 +23,23 @@ extern const uint8_t __trusted_start[]; extern const uint8_t __trusted_end[]; -extern const uint8_t __trusted_load_start[]; -extern const uint8_t __trusted_load_end[]; /* The canonical trusted measurement is always the flash image range. */ const uint8_t *trusted_region_start(void); const uint8_t *trusted_region_end(void); -const uint8_t *trusted_region_load_start(void); -const uint8_t *trusted_region_load_end(void); size_t trusted_region_size(void); void trusted_region_init(void); int trusted_region_sha256(uint8_t out[32]); +typedef void *(*picokeys_trusted_memset_fn)(void *, int, size_t); +typedef void *(*picokeys_trusted_memcpy_fn)(void *, const void *, size_t); +typedef void *(*picokeys_trusted_memmove_fn)(void *, const void *, size_t); +typedef int (*picokeys_trusted_memcmp_fn)(const void *, const void *, size_t); +typedef size_t (*picokeys_trusted_strlen_fn)(const char *); +typedef int (*picokeys_trusted_strncmp_fn)(const char *, const char *, size_t); +typedef char *(*picokeys_trusted_strncpy_fn)(char *, const char *, size_t); +typedef char *(*picokeys_trusted_strchr_fn)(const char *, int); +typedef void *(*picokeys_trusted_calloc_fn)(size_t, size_t); +typedef void (*picokeys_trusted_free_fn)(void *); + #endif diff --git a/src/trusted_mem.c b/src/trusted_mem.c new file mode 100644 index 0000000..7988290 --- /dev/null +++ b/src/trusted_mem.c @@ -0,0 +1,130 @@ +#include "mbedtls/platform_util.h" +#include "trusted.h" + +#include + +static picokeys_trusted_memset_fn picokeys_trusted_memset_impl; +static picokeys_trusted_memcpy_fn picokeys_trusted_memcpy_impl; +static picokeys_trusted_memmove_fn picokeys_trusted_memmove_impl; +static picokeys_trusted_memcmp_fn picokeys_trusted_memcmp_impl; +static picokeys_trusted_strlen_fn picokeys_trusted_strlen_impl; +static picokeys_trusted_strncmp_fn picokeys_trusted_strncmp_impl; +static picokeys_trusted_strncpy_fn picokeys_trusted_strncpy_impl; +static picokeys_trusted_strchr_fn picokeys_trusted_strchr_impl; +static picokeys_trusted_calloc_fn picokeys_trusted_calloc_impl; +static picokeys_trusted_free_fn picokeys_trusted_free_impl; + +static void picokeys_trusted_uninitialized_call(void) +{ + __builtin_trap(); +} + +void picokeys_trusted_set_memops(picokeys_trusted_memset_fn memset_impl, + picokeys_trusted_memcpy_fn memcpy_impl, + picokeys_trusted_memmove_fn memmove_impl, + picokeys_trusted_memcmp_fn memcmp_impl, + picokeys_trusted_strlen_fn strlen_impl, + picokeys_trusted_strncmp_fn strncmp_impl, + picokeys_trusted_strncpy_fn strncpy_impl, + picokeys_trusted_strchr_fn strchr_impl, + picokeys_trusted_calloc_fn calloc_impl, + picokeys_trusted_free_fn free_impl) +{ + picokeys_trusted_memset_impl = memset_impl; + picokeys_trusted_memcpy_impl = memcpy_impl; + picokeys_trusted_memmove_impl = memmove_impl; + picokeys_trusted_memcmp_impl = memcmp_impl; + picokeys_trusted_strlen_impl = strlen_impl; + picokeys_trusted_strncmp_impl = strncmp_impl; + picokeys_trusted_strncpy_impl = strncpy_impl; + picokeys_trusted_strchr_impl = strchr_impl; + picokeys_trusted_calloc_impl = calloc_impl; + picokeys_trusted_free_impl = free_impl; +} + +void *picokeys_trusted_memset(void *dst, int value, size_t len) +{ + if (picokeys_trusted_memset_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_memset_impl(dst, value, len); +} + +void *picokeys_trusted_memcpy(void *dst, const void *src, size_t len) +{ + if (picokeys_trusted_memcpy_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_memcpy_impl(dst, src, len); +} + +void *picokeys_trusted_memmove(void *dst, const void *src, size_t len) +{ + if (picokeys_trusted_memmove_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_memmove_impl(dst, src, len); +} + +int picokeys_trusted_memcmp(const void *lhs, const void *rhs, size_t len) +{ + if (picokeys_trusted_memcmp_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_memcmp_impl(lhs, rhs, len); +} + +size_t picokeys_trusted_strlen(const char *s) +{ + if (picokeys_trusted_strlen_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_strlen_impl(s); +} + +int picokeys_trusted_strncmp(const char *lhs, const char *rhs, size_t len) +{ + if (picokeys_trusted_strncmp_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_strncmp_impl(lhs, rhs, len); +} + +char *picokeys_trusted_strncpy(char *dst, const char *src, size_t len) +{ + if (picokeys_trusted_strncpy_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_strncpy_impl(dst, src, len); +} + +char *picokeys_trusted_strchr(const char *s, int c) +{ + if (picokeys_trusted_strchr_impl == NULL) { + picokeys_trusted_uninitialized_call(); + } + return picokeys_trusted_strchr_impl(s, c); +} + +void *picokeys_trusted_calloc(size_t nmemb, size_t size) +{ + if (picokeys_trusted_calloc_impl == NULL) { + return NULL; + } + return picokeys_trusted_calloc_impl(nmemb, size); +} + +void picokeys_trusted_free(void *ptr) +{ + if (picokeys_trusted_free_impl != NULL) { + picokeys_trusted_free_impl(ptr); + } +} + +void mbedtls_platform_zeroize(void *buf, size_t len) +{ + if (len > 0) { + picokeys_trusted_memset(buf, 0, len); + asm volatile ("" : : "m" (*(char (*)[len]) buf) :); + } +} diff --git a/src/trusted_pico_sha256.c b/src/trusted_pico_sha256.c new file mode 100644 index 0000000..7c3193f --- /dev/null +++ b/src/trusted_pico_sha256.c @@ -0,0 +1,196 @@ +#include +#include +#include + +#include "hardware/sha256.h" +#include "pico/bootrom/lock.h" +#include "pico/sha256.h" +#include "pico/time.h" + +#define SHA256_PADDING_DATA_BYTES 9 +#define SHA256_BLOCK_SIZE_BYTES 64 + +const absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(at_the_end_of_time, INT64_MAX); + +bool __weak pico_sha256_lock(pico_sha256_state_t *state) +{ + if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256)) { + return false; + } + state->locked = true; + return true; +} + +void __weak pico_sha256_unlock(pico_sha256_state_t *state) +{ + assert(state->locked); + bootrom_release_lock(BOOTROM_LOCK_SHA_256); + state->locked = false; +} + +void pico_sha256_cleanup(pico_sha256_state_t *state) +{ + if (state->locked) { + pico_sha256_unlock(state); + } +} + +int pico_sha256_try_start(pico_sha256_state_t *state, + enum sha256_endianness endianness, + bool use_dma) +{ + (void)use_dma; + + memset(state, 0, sizeof(*state)); + if (!pico_sha256_lock(state)) { + return PICO_ERROR_RESOURCE_IN_USE; + } + + state->endianness = endianness; + state->channel = -1; + sha256_err_not_ready_clear(); + sha256_set_bswap(endianness == SHA256_BIG_ENDIAN); + sha256_start(); + state->total_data_size = 0; + return PICO_OK; +} + +int pico_sha256_start_blocking_until(pico_sha256_state_t *state, + enum sha256_endianness endianness, + bool use_dma, + absolute_time_t until) +{ + int rc; + + (void)until; + + do { + rc = pico_sha256_try_start(state, endianness, use_dma); + } while (rc == PICO_ERROR_RESOURCE_IN_USE); + + return rc; +} + +static void write_to_hardware(pico_sha256_state_t *state, + const uint8_t *data, + size_t data_size_bytes) +{ + if (!state->cache_used && !(((uintptr_t)data) & 3u)) { + GCC_Like_Pragma("GCC diagnostic ignored \"-Wcast-align\"") + const uint32_t *data32 = (const uint32_t *)data; + + while (data_size_bytes >= 4) { + sha256_wait_ready_blocking(); + sha256_put_word(*data32++); + data_size_bytes -= 4; + } + + data = (const uint8_t *)data32; + } + + while (data_size_bytes--) { + state->cache.bytes[state->cache_used++] = *data++; + if (state->cache_used == 4) { + state->cache_used = 0; + sha256_wait_ready_blocking(); + sha256_put_word(state->cache.word); + } + } +} + +static void update_internal(pico_sha256_state_t *state, + const uint8_t *data, + size_t data_size_bytes) +{ + size_t bytes_left; + + assert(state->locked); + + bytes_left = ((state->total_data_size + (SHA256_BLOCK_SIZE_BYTES - 1)) & + ~(SHA256_BLOCK_SIZE_BYTES - 1)) - + state->total_data_size; + if (bytes_left > data_size_bytes) { + bytes_left = data_size_bytes; + } + + if (bytes_left > 0) { + write_to_hardware(state, data, bytes_left); + state->total_data_size += bytes_left; + data_size_bytes -= bytes_left; + data += bytes_left; + } + + if (data_size_bytes > 0) { + write_to_hardware(state, data, data_size_bytes); + state->total_data_size += data_size_bytes; + } +} + +static void add_zero_bytes(pico_sha256_state_t *state, size_t data_size_bytes) +{ + uint32_t zero = 0; + + assert(data_size_bytes < INT32_MAX); + while ((int32_t)data_size_bytes > 0) { + update_internal(state, (uint8_t *)&zero, MIN(4, data_size_bytes)); + data_size_bytes -= 4; + } +} + +void pico_sha256_update(pico_sha256_state_t *state, + const uint8_t *data, + size_t data_size_bytes) +{ + update_internal(state, data, data_size_bytes); +} + +void pico_sha256_update_blocking(pico_sha256_state_t *state, + const uint8_t *data, + size_t data_size_bytes) +{ + update_internal(state, data, data_size_bytes); +} + +static void write_padding(pico_sha256_state_t *state) +{ + uint64_t size; + size_t user_data_size = state->total_data_size; + size_t padding_size_bytes; + const uint8_t one_bit = 0x80; + + size = (state->total_data_size + SHA256_PADDING_DATA_BYTES + + (SHA256_BLOCK_SIZE_BYTES - 1)) & + ~(SHA256_BLOCK_SIZE_BYTES - 1); + padding_size_bytes = size - state->total_data_size; + + update_internal(state, &one_bit, 1); + add_zero_bytes(state, padding_size_bytes - SHA256_PADDING_DATA_BYTES); + + size = __builtin_bswap64(user_data_size * 8); + update_internal(state, (uint8_t *)&size, sizeof(uint64_t)); +} + +static void trusted_sha256_get_result(sha256_result_t *out, + enum sha256_endianness endianness) +{ + for (uint i = 0; i < count_of(out->words); ++i) { + uint32_t data = sha256_hw->sum[i]; + if (endianness == SHA256_BIG_ENDIAN) { + data = __builtin_bswap32(data); + } + out->words[i] = data; + } +} + +void pico_sha256_finish(pico_sha256_state_t *state, sha256_result_t *out) +{ + assert(state->locked); + + if (out) { + write_padding(state); + sha256_wait_valid_blocking(); + trusted_sha256_get_result(out, state->endianness); + } + + pico_sha256_unlock(state); +}