1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-08-05 13:26:57 +00:00

feat(core): ble in bootloader

[no changelog]
This commit is contained in:
tychovrahe 2023-03-20 21:31:05 +01:00
parent e1381f901b
commit f04d8da661
12 changed files with 586 additions and 183 deletions

View File

@ -20,7 +20,7 @@ if TREZOR_MODEL in ('1', ):
) )
Return() Return()
FEATURES_WANTED = ["input", "rgb_led"] FEATURES_WANTED = ["input", "rgb_led", "ble"]
CCFLAGS_MOD = '' CCFLAGS_MOD = ''
CPPPATH_MOD = [] CPPPATH_MOD = []
@ -34,9 +34,9 @@ if TREZOR_MODEL in ('1', 'R'):
FONT_MONO='Font_PixelOperatorMono_Regular_8' FONT_MONO='Font_PixelOperatorMono_Regular_8'
if TREZOR_MODEL in ('T', 'DISC1', ): if TREZOR_MODEL in ('T', 'DISC1', ):
FONT_NORMAL='Font_TTHoves_Regular_21' FONT_NORMAL='Font_TTHoves_Regular_21'
FONT_DEMIBOLD=None FONT_DEMIBOLD='Font_TTHoves_Regular_21'
FONT_BOLD='Font_TTHoves_Bold_17' FONT_BOLD='Font_TTHoves_Bold_17'
FONT_MONO=None FONT_MONO='Font_TTHoves_Regular_21'
# modtrezorcrypto # modtrezorcrypto
CCFLAGS_MOD += '-Wno-sequence-point ' 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_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.c',
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.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_fmc.c',
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.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', 'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c',
@ -126,6 +127,7 @@ SOURCE_BOOTLOADER = [
SOURCE_TREZORHAL = [ SOURCE_TREZORHAL = [
'embed/trezorhal/common.c', 'embed/trezorhal/common.c',
'embed/trezorhal/dma.c',
'embed/trezorhal/image.c', 'embed/trezorhal/image.c',
'embed/trezorhal/flash.c', 'embed/trezorhal/flash.c',
'embed/trezorhal/mini_printf.c', 'embed/trezorhal/mini_printf.c',

View File

@ -49,11 +49,16 @@
#ifdef USE_RGB_LED #ifdef USE_RGB_LED
#include "rgb_led.h" #include "rgb_led.h"
#endif #endif
#ifdef USE_BLE
#include "ble/comm.h"
#endif
#include "usb.h" #include "usb.h"
#include "version.h" #include "version.h"
#include "bootui.h" #include "bootui.h"
#include "messages.h" #include "messages.h"
#include "messages.pb.h"
#include "rust_ui.h" #include "rust_ui.h"
const uint8_t BOOTLOADER_KEY_M = 2; const uint8_t BOOTLOADER_KEY_M = 2;
@ -71,8 +76,6 @@ static const uint8_t * const BOOTLOADER_KEYS[] = {
#endif #endif
}; };
#define USB_IFACE_NUM 0
typedef enum { typedef enum {
CONTINUE = 0, CONTINUE = 0,
RETURN = 1, RETURN = 1,
@ -119,98 +122,221 @@ static void usb_init_all(secbool usb21_landing) {
usb_start(); usb_start();
} }
static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr, static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr,
const image_header *const hdr) { const image_header *const hdr) {
// if both are NULL, we don't have a firmware installed // if both are NULL, we don't have a firmware installed
// let's show a webusb landing page in this case // let's show a webusb landing page in this case
usb_init_all((vhdr == NULL && hdr == NULL) ? sectrue : secfalse); 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 (;;) {
for (;;) {
#ifdef TREZOR_EMULATOR #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 #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; #ifdef USE_BLE
uint32_t response; if (active_iface == BLE_INT_IFACE_NUM) {
if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { for (;;) {
// invalid header -> discard bool next = false;
continue; 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) { #endif
case 0: // Initialize
process_msg_Initialize(USB_IFACE_NUM, msg_size, buf, vhdr, hdr); if (active_iface == USB_IFACE_NUM || active_iface == BLE_EXT_IFACE_NUM) {
break; for (;;) {
case 1: // Ping #ifdef TREZOR_EMULATOR
process_msg_Ping(USB_IFACE_NUM, msg_size, buf); emulator_poll_events();
break; #endif
case 5: // WipeDevice if (r == 0) {
response = ui_screen_wipe_confirm(); if (active_iface == USB_IFACE_NUM) {
if (INPUT_CANCEL == response) { r = usb_webusb_read_blocking(active_iface, buf_usb, USB_PACKET_SIZE,
send_user_abort(USB_IFACE_NUM, "Wipe cancelled"); USB_TIMEOUT);
hal_delay(100); if (r != USB_PACKET_SIZE) {
usb_stop(); continue;
usb_deinit(); }
return RETURN; }
#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); r = 0;
if (r < 0) { // error
screen_wipe_fail(); uint16_t msg_id;
hal_delay(100); uint32_t msg_size;
usb_stop(); uint32_t response;
usb_deinit(); int32_t upload_response;
return SHUTDOWN; if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) {
} else { // success // invalid header -> discard
screen_wipe_success(); continue;
hal_delay(100);
usb_stop();
usb_deinit();
return SHUTDOWN;
} }
break; switch (msg_id) {
case 6: // FirmwareErase case 0: // Initialize
process_msg_FirmwareErase(USB_IFACE_NUM, msg_size, buf); process_msg_Initialize(active_iface, msg_size, buf, vhdr, hdr);
break; break;
case 7: // FirmwareUpload case 1: // Ping
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf); process_msg_Ping(active_iface, msg_size, buf);
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort break;
ui_screen_fail(); case 5: // WipeDevice
usb_stop(); response = ui_screen_wipe_confirm();
usb_deinit(); if (INPUT_CANCEL == response) {
return SHUTDOWN; send_user_abort(active_iface, "Wipe cancelled");
} else if (r == UPLOAD_ERR_USER_ABORT) { hal_delay(100);
hal_delay(100); usb_stop();
usb_stop(); usb_deinit();
usb_deinit(); return RETURN;
return RETURN; }
} else if (r == 0) { // last chunk received ui_screen_wipe();
ui_screen_install_progress_upload(1000); upload_response =
ui_screen_done(4, sectrue); process_msg_WipeDevice(active_iface, msg_size, buf);
ui_screen_done(3, secfalse); if (upload_response < 0) { // error
hal_delay(1000); screen_wipe_fail();
ui_screen_done(2, secfalse); usb_stop();
hal_delay(1000); usb_deinit();
ui_screen_done(1, secfalse); return SHUTDOWN;
hal_delay(1000); } else { // success
usb_stop(); screen_wipe_success();
usb_deinit(); usb_stop();
ui_screen_boot_empty(true); usb_deinit();
return CONTINUE; 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 #ifdef USE_RGB_LED
rgb_led_init(); rgb_led_init();
#endif #endif
#ifdef USE_BLE
ble_comm_init();
#endif
#if PRODUCTION #if PRODUCTION
check_bootloader_version(); check_bootloader_version();
@ -402,7 +531,7 @@ int bootloader_main(void) {
NULL); NULL);
// and start the usb loop // and start the usb loop
if (bootloader_usb_loop(NULL, NULL) != CONTINUE) { if (bootloader_comm_loop(NULL, NULL) != CONTINUE) {
return 1; return 1;
} }
} }
@ -461,7 +590,7 @@ int bootloader_main(void) {
break; break;
case SCREEN_WAIT_FOR_HOST: case SCREEN_WAIT_FOR_HOST:
screen_connect(); screen_connect();
switch (bootloader_usb_loop(&vhdr, hdr)) { switch (bootloader_comm_loop(&vhdr, hdr)) {
case CONTINUE: case CONTINUE:
continue_to_firmware = true; continue_to_firmware = true;
break; break;

View File

@ -24,6 +24,11 @@
#include <pb_encode.h> #include <pb_encode.h>
#include "messages.pb.h" #include "messages.pb.h"
#include TREZOR_BOARD
#ifdef USE_BLE
#include "ble/comm.h"
#endif
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "image.h" #include "image.h"
@ -36,6 +41,7 @@
#include "rust_ui.h" #include "rust_ui.h"
#include "memzero.h" #include "memzero.h"
#include STM32_HAL_H
#ifdef TREZOR_EMULATOR #ifdef TREZOR_EMULATOR
#include "emulator.h" #include "emulator.h"
@ -59,12 +65,11 @@ typedef struct {
uint8_t packet_index; uint8_t packet_index;
uint8_t packet_pos; uint8_t packet_pos;
uint8_t buf[USB_PACKET_SIZE]; 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 */ /* 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, static bool _write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) {
size_t count) { write_state *state = (write_state *)(stream->state);
usb_write_state *state = (usb_write_state *)(stream->state);
size_t written = 0; size_t written = 0;
// while we have data left // 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); USB_PACKET_SIZE - state->packet_pos);
written += USB_PACKET_SIZE - state->packet_pos; written += USB_PACKET_SIZE - state->packet_pos;
// send packet // send packet
int r = usb_webusb_write_blocking(state->iface_num, state->buf,
USB_PACKET_SIZE, USB_TIMEOUT); if (state->iface_num == USB_IFACE_NUM) {
ensure(sectrue * (r == USB_PACKET_SIZE), NULL); 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 // prepare new packet
state->packet_index++; state->packet_index++;
memzero(state->buf, USB_PACKET_SIZE); 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; 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 packet is not filled up completely
if (state->packet_pos < USB_PACKET_SIZE) { if (state->packet_pos < USB_PACKET_SIZE) {
// pad it with zeroes // pad it with zeroes
@ -106,9 +122,18 @@ static void _usb_write_flush(usb_write_state *state) {
USB_PACKET_SIZE - state->packet_pos); USB_PACKET_SIZE - state->packet_pos);
} }
// send packet // send packet
int r = usb_webusb_write_blocking(state->iface_num, state->buf, if (state->iface_num == USB_IFACE_NUM) {
USB_PACKET_SIZE, USB_TIMEOUT); int r = usb_webusb_write_blocking(state->iface_num, state->buf,
ensure(sectrue * (r == USB_PACKET_SIZE), NULL); 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, 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; const uint32_t msg_size = sizestream.bytes_written;
usb_write_state state = { write_state state = {
.iface_num = iface_num, .iface_num = iface_num,
.packet_index = 0, .packet_index = 0,
.packet_pos = MSG_HEADER1_LEN, .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, .state = &state,
.max_size = SIZE_MAX, .max_size = SIZE_MAX,
.bytes_written = 0, .bytes_written = 0,
@ -152,9 +177,17 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id,
return secfalse; 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 #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))); \ MIN(LEN, sizeof(msg_send.FIELD.bytes))); \
msg_send.FIELD.size = 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) \ #define MSG_SEND(TYPE) \
_send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send) _send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send)
@ -192,8 +230,9 @@ typedef struct {
uint8_t iface_num; uint8_t iface_num;
uint8_t packet_index; uint8_t packet_index;
uint8_t packet_pos; uint8_t packet_pos;
uint16_t packet_size;
uint8_t *buf; uint8_t *buf;
} usb_read_state; } read_state;
static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) { static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) {
for (int retry = 0;; retry++) { 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 */ /* 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) { static bool _read(pb_istream_t *stream, uint8_t *buf, size_t count) {
usb_read_state *state = (usb_read_state *)(stream->state); read_state *state = (read_state *)(stream->state);
size_t read = 0; size_t read = 0;
// while we have data left // while we have data left
while (read < count) { while (read < count) {
size_t remaining = count - read; size_t remaining = count - read;
// if all remaining data fit into our packet // 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 // append data from buf to state->buf
memcpy(buf + read, state->buf + state->packet_pos, remaining); memcpy(buf + read, state->buf + state->packet_pos, remaining);
// advance position // advance position
@ -232,10 +309,19 @@ static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) {
} else { } else {
// append data that fits // append data that fits
memcpy(buf + read, state->buf + state->packet_pos, memcpy(buf + read, state->buf + state->packet_pos,
USB_PACKET_SIZE - state->packet_pos); state->packet_size - state->packet_pos);
read += USB_PACKET_SIZE - state->packet_pos; read += state->packet_size - state->packet_pos;
// read next packet (with retry) // 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 // prepare next packet
state->packet_index++; state->packet_index++;
state->packet_pos = MSG_HEADER2_LEN; 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; 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, static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
const pb_msgdesc_t *fields, void *msg) { const pb_msgdesc_t *fields, void *msg) {
usb_read_state state = {.iface_num = iface_num, uint16_t packet_size = USB_PACKET_SIZE;
.packet_index = 0, #ifdef USE_BLE
.packet_pos = MSG_HEADER1_LEN, if (iface_num == BLE_EXT_IFACE_NUM) {
.buf = buf}; 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, .state = &state,
.bytes_left = msg_size, .bytes_left = msg_size,
.errmsg = NULL}; .errmsg = NULL};
@ -263,7 +357,7 @@ static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
return secfalse; return secfalse;
} }
_usb_read_flush(&state); _read_flush(&state);
return sectrue; return sectrue;
} }
@ -306,6 +400,39 @@ static void send_msg_features(uint8_t iface_num,
MSG_SEND(Features); 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, void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
const vendor_header *const vhdr, const vendor_header *const vhdr,
const image_header *const hdr) { const image_header *const hdr) {

View File

@ -24,6 +24,9 @@
#include "image.h" #include "image.h"
#include "secbool.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_TIMEOUT 500
#define USB_PACKET_SIZE 64 #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); 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 #endif

View File

@ -39,6 +39,15 @@ PB_BIND(FirmwareRequest, FirmwareRequest, AUTO)
PB_BIND(FirmwareUpload, FirmwareUpload, AUTO) PB_BIND(FirmwareUpload, FirmwareUpload, AUTO)
PB_BIND(PairingRequest, PairingRequest, AUTO)
PB_BIND(AuthKey, AuthKey, AUTO)
PB_BIND(RepairRequest, RepairRequest, AUTO)

View File

@ -21,7 +21,10 @@ typedef enum _MessageType {
MessageType_MessageType_Features = 17, MessageType_MessageType_Features = 17,
MessageType_MessageType_ButtonRequest = 26, MessageType_MessageType_ButtonRequest = 26,
MessageType_MessageType_ButtonAck = 27, MessageType_MessageType_ButtonAck = 27,
MessageType_MessageType_GetFeatures = 55 MessageType_MessageType_GetFeatures = 55,
MessageType_MessageType_PairingRequest = 8003,
MessageType_MessageType_AuthKey = 8004,
MessageType_MessageType_RepairRequest = 8005
} MessageType; } MessageType;
typedef enum _FailureType { typedef enum _FailureType {
@ -36,6 +39,10 @@ typedef enum _ButtonRequestType {
} ButtonRequestType; } ButtonRequestType;
/* Struct definitions */ /* Struct definitions */
typedef struct _AuthKey {
pb_callback_t key;
} AuthKey;
typedef struct _ButtonAck { typedef struct _ButtonAck {
char dummy_field; char dummy_field;
} ButtonAck; } ButtonAck;
@ -48,6 +55,14 @@ typedef struct _Initialize {
char dummy_field; char dummy_field;
} Initialize; } Initialize;
typedef struct _PairingRequest {
char dummy_field;
} PairingRequest;
typedef struct _RepairRequest {
char dummy_field;
} RepairRequest;
typedef struct _ButtonRequest { typedef struct _ButtonRequest {
bool has_code; bool has_code;
ButtonRequestType code; ButtonRequestType code;
@ -123,8 +138,8 @@ typedef struct _Success {
/* Helper constants for enums */ /* Helper constants for enums */
#define _MessageType_MIN MessageType_MessageType_Initialize #define _MessageType_MIN MessageType_MessageType_Initialize
#define _MessageType_MAX MessageType_MessageType_GetFeatures #define _MessageType_MAX MessageType_MessageType_RepairRequest
#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_GetFeatures+1)) #define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_RepairRequest+1))
#define _FailureType_MIN FailureType_Failure_UnexpectedMessage #define _FailureType_MIN FailureType_Failure_UnexpectedMessage
#define _FailureType_MAX FailureType_Failure_ProcessError #define _FailureType_MAX FailureType_Failure_ProcessError
@ -151,6 +166,9 @@ extern "C" {
#define FirmwareErase_init_default {false, 0} #define FirmwareErase_init_default {false, 0}
#define FirmwareRequest_init_default {0, 0} #define FirmwareRequest_init_default {0, 0}
#define FirmwareUpload_init_default {{{NULL}, NULL}, false, {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 Initialize_init_zero {0}
#define GetFeatures_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, ""} #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 FirmwareErase_init_zero {false, 0}
#define FirmwareRequest_init_zero {0, 0} #define FirmwareRequest_init_zero {0, 0}
#define FirmwareUpload_init_zero {{{NULL}, NULL}, false, {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) */ /* Field tags (for use in manual encoding/decoding) */
#define AuthKey_key_tag 1
#define ButtonRequest_code_tag 1 #define ButtonRequest_code_tag 1
#define Failure_code_tag 1 #define Failure_code_tag 1
#define Failure_message_tag 2 #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_CALLBACK pb_default_field_callback
#define FirmwareUpload_DEFAULT NULL #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 Initialize_msg;
extern const pb_msgdesc_t GetFeatures_msg; extern const pb_msgdesc_t GetFeatures_msg;
extern const pb_msgdesc_t Features_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 FirmwareErase_msg;
extern const pb_msgdesc_t FirmwareRequest_msg; extern const pb_msgdesc_t FirmwareRequest_msg;
extern const pb_msgdesc_t FirmwareUpload_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 */ /* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define Initialize_fields &Initialize_msg #define Initialize_fields &Initialize_msg
@ -289,9 +329,13 @@ extern const pb_msgdesc_t FirmwareUpload_msg;
#define FirmwareErase_fields &FirmwareErase_msg #define FirmwareErase_fields &FirmwareErase_msg
#define FirmwareRequest_fields &FirmwareRequest_msg #define FirmwareRequest_fields &FirmwareRequest_msg
#define FirmwareUpload_fields &FirmwareUpload_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) */ /* Maximum encoded size of messages (where known) */
/* FirmwareUpload_size depends on runtime parameters */ /* FirmwareUpload_size depends on runtime parameters */
/* AuthKey_size depends on runtime parameters */
#define ButtonAck_size 0 #define ButtonAck_size 0
#define ButtonRequest_size 2 #define ButtonRequest_size 2
#define Failure_size 260 #define Failure_size 260
@ -300,7 +344,9 @@ extern const pb_msgdesc_t FirmwareUpload_msg;
#define FirmwareRequest_size 12 #define FirmwareRequest_size 12
#define GetFeatures_size 0 #define GetFeatures_size 0
#define Initialize_size 0 #define Initialize_size 0
#define PairingRequest_size 0
#define Ping_size 258 #define Ping_size 258
#define RepairRequest_size 0
#define Success_size 258 #define Success_size 258
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -16,6 +16,9 @@ enum MessageType {
MessageType_ButtonRequest = 26; MessageType_ButtonRequest = 26;
MessageType_ButtonAck = 27; MessageType_ButtonAck = 27;
MessageType_GetFeatures = 55; 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 required bytes payload = 1; // firmware to be loaded into device
optional bytes hash = 2; // hash of the payload 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 {
}

View File

@ -26,4 +26,7 @@ void screen_welcome_model(void);
void screen_welcome(void); void screen_welcome(void);
void screen_boot_empty(bool fading); 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); void display_image(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen);

View File

@ -14,17 +14,19 @@ use crate::{
theme::{ theme::{
button_bld, button_confirm, button_wipe_cancel, button_wipe_confirm, BLD_BG, button_bld, button_confirm, button_wipe_cancel, button_wipe_confirm, BLD_BG,
BLD_FG, BLD_WIPE_COLOR, CHECK24, CHECK40, DOWNLOAD32, FIRE32, FIRE40, 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, welcome::Welcome,
}, },
component::{Button, ResultScreen, WelcomeScreen}, component::{Button, PinKeyboard, ResultScreen, WelcomeScreen},
constant, constant,
theme::{BACKLIGHT_DIM, BACKLIGHT_NORMAL, BLACK, FG, WHITE}, theme::{BACKLIGHT_DIM, BACKLIGHT_NORMAL, BLACK, FG, WHITE},
}, },
util::{from_c_array, from_c_str}, util::{from_c_array, from_c_str},
}, },
}; };
use core::slice;
use heapless::String; use heapless::String;
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
@ -72,13 +74,16 @@ fn fadeout() {
display::fade_backlight_duration(BACKLIGHT_DIM, 150); display::fade_backlight_duration(BACKLIGHT_DIM, 150);
} }
fn run<F>(frame: &mut F) -> u32 fn run<F>(frame: &mut F, clear: bool) -> u32
where where
F: Component, F: Component,
F::Msg: ReturnToC, F::Msg: ReturnToC,
{ {
frame.place(constant::screen()); frame.place(constant::screen());
fadeout(); fadeout();
if clear {
display::rect_fill(screen(), BLACK);
}
display::sync(); display::sync();
frame.paint(); frame.paint();
fadein(); fadein();
@ -191,7 +196,7 @@ extern "C" fn screen_install_confirm(
Some(("FW FINGERPRINT", fingerprint_str)), Some(("FW FINGERPRINT", fingerprint_str)),
); );
run(&mut frame) run(&mut frame, false)
} }
#[no_mangle] #[no_mangle]
@ -222,12 +227,12 @@ extern "C" fn screen_wipe_confirm() -> u32 {
None, None,
); );
run(&mut frame) run(&mut frame, false)
} }
#[no_mangle] #[no_mangle]
extern "C" fn screen_menu() -> u32 { extern "C" fn screen_menu() -> u32 {
run(&mut Menu::new()) run(&mut Menu::new(), false)
} }
#[no_mangle] #[no_mangle]
@ -253,7 +258,7 @@ extern "C" fn screen_intro(
let mut frame = Intro::new(title_str.as_str(), version_str.as_str()); let mut frame = Intro::new(title_str.as_str(), version_str.as_str());
run(&mut frame) run(&mut frame, false)
} }
fn screen_progress( fn screen_progress(
@ -419,3 +424,41 @@ extern "C" fn screen_welcome() {
let mut frame = Welcome::new(); let mut frame = Welcome::new();
show(&mut frame, true); 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)
}

View File

@ -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( pub const TEXT_TITLE: TextStyle = TextStyle::new(
Font::BOLD, Font::BOLD,
BLD_TITLE_COLOR, BLD_TITLE_COLOR,

View File

@ -19,9 +19,10 @@ use crate::{
}, },
}; };
#[derive(Copy, Clone, ToPrimitive)]
pub enum PinKeyboardMsg { pub enum PinKeyboardMsg {
Confirmed, Cancelled = 1,
Cancelled, Confirmed = 2,
} }
const MAX_LENGTH: usize = 50; const MAX_LENGTH: usize = 50;

View File

@ -22,6 +22,7 @@
#include "comm.h" #include "comm.h"
#include <string.h> #include <string.h>
#include "buffers.h"
#include "dma.h" #include "dma.h"
#include "int_comm_defs.h" #include "int_comm_defs.h"
#include "state.h" #include "state.h"
@ -40,7 +41,7 @@ typedef struct {
bool ready; bool ready;
} spi_buffer_t; } 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 int head = 0, tail = 0;
static bool overrun = false; static bool overrun = false;
volatile uint16_t overrun_count = 0; volatile uint16_t overrun_count = 0;