diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 5ce2f34fcd..fa389551d5 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -20,7 +20,7 @@ if TREZOR_MODEL in ('1', ): ) Return() -FEATURES_WANTED = ["input", "rgb_led"] +FEATURES_WANTED = ["input", "rgb_led", "ble"] CCFLAGS_MOD = '' CPPPATH_MOD = [] @@ -34,9 +34,9 @@ if TREZOR_MODEL in ('1', 'R'): FONT_MONO='Font_PixelOperatorMono_Regular_8' if TREZOR_MODEL in ('T', 'DISC1', ): FONT_NORMAL='Font_TTHoves_Regular_21' - FONT_DEMIBOLD=None + FONT_DEMIBOLD='Font_TTHoves_Regular_21' FONT_BOLD='Font_TTHoves_Bold_17' - FONT_MONO=None + FONT_MONO='Font_TTHoves_Regular_21' # modtrezorcrypto CCFLAGS_MOD += '-Wno-sequence-point ' @@ -104,6 +104,7 @@ SOURCE_STMHAL = [ 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c', 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c', 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c', + 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c', 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c', 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c', 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c', @@ -126,6 +127,7 @@ SOURCE_BOOTLOADER = [ SOURCE_TREZORHAL = [ 'embed/trezorhal/common.c', + 'embed/trezorhal/dma.c', 'embed/trezorhal/image.c', 'embed/trezorhal/flash.c', 'embed/trezorhal/mini_printf.c', diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 65053aeb51..26c80883ba 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -49,11 +49,16 @@ #ifdef USE_RGB_LED #include "rgb_led.h" #endif +#ifdef USE_BLE +#include "ble/comm.h" +#endif + #include "usb.h" #include "version.h" #include "bootui.h" #include "messages.h" +#include "messages.pb.h" #include "rust_ui.h" const uint8_t BOOTLOADER_KEY_M = 2; @@ -71,8 +76,6 @@ static const uint8_t * const BOOTLOADER_KEYS[] = { #endif }; -#define USB_IFACE_NUM 0 - typedef enum { CONTINUE = 0, RETURN = 1, @@ -119,98 +122,221 @@ static void usb_init_all(secbool usb21_landing) { usb_start(); } -static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr, - const image_header *const hdr) { +static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, + const image_header *const hdr) { // if both are NULL, we don't have a firmware installed // let's show a webusb landing page in this case usb_init_all((vhdr == NULL && hdr == NULL) ? sectrue : secfalse); - uint8_t buf[USB_PACKET_SIZE]; + uint8_t buf_usb[USB_PACKET_SIZE]; +#ifdef USE_BLE + uint8_t ble_buf[BLE_PACKET_SIZE]; +#endif + uint8_t *buf = NULL; + + uint8_t active_iface = 0; + int r = 0; for (;;) { + for (;;) { #ifdef TREZOR_EMULATOR - emulator_poll_events(); + emulator_poll_events(); +#endif + r = usb_webusb_read_blocking(USB_IFACE_NUM, buf_usb, USB_PACKET_SIZE, 20); + if (r == USB_PACKET_SIZE) { + active_iface = USB_IFACE_NUM; + buf = buf_usb; + break; + } +#ifdef USE_BLE + r = ble_ext_comm_receive(ble_buf, sizeof(ble_buf)); + + if (r == BLE_PACKET_SIZE) { + active_iface = BLE_EXT_IFACE_NUM; + buf = ble_buf; + break; + } + + r = ble_int_comm_receive(ble_buf, sizeof(ble_buf)); + if (r != 0) { + active_iface = BLE_INT_IFACE_NUM; + buf = ble_buf; + break; + } #endif - int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE, - USB_TIMEOUT); - if (r != USB_PACKET_SIZE) { - continue; } - uint16_t msg_id; - uint32_t msg_size; - uint32_t response; - if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { - // invalid header -> discard - continue; + +#ifdef USE_BLE + if (active_iface == BLE_INT_IFACE_NUM) { + for (;;) { + bool next = false; + if (r == 0) { + if (active_iface == BLE_INT_IFACE_NUM) { + r = ble_int_comm_receive(ble_buf, sizeof(ble_buf)); + + if (r == 0) { + continue; + } + } else { + // unknown interface + return CONTINUE; + } + } + + r = 0; + + uint16_t msg_id; + uint32_t msg_size; + uint32_t response; + if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { + // invalid header -> discard + continue; + } + switch (msg_id) { + case MessageType_MessageType_PairingRequest: // pairing request + response = process_msg_Pairing(active_iface, msg_size, ble_buf); + if (response != INPUT_CONFIRM) { + hal_delay(100); + usb_stop(); + usb_deinit(); + return RETURN; + } + screen_connect(); + next = true; + + break; + case MessageType_MessageType_RepairRequest: // repairing request + response = process_msg_Repair(active_iface, msg_size, ble_buf); + if (response != INPUT_CONFIRM) { + hal_delay(100); + usb_stop(); + usb_deinit(); + return RETURN; + } + // screen_connect(); + // todo - screen connect or timeout? + break; + default: + process_msg_unknown(active_iface, msg_size, ble_buf); + break; + } + if (next) { + break; + } + } } - switch (msg_id) { - case 0: // Initialize - process_msg_Initialize(USB_IFACE_NUM, msg_size, buf, vhdr, hdr); - break; - case 1: // Ping - process_msg_Ping(USB_IFACE_NUM, msg_size, buf); - break; - case 5: // WipeDevice - response = ui_screen_wipe_confirm(); - if (INPUT_CANCEL == response) { - send_user_abort(USB_IFACE_NUM, "Wipe cancelled"); - hal_delay(100); - usb_stop(); - usb_deinit(); - return RETURN; +#endif + + if (active_iface == USB_IFACE_NUM || active_iface == BLE_EXT_IFACE_NUM) { + for (;;) { +#ifdef TREZOR_EMULATOR + emulator_poll_events(); +#endif + if (r == 0) { + if (active_iface == USB_IFACE_NUM) { + r = usb_webusb_read_blocking(active_iface, buf_usb, USB_PACKET_SIZE, + USB_TIMEOUT); + if (r != USB_PACKET_SIZE) { + continue; + } + } +#ifdef USE_BLE + else if (active_iface == BLE_EXT_IFACE_NUM) { + r = ble_ext_comm_receive(ble_buf, sizeof(ble_buf)); + + if (r != BLE_PACKET_SIZE) { + continue; + } + } +#endif + else { + // unknown interface + return CONTINUE; + } } - ui_screen_wipe(); - r = process_msg_WipeDevice(USB_IFACE_NUM, msg_size, buf); - if (r < 0) { // error - screen_wipe_fail(); - hal_delay(100); - usb_stop(); - usb_deinit(); - return SHUTDOWN; - } else { // success - screen_wipe_success(); - hal_delay(100); - usb_stop(); - usb_deinit(); - return SHUTDOWN; + + r = 0; + + uint16_t msg_id; + uint32_t msg_size; + uint32_t response; + int32_t upload_response; + if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { + // invalid header -> discard + continue; } - break; - case 6: // FirmwareErase - 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 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort - ui_screen_fail(); - usb_stop(); - usb_deinit(); - return SHUTDOWN; - } else if (r == UPLOAD_ERR_USER_ABORT) { - hal_delay(100); - usb_stop(); - usb_deinit(); - return RETURN; - } else if (r == 0) { // last chunk received - ui_screen_install_progress_upload(1000); - ui_screen_done(4, sectrue); - ui_screen_done(3, secfalse); - hal_delay(1000); - ui_screen_done(2, secfalse); - hal_delay(1000); - ui_screen_done(1, secfalse); - hal_delay(1000); - usb_stop(); - usb_deinit(); - ui_screen_boot_empty(true); - return CONTINUE; + switch (msg_id) { + case 0: // Initialize + process_msg_Initialize(active_iface, msg_size, buf, vhdr, hdr); + break; + case 1: // Ping + process_msg_Ping(active_iface, msg_size, buf); + break; + case 5: // WipeDevice + response = ui_screen_wipe_confirm(); + if (INPUT_CANCEL == response) { + send_user_abort(active_iface, "Wipe cancelled"); + hal_delay(100); + usb_stop(); + usb_deinit(); + return RETURN; + } + ui_screen_wipe(); + upload_response = + process_msg_WipeDevice(active_iface, msg_size, buf); + if (upload_response < 0) { // error + screen_wipe_fail(); + usb_stop(); + usb_deinit(); + return SHUTDOWN; + } else { // success + screen_wipe_success(); + usb_stop(); + usb_deinit(); + return SHUTDOWN; + } + break; + case 6: // FirmwareErase + process_msg_FirmwareErase(active_iface, msg_size, buf); + break; + case 7: // FirmwareUpload + upload_response = + process_msg_FirmwareUpload(active_iface, msg_size, buf); + if (upload_response < 0 && + upload_response != + UPLOAD_ERR_USER_ABORT) { // error, but not user abort + ui_screen_fail(); + usb_stop(); + usb_deinit(); + return SHUTDOWN; + } else if (upload_response == UPLOAD_ERR_USER_ABORT) { + hal_delay(100); + usb_stop(); + usb_deinit(); + return RETURN; + } else if (upload_response == 0) { // last chunk received + ui_screen_install_progress_upload(1000); + ui_screen_done(4, sectrue); + ui_screen_done(3, secfalse); + hal_delay(1000); + ui_screen_done(2, secfalse); + hal_delay(1000); + ui_screen_done(1, secfalse); + hal_delay(1000); + usb_stop(); + usb_deinit(); + ui_screen_boot_empty(true); + return CONTINUE; + } + break; + case 55: // GetFeatures + process_msg_GetFeatures(active_iface, msg_size, buf, vhdr, hdr); + break; + default: + process_msg_unknown(active_iface, msg_size, buf); + break; } - break; - case 55: // GetFeatures - process_msg_GetFeatures(USB_IFACE_NUM, msg_size, buf, vhdr, hdr); - break; - default: - process_msg_unknown(USB_IFACE_NUM, msg_size, buf); - break; + } } } } @@ -343,6 +469,9 @@ int bootloader_main(void) { #ifdef USE_RGB_LED rgb_led_init(); #endif +#ifdef USE_BLE + ble_comm_init(); +#endif #if PRODUCTION check_bootloader_version(); @@ -402,7 +531,7 @@ int bootloader_main(void) { NULL); // and start the usb loop - if (bootloader_usb_loop(NULL, NULL) != CONTINUE) { + if (bootloader_comm_loop(NULL, NULL) != CONTINUE) { return 1; } } @@ -461,7 +590,7 @@ int bootloader_main(void) { break; case SCREEN_WAIT_FOR_HOST: screen_connect(); - switch (bootloader_usb_loop(&vhdr, hdr)) { + switch (bootloader_comm_loop(&vhdr, hdr)) { case CONTINUE: continue_to_firmware = true; break; diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index dd9106c308..9a11b792db 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -24,6 +24,11 @@ #include #include "messages.pb.h" +#include TREZOR_BOARD + +#ifdef USE_BLE +#include "ble/comm.h" +#endif #include "common.h" #include "flash.h" #include "image.h" @@ -36,6 +41,7 @@ #include "rust_ui.h" #include "memzero.h" +#include STM32_HAL_H #ifdef TREZOR_EMULATOR #include "emulator.h" @@ -59,12 +65,11 @@ typedef struct { uint8_t packet_index; uint8_t packet_pos; uint8_t buf[USB_PACKET_SIZE]; -} usb_write_state; +} write_state; /* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ -static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf, - size_t count) { - usb_write_state *state = (usb_write_state *)(stream->state); +static bool _write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) { + write_state *state = (write_state *)(stream->state); size_t written = 0; // while we have data left @@ -84,9 +89,20 @@ static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf, USB_PACKET_SIZE - state->packet_pos); written += USB_PACKET_SIZE - state->packet_pos; // send packet - int r = usb_webusb_write_blocking(state->iface_num, state->buf, - USB_PACKET_SIZE, USB_TIMEOUT); - ensure(sectrue * (r == USB_PACKET_SIZE), NULL); + + if (state->iface_num == USB_IFACE_NUM) { + int r = usb_webusb_write_blocking(state->iface_num, state->buf, + USB_PACKET_SIZE, USB_TIMEOUT); + ensure(sectrue * (r == USB_PACKET_SIZE), NULL); + } +#ifdef USE_BLE + else if (state->iface_num == BLE_INT_IFACE_NUM) { + ble_int_comm_send(state->buf, USB_PACKET_SIZE, INTERNAL_MESSAGE); + } else if (state->iface_num == BLE_EXT_IFACE_NUM) { + ble_int_comm_send(state->buf, USB_PACKET_SIZE, EXTERNAL_MESSAGE); + } +#endif + // prepare new packet state->packet_index++; memzero(state->buf, USB_PACKET_SIZE); @@ -98,7 +114,7 @@ static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf, return true; } -static void _usb_write_flush(usb_write_state *state) { +static void _write_flush(write_state *state) { // if packet is not filled up completely if (state->packet_pos < USB_PACKET_SIZE) { // pad it with zeroes @@ -106,9 +122,18 @@ static void _usb_write_flush(usb_write_state *state) { USB_PACKET_SIZE - state->packet_pos); } // send packet - int r = usb_webusb_write_blocking(state->iface_num, state->buf, - USB_PACKET_SIZE, USB_TIMEOUT); - ensure(sectrue * (r == USB_PACKET_SIZE), NULL); + if (state->iface_num == USB_IFACE_NUM) { + int r = usb_webusb_write_blocking(state->iface_num, state->buf, + USB_PACKET_SIZE, USB_TIMEOUT); + ensure(sectrue * (r == USB_PACKET_SIZE), NULL); + } +#ifdef USE_BLE + else if (state->iface_num == BLE_INT_IFACE_NUM) { + ble_int_comm_send(state->buf, USB_PACKET_SIZE, INTERNAL_MESSAGE); + } else if (state->iface_num == BLE_EXT_IFACE_NUM) { + ble_int_comm_send(state->buf, USB_PACKET_SIZE, EXTERNAL_MESSAGE); + } +#endif } static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, @@ -124,7 +149,7 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, } const uint32_t msg_size = sizestream.bytes_written; - usb_write_state state = { + write_state state = { .iface_num = iface_num, .packet_index = 0, .packet_pos = MSG_HEADER1_LEN, @@ -142,7 +167,7 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, }, }; - pb_ostream_t stream = {.callback = &_usb_write, + pb_ostream_t stream = {.callback = _write, .state = &state, .max_size = SIZE_MAX, .bytes_written = 0, @@ -152,9 +177,17 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, return secfalse; } - _usb_write_flush(&state); + _write_flush(&state); + return secfalse; +} - return sectrue; +/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ +static bool _write_authkey(pb_ostream_t *stream, const pb_field_iter_t *field, + void *const *arg) { + uint8_t *key = (uint8_t *)(*arg); + if (!pb_encode_tag_for_field(stream, field)) return false; + + return pb_encode_string(stream, (uint8_t *)key, 6); } #define MSG_SEND_INIT(TYPE) TYPE msg_send = TYPE##_init_default @@ -185,6 +218,11 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, MIN(LEN, sizeof(msg_send.FIELD.bytes))); \ msg_send.FIELD.size = MIN(LEN, sizeof(msg_send.FIELD.bytes)); \ } +#define MSG_SEND_CALLBACK(FIELD, CALLBACK, ARGUMENT) \ + { \ + msg_send.FIELD.funcs.encode = &CALLBACK; \ + msg_send.FIELD.arg = (void *)ARGUMENT; \ + } #define MSG_SEND(TYPE) \ _send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send) @@ -192,8 +230,9 @@ typedef struct { uint8_t iface_num; uint8_t packet_index; uint8_t packet_pos; + uint16_t packet_size; uint8_t *buf; -} usb_read_state; +} read_state; static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) { for (int retry = 0;; retry++) { @@ -213,16 +252,54 @@ static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) { } } +#ifdef USE_BLE +static void _ble_read_retry(uint8_t iface_num, uint8_t *buf) { + for (int retry = 0;; retry++) { + int r = ble_ext_comm_receive(buf, BLE_PACKET_SIZE); + if (r != BLE_PACKET_SIZE) { // reading failed + if (r == 0 && retry < 500) { + // only timeout => let's try again + HAL_Delay(10); + continue; + } else { + // error + error_shutdown("BLE ERROR", + "Error reading from BLE. Try different BLE cable."); + } + } + return; // success + } +} + +static void _ble_read_retry_int(uint8_t iface_num, uint8_t *buf) { + for (int retry = 0;; retry++) { + int r = ble_int_comm_receive(buf, USB_PACKET_SIZE); + if (r == 0) { // reading failed + if (retry < 500) { + // only timeout => let's try again + HAL_Delay(10); + continue; + } else { + // error + error_shutdown("BLE ERROR", + "Error reading from BLE. Try different BLE cable."); + } + } + return; // success + } +} +#endif + /* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ -static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) { - usb_read_state *state = (usb_read_state *)(stream->state); +static bool _read(pb_istream_t *stream, uint8_t *buf, size_t count) { + read_state *state = (read_state *)(stream->state); size_t read = 0; // while we have data left while (read < count) { size_t remaining = count - read; // if all remaining data fit into our packet - if (state->packet_pos + remaining <= USB_PACKET_SIZE) { + if (state->packet_pos + remaining <= state->packet_size) { // append data from buf to state->buf memcpy(buf + read, state->buf + state->packet_pos, remaining); // advance position @@ -232,10 +309,19 @@ static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) { } else { // append data that fits memcpy(buf + read, state->buf + state->packet_pos, - USB_PACKET_SIZE - state->packet_pos); - read += USB_PACKET_SIZE - state->packet_pos; + state->packet_size - state->packet_pos); + read += state->packet_size - state->packet_pos; // read next packet (with retry) - _usb_webusb_read_retry(state->iface_num, state->buf); +#ifdef USE_BLE + if (state->iface_num == BLE_EXT_IFACE_NUM) { + _ble_read_retry(state->iface_num, state->buf); + } else if (state->iface_num == BLE_INT_IFACE_NUM) { + _ble_read_retry_int(state->iface_num, state->buf); + } else +#endif + { + _usb_webusb_read_retry(state->iface_num, state->buf); + } // prepare next packet state->packet_index++; state->packet_pos = MSG_HEADER2_LEN; @@ -245,16 +331,24 @@ static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) { return true; } -static void _usb_read_flush(usb_read_state *state) { (void)state; } +static void _read_flush(read_state *state) { (void)state; } static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const pb_msgdesc_t *fields, void *msg) { - usb_read_state state = {.iface_num = iface_num, - .packet_index = 0, - .packet_pos = MSG_HEADER1_LEN, - .buf = buf}; + uint16_t packet_size = USB_PACKET_SIZE; +#ifdef USE_BLE + if (iface_num == BLE_EXT_IFACE_NUM) { + packet_size = BLE_PACKET_SIZE; + } +#endif - pb_istream_t stream = {.callback = &_usb_read, + read_state state = {.iface_num = iface_num, + .packet_index = 0, + .packet_pos = MSG_HEADER1_LEN, + .packet_size = packet_size, + .buf = buf}; + + pb_istream_t stream = {.callback = &_read, .state = &state, .bytes_left = msg_size, .errmsg = NULL}; @@ -263,7 +357,7 @@ static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, return secfalse; } - _usb_read_flush(&state); + _read_flush(&state); return sectrue; } @@ -306,6 +400,39 @@ static void send_msg_features(uint8_t iface_num, MSG_SEND(Features); } +uint32_t process_msg_Pairing(uint8_t iface_num, uint32_t msg_size, + uint8_t *buf) { + uint8_t buffer[6]; + MSG_RECV_INIT(PairingRequest); + MSG_RECV(PairingRequest); + + uint32_t result = screen_pairing_confirm(buffer); + + if (result == INPUT_CONFIRM) { + MSG_SEND_INIT(AuthKey); + MSG_SEND_CALLBACK(key, _write_authkey, buffer); + MSG_SEND(AuthKey); + } else { + send_user_abort(iface_num, "Pairing cancelled"); + } + + return result; +} + +uint32_t process_msg_Repair(uint8_t iface_num, uint32_t msg_size, + uint8_t *buf) { + MSG_RECV_INIT(RepairRequest); + MSG_RECV(RepairRequest); + uint32_t result = screen_repair_confirm(); + if (result == INPUT_CONFIRM) { + MSG_SEND_INIT(Success); + MSG_SEND(Success); + } else { + send_user_abort(iface_num, "Pairing cancelled"); + } + return result; +} + void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header *const vhdr, const image_header *const hdr) { diff --git a/core/embed/bootloader/messages.h b/core/embed/bootloader/messages.h index dd4f3df5be..fae4587a47 100644 --- a/core/embed/bootloader/messages.h +++ b/core/embed/bootloader/messages.h @@ -24,6 +24,9 @@ #include "image.h" #include "secbool.h" +#define USB_IFACE_NUM 0 +#define BLE_INT_IFACE_NUM 16 +#define BLE_EXT_IFACE_NUM 17 #define USB_TIMEOUT 500 #define USB_PACKET_SIZE 64 @@ -68,4 +71,9 @@ void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); secbool bootloader_WipeDevice(void); +uint32_t process_msg_Pairing(uint8_t iface_num, uint32_t msg_size, + uint8_t *buf); + +uint32_t process_msg_Repair(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); + #endif diff --git a/core/embed/bootloader/protob/messages.pb.c b/core/embed/bootloader/protob/messages.pb.c index 762e72e1bd..86020fe0a7 100644 --- a/core/embed/bootloader/protob/messages.pb.c +++ b/core/embed/bootloader/protob/messages.pb.c @@ -39,6 +39,15 @@ PB_BIND(FirmwareRequest, FirmwareRequest, AUTO) PB_BIND(FirmwareUpload, FirmwareUpload, AUTO) +PB_BIND(PairingRequest, PairingRequest, AUTO) + + +PB_BIND(AuthKey, AuthKey, AUTO) + + +PB_BIND(RepairRequest, RepairRequest, AUTO) + + diff --git a/core/embed/bootloader/protob/messages.pb.h b/core/embed/bootloader/protob/messages.pb.h index d42319a76e..cc04ad825d 100644 --- a/core/embed/bootloader/protob/messages.pb.h +++ b/core/embed/bootloader/protob/messages.pb.h @@ -10,121 +10,136 @@ #endif /* Enum definitions */ -typedef enum _MessageType { - MessageType_MessageType_Initialize = 0, - MessageType_MessageType_Ping = 1, - MessageType_MessageType_Success = 2, - MessageType_MessageType_Failure = 3, - MessageType_MessageType_FirmwareErase = 6, - MessageType_MessageType_FirmwareUpload = 7, - MessageType_MessageType_FirmwareRequest = 8, - MessageType_MessageType_Features = 17, - MessageType_MessageType_ButtonRequest = 26, - MessageType_MessageType_ButtonAck = 27, - MessageType_MessageType_GetFeatures = 55 +typedef enum _MessageType { + MessageType_MessageType_Initialize = 0, + MessageType_MessageType_Ping = 1, + MessageType_MessageType_Success = 2, + MessageType_MessageType_Failure = 3, + MessageType_MessageType_FirmwareErase = 6, + MessageType_MessageType_FirmwareUpload = 7, + MessageType_MessageType_FirmwareRequest = 8, + MessageType_MessageType_Features = 17, + MessageType_MessageType_ButtonRequest = 26, + MessageType_MessageType_ButtonAck = 27, + MessageType_MessageType_GetFeatures = 55, + MessageType_MessageType_PairingRequest = 8003, + MessageType_MessageType_AuthKey = 8004, + MessageType_MessageType_RepairRequest = 8005 } MessageType; -typedef enum _FailureType { - FailureType_Failure_UnexpectedMessage = 1, - FailureType_Failure_DataError = 3, - FailureType_Failure_ActionCancelled = 4, - FailureType_Failure_ProcessError = 9 +typedef enum _FailureType { + FailureType_Failure_UnexpectedMessage = 1, + FailureType_Failure_DataError = 3, + FailureType_Failure_ActionCancelled = 4, + FailureType_Failure_ProcessError = 9 } FailureType; -typedef enum _ButtonRequestType { - ButtonRequestType_ButtonRequest_Other = 1 +typedef enum _ButtonRequestType { + ButtonRequestType_ButtonRequest_Other = 1 } ButtonRequestType; /* Struct definitions */ -typedef struct _ButtonAck { +typedef struct _AuthKey { + pb_callback_t key; +} AuthKey; + +typedef struct _ButtonAck { char dummy_field; } ButtonAck; -typedef struct _GetFeatures { +typedef struct _GetFeatures { char dummy_field; } GetFeatures; -typedef struct _Initialize { +typedef struct _Initialize { char dummy_field; } Initialize; -typedef struct _ButtonRequest { +typedef struct _PairingRequest { + char dummy_field; +} PairingRequest; + +typedef struct _RepairRequest { + char dummy_field; +} RepairRequest; + +typedef struct _ButtonRequest { bool has_code; - ButtonRequestType code; + ButtonRequestType code; } ButtonRequest; -typedef struct _Failure { +typedef struct _Failure { bool has_code; - FailureType code; + FailureType code; bool has_message; - char message[256]; + char message[256]; } Failure; typedef PB_BYTES_ARRAY_T(20) Features_revision_t; -typedef struct _Features { +typedef struct _Features { bool has_vendor; - char vendor[33]; - uint32_t major_version; - uint32_t minor_version; - uint32_t patch_version; + char vendor[33]; + uint32_t major_version; + uint32_t minor_version; + uint32_t patch_version; bool has_bootloader_mode; - bool bootloader_mode; + bool bootloader_mode; bool has_device_id; - char device_id[25]; + char device_id[25]; bool has_language; - char language[17]; + char language[17]; bool has_label; - char label[33]; + char label[33]; bool has_initialized; - bool initialized; + bool initialized; bool has_revision; - Features_revision_t revision; + Features_revision_t revision; bool has_firmware_present; - bool firmware_present; + bool firmware_present; bool has_model; - char model[17]; + char model[17]; bool has_fw_major; - uint32_t fw_major; + uint32_t fw_major; bool has_fw_minor; - uint32_t fw_minor; + uint32_t fw_minor; bool has_fw_patch; - uint32_t fw_patch; + uint32_t fw_patch; bool has_fw_vendor; - char fw_vendor[256]; + char fw_vendor[256]; } Features; -typedef struct _FirmwareErase { +typedef struct _FirmwareErase { bool has_length; - uint32_t length; + uint32_t length; } FirmwareErase; -typedef struct _FirmwareRequest { - uint32_t offset; - uint32_t length; +typedef struct _FirmwareRequest { + uint32_t offset; + uint32_t length; } FirmwareRequest; typedef PB_BYTES_ARRAY_T(32) FirmwareUpload_hash_t; -typedef struct _FirmwareUpload { - pb_callback_t payload; +typedef struct _FirmwareUpload { + pb_callback_t payload; bool has_hash; - FirmwareUpload_hash_t hash; + FirmwareUpload_hash_t hash; } FirmwareUpload; -typedef struct _Ping { +typedef struct _Ping { bool has_message; - char message[256]; + char message[256]; } Ping; -typedef struct _Success { +typedef struct _Success { bool has_message; - char message[256]; + char message[256]; } Success; /* Helper constants for enums */ #define _MessageType_MIN MessageType_MessageType_Initialize -#define _MessageType_MAX MessageType_MessageType_GetFeatures -#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_GetFeatures+1)) +#define _MessageType_MAX MessageType_MessageType_RepairRequest +#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_RepairRequest+1)) #define _FailureType_MIN FailureType_Failure_UnexpectedMessage #define _FailureType_MAX FailureType_Failure_ProcessError @@ -151,6 +166,9 @@ extern "C" { #define FirmwareErase_init_default {false, 0} #define FirmwareRequest_init_default {0, 0} #define FirmwareUpload_init_default {{{NULL}, NULL}, false, {0, {0}}} +#define PairingRequest_init_default {0} +#define AuthKey_init_default {{{NULL}, NULL}} +#define RepairRequest_init_default {0} #define Initialize_init_zero {0} #define GetFeatures_init_zero {0} #define Features_init_zero {false, "", 0, 0, 0, false, 0, false, "", false, "", false, "", false, 0, false, {0, {0}}, false, 0, false, "", false, 0, false, 0, false, 0, false, ""} @@ -162,8 +180,12 @@ extern "C" { #define FirmwareErase_init_zero {false, 0} #define FirmwareRequest_init_zero {0, 0} #define FirmwareUpload_init_zero {{{NULL}, NULL}, false, {0, {0}}} +#define PairingRequest_init_zero {0} +#define AuthKey_init_zero {{{NULL}, NULL}} +#define RepairRequest_init_zero {0} /* Field tags (for use in manual encoding/decoding) */ +#define AuthKey_key_tag 1 #define ButtonRequest_code_tag 1 #define Failure_code_tag 1 #define Failure_message_tag 2 @@ -265,6 +287,21 @@ X(a, STATIC, OPTIONAL, BYTES, hash, 2) #define FirmwareUpload_CALLBACK pb_default_field_callback #define FirmwareUpload_DEFAULT NULL +#define PairingRequest_FIELDLIST(X, a) \ + +#define PairingRequest_CALLBACK NULL +#define PairingRequest_DEFAULT NULL + +#define AuthKey_FIELDLIST(X, a) \ +X(a, CALLBACK, REQUIRED, BYTES, key, 1) +#define AuthKey_CALLBACK pb_default_field_callback +#define AuthKey_DEFAULT NULL + +#define RepairRequest_FIELDLIST(X, a) \ + +#define RepairRequest_CALLBACK NULL +#define RepairRequest_DEFAULT NULL + extern const pb_msgdesc_t Initialize_msg; extern const pb_msgdesc_t GetFeatures_msg; extern const pb_msgdesc_t Features_msg; @@ -276,6 +313,9 @@ extern const pb_msgdesc_t ButtonAck_msg; extern const pb_msgdesc_t FirmwareErase_msg; extern const pb_msgdesc_t FirmwareRequest_msg; extern const pb_msgdesc_t FirmwareUpload_msg; +extern const pb_msgdesc_t PairingRequest_msg; +extern const pb_msgdesc_t AuthKey_msg; +extern const pb_msgdesc_t RepairRequest_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define Initialize_fields &Initialize_msg @@ -289,9 +329,13 @@ extern const pb_msgdesc_t FirmwareUpload_msg; #define FirmwareErase_fields &FirmwareErase_msg #define FirmwareRequest_fields &FirmwareRequest_msg #define FirmwareUpload_fields &FirmwareUpload_msg +#define PairingRequest_fields &PairingRequest_msg +#define AuthKey_fields &AuthKey_msg +#define RepairRequest_fields &RepairRequest_msg /* Maximum encoded size of messages (where known) */ /* FirmwareUpload_size depends on runtime parameters */ +/* AuthKey_size depends on runtime parameters */ #define ButtonAck_size 0 #define ButtonRequest_size 2 #define Failure_size 260 @@ -300,7 +344,9 @@ extern const pb_msgdesc_t FirmwareUpload_msg; #define FirmwareRequest_size 12 #define GetFeatures_size 0 #define Initialize_size 0 +#define PairingRequest_size 0 #define Ping_size 258 +#define RepairRequest_size 0 #define Success_size 258 #ifdef __cplusplus diff --git a/core/embed/bootloader/protob/messages.proto b/core/embed/bootloader/protob/messages.proto index 715f1db335..170e4146f0 100644 --- a/core/embed/bootloader/protob/messages.proto +++ b/core/embed/bootloader/protob/messages.proto @@ -16,6 +16,9 @@ enum MessageType { MessageType_ButtonRequest = 26; MessageType_ButtonAck = 27; MessageType_GetFeatures = 55; + MessageType_PairingRequest = 8003; + MessageType_AuthKey = 8004; + MessageType_RepairRequest = 8005; } /** @@ -140,3 +143,32 @@ message FirmwareUpload { required bytes payload = 1; // firmware to be loaded into device optional bytes hash = 2; // hash of the payload } + + +/** + * Request: initiates new pairing request + * @start + * @next AuthKey + * @next Failure + */ +message PairingRequest { +} + +/** + * Request: confirms pairing request with auth key entered on the device + * @end + */ +message AuthKey { + required bytes key = 1; +} + + +/** + * Request: initiates repairing request + * @start + * @next Success + * @next Failure + */ +message RepairRequest { +} + diff --git a/core/embed/rust/rust_ui.h b/core/embed/rust/rust_ui.h index 8b5a8f45ad..0de2fbeba9 100644 --- a/core/embed/rust/rust_ui.h +++ b/core/embed/rust/rust_ui.h @@ -26,4 +26,7 @@ void screen_welcome_model(void); void screen_welcome(void); void screen_boot_empty(bool fading); +uint32_t screen_pairing_confirm(uint8_t* buffer); +uint32_t screen_repair_confirm(void); + void display_image(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen); diff --git a/core/embed/rust/src/ui/model_tt/bootloader/mod.rs b/core/embed/rust/src/ui/model_tt/bootloader/mod.rs index 4417b282ca..6f66467350 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/mod.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/mod.rs @@ -14,17 +14,19 @@ use crate::{ theme::{ button_bld, button_confirm, button_wipe_cancel, button_wipe_confirm, BLD_BG, BLD_FG, BLD_WIPE_COLOR, CHECK24, CHECK40, DOWNLOAD32, FIRE32, FIRE40, - LOGO_EMPTY, TEXT_WIPE_BOLD, TEXT_WIPE_NORMAL, WARNING40, WELCOME_COLOR, X24, + LOGO_EMPTY, TEXT_NORMAL, TEXT_WIPE_BOLD, TEXT_WIPE_NORMAL, WARNING40, + WELCOME_COLOR, X24, }, welcome::Welcome, }, - component::{Button, ResultScreen, WelcomeScreen}, + component::{Button, PinKeyboard, ResultScreen, WelcomeScreen}, constant, theme::{BACKLIGHT_DIM, BACKLIGHT_NORMAL, BLACK, FG, WHITE}, }, util::{from_c_array, from_c_str}, }, }; +use core::slice; use heapless::String; use num_traits::ToPrimitive; @@ -72,13 +74,16 @@ fn fadeout() { display::fade_backlight_duration(BACKLIGHT_DIM, 150); } -fn run(frame: &mut F) -> u32 +fn run(frame: &mut F, clear: bool) -> u32 where F: Component, F::Msg: ReturnToC, { frame.place(constant::screen()); fadeout(); + if clear { + display::rect_fill(screen(), BLACK); + } display::sync(); frame.paint(); fadein(); @@ -191,7 +196,7 @@ extern "C" fn screen_install_confirm( Some(("FW FINGERPRINT", fingerprint_str)), ); - run(&mut frame) + run(&mut frame, false) } #[no_mangle] @@ -222,12 +227,12 @@ extern "C" fn screen_wipe_confirm() -> u32 { None, ); - run(&mut frame) + run(&mut frame, false) } #[no_mangle] extern "C" fn screen_menu() -> u32 { - run(&mut Menu::new()) + run(&mut Menu::new(), false) } #[no_mangle] @@ -253,7 +258,7 @@ extern "C" fn screen_intro( let mut frame = Intro::new(title_str.as_str(), version_str.as_str()); - run(&mut frame) + run(&mut frame, false) } fn screen_progress( @@ -419,3 +424,41 @@ extern "C" fn screen_welcome() { let mut frame = Welcome::new(); show(&mut frame, true); } + +#[no_mangle] +extern "C" fn screen_pairing_confirm(buffer: *const cty::uint8_t) -> u32 { + let pin_slice = unsafe { slice::from_raw_parts_mut(buffer as *mut u8, 6) }; + + let mut pin = PinKeyboard::new("Enter passkey", "", None, true); + let res = run(&mut pin, true); + + if res == 2 { + let pin = pin.pin().as_bytes(); + if pin.len() == 6 { + pin_slice.copy_from_slice(&pin[0..6]); + } + } + + res +} + +#[no_mangle] +extern "C" fn screen_repair_confirm() -> u32 { + let msg = Label::new("Allow repair?", Alignment::Center, TEXT_NORMAL); + let right = Button::with_text("ALLOW").styled(button_confirm()); + let left = Button::with_text("DENY").styled(button_bld()); + let title = Label::new("REPAIR", Alignment::Start, theme::TEXT_BOLD) + .vertically_aligned(Alignment::Center); + + let mut frame = Confirm::new( + BLD_BG, + left, + right, + ConfirmTitle::Text(title), + msg, + None, + None, + ); + + run(&mut frame, true) +} diff --git a/core/embed/rust/src/ui/model_tt/bootloader/theme.rs b/core/embed/rust/src/ui/model_tt/bootloader/theme.rs index e4165ecdb7..31506fe88a 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/theme.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/theme.rs @@ -230,6 +230,8 @@ pub fn button_bld() -> ButtonStyleSheet { } } +pub const TEXT_NORMAL_BLACK: TextStyle = TextStyle::new(Font::NORMAL, WHITE, BLACK, WHITE, WHITE); + pub const TEXT_TITLE: TextStyle = TextStyle::new( Font::BOLD, BLD_TITLE_COLOR, diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs index 632856dcac..10542be02e 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs @@ -19,9 +19,10 @@ use crate::{ }, }; +#[derive(Copy, Clone, ToPrimitive)] pub enum PinKeyboardMsg { - Confirmed, - Cancelled, + Cancelled = 1, + Confirmed = 2, } const MAX_LENGTH: usize = 50; diff --git a/core/embed/trezorhal/ble/comm.c b/core/embed/trezorhal/ble/comm.c index 48c1ab4ce8..18299a3119 100644 --- a/core/embed/trezorhal/ble/comm.c +++ b/core/embed/trezorhal/ble/comm.c @@ -22,6 +22,7 @@ #include "comm.h" #include +#include "buffers.h" #include "dma.h" #include "int_comm_defs.h" #include "state.h" @@ -40,7 +41,7 @@ typedef struct { bool ready; } spi_buffer_t; -spi_buffer_t spi_queue[SPI_QUEUE_SIZE]; +BUFFER_SECTION spi_buffer_t spi_queue[SPI_QUEUE_SIZE]; static int head = 0, tail = 0; static bool overrun = false; volatile uint16_t overrun_count = 0;