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:
parent
f5123c8b3f
commit
9f2dec6169
@ -468,6 +468,7 @@ ALLPATHS = [
|
||||
'embed/models',
|
||||
'embed/gfx/inc',
|
||||
'embed/sys/bsp/inc',
|
||||
'embed/util/bl_check/inc',
|
||||
'embed/util/image/inc',
|
||||
'embed/util/rsod/inc',
|
||||
'embed/util/scm_revision/inc',
|
||||
@ -907,6 +908,16 @@ if 'nrf' in FEATURES_AVAILABLE:
|
||||
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)
|
||||
|
||||
linkerscript_gen = env.Command(
|
||||
|
@ -408,16 +408,6 @@ obj_program.extend(
|
||||
' --rename-section .data=.vendorheader,alloc,load,readonly,contents'
|
||||
' $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:
|
||||
tools.embed_raw_binary(
|
||||
obj_program,
|
||||
|
@ -361,10 +361,6 @@ cmake_gen = env.Command(
|
||||
action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS',
|
||||
)
|
||||
|
||||
BOOTLOADER_SUFFIX = TREZOR_MODEL
|
||||
if BOOTLOADER_QA:
|
||||
BOOTLOADER_SUFFIX += '_qa'
|
||||
|
||||
# select vendor header
|
||||
if BOOTLOADER_QA or BOOTLOADER_DEVEL:
|
||||
vendor = "dev_DO_NOT_SIGN_signed_dev"
|
||||
@ -389,16 +385,6 @@ obj_program.extend(
|
||||
' --rename-section .data=.vendorheader,alloc,load,readonly,contents'
|
||||
' $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(
|
||||
target='memory.ld',
|
||||
source=[f'embed/models/{TREZOR_MODEL}/memory_secmon.ld', env.get('ENV')['LINKER_SCRIPT'].format(target='secmon')],
|
||||
|
@ -37,13 +37,33 @@
|
||||
#include <sys/linker_utils.h>
|
||||
#include <sys/systask.h>
|
||||
#include <sys/system.h>
|
||||
#include <util/bl_check.h>
|
||||
#include <util/rsod.h>
|
||||
#include "rust_ui_common.h"
|
||||
|
||||
#include <blake2s.h>
|
||||
|
||||
#ifdef USE_SECP256K1_ZKP
|
||||
#include "zkp_context.h"
|
||||
#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
|
||||
#include <io/nrf.h>
|
||||
|
||||
@ -62,14 +82,47 @@ int main_func(uint32_t cmd, void *arg) {
|
||||
|
||||
bool fading = DISPLAY_JUMP_BEHAVIOR == DISPLAY_RESET_CONTENT;
|
||||
|
||||
#ifdef USE_NRF
|
||||
if (nrf_update_required(&nrf_app_start, (size_t)&nrf_app_size)) {
|
||||
screen_update();
|
||||
nrf_update(&nrf_app_start, (size_t)&nrf_app_size);
|
||||
fading = true;
|
||||
}
|
||||
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
|
||||
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();
|
||||
fading = true;
|
||||
|
||||
#if PRODUCTION || BOOTLOADER_QA
|
||||
if (bl_update_required) {
|
||||
bl_check_replace(data, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_NRF
|
||||
if (nrf_update_required_) {
|
||||
nrf_update(&nrf_app_start, (size_t)&nrf_app_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
screen_boot_stage_2(fading);
|
||||
|
||||
#ifdef USE_SECP256K1_ZKP
|
||||
|
@ -157,9 +157,6 @@ void drivers_init() {
|
||||
check_oem_keys();
|
||||
#endif
|
||||
|
||||
#if PRODUCTION || BOOTLOADER_QA
|
||||
check_and_replace_bootloader();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_BUTTON
|
||||
|
@ -77,10 +77,6 @@ static void drivers_init(void) {
|
||||
check_oem_keys();
|
||||
#endif
|
||||
|
||||
#if PRODUCTION || BOOTLOADER_QA
|
||||
check_and_replace_bootloader();
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
optiga_init_and_configure();
|
||||
#endif
|
||||
|
@ -80,14 +80,7 @@ impl CommonUI for UIBolt {
|
||||
show(&mut frame, fade_in);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
fn screen_update() {}
|
||||
|
||||
#[cfg(feature = "ui_debug_overlay")]
|
||||
fn render_debug_overlay<'s>(_target: &mut impl shape::Renderer<'s>, _info: DebugOverlay) {
|
||||
|
@ -38,9 +38,7 @@ impl CommonUI for UICaesar {
|
||||
show(&mut frame, fade_in);
|
||||
}
|
||||
|
||||
fn screen_update() {
|
||||
unimplemented!()
|
||||
}
|
||||
fn screen_update() {}
|
||||
|
||||
#[cfg(feature = "ui_debug_overlay")]
|
||||
fn render_debug_overlay<'s>(_target: &mut impl shape::Renderer<'s>, _info: DebugOverlay) {
|
||||
|
@ -86,9 +86,7 @@ impl CommonUI for UIDelizia {
|
||||
show(&mut frame, fade_in);
|
||||
}
|
||||
|
||||
fn screen_update() {
|
||||
unimplemented!()
|
||||
}
|
||||
fn screen_update() {}
|
||||
|
||||
#[cfg(feature = "ui_debug_overlay")]
|
||||
fn render_debug_overlay<'s>(target: &mut impl shape::Renderer<'s>, info: DebugOverlay) {
|
||||
|
@ -53,6 +53,8 @@ SECTIONS {
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.bootloader));
|
||||
*(.bootloader*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
|
@ -44,9 +44,6 @@ SECTIONS {
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.bootloader));
|
||||
*(.bootloader*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
|
@ -44,6 +44,9 @@ SECTIONS {
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.bootloader));
|
||||
*(.bootloader*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
|
@ -45,9 +45,6 @@ SECTIONS {
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.bootloader));
|
||||
*(.bootloader*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
|
@ -49,6 +49,9 @@ SECTIONS {
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.nrf_app));
|
||||
*(.nrf_app*);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.bootloader));
|
||||
*(.bootloader*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
|
@ -49,9 +49,6 @@ SECTIONS {
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.bootloader));
|
||||
*(.bootloader*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
|
@ -55,9 +55,6 @@ SECTIONS {
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.bootloader));
|
||||
*(.bootloader*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH
|
||||
|
||||
|
@ -49,6 +49,8 @@
|
||||
#include <sec/secret.h>
|
||||
#endif
|
||||
|
||||
#include <util/bl_check.h>
|
||||
|
||||
#include "smcall_numbers.h"
|
||||
#include "smcall_probe.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);
|
||||
} 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: {
|
||||
args[0] = get_board_name();
|
||||
} break;
|
||||
|
@ -33,6 +33,9 @@ typedef enum {
|
||||
SMCALL_BOOTARGS_SET = 1,
|
||||
SMCALL_BOOTARGS_GET_ARGS,
|
||||
|
||||
SMCALL_BL_CHECK_CHECK,
|
||||
SMCALL_BL_CHECK_REPLACE,
|
||||
|
||||
SMCALL_REBOOT_DEVICE,
|
||||
SMCALL_REBOOT_TO_BOOTLOADER,
|
||||
SMCALL_REBOOT_AND_UPGRADE,
|
||||
|
@ -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) {
|
||||
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
|
||||
|
@ -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]) {
|
||||
if (!probe_read_access(hash, 32)) {
|
||||
goto access_violation;
|
||||
|
@ -29,6 +29,15 @@ void bootargs_set__verified(boot_command_t command, const void *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>
|
||||
|
||||
|
@ -42,6 +42,9 @@ typedef enum {
|
||||
|
||||
SYSCALL_SYSEVENTS_POLL,
|
||||
|
||||
SYSCALL_BL_CHECK_CHECK,
|
||||
SYSCALL_BL_CHECK_REPLACE,
|
||||
|
||||
SYSCALL_REBOOT_DEVICE,
|
||||
SYSCALL_REBOOT_TO_BOOTLOADER,
|
||||
SYSCALL_REBOOT_AND_UPGRADE,
|
||||
|
@ -81,6 +81,10 @@
|
||||
#include <io/touch.h>
|
||||
#endif
|
||||
|
||||
#if PRODUCTION || BOOTLOADER_QA
|
||||
#include <util/bl_check.h>
|
||||
#endif
|
||||
|
||||
#include "syscall_context.h"
|
||||
#include "syscall_internal.h"
|
||||
#include "syscall_verifiers.h"
|
||||
@ -166,6 +170,19 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
|
||||
}
|
||||
} 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: {
|
||||
reboot_device();
|
||||
} break;
|
||||
|
@ -84,6 +84,20 @@ void sysevents_poll(const sysevents_t *awaited, sysevents_t *signalled,
|
||||
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
|
||||
// =============================================================================
|
||||
|
@ -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) {
|
||||
systask_t *task = systask_active();
|
||||
|
||||
|
@ -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]);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
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>
|
||||
|
||||
|
@ -30,40 +30,15 @@
|
||||
#include "memzero.h"
|
||||
#include "uzlib.h"
|
||||
|
||||
// symbols from bootloader.bin => bootloader.o
|
||||
extern const void _deflated_bootloader_start;
|
||||
extern const void _deflated_bootloader_size;
|
||||
|
||||
#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;
|
||||
static secbool hash_match(const uint8_t *hash, const uint8_t *hash_00,
|
||||
const uint8_t *hash_FF) {
|
||||
if (0 == memcmp(hash, hash_00, BLAKE2S_DIGEST_LENGTH)) return sectrue;
|
||||
if (0 == memcmp(hash, hash_FF, BLAKE2S_DIGEST_LENGTH)) return sectrue;
|
||||
return secfalse;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define UZLIB_WINDOW_SIZE (1 << 10)
|
||||
|
||||
#if PRODUCTION || BOOTLOADER_QA
|
||||
static void uzlib_prepare(struct uzlib_uncomp *decomp, uint8_t *window,
|
||||
const void *src, uint32_t srcsize, void *dest,
|
||||
uint32_t destsize) {
|
||||
@ -78,12 +53,15 @@ static void uzlib_prepare(struct uzlib_uncomp *decomp, uint8_t *window,
|
||||
decomp->dest_limit = decomp->dest + destsize;
|
||||
uzlib_uncompress_init(decomp, window, window ? UZLIB_WINDOW_SIZE : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void check_and_replace_bootloader(void) {
|
||||
#if PRODUCTION || BOOTLOADER_QA
|
||||
bool bl_check_check(const uint8_t *hash_00, const uint8_t *hash_FF,
|
||||
size_t hash_len) {
|
||||
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
|
||||
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
|
||||
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
|
||||
// detected");
|
||||
|
||||
// do we have the latest bootloader?
|
||||
if (sectrue == latest_bootloader(hash, BLAKE2S_DIGEST_LENGTH)) {
|
||||
// does the bootloader match?
|
||||
if (sectrue == hash_match(hash, hash_00, hash_FF)) {
|
||||
mpu_reconfig(mode);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// replace bootloader with the latest one
|
||||
const uint32_t *data = (const uint32_t *)&_deflated_bootloader_start;
|
||||
const uint32_t len = (const uint32_t)&_deflated_bootloader_size;
|
||||
mpu_reconfig(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
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};
|
||||
uint8_t decomp_window[UZLIB_WINDOW_SIZE] = {0};
|
||||
@ -125,6 +109,8 @@ void check_and_replace_bootloader(void) {
|
||||
const image_header *current_bld_hdr =
|
||||
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
|
||||
ensure(current_bld_hdr == (const image_header *)bl_data ? sectrue : secfalse,
|
||||
"Invalid bootloader header");
|
||||
@ -182,7 +168,6 @@ void check_and_replace_bootloader(void) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
|
||||
mpu_reconfig(mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -17,9 +17,33 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __BL_CHECK_H__
|
||||
#define __BL_CHECK_H__
|
||||
#pragma once
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user