Skip to content

Commit a13e443

Browse files
committed
Add single use support
1 parent 46056c4 commit a13e443

9 files changed

Lines changed: 85 additions & 12 deletions

File tree

src/rp2_common/pico_aes/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ pico_mirrored_target_link_libraries(pico_aes INTERFACE
1616
function(pico_aes_configure_binary TARGET)
1717
pico_include_in_generated_section(${TARGET} post_data section_aes_scratch.incl)
1818
pico_include_in_generated_section(${TARGET} post_end section_aes_end.incl)
19-
target_compile_definitions(${TARGET} PRIVATE PICO_AES_CONFIGURED=1)
19+
target_compile_definitions(${TARGET} PRIVATE PICO_AES_CONFIGURED=1 PICO_AES_SINGLE_USE=0)
20+
endfunction()
21+
22+
function(pico_aes_configure_single_use_binary TARGET)
23+
target_compile_definitions(${TARGET} PRIVATE PICO_AES_CONFIGURED=1 PICO_AES_SINGLE_USE=1)
2024
endfunction()

src/rp2_common/pico_aes/aes.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,11 @@ rcp_iequal_nodelay r1, r0
175175
@ Put workspace in the second scratch area
176176
@ The "a"=allocatable attribute (and possibly the %progbits attribute) are necessary to store the murmur3 constants,
177177
@ otherwise they may end up silently replaced with 0 or 0xffffffff
178+
#if PICO_AES_SINGLE_USE
179+
.section .scratch_y.aes,"aw",%progbits
180+
#else
178181
.section .aes_scratch_y.aes,"aw",%progbits
182+
#endif
179183

180184
aes_workspace_start:
181185

src/rp2_common/pico_aes/aes.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ static pico_aes_context_t aes_context = {};
3838
})
3939

4040

41+
#if PICO_AES_SINGLE_USE
4142
// The function lock_key() is called from pico_aes_decrypt_internal() after key initialisation is complete and before decryption begins.
4243
// That is a suitable point to lock the OTP area where key information is stored.
43-
__weak void pico_aes_lock_key() {
44+
void pico_aes_lock_key() {
4445
io_rw_32 *sw_lock = __get_opaque_ptr(&otp_hw->sw_lock[0]) + aes_context.otp_key_page;
4546
#if PICO_AES_HARDENING
4647
// prevent compiler from re-using sw_lock pointer
@@ -79,7 +80,15 @@ __weak void pico_aes_lock_key() {
7980
#endif
8081
}
8182

82-
__weak void pico_aes_lock_all(void) {
83+
#else // not PICO_AES_SINGLE_USE
84+
void pico_aes_lock_key(void) {
85+
#if RC_COUNT
86+
rcp_count_check_nodelay(31 + PICO_AES256_RCP_COUNT_DELTA);
87+
#endif
88+
}
89+
#endif // PICO_AES_SINGLE_USE
90+
91+
void pico_aes_lock_all(void) {
8392
io_rw_32 *sw_lock = __get_opaque_ptr(&otp_hw->sw_lock[0]) + aes_context.otp_key_page;
8493
#if PICO_AES_HARDENING
8594
// we only actually need to lock page 2 but we lock and check 0, 1, 2 anyway
@@ -116,21 +125,23 @@ __weak void pico_aes_lock_all(void) {
116125
#endif
117126
}
118127

119-
#include <stdio.h>
128+
120129
int pico_aes_try_decrypt(uint8_t(*data)[16], size_t data_size, uint32_t otp_key_page, uint8_t* iv_public) {
121130
if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256)) return PICO_ERROR_RESOURCE_IN_USE;
122131

123132
aes_context.otp_key_page = otp_key_page;
124133

125134
uint16_t* otp_data = (uint16_t*)OTP_DATA_GUARDED_BASE;
126135

136+
#if !PICO_AES_SINGLE_USE
127137
// Restore aes_scratch_y from stored location in RAM_STORE
128138
extern uint32_t __aes_scratch_y_source__;
129139
extern uint32_t __aes_scratch_y_start__;
130140
extern uint32_t __aes_scratch_y_end__;
131141

132142
uint32_t stored_words = (uint32_t)(&__aes_scratch_y_end__ - &__aes_scratch_y_start__);
133143
memcpy(&__aes_scratch_y_start__, &__aes_scratch_y_source__, stored_words * sizeof(uint32_t));
144+
#endif // !PICO_AES_SINGLE_USE
134145

135146
pico_aes_decrypt_internal(
136147
(uint8_t*)&(otp_data[otp_key_page * 0x40]),

src/rp2_common/pico_aes/include/pico/aes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646

4747
int pico_aes_try_decrypt(uint8_t(*data)[16], size_t data_size, uint32_t otp_key_page, uint8_t* iv_public);
4848

49+
void pico_aes_lock_all(void);
50+
4951
#endif
5052

5153
#endif
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* Contains some assertions for use with pico_aes */
2+
3+
SECTIONS
4+
{
5+
ASSERT(chaff==0x20081000, "Chaff array must be located at 0x20081000")
6+
ASSERT(__scratch_y_start__ == __scratch_y_end__, "Cannot use scratch_y when using pico_aes")
7+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* Defines the following symbols for use by code:
2+
__aes_scratch_y_start__, __aes_scratch_y_end__, __aes_scratch_y_source__
3+
*/
4+
5+
SECTIONS
6+
{
7+
.aes_scratch_y : {
8+
__aes_scratch_y_start__ = .;
9+
*(.aes_scratch_y.*)
10+
. = ALIGN(4);
11+
__aes_scratch_y_end__ = .;
12+
} > SCRATCH_Y AT> RAM_STORE
13+
__aes_scratch_y_source__ = LOADADDR(.aes_scratch_y);
14+
}

test/pico_aes_test/BUILD.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# pico_aes is not supported in Bazel, as it requires encryption
32

43
exports_files(

test/pico_aes_test/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,24 @@ target_compile_definitions(pico_aes_test PRIVATE
2222
pico_aes_configure_binary(pico_aes_test)
2323
pico_sign_binary(pico_aes_test ${PICO_SDK_PATH}/tools/example_keys/private.pem)
2424
pico_add_extra_outputs(pico_aes_test)
25+
26+
27+
add_executable(pico_aes_test_single
28+
pico_aes_test.c
29+
)
30+
target_link_libraries(pico_aes_test_single
31+
pico_stdlib
32+
pico_aes
33+
pico_rand
34+
)
35+
target_include_directories(pico_aes_test_single PRIVATE
36+
${CMAKE_CURRENT_LIST_DIR}
37+
)
38+
target_compile_definitions(pico_aes_test_single PRIVATE
39+
PICO_USE_STACK_GUARDS=1
40+
PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64
41+
PICO_STACK_SIZE=0x9e0 # maximum stack size that fits
42+
)
43+
pico_aes_configure_single_use_binary(pico_aes_test_single)
44+
pico_sign_binary(pico_aes_test_single ${PICO_SDK_PATH}/tools/example_keys/private.pem)
45+
pico_add_extra_outputs(pico_aes_test_single)

test/pico_aes_test/pico_aes_test.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,25 @@
2121
#define BUFFER_WORD_SIZE (BUFFER_SIZE/sizeof(uint32_t))
2222

2323

24-
void pico_aes_lock_key(void) {
25-
#if RC_COUNT
26-
rcp_count_check_nodelay(31 + PICO_AES256_RCP_COUNT_DELTA);
27-
#endif
28-
}
29-
void pico_aes_lock_all(void) {}
30-
3124
int main() {
3225
stdio_init_all();
3326
printf("AES Test Starting\n");
3427

3528
bool passing = true;
29+
#if PICO_AES_SINGLE_USE
30+
uint32_t *data = malloc(BUFFER_SIZE);
31+
hard_assert(data);
32+
for (int i=0; i < BUFFER_WORD_SIZE; i++) data[i] = get_rand_32();
33+
printf("Buffer start %08x %08x %08x\n", data[0], data[1], data[2]);
34+
35+
uint32_t* iv_public = malloc(16);
36+
hard_assert(iv_public);
37+
for (int i=0; i < 16/sizeof(uint32_t); i++) iv_public[i] = get_rand_32();
38+
39+
pico_aes_try_decrypt((void*)data, BUFFER_SIZE, 29, (uint8_t*)iv_public);
40+
41+
printf("Buffer encrypt %08x %08x %08x\n", data[0], data[1], data[2]);
42+
#else
3643
for (int n=0; n < 10; n++) {
3744
uint32_t *data = malloc(BUFFER_SIZE);
3845
uint32_t *data_orig = malloc(BUFFER_SIZE);
@@ -65,6 +72,10 @@ int main() {
6572
if (!passing) break;
6673
else printf("run %d passed\n", n);
6774
}
75+
#endif
76+
77+
// Lock all keys now decryption is finished
78+
pico_aes_lock_all();
6879

6980
if (passing) printf("PASSED\n");
7081
else printf("FAILED\n");

0 commit comments

Comments
 (0)