1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-27 08:38:07 +00:00

feat(core): prevent installing and running of incompatible firmware, prevent bootloader downgrade

This commit is contained in:
tychovrahe 2022-11-21 14:12:49 +01:00 committed by TychoVrahe
parent 99d4b0185a
commit 115f7daaaa
27 changed files with 503 additions and 195 deletions

View File

@ -0,0 +1 @@
Add model info to image and check when installing bootloader, prevent bootloader downgrade

View File

@ -0,0 +1 @@
Check image model when replacing bootloader

View File

@ -53,14 +53,8 @@ struct BoardCapabilities capablities
__attribute__((section(".capabilities_section"))) = {
.header = CAPABILITIES_HEADER,
.model_tag = MODEL_NAME,
.model_length = MODEL_NAME_MAX_LENGTH,
#if defined TREZOR_MODEL_T
.model_name = "TREZORT",
#elif defined TREZOR_MODEL_R
.model_name = "TREZORR",
#else
#error Unknown model
#endif
.model_length = sizeof(uint32_t),
.model_name = HW_MODEL,
.version_tag = BOARDLOADER_VERSION,
.version_length = sizeof(struct BoardloaderVersion),
.version = {.version_major = VERSION_MAJOR,
@ -93,17 +87,29 @@ static uint32_t check_sdcard(void) {
sdcard_power_off();
image_header hdr;
if (sectrue == read_status) {
const image_header *hdr =
read_image_header((const uint8_t *)sdcard_buf, BOOTLOADER_IMAGE_MAGIC,
BOOTLOADER_IMAGE_MAXSIZE);
if ((sectrue == read_status) &&
(sectrue ==
load_image_header((const uint8_t *)sdcard_buf, BOOTLOADER_IMAGE_MAGIC,
BOOTLOADER_IMAGE_MAXSIZE, BOARDLOADER_KEY_M,
BOARDLOADER_KEY_N, BOARDLOADER_KEYS, &hdr))) {
return hdr.codelen;
} else {
return 0;
if (hdr != (const image_header *)sdcard_buf) {
return 0;
}
if (sectrue != check_image_model(hdr)) {
return 0;
}
if (sectrue != check_image_header_sig(hdr, BOARDLOADER_KEY_M,
BOARDLOADER_KEY_N,
BOARDLOADER_KEYS)) {
return 0;
}
return hdr->codelen;
}
return 0;
}
static void progress_callback(int pos, int len) { display_printf("."); }
@ -220,18 +226,21 @@ int main(void) {
}
#endif
image_header hdr;
const image_header *hdr =
read_image_header((const uint8_t *)BOOTLOADER_START,
BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE);
ensure(load_image_header((const uint8_t *)BOOTLOADER_START,
BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE,
BOARDLOADER_KEY_M, BOARDLOADER_KEY_N,
BOARDLOADER_KEYS, &hdr),
ensure(hdr == (const image_header *)BOOTLOADER_START ? sectrue : secfalse,
"invalid bootloader header");
ensure(check_image_header_sig(hdr, BOARDLOADER_KEY_M, BOARDLOADER_KEY_N,
BOARDLOADER_KEYS),
"invalid bootloader signature");
const uint8_t sectors[] = {
FLASH_SECTOR_BOOTLOADER,
};
ensure(check_image_contents(&hdr, IMAGE_HEADER_SIZE, sectors, 1),
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE, sectors, 1),
"invalid bootloader hash");
ensure_compatible_settings();

View File

@ -0,0 +1 @@
Add model info to image and check when installing/running firmware

View File

@ -215,31 +215,6 @@ void ui_screen_firmware_info(const vendor_header *const vhdr,
display_refresh();
}
void ui_screen_firmware_fingerprint(const image_header *const hdr) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_BL_BG);
display_text(16, 32, "Firmware fingerprint", -1, FONT_NORMAL, COLOR_BL_FG,
COLOR_BL_BG);
display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BL_FG);
static const char *hexdigits = "0123456789abcdef";
char fingerprint_str[64];
for (int i = 0; i < 32; i++) {
fingerprint_str[i * 2] = hexdigits[(hdr->fingerprint[i] >> 4) & 0xF];
fingerprint_str[i * 2 + 1] = hexdigits[hdr->fingerprint[i] & 0xF];
}
for (int i = 0; i < 4; i++) {
display_text_center(120, 70 + i * 25, fingerprint_str + i * 16, 16,
FONT_MONO, COLOR_BL_FG, COLOR_BL_BG);
}
display_bar_radius(9, 184, 222, 50, COLOR_BL_DONE, COLOR_BL_BG, 4);
display_icon(9 + (222 - 19) / 2, 184 + (50 - 16) / 2, 20, 16,
toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12,
COLOR_BL_BG, COLOR_BL_DONE);
PIXELDATA_DIRTY();
display_refresh();
}
// install UI
void ui_screen_install_confirm_upgrade(const vendor_header *const vhdr,

View File

@ -34,7 +34,6 @@ void ui_screen_welcome_third(void);
void ui_screen_firmware_info(const vendor_header* const vhdr,
const image_header* const hdr);
void ui_screen_firmware_fingerprint(const image_header* const hdr);
void ui_screen_install_confirm_upgrade(const vendor_header* const vhdr,
const image_header* const hdr);

View File

@ -10,7 +10,11 @@
g_header:
.byte 'T','R','Z','B' // magic
.word g_header_end - g_header // hdrlen
#ifdef TREZOR_MODEL_T
.word 0 // expiry
#else
.word 1 // expiry
#endif
.word _codelen // codelen
.byte VERSION_MAJOR // vmajor
.byte VERSION_MINOR // vminor
@ -20,7 +24,10 @@ g_header:
.byte FIX_VERSION_MINOR // fix_vminor
.byte FIX_VERSION_PATCH // fix_vpatch
.byte FIX_VERSION_BUILD // fix_vbuild
. = . + 8 // reserved
.word HW_MODEL // type of the designated hardware
.byte HW_REVISION // revision of the designated hardware
.byte VERSION_MONOTONIC // monotonic version of the binary
. = . + 2 // reserved
. = . + 512 // hash1 ... hash16
. = . + 415 // reserved
.byte 0 // sigmask

View File

@ -159,7 +159,7 @@ static secbool bootloader_usb_loop(const vendor_header *const vhdr,
break;
case 7: // FirmwareUpload
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
if (r < 0 && r != -4) { // error, but not user abort (-4)
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
ui_fadeout();
ui_screen_fail();
ui_fadein();
@ -193,10 +193,9 @@ static secbool bootloader_usb_loop(const vendor_header *const vhdr,
}
}
secbool load_vendor_header_keys(const uint8_t *const data,
vendor_header *const vhdr) {
return load_vendor_header(data, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N,
BOOTLOADER_KEYS, vhdr);
secbool check_vendor_header_keys(const vendor_header *const vhdr) {
return check_vendor_header_sig(vhdr, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N,
BOOTLOADER_KEYS);
}
static secbool check_vendor_header_lock(const vendor_header *const vhdr) {
@ -303,23 +302,40 @@ int main(void) {
}
#endif
const image_header *hdr = NULL;
vendor_header vhdr;
image_header hdr;
// detect whether the devices contains a valid firmware
// detect whether the device contains a valid firmware
secbool firmware_present = sectrue;
if (sectrue != read_vendor_header((const uint8_t *)FIRMWARE_START, &vhdr)) {
firmware_present = secfalse;
}
if (sectrue == firmware_present) {
firmware_present = check_vendor_header_keys(&vhdr);
}
secbool firmware_present =
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr);
if (sectrue == firmware_present) {
firmware_present = check_vendor_header_lock(&vhdr);
}
if (sectrue == firmware_present) {
firmware_present = load_image_header(
(const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), FIRMWARE_IMAGE_MAGIC,
FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr);
hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
if (hdr != (const image_header *)(FIRMWARE_START + vhdr.hdrlen)) {
firmware_present = secfalse;
}
}
if (sectrue == firmware_present) {
firmware_present = check_image_model(hdr);
}
if (sectrue == firmware_present) {
firmware_present =
check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub);
}
if (sectrue == firmware_present) {
firmware_present =
check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT);
}
@ -357,26 +373,35 @@ int main(void) {
// ... or we have stay_in_bootloader flag to force it
if (touched || stay_in_bootloader == sectrue) {
// no ui_fadeout(); - we already start from black screen
ui_screen_firmware_info(&vhdr, &hdr);
ui_screen_firmware_info(&vhdr, hdr);
ui_fadein();
// and start the usb loop
if (bootloader_usb_loop(&vhdr, &hdr) != sectrue) {
if (bootloader_usb_loop(&vhdr, hdr) != sectrue) {
return 1;
}
}
ensure(load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr),
ensure(read_vendor_header((const uint8_t *)FIRMWARE_START, &vhdr),
"invalid vendor header");
ensure(check_vendor_header_keys(&vhdr), "invalid vendor header signature");
ensure(check_vendor_header_lock(&vhdr), "unauthorized vendor keys");
ensure(load_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE,
vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr),
hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
ensure(hdr == (const image_header *)(FIRMWARE_START + vhdr.hdrlen) ? sectrue
: secfalse,
"invalid firmware header");
ensure(check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
ensure(check_image_model(hdr), "wrong firmware model");
ensure(check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub),
"invalid firmware signature");
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT),
"invalid firmware hash");
@ -384,7 +409,7 @@ int main(void) {
if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) {
// ui_fadeout(); // no fadeout - we start from black screen
ui_screen_boot(&vhdr, &hdr);
ui_screen_boot(&vhdr, hdr);
ui_fadein();
int delay = (vhdr.vtrust & VTRUST_WAIT) ^ VTRUST_WAIT;

View File

@ -403,8 +403,7 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
return true;
}
secbool load_vendor_header_keys(const uint8_t *const data,
vendor_header *const vhdr);
secbool check_vendor_header_keys(const vendor_header *const vhdr);
static int version_compare(uint32_t vera, uint32_t verb) {
int a, b;
@ -422,8 +421,8 @@ static int version_compare(uint32_t vera, uint32_t verb) {
return a - b;
}
static void detect_installation(vendor_header *current_vhdr,
image_header *current_hdr,
static void detect_installation(const vendor_header *current_vhdr,
const image_header *current_hdr,
const vendor_header *const new_vhdr,
const image_header *const new_hdr,
secbool *is_new, secbool *is_upgrade,
@ -431,16 +430,17 @@ static void detect_installation(vendor_header *current_vhdr,
*is_new = secfalse;
*is_upgrade = secfalse;
*is_downgrade_wipe = secfalse;
if (sectrue !=
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, current_vhdr)) {
if (sectrue != check_vendor_header_keys(current_vhdr)) {
*is_new = sectrue;
return;
}
if (sectrue !=
load_image_header((const uint8_t *)FIRMWARE_START + current_vhdr->hdrlen,
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE,
current_vhdr->vsig_m, current_vhdr->vsig_n,
current_vhdr->vpub, current_hdr)) {
if (sectrue != check_image_model(current_hdr)) {
*is_new = sectrue;
return;
}
if (sectrue != check_image_header_sig(current_hdr, current_vhdr->vsig_m,
current_vhdr->vsig_n,
current_vhdr->vpub)) {
*is_new = sectrue;
return;
}
@ -472,7 +472,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk size");
MSG_SEND(Failure);
return -1;
return UPLOAD_ERR_INVALID_CHUNK_SIZE;
}
static image_header hdr;
@ -483,29 +483,81 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
if (headers_offset == 0) {
// first block and headers are not yet parsed
vendor_header vhdr;
if (sectrue != load_vendor_header_keys(CHUNK_BUFFER_PTR, &vhdr)) {
if (sectrue != read_vendor_header(CHUNK_BUFFER_PTR, &vhdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header");
MSG_SEND(Failure);
return -2;
return UPLOAD_ERR_INVALID_VENDOR_HEADER;
}
if (sectrue != load_image_header(CHUNK_BUFFER_PTR + vhdr.hdrlen,
FIRMWARE_IMAGE_MAGIC,
FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m,
vhdr.vsig_n, vhdr.vpub, &hdr)) {
if (sectrue != check_vendor_header_keys(&vhdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header signature");
MSG_SEND(Failure);
return UPLOAD_ERR_INVALID_VENDOR_HEADER_SIG;
}
const image_header *received_hdr =
read_image_header(CHUNK_BUFFER_PTR + vhdr.hdrlen,
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
if (received_hdr !=
(const image_header *)(CHUNK_BUFFER_PTR + vhdr.hdrlen)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid firmware header");
MSG_SEND(Failure);
return -3;
return UPLOAD_ERR_INVALID_IMAGE_HEADER;
}
if (sectrue != check_image_model(received_hdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Wrong firmware model");
MSG_SEND(Failure);
return UPLOAD_ERR_INVALID_IMAGE_MODEL;
}
if (sectrue != check_image_header_sig(received_hdr, vhdr.vsig_m,
vhdr.vsig_n, vhdr.vpub)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid firmware signature");
MSG_SEND(Failure);
return UPLOAD_ERR_INVALID_IMAGE_HEADER_SIG;
}
memcpy(&hdr, received_hdr, sizeof(hdr));
vendor_header current_vhdr;
image_header current_hdr;
secbool is_new = secfalse;
detect_installation(&current_vhdr, &current_hdr, &vhdr, &hdr, &is_new,
&is_upgrade, &is_downgrade_wipe);
if (sectrue !=
read_vendor_header((const uint8_t *)FIRMWARE_START, &current_vhdr)) {
is_new = sectrue;
}
const image_header *current_hdr = NULL;
if (is_new == secfalse) {
current_hdr = read_image_header(
(const uint8_t *)FIRMWARE_START + current_vhdr.hdrlen,
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
if (current_hdr !=
(const image_header *)FIRMWARE_START + current_vhdr.hdrlen) {
is_new = sectrue;
}
}
if (is_new == secfalse) {
detect_installation(&current_vhdr, current_hdr, &vhdr, &hdr, &is_new,
&is_upgrade, &is_downgrade_wipe);
}
int response = INPUT_CANCEL;
if (sectrue == is_new) {
@ -528,10 +580,10 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
if (INPUT_CANCEL == response) {
ui_fadeout();
ui_screen_firmware_info(&current_vhdr, &current_hdr);
ui_screen_firmware_info(&current_vhdr, current_hdr);
ui_fadein();
send_user_abort(iface_num, "Firmware install cancelled");
return -4;
return UPLOAD_ERR_USER_ABORT;
}
headers_offset = IMAGE_HEADER_SIZE + vhdr.hdrlen;
@ -572,7 +624,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Firmware too big");
MSG_SEND(Failure);
return -5;
return UPLOAD_ERR_FIRMWARE_TOO_BIG;
}
if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32,
@ -591,7 +643,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk hash");
MSG_SEND(Failure);
return -6;
return UPLOAD_ERR_INVALID_CHUNK_HASH;
}
ensure(flash_unlock_write(), NULL);
@ -654,11 +706,11 @@ int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Could not erase flash");
MSG_SEND(Failure);
return -1;
return WIPE_ERR_CANNOT_ERASE;
} else {
MSG_SEND_INIT(Success);
MSG_SEND(Success);
return 0;
return WIPE_OK;
}
}

View File

@ -29,6 +29,24 @@
#define FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT 2
enum {
UPLOAD_OK = 0,
UPLOAD_ERR_INVALID_CHUNK_SIZE = -1,
UPLOAD_ERR_INVALID_VENDOR_HEADER = -2,
UPLOAD_ERR_INVALID_VENDOR_HEADER_SIG = -3,
UPLOAD_ERR_INVALID_IMAGE_HEADER = -4,
UPLOAD_ERR_INVALID_IMAGE_MODEL = -5,
UPLOAD_ERR_INVALID_IMAGE_HEADER_SIG = -6,
UPLOAD_ERR_USER_ABORT = -7,
UPLOAD_ERR_FIRMWARE_TOO_BIG = -8,
UPLOAD_ERR_INVALID_CHUNK_HASH = -9,
};
enum {
WIPE_OK = 0,
WIPE_ERR_CANNOT_ERASE = -1,
};
secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id,
uint32_t *msg_size);

View File

@ -0,0 +1 @@
Add model info to image and check when installing/running firmware

View File

@ -10,7 +10,11 @@
g_header:
.byte 'T','R','Z','B' // magic
.word g_header_end - g_header // hdrlen
#ifdef TREZOR_MODEL_T
.word 0 // expiry
#else
.word 1 // expiry
#endif
.word _codelen // codelen
.byte VERSION_MAJOR // vmajor
.byte VERSION_MINOR // vminor
@ -20,7 +24,10 @@ g_header:
.byte FIX_VERSION_MINOR // fix_vminor
.byte FIX_VERSION_PATCH // fix_vpatch
.byte FIX_VERSION_BUILD // fix_vbuild
. = . + 8 // reserved
.word HW_MODEL // type of the designated hardware
.byte HW_REVISION // revision of the designated hardware
.byte VERSION_MONOTONIC // monotonic version
. = . + 2 // reserved
. = . + 512 // hash1 ... hash16
. = . + 415 // reserved
.byte 0 // sigmask

View File

@ -134,7 +134,7 @@ static secbool bootloader_usb_loop(const vendor_header *const vhdr,
break;
case 7: // FirmwareUpload
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
if (r < 0 && r != -4) { // error, but not user abort (-4)
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
ui_screen_fail();
usb_stop();
usb_deinit();
@ -163,10 +163,9 @@ static secbool bootloader_usb_loop(const vendor_header *const vhdr,
}
}
secbool load_vendor_header_keys(const uint8_t *const data,
vendor_header *const vhdr) {
return load_vendor_header(data, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N,
BOOTLOADER_KEYS, vhdr);
secbool check_vendor_header_keys(vendor_header *const vhdr) {
return check_vendor_header_sig(vhdr, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N,
BOOTLOADER_KEYS);
}
static secbool check_vendor_header_lock(const vendor_header *const vhdr) {
@ -227,24 +226,40 @@ int main(void) {
display_clear();
const image_header *hdr = NULL;
vendor_header vhdr;
image_header hdr;
// detect whether the device contains a valid firmware
secbool firmware_present = sectrue;
// detect whether the devices contains a valid firmware
if (sectrue != read_vendor_header((const uint8_t *)FIRMWARE_START, &vhdr)) {
firmware_present = secfalse;
}
if (sectrue == firmware_present) {
firmware_present = check_vendor_header_keys(&vhdr);
}
secbool firmware_present =
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr);
if (sectrue == firmware_present) {
firmware_present = check_vendor_header_lock(&vhdr);
}
if (sectrue == firmware_present) {
firmware_present = load_image_header(
(const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), FIRMWARE_IMAGE_MAGIC,
FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr);
hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
if (hdr != (const image_header *)(FIRMWARE_START + vhdr.hdrlen)) {
firmware_present = secfalse;
}
}
if (sectrue == firmware_present) {
firmware_present = check_image_model(hdr);
}
if (sectrue == firmware_present) {
firmware_present =
check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub);
}
if (sectrue == firmware_present) {
firmware_present =
check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT);
}
@ -260,17 +275,26 @@ int main(void) {
return 1;
}
ensure(load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr),
ensure(read_vendor_header((const uint8_t *)FIRMWARE_START, &vhdr),
"invalid vendor header");
ensure(check_vendor_header_keys(&vhdr), "invalid vendor header signature");
ensure(check_vendor_header_lock(&vhdr), "unauthorized vendor keys");
ensure(load_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE,
vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr),
hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
ensure(hdr == (const image_header *)(FIRMWARE_START + vhdr.hdrlen) ? sectrue
: secfalse,
"invalid firmware header");
ensure(check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
ensure(check_image_model(hdr), "wrong firmware model");
ensure(check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub),
"invalid firmware signature");
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT),
"invalid firmware hash");

View File

@ -401,8 +401,7 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
return true;
}
secbool load_vendor_header_keys(const uint8_t *const data,
vendor_header *const vhdr);
secbool check_vendor_header_keys(const vendor_header *const vhdr);
static int version_compare(uint32_t vera, uint32_t verb) {
int a, b;
@ -420,8 +419,8 @@ static int version_compare(uint32_t vera, uint32_t verb) {
return a - b;
}
static void detect_installation(vendor_header *current_vhdr,
image_header *current_hdr,
static void detect_installation(const vendor_header *current_vhdr,
const image_header *current_hdr,
const vendor_header *const new_vhdr,
const image_header *const new_hdr,
secbool *is_new, secbool *is_upgrade,
@ -429,16 +428,17 @@ static void detect_installation(vendor_header *current_vhdr,
*is_new = secfalse;
*is_upgrade = secfalse;
*is_downgrade_wipe = secfalse;
if (sectrue !=
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, current_vhdr)) {
if (sectrue != check_vendor_header_keys(current_vhdr)) {
*is_new = sectrue;
return;
}
if (sectrue !=
load_image_header((const uint8_t *)FIRMWARE_START + current_vhdr->hdrlen,
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE,
current_vhdr->vsig_m, current_vhdr->vsig_n,
current_vhdr->vpub, current_hdr)) {
if (sectrue != check_image_model(current_hdr)) {
*is_new = sectrue;
return;
}
if (sectrue != check_image_header_sig(current_hdr, current_vhdr->vsig_m,
current_vhdr->vsig_n,
current_vhdr->vpub)) {
*is_new = sectrue;
return;
}
@ -470,7 +470,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk size");
MSG_SEND(Failure);
return -1;
return UPLOAD_ERR_INVALID_CHUNK_SIZE;
}
static image_header hdr;
@ -481,29 +481,80 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
if (headers_offset == 0) {
// first block and headers are not yet parsed
vendor_header vhdr;
if (sectrue != load_vendor_header_keys(chunk_buffer, &vhdr)) {
if (sectrue != read_vendor_header(chunk_buffer, &vhdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header");
MSG_SEND(Failure);
return -2;
return UPLOAD_ERR_INVALID_VENDOR_HEADER;
}
if (sectrue != load_image_header(chunk_buffer + vhdr.hdrlen,
FIRMWARE_IMAGE_MAGIC,
FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m,
vhdr.vsig_n, vhdr.vpub, &hdr)) {
if (sectrue != check_vendor_header_keys(&vhdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header signature");
MSG_SEND(Failure);
return UPLOAD_ERR_INVALID_VENDOR_HEADER_SIG;
}
const image_header *received_hdr =
read_image_header(chunk_buffer + vhdr.hdrlen, FIRMWARE_IMAGE_MAGIC,
FIRMWARE_IMAGE_MAXSIZE);
if (received_hdr != (const image_header *)chunk_buffer + vhdr.hdrlen) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid firmware header");
MSG_SEND(Failure);
return -3;
return UPLOAD_ERR_INVALID_IMAGE_HEADER;
}
if (sectrue != check_image_model(received_hdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Wrong firmware model");
MSG_SEND(Failure);
return UPLOAD_ERR_INVALID_IMAGE_MODEL;
}
if (sectrue != check_image_header_sig(received_hdr, vhdr.vsig_m,
vhdr.vsig_n, vhdr.vpub)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid firmware signature");
MSG_SEND(Failure);
return UPLOAD_ERR_INVALID_IMAGE_HEADER_SIG;
}
memcpy(&hdr, received_hdr, sizeof(hdr));
vendor_header current_vhdr;
image_header current_hdr;
secbool is_new = secfalse;
detect_installation(&current_vhdr, &current_hdr, &vhdr, &hdr, &is_new,
&is_upgrade, &is_downgrade_wipe);
if (sectrue !=
read_vendor_header((const uint8_t *)FIRMWARE_START, &current_vhdr)) {
is_new = sectrue;
}
const image_header *current_hdr = NULL;
if (is_new == secfalse) {
current_hdr = read_image_header(
(const uint8_t *)FIRMWARE_START + current_vhdr.hdrlen,
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
if (current_hdr !=
(const image_header *)FIRMWARE_START + current_vhdr.hdrlen) {
is_new = sectrue;
}
}
if (is_new == secfalse) {
detect_installation(&current_vhdr, current_hdr, &vhdr, &hdr, &is_new,
&is_upgrade, &is_downgrade_wipe);
}
// no user confirmations, go directly to upload
@ -539,7 +590,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Firmware too big");
MSG_SEND(Failure);
return -5;
return UPLOAD_ERR_FIRMWARE_TOO_BIG;
}
if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32,
@ -558,7 +609,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk hash");
MSG_SEND(Failure);
return -6;
return UPLOAD_ERR_INVALID_CHUNK_HASH;
}
ensure(flash_unlock_write(), NULL);
@ -621,11 +672,11 @@ int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Could not erase flash");
MSG_SEND(Failure);
return -1;
return WIPE_ERR_CANNOT_ERASE;
} else {
MSG_SEND_INIT(Success);
MSG_SEND(Success);
return 0;
return WIPE_OK;
}
}

View File

@ -29,6 +29,24 @@
#define FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT 2
enum {
UPLOAD_OK = 0,
UPLOAD_ERR_INVALID_CHUNK_SIZE = -1,
UPLOAD_ERR_INVALID_VENDOR_HEADER = -2,
UPLOAD_ERR_INVALID_VENDOR_HEADER_SIG = -3,
UPLOAD_ERR_INVALID_IMAGE_HEADER = -4,
UPLOAD_ERR_INVALID_IMAGE_MODEL = -5,
UPLOAD_ERR_INVALID_IMAGE_HEADER_SIG = -6,
UPLOAD_ERR_USER_ABORT = -7,
UPLOAD_ERR_FIRMWARE_TOO_BIG = -8,
UPLOAD_ERR_INVALID_CHUNK_HASH = -9,
};
enum {
WIPE_OK = 0,
WIPE_ERR_CANNOT_ERASE = -1,
};
secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id,
uint32_t *msg_size);

View File

@ -20,12 +20,14 @@
#include <stdint.h>
#include <string.h>
#include "blake2s.h"
#include "board_capabilities.h"
#include "common.h"
#include "flash.h"
#include "image.h"
// symbols from bootloader.bin => bootloader.o
extern const uint32_t _binary_embed_firmware_bootloader_bin_start;
extern const uint32_t _binary_embed_firmware_bootloader_bin_size;
extern const void _binary_embed_firmware_bootloader_bin_start;
extern const void _binary_embed_firmware_bootloader_bin_size;
/*
static secbool known_bootloader(const uint8_t *hash, int len) {
@ -97,6 +99,48 @@ void check_and_replace_bootloader(void) {
(const uint32_t *)&_binary_embed_firmware_bootloader_bin_start;
const uint32_t len =
(const uint32_t)&_binary_embed_firmware_bootloader_bin_size;
const image_header *new_bld_hdr = read_image_header(
(uint8_t *)data, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE);
ensure(new_bld_hdr == (const image_header *)data ? sectrue : secfalse,
"Invalid embedded bootloader");
ensure(check_image_model(new_bld_hdr), "Incompatible embedded bootloader");
const image_header *current_bld_hdr = read_image_header(
bl_data, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE);
// cannot find valid header for current bootloader, something is wrong
ensure(current_bld_hdr == (const image_header *)bl_data ? sectrue : secfalse,
"Invalid bootloader header");
ensure(check_image_model(current_bld_hdr), "Incompatible bootloader found");
if (new_bld_hdr->monotonic < current_bld_hdr->monotonic) {
// reject downgrade
return;
}
uint32_t board_name = get_board_name();
if (board_name == 0 || strncmp((const char *)&board_name, "T2T1", 4) == 0) {
// no board capabilities, assume Model T
if ((strncmp((const char *)&new_bld_hdr->hw_model, "T2T1", 4) != 0) &&
(new_bld_hdr->hw_model != 0)) {
// reject non-model T bootloader
// 0 represents pre-model check bootloader
ensure(secfalse, "Incompatible embedded bootloader");
}
}
// at this point, due to the previous check_image_model call, we know that the
// new_bld_hdr is
// meant for the same model as this firmware, so we can check the board name
// against the firmware hw_model.
else if (board_name != HW_MODEL) {
// reject incompatible bootloader
ensure(secfalse, "Incompatible embedded bootloader");
}
ensure(flash_erase(FLASH_SECTOR_BOOTLOADER), NULL);
ensure(flash_unlock_write(), NULL);
for (int i = 0; i < len / sizeof(uint32_t); i++) {

View File

@ -13,7 +13,11 @@
g_header:
.byte 'T','R','Z','F' // magic
.word g_header_end - g_header // hdrlen
#ifdef TREZOR_MODEL_T
.word 0 // expiry
#else
.word 1 // expiry
#endif
.word _codelen // codelen
.byte VERSION_MAJOR // vmajor
.byte VERSION_MINOR // vminor
@ -23,7 +27,10 @@ g_header:
.byte FIX_VERSION_MINOR // fix_vminor
.byte FIX_VERSION_PATCH // fix_vpatch
.byte FIX_VERSION_BUILD // fix_vbuild
. = . + 8 // reserved
.word HW_MODEL // type of the designated hardware
.byte HW_REVISION // revision of the designated hardware
.byte VERSION_MONOTONIC // monotonic version of the binary
. = . + 2 // reserved
. = . + 512 // hash1 ... hash16
#if !defined TREZOR_MODEL_1

View File

@ -7,3 +7,5 @@
#define FIX_VERSION_MINOR 4
#define FIX_VERSION_PATCH 0
#define FIX_VERSION_BUILD 0
#define VERSION_MONOTONIC 1

View File

@ -10,7 +10,11 @@
g_header:
.byte 'T','R','Z','F' // magic
.word g_header_end - g_header // hdrlen
#ifdef TREZOR_MODEL_T
.word 0 // expiry
#else
.word 1 // expiry
#endif
.word _codelen // codelen
.byte VERSION_MAJOR // vmajor
.byte VERSION_MINOR // vminor
@ -20,7 +24,10 @@ g_header:
.byte FIX_VERSION_MINOR // fix_vminor
.byte FIX_VERSION_PATCH // fix_vpatch
.byte FIX_VERSION_BUILD // fix_vbuild
. = . + 8 // reserved
.word HW_MODEL // type of the designated hardware
.byte HW_REVISION // revision of the designated hardware
.byte VERSION_MONOTONIC // monotonic version of the binary
. = . + 2 // reserved
. = . + 512 // hash1 ... hash16
. = . + 415 // reserved
.byte 0 // sigmask

View File

@ -7,3 +7,5 @@
#define FIX_VERSION_MINOR 1
#define FIX_VERSION_PATCH 0
#define FIX_VERSION_BUILD 0
#define VERSION_MONOTONIC 1

View File

@ -10,7 +10,11 @@
g_header:
.byte 'T','R','Z','F' // magic
.word g_header_end - g_header // hdrlen
#ifdef TREZOR_MODEL_T
.word 0 // expiry
#else
.word 1 // expiry
#endif
.word _codelen // codelen
.byte VERSION_MAJOR // vmajor
.byte VERSION_MINOR // vminor
@ -20,7 +24,10 @@ g_header:
.byte FIX_VERSION_MINOR // fix_vminor
.byte FIX_VERSION_PATCH // fix_vpatch
.byte FIX_VERSION_BUILD // fix_vbuild
. = . + 8 // reserved
.word HW_MODEL // type of the designated hardware
.byte HW_REVISION // revision of the designated hardware
.byte VERSION_MONOTONIC // monotonic version of the binary
. = . + 2 // reserved
. = . + 512 // hash1 ... hash16
. = . + 415 // reserved
.byte 0 // sigmask

View File

@ -7,3 +7,5 @@
#define FIX_VERSION_MINOR 1
#define FIX_VERSION_PATCH 0
#define FIX_VERSION_BUILD 0
#define VERSION_MONOTONIC 1

View File

@ -24,11 +24,11 @@
#define handle_fault(msg) \
(__fatal_error("Fault detected", msg, __FILE__, __LINE__, __func__))
static uint8_t board_name[MODEL_NAME_MAX_LENGTH + 1] = {0};
static uint32_t board_name = 0;
static struct BoardloaderVersion boardloader_version;
const uint8_t *get_board_name() { return board_name; }
const uint32_t get_board_name() { return board_name; }
const struct BoardloaderVersion *get_boardloader_version() {
return &boardloader_version;
@ -49,7 +49,6 @@ void parse_boardloader_capabilities() {
while (pos <= end - 2) {
enum CapabilityTag tag = pos[0];
uint8_t length = pos[1];
uint8_t used_length;
pos += 2;
if (pos + length > end) {
@ -61,9 +60,10 @@ void parse_boardloader_capabilities() {
// not used yet, just advance pointer
break;
case MODEL_NAME:
used_length = MIN(MODEL_NAME_MAX_LENGTH, length);
memcpy(board_name, pos, used_length);
board_name[MODEL_NAME_MAX_LENGTH] = 0;
if (length != sizeof(uint32_t)) {
break;
}
memcpy((uint8_t *)&board_name, pos, sizeof(uint32_t));
break;
case BOARDLOADER_VERSION:
if (length != sizeof(boardloader_version)) {

View File

@ -38,7 +38,6 @@ Last tag must be terminator or all space used.
#define BOARD_CAPABILITIES_ADDR 0x0800BF00
#define BOARD_CAPABILITIES_SIZE 256
#define CAPABILITIES_HEADER "TRZC"
#define MODEL_NAME_MAX_LENGTH 16
enum CapabilityTag {
TERMINATOR = 0x00,
@ -62,7 +61,7 @@ struct __attribute__((packed)) BoardCapabilities {
uint8_t header[4];
uint8_t model_tag;
uint8_t model_length;
uint8_t model_name[MODEL_NAME_MAX_LENGTH];
uint32_t model_name;
uint8_t version_tag;
uint8_t version_length;
struct BoardloaderVersion version;
@ -76,7 +75,7 @@ struct __attribute__((packed)) BoardCapabilities {
*/
void parse_boardloader_capabilities();
const uint8_t* get_board_name();
const uint32_t get_board_name();
const struct BoardloaderVersion* get_boardloader_version();
#endif

View File

@ -50,57 +50,84 @@ static secbool compute_pubkey(uint8_t sig_m, uint8_t sig_n,
return sectrue * (0 == ed25519_cosi_combine_publickeys(res, keys, sig_m));
}
secbool load_image_header(const uint8_t *const data, const uint32_t magic,
const uint32_t maxsize, uint8_t key_m, uint8_t key_n,
const uint8_t *const *keys, image_header *const hdr) {
memcpy(&hdr->magic, data, 4);
if (hdr->magic != magic) return secfalse;
const image_header *read_image_header(const uint8_t *const data,
const uint32_t magic,
const uint32_t maxsize) {
const image_header *hdr = (const image_header *)data;
memcpy(&hdr->hdrlen, data + 4, 4);
if (hdr->hdrlen != IMAGE_HEADER_SIZE) return secfalse;
if (hdr->magic != magic) {
return NULL;
}
if (hdr->hdrlen != IMAGE_HEADER_SIZE) {
return NULL;
}
memcpy(&hdr->expiry, data + 8, 4);
// TODO: expiry mechanism needs to be ironed out before production or those
// devices won't accept expiring bootloaders (due to boardloader write
// protection).
if (hdr->expiry != 0) return secfalse;
// lowest bit is used for breaking compatibility between old TT bootloaders
// and non TT images
// which is evaluated in check_image_model function
if ((hdr->expiry & 0xFFFFFFFE) != 0) return secfalse;
memcpy(&hdr->codelen, data + 12, 4);
if (hdr->codelen > (maxsize - hdr->hdrlen)) return secfalse;
if ((hdr->hdrlen + hdr->codelen) < 4 * 1024) return secfalse;
if ((hdr->hdrlen + hdr->codelen) % 512 != 0) return secfalse;
memcpy(&hdr->version, data + 16, 4);
memcpy(&hdr->fix_version, data + 20, 4);
return hdr;
}
memcpy(hdr->hashes, data + 32, 512);
secbool check_image_model(const image_header *const hdr) {
// abusing expiry field to break compatibility of non-TT images with existing
// bootloaders/boardloaders
#ifdef TREZOR_MODEL_T
if (hdr->expiry == 0 && hdr->hw_model == 0 && hdr->hw_revision == 0) {
// images for model TT older than this check
return sectrue;
}
#else
if ((hdr->expiry & 0x01) == 0) {
// for models other than TT, expiry == 0 is unacceptable, as the image will
// run on bootloaders older that this check
return secfalse;
}
#endif
memcpy(&hdr->sigmask, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE, 1);
if (hdr->hw_model != HW_MODEL) {
return secfalse;
}
if (hdr->hw_revision != HW_REVISION) {
return secfalse;
}
memcpy(hdr->sig, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE + 1,
IMAGE_SIG_SIZE - 1);
return sectrue;
}
secbool check_image_header_sig(const image_header *const hdr, uint8_t key_m,
uint8_t key_n, const uint8_t *const *keys) {
// check header signature
BLAKE2S_CTX ctx;
uint8_t fingerprint[32];
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
blake2s_Update(&ctx, data, IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE);
blake2s_Update(&ctx, hdr, IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE);
for (int i = 0; i < IMAGE_SIG_SIZE; i++) {
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
}
blake2s_Final(&ctx, hdr->fingerprint, BLAKE2S_DIGEST_LENGTH);
blake2s_Final(&ctx, fingerprint, BLAKE2S_DIGEST_LENGTH);
ed25519_public_key pub;
if (sectrue != compute_pubkey(key_m, key_n, keys, hdr->sigmask, pub))
return secfalse;
return sectrue *
(0 == ed25519_sign_open(hdr->fingerprint, BLAKE2S_DIGEST_LENGTH, pub,
(0 == ed25519_sign_open(fingerprint, BLAKE2S_DIGEST_LENGTH, pub,
*(const ed25519_signature *)hdr->sig));
}
secbool read_vendor_header(const uint8_t *const data,
vendor_header *const vhdr) {
secbool __wur read_vendor_header(const uint8_t *const data,
vendor_header *const vhdr) {
memcpy(&vhdr->magic, data, 4);
if (vhdr->magic != 0x565A5254) return secfalse; // TRZV
@ -110,6 +137,8 @@ secbool read_vendor_header(const uint8_t *const data,
memcpy(&vhdr->expiry, data + 8, 4);
if (vhdr->expiry != 0) return secfalse;
vhdr->origin = data;
memcpy(&vhdr->version, data + 12, 2);
memcpy(&vhdr->vsig_m, data + 14, 1);
@ -143,10 +172,9 @@ secbool read_vendor_header(const uint8_t *const data,
return sectrue;
}
secbool load_vendor_header(const uint8_t *const data, uint8_t key_m,
uint8_t key_n, const uint8_t *const *keys,
vendor_header *const vhdr) {
if (sectrue != read_vendor_header(data, vhdr)) {
secbool check_vendor_header_sig(const vendor_header *const vhdr, uint8_t key_m,
uint8_t key_n, const uint8_t *const *keys) {
if (vhdr == NULL) {
return secfalse;
}
@ -155,7 +183,7 @@ secbool load_vendor_header(const uint8_t *const data, uint8_t key_m,
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
BLAKE2S_CTX ctx;
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
blake2s_Update(&ctx, data, vhdr->hdrlen - IMAGE_SIG_SIZE);
blake2s_Update(&ctx, vhdr->origin, vhdr->hdrlen - IMAGE_SIG_SIZE);
for (int i = 0; i < IMAGE_SIG_SIZE; i++) {
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
}

View File

@ -45,12 +45,14 @@ typedef struct {
uint32_t codelen;
uint32_t version;
uint32_t fix_version;
// uint8_t reserved[8];
uint32_t hw_model;
uint8_t hw_revision;
uint8_t monotonic;
uint8_t reserved_0[2];
uint8_t hashes[512];
// uint8_t reserved[415];
uint8_t reserved_1[415];
uint8_t sigmask;
uint8_t sig[64];
uint8_t fingerprint[32];
} image_header;
#define MAX_VENDOR_PUBLIC_KEYS 8
@ -76,20 +78,26 @@ typedef struct {
const uint8_t *vimg;
uint8_t sigmask;
uint8_t sig[64];
const uint8_t *origin; // pointer to the underlying data
} vendor_header;
secbool __wur load_image_header(const uint8_t *const data, const uint32_t magic,
const uint32_t maxsize, uint8_t key_m,
uint8_t key_n, const uint8_t *const *keys,
image_header *const hdr);
const image_header *read_image_header(const uint8_t *const data,
const uint32_t magic,
const uint32_t maxsize);
secbool __wur load_vendor_header(const uint8_t *const data, uint8_t key_m,
uint8_t key_n, const uint8_t *const *keys,
vendor_header *const vhdr);
secbool __wur check_image_model(const image_header *const hdr);
secbool __wur check_image_header_sig(const image_header *const hdr,
uint8_t key_m, uint8_t key_n,
const uint8_t *const *keys);
secbool __wur read_vendor_header(const uint8_t *const data,
vendor_header *const vhdr);
secbool __wur check_vendor_header_sig(const vendor_header *const vhdr,
uint8_t key_m, uint8_t key_n,
const uint8_t *const *keys);
void vendor_header_hash(const vendor_header *const vhdr, uint8_t *hash);
secbool __wur check_single_hash(const uint8_t *const hash,

View File

@ -9,16 +9,27 @@ def add_font(font_name, font, defines, sources):
sources.append(sourcefile)
def get_hw_model_as_number(hw_model):
return int.from_bytes(hw_model.encode(), 'little')
def configure_board(model, env, defines, sources):
model_r_version = 4
if model in ('1',):
board = 'trezor_1.h'
display = 'vg-2864ksweg01.c'
hw_model = get_hw_model_as_number('T1B1')
hw_revision = 0
elif model in ('T',):
board = 'trezor_t.h'
display = 'st7789v.c'
hw_model = get_hw_model_as_number('T2T1')
hw_revision = 0
elif model in ('R',):
hw_model = get_hw_model_as_number('T2B1')
hw_revision = model_r_version
if model_r_version == 3:
board = 'trezor_r_v3.h'
display = "ug-2828tswig01.c"
@ -29,5 +40,7 @@ def configure_board(model, env, defines, sources):
raise Exception("Unknown model")
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"', ]
defines += [f'HW_MODEL={hw_model}', ]
defines += [f'HW_REVISION={hw_revision}', ]
sources += [f'embed/trezorhal/displays/{display}', ]
env.get('ENV')['TREZOR_BOARD'] = board