bootloader: show different dialogs for firmware upgrade and vendor change

pull/25/head
Pavol Rusnak 6 years ago
parent 6e81a68fbe
commit 0d7f486733
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D

@ -89,8 +89,20 @@ void ui_screen_third(void)
display_text_center(120, 220, "Open trezor.io/start", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
}
// buttons
static void ui_confirm_cancel_buttons(void)
{
display_bar_radius(9, 184, 108, 50, COLOR_BL_FAIL, COLOR_WHITE, 4);
display_icon(9 + (108 - 16) / 2, 184 + (50 - 16) / 2, 16, 16, toi_icon_cancel + 12, sizeof(toi_icon_cancel) - 12, COLOR_WHITE, COLOR_BL_FAIL);
display_bar_radius(123, 184, 108, 50, COLOR_BL_DONE, COLOR_WHITE, 4);
display_icon(123 + (108 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, COLOR_WHITE, COLOR_BL_DONE);
}
// info UI
void ui_screen_info(secbool buttons, const vendor_header * const vhdr, const image_header * const hdr)
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
@ -120,10 +132,7 @@ void ui_screen_info(secbool buttons, const vendor_header * const vhdr, const ima
if (sectrue == buttons) {
display_text_center(120, 170, "Connect to host?", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_bar_radius(9, 184, 108, 50, COLOR_BL_FAIL, COLOR_WHITE, 4);
display_icon(9 + (108 - 16) / 2, 184 + (50 - 16) / 2, 16, 16, toi_icon_cancel + 12, sizeof(toi_icon_cancel) - 12, COLOR_WHITE, COLOR_BL_FAIL);
display_bar_radius(123, 184, 108, 50, COLOR_BL_DONE, COLOR_WHITE, 4);
display_icon(123 + (108 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, COLOR_WHITE, COLOR_BL_DONE);
ui_confirm_cancel_buttons();
} else {
display_text_center(120, 220, "Open trezor.io/start", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
}
@ -151,19 +160,43 @@ void ui_screen_info_fingerprint(const image_header * const hdr)
// install UI
void ui_screen_install_confirm(void)
void ui_screen_install_confirm_upgrade(const vendor_header * const vhdr, const image_header * const hdr)
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_text(16, 32, "Firmware update", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK);
display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, COLOR_BLACK, COLOR_WHITE);
display_text(55, 70, "Do you want to", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_text(55, 95, "update firmware?", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_text(55, 70, "Update firmware by", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
char ver_str[32];
mini_snprintf(ver_str, sizeof(ver_str), "to version %d.%d.%d.%d?",
(int)(hdr->version & 0xFF),
(int)((hdr->version >> 8) & 0xFF),
(int)((hdr->version >> 16) & 0xFF),
(int)((hdr->version >> 24) & 0xFF)
);
display_text(55, 120, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
ui_confirm_cancel_buttons();
}
display_bar_radius(9, 184, 108, 50, COLOR_BL_FAIL, COLOR_WHITE, 4);
display_icon(9 + (108 - 16) / 2, 184 + (50 - 16) / 2, 16, 16, toi_icon_cancel + 12, sizeof(toi_icon_cancel) - 12, COLOR_WHITE, COLOR_BL_FAIL);
display_bar_radius(123, 184, 108, 50, COLOR_BL_DONE, COLOR_WHITE, 4);
display_icon(123 + (108 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, COLOR_WHITE, COLOR_BL_DONE);
void ui_screen_install_confirm_newvendor(const vendor_header * const vhdr, const image_header * const hdr)
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_text(16, 32, "Re-install firmware", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK);
display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, COLOR_BLACK, COLOR_WHITE);
display_text(55, 70, "Install firmware by", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
char ver_str[32];
mini_snprintf(ver_str, sizeof(ver_str), "(version %d.%d.%d.%d)?",
(int)(hdr->version & 0xFF),
(int)((hdr->version >> 8) & 0xFF),
(int)((hdr->version >> 16) & 0xFF),
(int)((hdr->version >> 24) & 0xFF)
);
display_text(55, 120, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL, COLOR_BL_FAIL, COLOR_WHITE, 0);
ui_confirm_cancel_buttons();
}
void ui_screen_install(void)
@ -175,7 +208,7 @@ void ui_screen_install(void)
void ui_screen_install_progress_erase(int pos, int len)
{
display_loader(200 + 200 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK);
display_loader(250 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK);
}
void ui_screen_install_progress_upload(int pos)
@ -195,11 +228,7 @@ void ui_screen_wipe_confirm(void)
display_text(55, 95, "wipe the device?", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE, 0);
display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL, COLOR_BL_FAIL, COLOR_WHITE, 0);
display_bar_radius(9, 184, 108, 50, COLOR_BL_FAIL, COLOR_WHITE, 4);
display_icon(9 + (108 - 16) / 2, 184 + (50 - 16) / 2, 16, 16, toi_icon_cancel + 12, sizeof(toi_icon_cancel) - 12, COLOR_WHITE, COLOR_BL_FAIL);
display_bar_radius(123, 184, 108, 50, COLOR_BL_DONE, COLOR_WHITE, 4);
display_icon(123 + (108 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, COLOR_WHITE, COLOR_BL_DONE);
ui_confirm_cancel_buttons();
}
void ui_screen_wipe(void)

@ -15,7 +15,8 @@ void ui_screen_third(void);
void ui_screen_info(secbool buttons, const vendor_header * const vhdr, const image_header * const hdr);
void ui_screen_info_fingerprint(const image_header * const hdr);
void ui_screen_install_confirm(void);
void ui_screen_install_confirm_upgrade(const vendor_header * const vhdr, const image_header * const hdr);
void ui_screen_install_confirm_newvendor(const vendor_header * const vhdr, const image_header * const hdr);
void ui_screen_install(void);
void ui_screen_install_progress_erase(int pos, int len);
void ui_screen_install_progress_upload(int pos);

@ -159,28 +159,11 @@ static secbool bootloader_usb_loop(const vendor_header * const vhdr, const image
}
break;
case 6: // FirmwareErase
// skip confirmation when no firmware is present
if (vhdr && hdr) {
ui_fadeout();
ui_screen_install_confirm();
ui_fadein();
int response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL);
if (INPUT_CANCEL == response) {
ui_fadeout();
ui_screen_info(secfalse, vhdr, hdr);
ui_fadein();
send_user_abort(USB_IFACE_NUM, "Firmware install cancelled");
break;
}
}
ui_fadeout();
ui_screen_install();
ui_fadein();
process_msg_FirmwareErase(USB_IFACE_NUM, msg_size, buf);
break;
case 7: // FirmwareUpload
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
if (r < 0) { // error
if (r < 0 && r != -4) { // error, but not user abort (-4)
ui_fadeout();
ui_screen_fail();
ui_fadein();

@ -315,14 +315,9 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field, void **
chunk_size = stream->bytes_left;
while (stream->bytes_left) {
// update loader
if (firmware_block == 0) {
// first chunk is 0 - 200
// followed by erase 200 - 400
ui_screen_install_progress_upload(200 * chunk_written / chunk_size);
} else {
// remaining chunks are 400 - 1000
ui_screen_install_progress_upload(400 + 600 * (firmware_block * IMAGE_CHUNK_SIZE + chunk_written) / (firmware_block * IMAGE_CHUNK_SIZE + firmware_remaining));
// update loader but skip first block
if (firmware_block > 0) {
ui_screen_install_progress_upload(250 + 750 * (firmware_block * IMAGE_CHUNK_SIZE + chunk_written) / (firmware_block * IMAGE_CHUNK_SIZE + firmware_remaining));
}
// read data
if (!pb_read(stream, (pb_byte_t *)(chunk_buffer + chunk_written), (stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) {
@ -354,26 +349,28 @@ static int version_compare(uint32_t vera, uint32_t verb)
return a - b;
}
static secbool is_legit_upgrade(const vendor_header * const new_vhdr, const image_header * const new_hdr)
static void detect_installation(vendor_header *current_vhdr, image_header *current_hdr, const vendor_header * const new_vhdr, const image_header * const new_hdr, secbool *is_new, secbool *is_upgrade)
{
vendor_header current_vhdr;
if (sectrue != load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &current_vhdr)) {
return secfalse;
*is_new = secfalse;
*is_upgrade = secfalse;
if (sectrue != load_vendor_header_keys((const uint8_t *)FIRMWARE_START, 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)) {
*is_new = sectrue;
return;
}
uint8_t hash1[32], hash2[32];
vendor_keys_hash(new_vhdr, hash1);
vendor_keys_hash(&current_vhdr, hash2);
vendor_keys_hash(current_vhdr, hash2);
if (0 != memcmp(hash1, hash2, 32)) {
return secfalse;
return;
}
image_header current_hdr;
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)) {
return secfalse;
}
if (version_compare(new_hdr->version, current_hdr.fix_version) < 0) {
return secfalse;
if (version_compare(new_hdr->version, current_hdr->fix_version) < 0) {
return;
}
return sectrue;
*is_upgrade = sectrue;
}
int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *buf)
@ -410,7 +407,44 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
return -3;
}
if (sectrue != is_legit_upgrade(&vhdr, &hdr)) {
vendor_header current_vhdr;
image_header current_hdr;
secbool is_new = secfalse, is_upgrade = secfalse;
detect_installation(&current_vhdr, &current_hdr, &vhdr, &hdr, &is_new, &is_upgrade);
int response = INPUT_CANCEL;
if (sectrue == is_new) {
// new installation - auto confirm
response = INPUT_CONFIRM;
} else
if (sectrue == is_upgrade) {
// firmware upgrade
ui_fadeout();
ui_screen_install_confirm_upgrade(&vhdr, &hdr);
ui_fadein();
response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL);
} else {
// new firmware vendor
ui_fadeout();
ui_screen_install_confirm_newvendor(&vhdr, &hdr);
ui_fadein();
response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL);
}
if (INPUT_CANCEL == response) {
ui_fadeout();
ui_screen_info(secfalse, &current_vhdr, &current_hdr);
ui_fadein();
send_user_abort(USB_IFACE_NUM, "Firmware install cancelled");
return -4;
}
ui_fadeout();
ui_screen_install();
ui_fadein();
// if firmware is not upgrade, erase storage
if (sectrue != is_upgrade) {
const uint8_t sectors_storage[] = {
FLASH_SECTOR_STORAGE_1,
FLASH_SECTOR_STORAGE_2,
@ -428,7 +462,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Firmware too big");
MSG_SEND(Failure);
return -3;
return -5;
}
if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32, chunk_buffer + firstskip, chunk_size - firstskip)) {
@ -436,7 +470,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk hash");
MSG_SEND(Failure);
return -4;
return -6;
}
ensure(flash_unlock(), NULL);

Loading…
Cancel
Save