Add single use support
diff --git a/src/rp2_common/pico_aes/CMakeLists.txt b/src/rp2_common/pico_aes/CMakeLists.txt index b1b82e3..cc11494 100644 --- a/src/rp2_common/pico_aes/CMakeLists.txt +++ b/src/rp2_common/pico_aes/CMakeLists.txt
@@ -16,5 +16,9 @@ function(pico_aes_configure_binary TARGET) pico_include_in_generated_section(${TARGET} post_data section_aes_scratch.incl) pico_include_in_generated_section(${TARGET} post_end section_aes_end.incl) - target_compile_definitions(${TARGET} PRIVATE PICO_AES_CONFIGURED=1) + target_compile_definitions(${TARGET} PRIVATE PICO_AES_CONFIGURED=1 PICO_AES_SINGLE_USE=0) +endfunction() + +function(pico_aes_configure_single_use_binary TARGET) + target_compile_definitions(${TARGET} PRIVATE PICO_AES_CONFIGURED=1 PICO_AES_SINGLE_USE=1) endfunction()
diff --git a/src/rp2_common/pico_aes/aes.S b/src/rp2_common/pico_aes/aes.S index b3b4fb3..e8137c0 100644 --- a/src/rp2_common/pico_aes/aes.S +++ b/src/rp2_common/pico_aes/aes.S
@@ -175,7 +175,11 @@ @ Put workspace in the second scratch area @ The "a"=allocatable attribute (and possibly the %progbits attribute) are necessary to store the murmur3 constants, @ otherwise they may end up silently replaced with 0 or 0xffffffff +#if PICO_AES_SINGLE_USE +.section .scratch_y.aes,"aw",%progbits +#else .section .aes_scratch_y.aes,"aw",%progbits +#endif aes_workspace_start:
diff --git a/src/rp2_common/pico_aes/aes.c b/src/rp2_common/pico_aes/aes.c index d49f0d1..cf7f390 100644 --- a/src/rp2_common/pico_aes/aes.c +++ b/src/rp2_common/pico_aes/aes.c
@@ -38,9 +38,10 @@ }) +#if PICO_AES_SINGLE_USE // The function lock_key() is called from pico_aes_decrypt_internal() after key initialisation is complete and before decryption begins. // That is a suitable point to lock the OTP area where key information is stored. -__weak void pico_aes_lock_key() { +void pico_aes_lock_key() { io_rw_32 *sw_lock = __get_opaque_ptr(&otp_hw->sw_lock[0]) + aes_context.otp_key_page; #if PICO_AES_HARDENING // prevent compiler from re-using sw_lock pointer @@ -79,7 +80,15 @@ #endif } -__weak void pico_aes_lock_all(void) { +#else // not PICO_AES_SINGLE_USE +void pico_aes_lock_key(void) { +#if RC_COUNT + rcp_count_check_nodelay(31 + PICO_AES256_RCP_COUNT_DELTA); +#endif +} +#endif // PICO_AES_SINGLE_USE + +void pico_aes_lock_all(void) { io_rw_32 *sw_lock = __get_opaque_ptr(&otp_hw->sw_lock[0]) + aes_context.otp_key_page; #if PICO_AES_HARDENING // we only actually need to lock page 2 but we lock and check 0, 1, 2 anyway @@ -116,7 +125,7 @@ #endif } -#include <stdio.h> + int pico_aes_try_decrypt(uint8_t(*data)[16], size_t data_size, uint32_t otp_key_page, uint8_t* iv_public) { if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256)) return PICO_ERROR_RESOURCE_IN_USE; @@ -124,6 +133,7 @@ uint16_t* otp_data = (uint16_t*)OTP_DATA_GUARDED_BASE; +#if !PICO_AES_SINGLE_USE // Restore aes_scratch_y from stored location in RAM_STORE extern uint32_t __aes_scratch_y_source__; extern uint32_t __aes_scratch_y_start__; @@ -131,6 +141,7 @@ uint32_t stored_words = (uint32_t)(&__aes_scratch_y_end__ - &__aes_scratch_y_start__); memcpy(&__aes_scratch_y_start__, &__aes_scratch_y_source__, stored_words * sizeof(uint32_t)); +#endif // !PICO_AES_SINGLE_USE pico_aes_decrypt_internal( (uint8_t*)&(otp_data[otp_key_page * 0x40]),
diff --git a/src/rp2_common/pico_aes/include/pico/aes.h b/src/rp2_common/pico_aes/include/pico/aes.h index 0e02c13..37ed37f 100644 --- a/src/rp2_common/pico_aes/include/pico/aes.h +++ b/src/rp2_common/pico_aes/include/pico/aes.h
@@ -46,6 +46,8 @@ int pico_aes_try_decrypt(uint8_t(*data)[16], size_t data_size, uint32_t otp_key_page, uint8_t* iv_public); +void pico_aes_lock_all(void); + #endif #endif
diff --git a/src/rp2_common/pico_standard_link/script_include/section_aes_end.incl b/src/rp2_common/pico_standard_link/script_include/section_aes_end.incl new file mode 100644 index 0000000..7313305 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_aes_end.incl
@@ -0,0 +1,7 @@ +/* Contains some assertions for use with pico_aes */ + +SECTIONS +{ + ASSERT(chaff==0x20081000, "Chaff array must be located at 0x20081000") + ASSERT(__scratch_y_start__ == __scratch_y_end__, "Cannot use scratch_y when using pico_aes") +}
diff --git a/src/rp2_common/pico_standard_link/script_include/section_aes_scratch.incl b/src/rp2_common/pico_standard_link/script_include/section_aes_scratch.incl new file mode 100644 index 0000000..5c6c2e6 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_aes_scratch.incl
@@ -0,0 +1,14 @@ +/* Defines the following symbols for use by code: + __aes_scratch_y_start__, __aes_scratch_y_end__, __aes_scratch_y_source__ +*/ + +SECTIONS +{ + .aes_scratch_y : { + __aes_scratch_y_start__ = .; + *(.aes_scratch_y.*) + . = ALIGN(4); + __aes_scratch_y_end__ = .; + } > SCRATCH_Y AT> RAM_STORE + __aes_scratch_y_source__ = LOADADDR(.aes_scratch_y); +}
diff --git a/test/pico_aes_test/BUILD.bazel b/test/pico_aes_test/BUILD.bazel index 6413a72..fc1fe75 100644 --- a/test/pico_aes_test/BUILD.bazel +++ b/test/pico_aes_test/BUILD.bazel
@@ -1,4 +1,3 @@ - # pico_aes is not supported in Bazel, as it requires encryption exports_files(
diff --git a/test/pico_aes_test/CMakeLists.txt b/test/pico_aes_test/CMakeLists.txt index 619cd3b..01c20a4 100644 --- a/test/pico_aes_test/CMakeLists.txt +++ b/test/pico_aes_test/CMakeLists.txt
@@ -22,3 +22,24 @@ pico_aes_configure_binary(pico_aes_test) pico_sign_binary(pico_aes_test ${PICO_SDK_PATH}/tools/example_keys/private.pem) pico_add_extra_outputs(pico_aes_test) + + +add_executable(pico_aes_test_single + pico_aes_test.c + ) +target_link_libraries(pico_aes_test_single + pico_stdlib + pico_aes + pico_rand +) +target_include_directories(pico_aes_test_single PRIVATE + ${CMAKE_CURRENT_LIST_DIR} +) +target_compile_definitions(pico_aes_test_single PRIVATE + PICO_USE_STACK_GUARDS=1 + PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64 + PICO_STACK_SIZE=0x9e0 # maximum stack size that fits +) +pico_aes_configure_single_use_binary(pico_aes_test_single) +pico_sign_binary(pico_aes_test_single ${PICO_SDK_PATH}/tools/example_keys/private.pem) +pico_add_extra_outputs(pico_aes_test_single)
diff --git a/test/pico_aes_test/pico_aes_test.c b/test/pico_aes_test/pico_aes_test.c index 887f92c..3fb8dfd 100644 --- a/test/pico_aes_test/pico_aes_test.c +++ b/test/pico_aes_test/pico_aes_test.c
@@ -21,18 +21,25 @@ #define BUFFER_WORD_SIZE (BUFFER_SIZE/sizeof(uint32_t)) -void pico_aes_lock_key(void) { -#if RC_COUNT - rcp_count_check_nodelay(31 + PICO_AES256_RCP_COUNT_DELTA); -#endif -} -void pico_aes_lock_all(void) {} - int main() { stdio_init_all(); printf("AES Test Starting\n"); bool passing = true; +#if PICO_AES_SINGLE_USE + uint32_t *data = malloc(BUFFER_SIZE); + hard_assert(data); + for (int i=0; i < BUFFER_WORD_SIZE; i++) data[i] = get_rand_32(); + printf("Buffer start %08x %08x %08x\n", data[0], data[1], data[2]); + + uint32_t* iv_public = malloc(16); + hard_assert(iv_public); + for (int i=0; i < 16/sizeof(uint32_t); i++) iv_public[i] = get_rand_32(); + + pico_aes_try_decrypt((void*)data, BUFFER_SIZE, 29, (uint8_t*)iv_public); + + printf("Buffer encrypt %08x %08x %08x\n", data[0], data[1], data[2]); +#else for (int n=0; n < 10; n++) { uint32_t *data = malloc(BUFFER_SIZE); uint32_t *data_orig = malloc(BUFFER_SIZE); @@ -65,6 +72,10 @@ if (!passing) break; else printf("run %d passed\n", n); } +#endif + + // Lock all keys now decryption is finished + pico_aes_lock_all(); if (passing) printf("PASSED\n"); else printf("FAILED\n");