1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-05-15 13:28:48 +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;
}
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,
uint32_t 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);
} break;
case SYSCALL_FIRMWARE_CALC_HASH: {
case SYSCALL_FIRMWARE_HASH_START: {
const uint8_t *challenge = (const uint8_t *)args[0];
size_t challenge_len = args[1];
uint8_t *hash = (uint8_t *)args[2];
size_t hash_len = args[3];
firmware_hash_callback = (firmware_hash_callback_t)args[4];
void *callback_context = (void *)args[5];
args[0] = firmware_hash_start__verified(challenge, challenge_len);
} break;
args[0] = firmware_calc_hash__verified(
challenge, challenge_len, hash, hash_len,
firmware_hash_callback_wrapper, callback_context);
case SYSCALL_FIRMWARE_HASH_CONTINUE: {
uint8_t *hash = (uint8_t *)args[0];
size_t hash_len = args[1];
args[0] = firmware_hash_continue__verified(hash, hash_len);
} break;
#ifdef USE_BLE

View File

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

View File

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

View File

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

View File

@ -49,15 +49,6 @@
#include <sys/stack_utils.h>
#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:
/// """
/// 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_init_len(&vstr, BLAKE2S_DIGEST_LENGTH);
if (sectrue != firmware_calc_hash(chal.buf, chal.len, (uint8_t *)vstr.buf,
vstr.len, ui_progress, ui_wait_callback)) {
if (firmware_hash_start(chal.buf, chal.len) < 0) {
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);
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);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_firmware_hash_obj, 0,
2, mod_trezorutils_firmware_hash);

View File

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

View File

@ -22,26 +22,23 @@
#include <trezor_types.h>
// Callback function for firmware hash calculation.
typedef void (*firmware_hash_callback_t)(void* context, uint32_t progress,
uint32_t total);
// Calculates hash of the firmware area.
// (Re)starts calculation of the firmware hash
//
// `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).
//
// 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_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`
// otherwise.
secbool firmware_calc_hash(const uint8_t* challenge, size_t challenge_len,
uint8_t* hash, size_t hash_len,
firmware_hash_callback_t callback,
void* callback_context);
// Return value between 0 and 100 indicates the progress of the hash
// calculation. 100 means the hash was calculated successfully and
// `hash` contains the hash. -1 means an error occurred during the
int firmware_hash_continue(uint8_t* hash, size_t hash_len);
// Reads the firmware vendor string from the header in the firmware area.
//