1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-05-16 05:48:45 +00:00

refactor(core): remove firmware_calc_hash callback

[no changelog]
This commit is contained in:
cepetr 2025-05-06 12:48:04 +02:00 committed by cepetr
parent 4005e136e0
commit 010c5adf89
8 changed files with 121 additions and 106 deletions

View File

@ -93,16 +93,6 @@ static secbool storage_init_callback_wrapper(
return result; return result;
} }
static firmware_hash_callback_t firmware_hash_callback = NULL;
static void firmware_hash_callback_wrapper(void *context, uint32_t progress,
uint32_t total) {
g_in_app_callback = true;
invoke_app_callback((uint32_t)context, progress, total,
firmware_hash_callback);
g_in_app_callback = false;
}
__attribute((no_stack_protector)) void syscall_handler(uint32_t *args, __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
uint32_t syscall) { uint32_t syscall) {
switch (syscall) { switch (syscall) {
@ -687,17 +677,16 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
args[0] = firmware_get_vendor__verified(buff, buff_size); args[0] = firmware_get_vendor__verified(buff, buff_size);
} break; } break;
case SYSCALL_FIRMWARE_CALC_HASH: { case SYSCALL_FIRMWARE_HASH_START: {
const uint8_t *challenge = (const uint8_t *)args[0]; const uint8_t *challenge = (const uint8_t *)args[0];
size_t challenge_len = args[1]; size_t challenge_len = args[1];
uint8_t *hash = (uint8_t *)args[2]; args[0] = firmware_hash_start__verified(challenge, challenge_len);
size_t hash_len = args[3]; } break;
firmware_hash_callback = (firmware_hash_callback_t)args[4];
void *callback_context = (void *)args[5];
args[0] = firmware_calc_hash__verified( case SYSCALL_FIRMWARE_HASH_CONTINUE: {
challenge, challenge_len, hash, hash_len, uint8_t *hash = (uint8_t *)args[0];
firmware_hash_callback_wrapper, callback_context); size_t hash_len = args[1];
args[0] = firmware_hash_continue__verified(hash, hash_len);
} break; } break;
#ifdef USE_BLE #ifdef USE_BLE

View File

@ -137,7 +137,8 @@ typedef enum {
SYSCALL_RNG_GET, SYSCALL_RNG_GET,
SYSCALL_FIRMWARE_GET_VENDOR, SYSCALL_FIRMWARE_GET_VENDOR,
SYSCALL_FIRMWARE_CALC_HASH, SYSCALL_FIRMWARE_HASH_START,
SYSCALL_FIRMWARE_HASH_CONTINUE,
SYSCALL_BLE_START, SYSCALL_BLE_START,
SYSCALL_BLE_ISSUE_COMMAND, SYSCALL_BLE_ISSUE_COMMAND,

View File

@ -631,24 +631,14 @@ secbool firmware_get_vendor(char *buff, size_t buff_size) {
SYSCALL_FIRMWARE_GET_VENDOR); SYSCALL_FIRMWARE_GET_VENDOR);
} }
static firmware_hash_callback_t firmware_hash_callback = NULL; int firmware_hash_start(const uint8_t *challenge, size_t challenge_len) {
return (int)syscall_invoke2((uint32_t)challenge, challenge_len,
static void firmware_hash_callback_wrapper(void *context, uint32_t progress, SYSCALL_FIRMWARE_HASH_START);
uint32_t total) {
firmware_hash_callback(context, progress, total);
syscall_return_from_callback(0);
} }
secbool firmware_calc_hash(const uint8_t *challenge, size_t challenge_len, int firmware_hash_continue(uint8_t *hash, size_t hash_len) {
uint8_t *hash, size_t hash_len, return (int)syscall_invoke2((uint32_t)hash, hash_len,
firmware_hash_callback_t callback, SYSCALL_FIRMWARE_HASH_CONTINUE);
void *callback_context) {
firmware_hash_callback = callback;
return syscall_invoke6((uint32_t)challenge, challenge_len, (uint32_t)hash,
hash_len, (uint32_t)firmware_hash_callback_wrapper,
(uint32_t)callback_context,
SYSCALL_FIRMWARE_CALC_HASH);
} }
#ifdef USE_BLE #ifdef USE_BLE

View File

@ -712,25 +712,29 @@ access_violation:
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
secbool firmware_calc_hash__verified(const uint8_t *challenge, int firmware_hash_start__verified(const uint8_t *challenge,
size_t challenge_len, uint8_t *hash, size_t challenge_len) {
size_t hash_len,
firmware_hash_callback_t callback,
void *callback_context) {
if (!probe_read_access(challenge, challenge_len)) { if (!probe_read_access(challenge, challenge_len)) {
goto access_violation; goto access_violation;
} }
return firmware_hash_start(challenge, challenge_len);
access_violation:
apptask_access_violation();
return -1;
}
int firmware_hash_continue__verified(uint8_t *hash, size_t hash_len) {
if (!probe_write_access(hash, hash_len)) { if (!probe_write_access(hash, hash_len)) {
goto access_violation; goto access_violation;
} }
return firmware_calc_hash(challenge, challenge_len, hash, hash_len, callback, return firmware_hash_continue(hash, hash_len);
callback_context);
access_violation: access_violation:
apptask_access_violation(); apptask_access_violation();
return secfalse; return -1;
} }
secbool firmware_get_vendor__verified(char *buff, size_t buff_size) { secbool firmware_get_vendor__verified(char *buff, size_t buff_size) {

View File

@ -183,11 +183,10 @@ void entropy_get__verified(uint8_t *buf);
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
#include <util/fwutils.h> #include <util/fwutils.h>
secbool firmware_calc_hash__verified(const uint8_t *challenge, int firmware_hash_start__verified(const uint8_t *challenge,
size_t challenge_len, uint8_t *hash, size_t challenge_len);
size_t hash_len,
firmware_hash_callback_t callback, int firmware_hash_continue__verified(uint8_t *hash, size_t hash_len);
void *callback_context);
secbool firmware_get_vendor__verified(char *buff, size_t buff_size); secbool firmware_get_vendor__verified(char *buff, size_t buff_size);

View File

@ -49,15 +49,6 @@
#include <sys/stack_utils.h> #include <sys/stack_utils.h>
#endif #endif
static void ui_progress(void *context, uint32_t current, uint32_t total) {
mp_obj_t ui_wait_callback = (mp_obj_t)context;
if (mp_obj_is_callable(ui_wait_callback)) {
mp_call_function_2_protected(ui_wait_callback, mp_obj_new_int(current),
mp_obj_new_int(total));
}
}
/// def consteq(sec: bytes, pub: bytes) -> bool: /// def consteq(sec: bytes, pub: bytes) -> bool:
/// """ /// """
/// Compares the private information in `sec` with public, user-provided /// Compares the private information in `sec` with public, user-provided
@ -168,14 +159,31 @@ STATIC mp_obj_t mod_trezorutils_firmware_hash(size_t n_args,
vstr_t vstr = {0}; vstr_t vstr = {0};
vstr_init_len(&vstr, BLAKE2S_DIGEST_LENGTH); vstr_init_len(&vstr, BLAKE2S_DIGEST_LENGTH);
if (sectrue != firmware_calc_hash(chal.buf, chal.len, (uint8_t *)vstr.buf, if (firmware_hash_start(chal.buf, chal.len) < 0) {
vstr.len, ui_progress, ui_wait_callback)) { vstr_clear(&vstr);
mp_raise_msg(&mp_type_RuntimeError, "Failed to start firmware hash.");
}
int progress = 0;
while (progress < 100) {
progress = firmware_hash_continue((uint8_t *)vstr.buf, vstr.len);
if (progress < 0) {
vstr_clear(&vstr); vstr_clear(&vstr);
mp_raise_msg(&mp_type_RuntimeError, "Failed to calculate firmware hash."); mp_raise_msg(&mp_type_RuntimeError, "Failed to calculate firmware hash.");
break;
}
if (mp_obj_is_callable(ui_wait_callback)) {
mp_call_function_2_protected(ui_wait_callback, mp_obj_new_int(progress),
mp_obj_new_int(100));
}
} }
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_firmware_hash_obj, 0, STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_firmware_hash_obj, 0,
2, mod_trezorutils_firmware_hash); 2, mod_trezorutils_firmware_hash);

View File

@ -21,9 +21,11 @@
#include <trezor_model.h> #include <trezor_model.h>
#include <trezor_rtl.h> #include <trezor_rtl.h>
#include <sys/systask.h>
#include <util/flash.h> #include <util/flash.h>
#include <util/fwutils.h> #include <util/fwutils.h>
#include <util/image.h> #include <util/image.h>
#include "blake2s.h" #include "blake2s.h"
#include "flash_area.h" #include "flash_area.h"
@ -31,51 +33,76 @@
#define FW_HASHING_CHUNK_SIZE 1024 #define FW_HASHING_CHUNK_SIZE 1024
secbool firmware_calc_hash(const uint8_t* challenge, size_t challenge_len, typedef struct {
uint8_t* hash, size_t hash_len, bool initialized;
firmware_hash_callback_t callback, BLAKE2S_CTX blake;
void* callback_context) { uint32_t fw_offset;
BLAKE2S_CTX ctx; uint32_t fw_size;
} firmware_hash_context_t;
static firmware_hash_context_t g_hash_context[SYSTASK_MAX_TASKS];
int firmware_hash_start(const uint8_t* challenge, size_t challenge_len) {
firmware_hash_context_t* ctx = &g_hash_context[systask_id(systask_active())];
int err;
if (challenge_len != 0) { if (challenge_len != 0) {
if (blake2s_InitKey(&ctx, BLAKE2S_DIGEST_LENGTH, challenge, err = blake2s_InitKey(&ctx->blake, BLAKE2S_DIGEST_LENGTH, challenge,
challenge_len) != 0) { challenge_len);
return secfalse;
}
} else { } else {
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); err = blake2s_Init(&ctx->blake, BLAKE2S_DIGEST_LENGTH);
} }
uint32_t firmware_size = flash_area_get_size(&FIRMWARE_AREA); if (err != 0) {
uint32_t chunks = firmware_size / FW_HASHING_CHUNK_SIZE; return -1;
}
ensure((firmware_size % FW_HASHING_CHUNK_SIZE == 0) * sectrue, ctx->fw_offset = 0;
ctx->fw_size = flash_area_get_size(&FIRMWARE_AREA);
ensure((ctx->fw_size % FW_HASHING_CHUNK_SIZE == 0) * sectrue,
"Cannot compute FW hash."); "Cannot compute FW hash.");
for (int i = 0; i < chunks; i++) { ctx->initialized = true;
if (callback != NULL && (i % 128 == 0)) { return 0;
callback(callback_context, i, chunks); }
int firmware_hash_continue(uint8_t* hash, size_t hash_len) {
firmware_hash_context_t* ctx = &g_hash_context[systask_id(systask_active())];
memset(hash, 0, hash_len);
if (!ctx->initialized) {
return -1;
} }
const void* data = flash_area_get_address( int n_chunks = 128;
&FIRMWARE_AREA, i * FW_HASHING_CHUNK_SIZE, FW_HASHING_CHUNK_SIZE);
if (data == NULL) { while (ctx->fw_offset < ctx->fw_size && n_chunks > 0) {
return secfalse; const void* chunk_ptr = flash_area_get_address(
&FIRMWARE_AREA, ctx->fw_offset, FW_HASHING_CHUNK_SIZE);
int err = blake2s_Update(&ctx->blake, chunk_ptr, FW_HASHING_CHUNK_SIZE);
if (err != 0) {
ctx->initialized = false;
return -1;
} }
blake2s_Update(&ctx, data, FW_HASHING_CHUNK_SIZE); ctx->fw_offset += FW_HASHING_CHUNK_SIZE;
--n_chunks;
} }
if (callback != NULL) { if (ctx->fw_offset >= ctx->fw_size) {
callback(callback_context, chunks, chunks); ctx->initialized = false;
int err = blake2s_Final(&ctx->blake, hash, hash_len);
if (err != 0) {
return -1;
}
} }
if (blake2s_Final(&ctx, hash, hash_len) != 0) { return (100 * ctx->fw_offset) / ctx->fw_size;
return secfalse;
}
return sectrue;
} }
secbool firmware_get_vendor(char* buff, size_t buff_size) { secbool firmware_get_vendor(char* buff, size_t buff_size) {

View File

@ -22,26 +22,23 @@
#include <trezor_types.h> #include <trezor_types.h>
// Callback function for firmware hash calculation. // (Re)starts calculation of the firmware hash
typedef void (*firmware_hash_callback_t)(void* context, uint32_t progress,
uint32_t total);
// Calculates hash of the firmware area.
// //
// `challenge` is a optional pointer to the challenge data. // `challenge` is a pointer to the challenge data (optional, can be NULL).
// `challenge_len` is the length of the challenge data (1..32). // `challenge_len` is the length of the challenge data (1..32).
//
// Return 0 on success, -1 on error.
int firmware_hash_start(const uint8_t* challenge, size_t challenge_len);
// Continues with the firmware hash calculation.
//
// `hash` is a pointer to a buffer where the hash will be stored. // `hash` is a pointer to a buffer where the hash will be stored.
// `hash_len` is size of the buffer (must be at least 32). // `hash_len` is size of the buffer (must be at least 32).
// `callback` is an optional callback function that will be called during the
// hash calculation.
// `callback_context` is a pointer that will be passed to the callback function.
// //
// Returns `sectrue` if the hash was calculated successfully, `secfalse` // Return value between 0 and 100 indicates the progress of the hash
// otherwise. // calculation. 100 means the hash was calculated successfully and
secbool firmware_calc_hash(const uint8_t* challenge, size_t challenge_len, // `hash` contains the hash. -1 means an error occurred during the
uint8_t* hash, size_t hash_len, int firmware_hash_continue(uint8_t* hash, size_t hash_len);
firmware_hash_callback_t callback,
void* callback_context);
// Reads the firmware vendor string from the header in the firmware area. // Reads the firmware vendor string from the header in the firmware area.
// //