1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-07 15:18:08 +00:00

refactor(core): update bootloader from coreapp, using syscalls (and smcalls)

[no changelog]
This commit is contained in:
tychovrahe 2025-06-18 16:40:41 +02:00 committed by TychoVrahe
parent f5123c8b3f
commit 9f2dec6169
28 changed files with 277 additions and 106 deletions

View File

@ -468,6 +468,7 @@ ALLPATHS = [
'embed/models', 'embed/models',
'embed/gfx/inc', 'embed/gfx/inc',
'embed/sys/bsp/inc', 'embed/sys/bsp/inc',
'embed/util/bl_check/inc',
'embed/util/image/inc', 'embed/util/image/inc',
'embed/util/rsod/inc', 'embed/util/rsod/inc',
'embed/util/scm_revision/inc', 'embed/util/scm_revision/inc',
@ -907,6 +908,16 @@ if 'nrf' in FEATURES_AVAILABLE:
f'embed/models/{TREZOR_MODEL}/trezor-ble.bin', f'embed/models/{TREZOR_MODEL}/trezor-ble.bin',
) )
tools.embed_compressed_binary(
obj_program,
env,
'bootloader',
'embed/projects/bootloaders/bootloader.o',
f'embed/models/{TREZOR_MODEL}/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin',
'firmware',
'bootloader',
)
env.Depends(obj_program, qstr_generated) env.Depends(obj_program, qstr_generated)
linkerscript_gen = env.Command( linkerscript_gen = env.Command(

View File

@ -408,16 +408,6 @@ obj_program.extend(
' --rename-section .data=.vendorheader,alloc,load,readonly,contents' ' --rename-section .data=.vendorheader,alloc,load,readonly,contents'
' $SOURCE $TARGET', )) ' $SOURCE $TARGET', ))
tools.embed_compressed_binary(
obj_program,
env,
'bootloader',
'embed/projects/bootloaders/bootloader.o',
f'embed/models/{TREZOR_MODEL}/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin',
'kernel',
'bootloader',
)
if "secmon_layout" in FEATURES_AVAILABLE: if "secmon_layout" in FEATURES_AVAILABLE:
tools.embed_raw_binary( tools.embed_raw_binary(
obj_program, obj_program,

View File

@ -361,10 +361,6 @@ cmake_gen = env.Command(
action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS',
) )
BOOTLOADER_SUFFIX = TREZOR_MODEL
if BOOTLOADER_QA:
BOOTLOADER_SUFFIX += '_qa'
# select vendor header # select vendor header
if BOOTLOADER_QA or BOOTLOADER_DEVEL: if BOOTLOADER_QA or BOOTLOADER_DEVEL:
vendor = "dev_DO_NOT_SIGN_signed_dev" vendor = "dev_DO_NOT_SIGN_signed_dev"
@ -389,16 +385,6 @@ obj_program.extend(
' --rename-section .data=.vendorheader,alloc,load,readonly,contents' ' --rename-section .data=.vendorheader,alloc,load,readonly,contents'
' $SOURCE $TARGET', )) ' $SOURCE $TARGET', ))
tools.embed_compressed_binary(
obj_program,
env,
'bootloader',
'embed/projects/bootloaders/bootloader.o',
f'embed/models/{TREZOR_MODEL}/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin',
'secmon',
'bootloader',
)
linkerscript_gen = env.Command( linkerscript_gen = env.Command(
target='memory.ld', target='memory.ld',
source=[f'embed/models/{TREZOR_MODEL}/memory_secmon.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='secmon')], source=[f'embed/models/{TREZOR_MODEL}/memory_secmon.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='secmon')],

View File

@ -37,13 +37,33 @@
#include <sys/linker_utils.h> #include <sys/linker_utils.h>
#include <sys/systask.h> #include <sys/systask.h>
#include <sys/system.h> #include <sys/system.h>
#include <util/bl_check.h>
#include <util/rsod.h> #include <util/rsod.h>
#include "rust_ui_common.h" #include "rust_ui_common.h"
#include <blake2s.h>
#ifdef USE_SECP256K1_ZKP #ifdef USE_SECP256K1_ZKP
#include "zkp_context.h" #include "zkp_context.h"
#endif #endif
#define CONCAT_NAME_HELPER(prefix, name, suffix) prefix##name##suffix
#define CONCAT_NAME(name, var) CONCAT_NAME_HELPER(BOOTLOADER_, name, var)
#if BOOTLOADER_QA
// QA bootloaders
#define BOOTLOADER_00 CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _QA_00)
#define BOOTLOADER_FF CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _QA_FF)
#else
// normal bootloaders
#define BOOTLOADER_00 CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _00)
#define BOOTLOADER_FF CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _FF)
#endif
// symbols from bootloader.bin => bootloader.o
extern const void _deflated_bootloader_start;
extern const void _deflated_bootloader_size;
#ifdef USE_NRF #ifdef USE_NRF
#include <io/nrf.h> #include <io/nrf.h>
@ -62,14 +82,47 @@ int main_func(uint32_t cmd, void *arg) {
bool fading = DISPLAY_JUMP_BEHAVIOR == DISPLAY_RESET_CONTENT; bool fading = DISPLAY_JUMP_BEHAVIOR == DISPLAY_RESET_CONTENT;
bool update_required = false;
#if PRODUCTION || BOOTLOADER_QA
// replace bootloader with the latest one
const uint8_t *data = (const uint8_t *)&_deflated_bootloader_start;
const size_t len = (size_t)&_deflated_bootloader_size;
uint8_t hash_00[] = BOOTLOADER_00;
uint8_t hash_FF[] = BOOTLOADER_FF;
// Check if the boardloader is valid and replace it if not
bool bl_update_required =
bl_check_check(hash_00, hash_FF, BLAKE2S_DIGEST_LENGTH);
update_required = update_required || bl_update_required;
#endif
#ifdef USE_NRF #ifdef USE_NRF
if (nrf_update_required(&nrf_app_start, (size_t)&nrf_app_size)) { bool nrf_update_required_ =
nrf_update_required(&nrf_app_start, (size_t)&nrf_app_size);
update_required = update_required || nrf_update_required_;
#endif
if (update_required) {
screen_update(); screen_update();
nrf_update(&nrf_app_start, (size_t)&nrf_app_size);
fading = true; fading = true;
#if PRODUCTION || BOOTLOADER_QA
if (bl_update_required) {
bl_check_replace(data, len);
} }
#endif #endif
#ifdef USE_NRF
if (nrf_update_required_) {
nrf_update(&nrf_app_start, (size_t)&nrf_app_size);
}
#endif
}
screen_boot_stage_2(fading); screen_boot_stage_2(fading);
#ifdef USE_SECP256K1_ZKP #ifdef USE_SECP256K1_ZKP

View File

@ -157,9 +157,6 @@ void drivers_init() {
check_oem_keys(); check_oem_keys();
#endif #endif
#if PRODUCTION || BOOTLOADER_QA
check_and_replace_bootloader();
#endif
#endif #endif
#ifdef USE_BUTTON #ifdef USE_BUTTON

View File

@ -77,10 +77,6 @@ static void drivers_init(void) {
check_oem_keys(); check_oem_keys();
#endif #endif
#if PRODUCTION || BOOTLOADER_QA
check_and_replace_bootloader();
#endif
#ifdef USE_OPTIGA #ifdef USE_OPTIGA
optiga_init_and_configure(); optiga_init_and_configure();
#endif #endif

View File

@ -80,14 +80,7 @@ impl CommonUI for UIBolt {
show(&mut frame, fade_in); show(&mut frame, fade_in);
} }
fn screen_update() { fn screen_update() {}
let mut frame = ErrorScreen::new(
"Update".into(),
"Finishing firmware update".into(),
"Do not turn off your Trezor".into(),
);
show(&mut frame, true);
}
#[cfg(feature = "ui_debug_overlay")] #[cfg(feature = "ui_debug_overlay")]
fn render_debug_overlay<'s>(_target: &mut impl shape::Renderer<'s>, _info: DebugOverlay) { fn render_debug_overlay<'s>(_target: &mut impl shape::Renderer<'s>, _info: DebugOverlay) {

View File

@ -38,9 +38,7 @@ impl CommonUI for UICaesar {
show(&mut frame, fade_in); show(&mut frame, fade_in);
} }
fn screen_update() { fn screen_update() {}
unimplemented!()
}
#[cfg(feature = "ui_debug_overlay")] #[cfg(feature = "ui_debug_overlay")]
fn render_debug_overlay<'s>(_target: &mut impl shape::Renderer<'s>, _info: DebugOverlay) { fn render_debug_overlay<'s>(_target: &mut impl shape::Renderer<'s>, _info: DebugOverlay) {

View File

@ -86,9 +86,7 @@ impl CommonUI for UIDelizia {
show(&mut frame, fade_in); show(&mut frame, fade_in);
} }
fn screen_update() { fn screen_update() {}
unimplemented!()
}
#[cfg(feature = "ui_debug_overlay")] #[cfg(feature = "ui_debug_overlay")]
fn render_debug_overlay<'s>(target: &mut impl shape::Renderer<'s>, info: DebugOverlay) { fn render_debug_overlay<'s>(target: &mut impl shape::Renderer<'s>, info: DebugOverlay) {

View File

@ -53,6 +53,8 @@ SECTIONS {
. = ALIGN(4); . = ALIGN(4);
*(.rodata*); *(.rodata*);
. = ALIGN(4); . = ALIGN(4);
KEEP(*(.bootloader));
*(.bootloader*);
. = ALIGN(512); . = ALIGN(512);
} >FLASH AT>FLASH } >FLASH AT>FLASH

View File

@ -44,9 +44,6 @@ SECTIONS {
*(.text*); *(.text*);
. = ALIGN(4); . = ALIGN(4);
*(.rodata*); *(.rodata*);
. = ALIGN(4);
KEEP(*(.bootloader));
*(.bootloader*);
. = ALIGN(512); . = ALIGN(512);
} >FLASH AT>FLASH } >FLASH AT>FLASH

View File

@ -44,6 +44,9 @@ SECTIONS {
*(.text*); *(.text*);
. = ALIGN(4); . = ALIGN(4);
*(.rodata*); *(.rodata*);
. = ALIGN(4);
KEEP(*(.bootloader));
*(.bootloader*);
. = ALIGN(512); . = ALIGN(512);
} >FLASH AT>FLASH } >FLASH AT>FLASH

View File

@ -45,9 +45,6 @@ SECTIONS {
*(.text*); *(.text*);
. = ALIGN(4); . = ALIGN(4);
*(.rodata*); *(.rodata*);
. = ALIGN(4);
KEEP(*(.bootloader));
*(.bootloader*);
. = ALIGN(512); . = ALIGN(512);
} >FLASH AT>FLASH } >FLASH AT>FLASH

View File

@ -49,6 +49,9 @@ SECTIONS {
. = ALIGN(4); . = ALIGN(4);
KEEP(*(.nrf_app)); KEEP(*(.nrf_app));
*(.nrf_app*); *(.nrf_app*);
. = ALIGN(4);
KEEP(*(.bootloader));
*(.bootloader*);
. = ALIGN(512); . = ALIGN(512);
} >FLASH AT>FLASH } >FLASH AT>FLASH

View File

@ -49,9 +49,6 @@ SECTIONS {
*(.text*); *(.text*);
. = ALIGN(4); . = ALIGN(4);
*(.rodata*); *(.rodata*);
. = ALIGN(4);
KEEP(*(.bootloader));
*(.bootloader*);
. = ALIGN(512); . = ALIGN(512);
} >FLASH AT>FLASH } >FLASH AT>FLASH

View File

@ -55,9 +55,6 @@ SECTIONS {
*(.text*); *(.text*);
. = ALIGN(4); . = ALIGN(4);
*(.rodata*); *(.rodata*);
. = ALIGN(4);
KEEP(*(.bootloader));
*(.bootloader*);
. = ALIGN(512); . = ALIGN(512);
} >FLASH } >FLASH

View File

@ -49,6 +49,8 @@
#include <sec/secret.h> #include <sec/secret.h>
#endif #endif
#include <util/bl_check.h>
#include "smcall_numbers.h" #include "smcall_numbers.h"
#include "smcall_probe.h" #include "smcall_probe.h"
#include "smcall_verifiers.h" #include "smcall_verifiers.h"
@ -68,6 +70,19 @@ __attribute((no_stack_protector)) void smcall_handler(uint32_t *args,
bootargs_get_args__verified(boot_args); bootargs_get_args__verified(boot_args);
} break; } break;
case SMCALL_BL_CHECK_CHECK: {
const uint8_t *hash_00 = (const uint8_t *)args[0];
const uint8_t *hash_FF = (const uint8_t *)args[1];
size_t hash_len = args[2];
args[0] = bl_check_check__verified(hash_00, hash_FF, hash_len);
} break;
case SMCALL_BL_CHECK_REPLACE: {
const uint8_t *data = (const uint8_t *)args[0];
size_t len = args[1];
bl_check_replace__verified(data, len);
} break;
case SMCALL_GET_BOARD_NAME: { case SMCALL_GET_BOARD_NAME: {
args[0] = get_board_name(); args[0] = get_board_name();
} break; } break;

View File

@ -33,6 +33,9 @@ typedef enum {
SMCALL_BOOTARGS_SET = 1, SMCALL_BOOTARGS_SET = 1,
SMCALL_BOOTARGS_GET_ARGS, SMCALL_BOOTARGS_GET_ARGS,
SMCALL_BL_CHECK_CHECK,
SMCALL_BL_CHECK_REPLACE,
SMCALL_REBOOT_DEVICE, SMCALL_REBOOT_DEVICE,
SMCALL_REBOOT_TO_BOOTLOADER, SMCALL_REBOOT_TO_BOOTLOADER,
SMCALL_REBOOT_AND_UPGRADE, SMCALL_REBOOT_AND_UPGRADE,

View File

@ -35,6 +35,19 @@ void bootargs_set(boot_command_t command, const void *args, size_t args_size) {
void bootargs_get_args(boot_args_t *args) { void bootargs_get_args(boot_args_t *args) {
smcall_invoke1((uint32_t)args, SMCALL_BOOTARGS_GET_ARGS); smcall_invoke1((uint32_t)args, SMCALL_BOOTARGS_GET_ARGS);
} }
// =============================================================================
// bl_check.h
// =============================================================================
bool bl_check_check(const uint8_t *hash_00, const uint8_t *hash_FF,
size_t hash_len) {
return (bool)smcall_invoke3((uint32_t)hash_00, (uint32_t)hash_FF,
(uint32_t)hash_len, SMCALL_BL_CHECK_CHECK);
}
void bl_check_replace(const uint8_t *data, size_t len) {
smcall_invoke2((uint32_t)data, len, SMCALL_BL_CHECK_REPLACE);
}
// ============================================================================= // =============================================================================
// board_capabilities.h // board_capabilities.h

View File

@ -60,6 +60,37 @@ access_violation:
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
bool bl_check_check__verified(const uint8_t *hash_00, const uint8_t *hash_FF,
size_t hash_len) {
if (!probe_read_access(hash_00, hash_len)) {
goto access_violation;
}
if (!probe_read_access(hash_FF, hash_len)) {
goto access_violation;
}
return bl_check_check(hash_00, hash_FF, hash_len);
access_violation:
apptask_access_violation();
return false;
}
void bl_check_replace__verified(const uint8_t *data, size_t len) {
if (!probe_read_access(data, len)) {
goto access_violation;
}
bl_check_replace(data, len);
return;
access_violation:
apptask_access_violation();
}
// ---------------------------------------------------------------------
void reboot_and_upgrade__verified(const uint8_t hash[32]) { void reboot_and_upgrade__verified(const uint8_t hash[32]) {
if (!probe_read_access(hash, 32)) { if (!probe_read_access(hash, 32)) {
goto access_violation; goto access_violation;

View File

@ -29,6 +29,15 @@ void bootargs_set__verified(boot_command_t command, const void *args,
void bootargs_get_args__verified(boot_args_t *args); void bootargs_get_args__verified(boot_args_t *args);
// ---------------------------------------------------------------------
#include <util/bl_check.h>
bool bl_check_check__verified(const uint8_t *hash_00, const uint8_t *hash_FF,
size_t hash_len);
void bl_check_replace__verified(const uint8_t *data, size_t len);
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
#include <sys/bootutils.h> #include <sys/bootutils.h>

View File

@ -42,6 +42,9 @@ typedef enum {
SYSCALL_SYSEVENTS_POLL, SYSCALL_SYSEVENTS_POLL,
SYSCALL_BL_CHECK_CHECK,
SYSCALL_BL_CHECK_REPLACE,
SYSCALL_REBOOT_DEVICE, SYSCALL_REBOOT_DEVICE,
SYSCALL_REBOOT_TO_BOOTLOADER, SYSCALL_REBOOT_TO_BOOTLOADER,
SYSCALL_REBOOT_AND_UPGRADE, SYSCALL_REBOOT_AND_UPGRADE,

View File

@ -81,6 +81,10 @@
#include <io/touch.h> #include <io/touch.h>
#endif #endif
#if PRODUCTION || BOOTLOADER_QA
#include <util/bl_check.h>
#endif
#include "syscall_context.h" #include "syscall_context.h"
#include "syscall_internal.h" #include "syscall_internal.h"
#include "syscall_verifiers.h" #include "syscall_verifiers.h"
@ -166,6 +170,19 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
} }
} break; } break;
case SYSCALL_BL_CHECK_CHECK: {
const uint8_t *hash_00 = (const uint8_t *)args[0];
const uint8_t *hash_FF = (const uint8_t *)args[1];
size_t hash_len = args[2];
args[0] = bl_check_check__verified(hash_00, hash_FF, hash_len);
} break;
case SYSCALL_BL_CHECK_REPLACE: {
const uint8_t *data = (const uint8_t *)args[0];
size_t len = args[1];
bl_check_replace__verified(data, len);
} break;
case SYSCALL_REBOOT_DEVICE: { case SYSCALL_REBOOT_DEVICE: {
reboot_device(); reboot_device();
} break; } break;

View File

@ -84,6 +84,20 @@ void sysevents_poll(const sysevents_t *awaited, sysevents_t *signalled,
SYSCALL_SYSEVENTS_POLL); SYSCALL_SYSEVENTS_POLL);
} }
// =============================================================================
// bl_check.h
// =============================================================================
bool bl_check_check(const uint8_t *hash_00, const uint8_t *hash_FF,
size_t hash_len) {
return (bool)syscall_invoke3((uint32_t)hash_00, (uint32_t)hash_FF,
(uint32_t)hash_len, SYSCALL_BL_CHECK_CHECK);
}
void bl_check_replace(const uint8_t *data, size_t len) {
syscall_invoke2((uint32_t)data, len, SYSCALL_BL_CHECK_REPLACE);
}
// ============================================================================= // =============================================================================
// bootutils.h // bootutils.h
// ============================================================================= // =============================================================================

View File

@ -64,6 +64,37 @@ access_violation:
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
bool bl_check_check__verified(const uint8_t *hash_00, const uint8_t *hash_FF,
size_t hash_len) {
if (!probe_read_access(hash_00, hash_len)) {
goto access_violation;
}
if (!probe_read_access(hash_FF, hash_len)) {
goto access_violation;
}
return bl_check_check(hash_00, hash_FF, hash_len);
access_violation:
apptask_access_violation();
return false;
};
void bl_check_replace__verified(const uint8_t *data, size_t len) {
if (!probe_read_access(data, len)) {
goto access_violation;
}
bl_check_replace(data, len);
return;
access_violation:
apptask_access_violation();
}
// ---------------------------------------------------------------------
void system_exit__verified(int exit_code) { void system_exit__verified(int exit_code) {
systask_t *task = systask_active(); systask_t *task = systask_active();

View File

@ -44,6 +44,14 @@ void system_exit_fatal__verified(const char *message, size_t message_len,
void reboot_and_upgrade__verified(const uint8_t hash[32]); void reboot_and_upgrade__verified(const uint8_t hash[32]);
// ---------------------------------------------------------------------
bool bl_check_check__verified(const uint8_t *hash_00, const uint8_t *hash_FF,
size_t hash_len);
#include <util/bl_check.h>
void bl_check_replace__verified(const uint8_t *data, size_t len);
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
#include <io/display.h> #include <io/display.h>

View File

@ -30,40 +30,15 @@
#include "memzero.h" #include "memzero.h"
#include "uzlib.h" #include "uzlib.h"
// symbols from bootloader.bin => bootloader.o static secbool hash_match(const uint8_t *hash, const uint8_t *hash_00,
extern const void _deflated_bootloader_start; const uint8_t *hash_FF) {
extern const void _deflated_bootloader_size; if (0 == memcmp(hash, hash_00, BLAKE2S_DIGEST_LENGTH)) return sectrue;
if (0 == memcmp(hash, hash_FF, BLAKE2S_DIGEST_LENGTH)) return sectrue;
#define CONCAT_NAME_HELPER(prefix, name, suffix) prefix##name##suffix
#define CONCAT_NAME(name, var) CONCAT_NAME_HELPER(BOOTLOADER_, name, var)
#if BOOTLOADER_QA
// QA bootloaders
#define BOOTLOADER_00 CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _QA_00)
#define BOOTLOADER_FF CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _QA_FF)
#else
// normal bootloaders
#define BOOTLOADER_00 CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _00)
#define BOOTLOADER_FF CONCAT_NAME(MODEL_INTERNAL_NAME_TOKEN, _FF)
#endif
// clang-format on
#if PRODUCTION || BOOTLOADER_QA
static secbool latest_bootloader(const uint8_t *hash, int len) {
if (len != 32) return secfalse;
uint8_t hash_00[] = BOOTLOADER_00;
uint8_t hash_FF[] = BOOTLOADER_FF;
if (0 == memcmp(hash, hash_00, 32)) return sectrue;
if (0 == memcmp(hash, hash_FF, 32)) return sectrue;
return secfalse; return secfalse;
} }
#endif
#define UZLIB_WINDOW_SIZE (1 << 10) #define UZLIB_WINDOW_SIZE (1 << 10)
#if PRODUCTION || BOOTLOADER_QA
static void uzlib_prepare(struct uzlib_uncomp *decomp, uint8_t *window, static void uzlib_prepare(struct uzlib_uncomp *decomp, uint8_t *window,
const void *src, uint32_t srcsize, void *dest, const void *src, uint32_t srcsize, void *dest,
uint32_t destsize) { uint32_t destsize) {
@ -78,12 +53,15 @@ static void uzlib_prepare(struct uzlib_uncomp *decomp, uint8_t *window,
decomp->dest_limit = decomp->dest + destsize; decomp->dest_limit = decomp->dest + destsize;
uzlib_uncompress_init(decomp, window, window ? UZLIB_WINDOW_SIZE : 0); uzlib_uncompress_init(decomp, window, window ? UZLIB_WINDOW_SIZE : 0);
} }
#endif
void check_and_replace_bootloader(void) { bool bl_check_check(const uint8_t *hash_00, const uint8_t *hash_FF,
#if PRODUCTION || BOOTLOADER_QA size_t hash_len) {
mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTUPDATE); mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTUPDATE);
if (hash_len != BLAKE2S_DIGEST_LENGTH) {
error_shutdown("Invalid bootloader hash length");
}
// compute current bootloader hash // compute current bootloader hash
uint8_t hash[BLAKE2S_DIGEST_LENGTH]; uint8_t hash[BLAKE2S_DIGEST_LENGTH];
const uint32_t bl_len = flash_area_get_size(&BOOTLOADER_AREA); const uint32_t bl_len = flash_area_get_size(&BOOTLOADER_AREA);
@ -94,15 +72,21 @@ void check_and_replace_bootloader(void) {
// ensure(known_bootloader(hash, BLAKE2S_DIGEST_LENGTH), "Unknown bootloader // ensure(known_bootloader(hash, BLAKE2S_DIGEST_LENGTH), "Unknown bootloader
// detected"); // detected");
// do we have the latest bootloader? // does the bootloader match?
if (sectrue == latest_bootloader(hash, BLAKE2S_DIGEST_LENGTH)) { if (sectrue == hash_match(hash, hash_00, hash_FF)) {
mpu_reconfig(mode); mpu_reconfig(mode);
return; return false;
} }
// replace bootloader with the latest one mpu_reconfig(mode);
const uint32_t *data = (const uint32_t *)&_deflated_bootloader_start; return true;
const uint32_t len = (const uint32_t)&_deflated_bootloader_size; }
void bl_check_replace(const uint8_t *data, size_t len) {
const uint32_t bl_len = flash_area_get_size(&BOOTLOADER_AREA);
const void *bl_data = flash_area_get_address(&BOOTLOADER_AREA, 0, bl_len);
mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTUPDATE);
struct uzlib_uncomp decomp = {0}; struct uzlib_uncomp decomp = {0};
uint8_t decomp_window[UZLIB_WINDOW_SIZE] = {0}; uint8_t decomp_window[UZLIB_WINDOW_SIZE] = {0};
@ -125,6 +109,8 @@ void check_and_replace_bootloader(void) {
const image_header *current_bld_hdr = const image_header *current_bld_hdr =
read_image_header(bl_data, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_MAXSIZE); read_image_header(bl_data, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_MAXSIZE);
// todo check sig and contents, as data is now coming from outside
// cannot find valid header for current bootloader, something is wrong // cannot find valid header for current bootloader, something is wrong
ensure(current_bld_hdr == (const image_header *)bl_data ? sectrue : secfalse, ensure(current_bld_hdr == (const image_header *)bl_data ? sectrue : secfalse,
"Invalid bootloader header"); "Invalid bootloader header");
@ -182,7 +168,6 @@ void check_and_replace_bootloader(void) {
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
mpu_reconfig(mode); mpu_reconfig(mode);
#endif
} }
#endif #endif

View File

@ -17,9 +17,33 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __BL_CHECK_H__ #pragma once
#define __BL_CHECK_H__
void check_and_replace_bootloader(void); #include <trezor_types.h>
#endif /**
* @brief Verify the installed bootloader against expected hashes.
*
* Calculates the hash of the currently installed bootloader and compares
* it against two known-good expected hashes.
*
* @param hash_00 Pointer to the expected hash for 0x00 padded image.
* @param hash_FF Pointer to the expected hash for 0xFF padded image.
* @param hash_len Length of each hash, in bytes.
*
* @return `true` if the installed bootloader's hash does not match either
* of the expected hashes (indicating it should be replaced),
* `false` if it matches one of them.
*/
bool bl_check_check(const uint8_t *hash_00, const uint8_t *hash_FF,
size_t hash_len);
/**
* @brief Replace the currently installed bootloader.
*
* Writes a new bootloader image into flash.
*
* @param data Pointer to the bootloader image data.
* @param len Size of the bootloader data in bytes.
*/
void bl_check_replace(const uint8_t *data, size_t len);