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:
parent
4005e136e0
commit
010c5adf89
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 calculate firmware hash.");
|
||||
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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const void* data = flash_area_get_address(
|
||||
&FIRMWARE_AREA, i * FW_HASHING_CHUNK_SIZE, FW_HASHING_CHUNK_SIZE);
|
||||
ctx->fw_offset += FW_HASHING_CHUNK_SIZE;
|
||||
--n_chunks;
|
||||
}
|
||||
|
||||
if (data == NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
blake2s_Update(&ctx, data, FW_HASHING_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
if (callback != NULL) {
|
||||
callback(callback_context, chunks, chunks);
|
||||
}
|
||||
|
||||
if (blake2s_Final(&ctx, hash, hash_len) != 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
return sectrue;
|
||||
return (100 * ctx->fw_offset) / ctx->fw_size;
|
||||
}
|
||||
|
||||
secbool firmware_get_vendor(char* buff, size_t buff_size) {
|
||||
|
@ -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.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user