fw/testfw: Use fw_ram for firmware stack

This means firmware's stack shouldn't be accessible to programs
running in app_mode.

It also means we don't need to take special care of secure_ctx which
can now be an ordinary stack variable.

Nonetheless we zero out secure_ctx after final use and inline some
assembler to zero out the entire fw_ram after use, just before
switching to app_mode.

Signed-off-by: Daniel Lublin <daniel@lublin.se>
This commit is contained in:
Michael Cardell Widerkrantz 2023-03-02 18:20:28 +01:00 committed by Daniel Lublin
parent d2240b3e0f
commit 56e34b3add
No known key found for this signature in database
GPG Key ID: 75BD0FEB8D3E7830
3 changed files with 39 additions and 23 deletions

View File

@ -187,6 +187,13 @@ int main()
// Turn on application mode. // Turn on application mode.
// ------------------------- // -------------------------
// Set up another stack because fw_ram is not available
// anymore in app_mode.
asm volatile(
"li sp, 0x40006ff0"
);
*switch_app = 1; *switch_app = 1;
sw = *switch_app; sw = *switch_app;

View File

@ -21,7 +21,6 @@ static volatile uint32_t *udi = (volatile uint32_t *)TK1_MMIO_TK1_UD
static volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST; static volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
static volatile uint32_t *app_addr = (volatile uint32_t *)TK1_MMIO_TK1_APP_ADDR; static volatile uint32_t *app_addr = (volatile uint32_t *)TK1_MMIO_TK1_APP_ADDR;
static volatile uint32_t *app_size = (volatile uint32_t *)TK1_MMIO_TK1_APP_SIZE; static volatile uint32_t *app_size = (volatile uint32_t *)TK1_MMIO_TK1_APP_SIZE;
static volatile uint8_t *fw_ram = (volatile uint8_t *)TK1_MMIO_FW_RAM_BASE;
static volatile uint32_t *fw_blake2s_addr = (volatile uint32_t *)TK1_MMIO_TK1_BLAKE2S; static volatile uint32_t *fw_blake2s_addr = (volatile uint32_t *)TK1_MMIO_TK1_BLAKE2S;
static volatile uint32_t *trng_status = (volatile uint32_t *)TK1_MMIO_TRNG_STATUS; static volatile uint32_t *trng_status = (volatile uint32_t *)TK1_MMIO_TRNG_STATUS;
static volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY; static volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY;
@ -95,6 +94,7 @@ static void print_digest(uint8_t *md)
static void compute_cdi(uint8_t digest[32], uint8_t use_uss, uint8_t uss[32]) static void compute_cdi(uint8_t digest[32], uint8_t use_uss, uint8_t uss[32])
{ {
uint32_t local_cdi[8]; uint32_t local_cdi[8];
blake2s_ctx secure_ctx;
// Prepare to sleep a random number of cycles before reading out UDS // Prepare to sleep a random number of cycles before reading out UDS
*timer_prescaler = 1; *timer_prescaler = 1;
@ -108,30 +108,26 @@ static void compute_cdi(uint8_t digest[32], uint8_t use_uss, uint8_t uss[32])
while (*timer_status & (1 << TK1_MMIO_TIMER_STATUS_RUNNING_BIT)) { while (*timer_status & (1 << TK1_MMIO_TIMER_STATUS_RUNNING_BIT)) {
} }
// Use firmware-only RAM for BLAKE2s context instead of int blake2err = blake2s_init(&secure_ctx, 32, NULL, 0);
// ordinary RAM
blake2s_ctx *secure_ctx = (blake2s_ctx *)fw_ram;
int blake2err = blake2s_init(secure_ctx, 32, NULL, 0);
assert(blake2err == 0); assert(blake2err == 0);
// Update hash with UDS. This means UDS will live for a short // Update hash with UDS. This means UDS will live for a short
// while in secure_ctx->b which is in the special fw_ram. // while on the firmware stack which is in the special fw_ram.
blake2s_update(secure_ctx, (const void *)uds, 32); blake2s_update(&secure_ctx, (const void *)uds, 32);
// Update with TKey program digest // Update with TKey program digest
blake2s_update(secure_ctx, digest, 32); blake2s_update(&secure_ctx, digest, 32);
// Possibly hash in the USS as well // Possibly hash in the USS as well
if (use_uss != 0) { if (use_uss != 0) {
blake2s_update(secure_ctx, uss, 32); blake2s_update(&secure_ctx, uss, 32);
} }
// Write hashed result to Compound Device Identity (CDI) // Write hashed result to Compound Device Identity (CDI)
blake2s_final(secure_ctx, local_cdi); blake2s_final(&secure_ctx, local_cdi);
// Write over the firmware-only RAM // Clear secure_ctx of any residue
memset((void *)fw_ram, 0, TK1_MMIO_FW_RAM_SIZE); memset(&secure_ctx, 0, sizeof(secure_ctx));
// CDI only word writable // CDI only word writable
wordcpy_s((void *)cdi, 8, local_cdi, 8); wordcpy_s((void *)cdi, 8, local_cdi, 8);
@ -186,31 +182,42 @@ int main()
break; break;
case FW_STATE_RUN: case FW_STATE_RUN:
htif_puts("state_run\n");
*app_addr = TK1_APP_ADDR; *app_addr = TK1_APP_ADDR;
// CDI = hash(uds, hash(app), uss) // CDI = hash(uds, hash(app), uss)
compute_cdi(digest, use_uss, uss); compute_cdi(digest, use_uss, uss);
// Flip over to application mode htif_puts("Flipping to app mode!\n");
*switch_app = 1;
// Jump to app - doesn't return
// First clears memory of firmware remains
htif_puts("Jumping to "); htif_puts("Jumping to ");
htif_putinthex(*app_addr); htif_putinthex(*app_addr);
htif_lf(); htif_lf();
// Clear the firmware stack
// clang-format off // clang-format off
asm volatile( asm volatile(
// Clear the stack "li a0, 0xd0000000;" // FW_RAM
"li a0, 0x40000000;" // TK1_RAM_BASE "li a1, 0xd0000400;" // End of FW_RAM
"li a1, 0x40007000;" // TK1_APP_ADDR
"loop:;" "loop:;"
"sw zero, 0(a0);" "sw zero, 0(a0);"
"addi a0, a0, 4;" "addi a0, a0, 4;"
"blt a0, a1, loop;" "blt a0, a1, loop;"
::: "memory");
// clang-format on
// Flip over to application mode
*switch_app = 1;
// XXX Firmware stack now no longer available
// Don't use any function calls!
// Jump to app - doesn't return
// clang-format off
asm volatile(
// Get value at TK1_MMIO_TK1_APP_ADDR // Get value at TK1_MMIO_TK1_APP_ADDR
"lui a0,0xff000;" "lui a0,0xff000;"
"lw a0,0x030(a0);" "lw a0,0x030(a0);"
// Jump to it
"jalr x0,0(a0);" "jalr x0,0(a0);"
::: "memory"); ::: "memory");
// clang-format on // clang-format on

View File

@ -46,8 +46,10 @@ clear:
addi a0, a0, 4 addi a0, a0, 4
blt a0, a1, clear blt a0, a1, clear
/* init stack below 0x40007000 (TK1_APP_ADDR) where we load app */ /*
li sp, 0x40006ff0 * Init stack at top of fw_ram. Leave 16 byte for entering our first function
*/
li sp, 0xd00003f0 // 1 kiB - 16 byte in FW_RAM
/* copy data section */ /* copy data section */
la a0, _sidata la a0, _sidata