1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-22 10:09:04 +00:00

feat(nordic): send busy response when trezor is not listening to BLE messages

[no changelog]
This commit is contained in:
tychovrahe 2025-04-11 20:43:01 +02:00
parent 6241c0b986
commit 1bc88230ab
14 changed files with 132 additions and 52 deletions

View File

@ -39,6 +39,7 @@ message Failure {
Failure_PinMismatch = 12;
Failure_WipeCodeMismatch = 13;
Failure_InvalidSession = 14;
Failure_Busy = 15;
Failure_FirmwareError = 99;
}
}

View File

@ -55,6 +55,7 @@ typedef struct {
bool initialized;
bool status_valid;
bool accept_msgs;
uint8_t busy_flag;
bool pairing_requested;
ble_event_t event_queue_buffers[EVENT_QUEUE_LEN];
tsqueue_entry_t event_queue_entries[EVENT_QUEUE_LEN];
@ -217,6 +218,7 @@ static void ble_process_rx_msg_status(const uint8_t *data, uint32_t len) {
drv->mode_current = BLE_MODE_OFF;
}
drv->busy_flag = msg.busy_flag;
drv->peer_count = msg.peer_count;
drv->status_valid = true;
@ -351,6 +353,24 @@ static void ble_loop(void *context) {
}
}
if (drv->accept_msgs && drv->busy_flag != 0) {
cmd_set_busy_t cmd = {
.cmd_id = INTERNAL_CMD_SET_BUSY,
.flag = 0,
};
nrf_send_msg(NRF_SERVICE_BLE_MANAGER, (uint8_t *)&cmd, sizeof(cmd), NULL,
NULL);
}
if (!drv->accept_msgs && drv->busy_flag == 0) {
cmd_set_busy_t cmd = {
.cmd_id = INTERNAL_CMD_SET_BUSY,
.flag = 1,
};
nrf_send_msg(NRF_SERVICE_BLE_MANAGER, (uint8_t *)&cmd, sizeof(cmd), NULL,
NULL);
}
if (drv->mode_current != drv->mode_requested) {
if (drv->mode_requested == BLE_MODE_OFF) {
ble_send_advertising_off(drv);

View File

@ -30,7 +30,8 @@ typedef struct {
uint8_t advertising_whitelist;
uint8_t peer_count;
uint8_t reserved[2];
uint8_t busy_flag;
uint8_t reserved;
uint8_t sd_version_number;
uint16_t sd_company_id;
@ -62,6 +63,7 @@ typedef enum {
INTERNAL_CMD_REJECT_PAIRING = 0x07,
INTERNAL_CMD_UNPAIR = 0x08,
INTERNAL_CMD_GET_MAC = 0x09,
INTERNAL_CMD_SET_BUSY = 0x0A,
} internal_cmd_t;
typedef struct {
@ -77,3 +79,8 @@ typedef struct {
uint8_t cmd_id;
uint8_t code[BLE_PAIRING_CODE_LEN];
} cmd_allow_pairing_t;
typedef struct {
uint8_t cmd_id;
uint8_t flag;
} cmd_set_busy_t;

View File

@ -30,7 +30,8 @@ typedef enum _FailureType {
FailureType_Failure_UnexpectedMessage = 1,
FailureType_Failure_DataError = 3,
FailureType_Failure_ActionCancelled = 4,
FailureType_Failure_ProcessError = 9
FailureType_Failure_ProcessError = 9,
FailureType_Failure_Busy = 15
} FailureType;
typedef enum _ButtonRequestType {

View File

@ -103,6 +103,7 @@ message Failure {
Failure_DataError = 3;
Failure_ActionCancelled = 4;
Failure_ProcessError = 9;
Failure_Busy = 15;
}
}

View File

@ -155,7 +155,7 @@ exit_host_control:
systick_delay_ms(100);
usb_iface_deinit();
#ifdef USE_BLE
ble_iface_init();
ble_iface_deinit();
#endif
return result;
}

View File

@ -16,4 +16,5 @@ NotInitialized = 11
PinMismatch = 12
WipeCodeMismatch = 13
InvalidSession = 14
Busy = 15
FirmwareError = 99

View File

@ -39,6 +39,7 @@ if TYPE_CHECKING:
PinMismatch = 12
WipeCodeMismatch = 13
InvalidSession = 14
Busy = 15
FirmwareError = 99
class ButtonRequestType(IntEnum):

View File

@ -25,9 +25,6 @@
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/uuid.h>
#include <signals/signals.h>
#include "ble_internal.h"
#define LOG_MODULE_NAME ble
@ -35,11 +32,13 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
static K_SEM_DEFINE(ble_init_ok, 0, 1);
static uint8_t g_busy_flag = 0;
static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data,
uint16_t len) {
if (!signals_is_trz_ready()) {
if (g_busy_flag != 0) {
LOG_INF("Trezor not ready, rejecting data");
// send_error_response();
service_send_busy();
return;
}
@ -101,5 +100,9 @@ void ble_write_thread(void) {
}
}
void ble_set_busy_flag(uint8_t flag) { g_busy_flag = flag; }
uint8_t ble_get_busy_flag(void) { return g_busy_flag; }
K_THREAD_DEFINE(ble_write_thread_id, CONFIG_DEFAULT_THREAD_STACK_SIZE,
ble_write_thread, NULL, NULL, NULL, 7, 0, 0);

View File

@ -46,6 +46,9 @@
#define BT_UUID_TRZ_RX BT_UUID_DECLARE_128(BT_UUID_TRZ_RX_VAL)
#define BT_UUID_TRZ_TX BT_UUID_DECLARE_128(BT_UUID_TRZ_TX_VAL)
#define BLE_TX_PACKET_SIZE 64
#define BLE_RX_PACKET_SIZE 244
#define BLE_PAIRING_CODE_LEN 6
#define BLE_ADV_NAME_LEN 20
@ -56,7 +59,8 @@ typedef struct {
uint8_t advertising_whitelist;
uint8_t peer_count;
uint8_t reserved[2];
uint8_t busy_flag;
uint8_t reserved;
uint8_t sd_version_number;
uint16_t sd_company_id;
@ -88,6 +92,7 @@ typedef enum {
INTERNAL_CMD_REJECT_PAIRING = 0x07,
INTERNAL_CMD_UNPAIR = 0x08,
INTERNAL_CMD_GET_MAC = 0x09,
INTERNAL_CMD_SET_BUSY = 0x0A,
} internal_cmd_t;
typedef struct {
@ -104,6 +109,16 @@ typedef struct {
uint8_t code[BLE_PAIRING_CODE_LEN];
} cmd_allow_pairing_t;
typedef struct {
uint8_t cmd_id;
uint8_t flag;
} cmd_set_busy_t;
// Set device to busy state, autoresponse
void ble_set_busy_flag(uint8_t flag);
uint8_t ble_get_busy_flag(void);
// BLE management functions
// Initialization
void ble_management_init(void);
@ -165,3 +180,5 @@ typedef void (*service_received_cb)(struct bt_conn *conn,
int service_init(service_received_cb callbacks);
// Send data to the connected device
int service_send(struct bt_conn *conn, trz_packet_t *data);
// Send hard-coded error response
void service_send_busy(void);

View File

@ -56,6 +56,7 @@ void ble_management_send_status_event(void) {
msg.sd_subversion_number = 0;
msg.app_version = 0;
msg.bld_version = 0;
msg.busy_flag = ble_get_busy_flag();
trz_comm_send_msg(NRF_SERVICE_BLE_MANAGER, (uint8_t *)&msg, sizeof(msg));
}
@ -138,11 +139,11 @@ static void process_command(uint8_t *data, uint16_t len) {
case INTERNAL_CMD_ACK:
// pb_msg_ack();
break;
case INTERNAL_CMD_ALLOW_PAIRING:
case INTERNAL_CMD_ALLOW_PAIRING: {
cmd_allow_pairing_t *cmd = (cmd_allow_pairing_t *)data;
pairing_num_comp_reply(true, cmd->code);
break;
} break;
case INTERNAL_CMD_REJECT_PAIRING:
pairing_num_comp_reply(false, NULL);
break;
@ -155,6 +156,9 @@ static void process_command(uint8_t *data, uint16_t len) {
management_send_mac(mac);
send_response = false;
} break;
case INTERNAL_CMD_SET_BUSY: {
ble_set_busy_flag(data[1]);
}
default:
break;
}

View File

@ -88,3 +88,20 @@ int service_send(struct bt_conn *conn, trz_packet_t *data) {
return -EINVAL;
}
}
void service_send_busy(void) {
struct bt_conn *conn = connection_get_current();
trz_packet_t *rx = k_malloc(sizeof(*rx));
static const uint8_t busy_packet[] = {
0x3f, 0x23, 0x23, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x08, 0x0f, 0x12,
0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6c, 0x6f, 0x63, 0x6b,
0x65, 0x64, 0x20, 0x6f, 0x64, 0x20, 0x62, 0x75, 0x73, 0x79};
if (rx) {
memcpy(rx->data, busy_packet, sizeof(busy_packet));
rx->len = BLE_TX_PACKET_SIZE;
service_send(conn, rx);
}
}

View File

@ -43,6 +43,7 @@ class FailureType(IntEnum):
PinMismatch = 12
WipeCodeMismatch = 13
InvalidSession = 14
Busy = 15
FirmwareError = 99

View File

@ -414,6 +414,8 @@ pub mod failure {
Failure_WipeCodeMismatch = 13,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.common.Failure.FailureType.Failure_InvalidSession)
Failure_InvalidSession = 14,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.common.Failure.FailureType.Failure_Busy)
Failure_Busy = 15,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.common.Failure.FailureType.Failure_FirmwareError)
Failure_FirmwareError = 99,
}
@ -441,6 +443,7 @@ pub mod failure {
12 => ::std::option::Option::Some(FailureType::Failure_PinMismatch),
13 => ::std::option::Option::Some(FailureType::Failure_WipeCodeMismatch),
14 => ::std::option::Option::Some(FailureType::Failure_InvalidSession),
15 => ::std::option::Option::Some(FailureType::Failure_Busy),
99 => ::std::option::Option::Some(FailureType::Failure_FirmwareError),
_ => ::std::option::Option::None
}
@ -462,6 +465,7 @@ pub mod failure {
"Failure_PinMismatch" => ::std::option::Option::Some(FailureType::Failure_PinMismatch),
"Failure_WipeCodeMismatch" => ::std::option::Option::Some(FailureType::Failure_WipeCodeMismatch),
"Failure_InvalidSession" => ::std::option::Option::Some(FailureType::Failure_InvalidSession),
"Failure_Busy" => ::std::option::Option::Some(FailureType::Failure_Busy),
"Failure_FirmwareError" => ::std::option::Option::Some(FailureType::Failure_FirmwareError),
_ => ::std::option::Option::None
}
@ -482,6 +486,7 @@ pub mod failure {
FailureType::Failure_PinMismatch,
FailureType::Failure_WipeCodeMismatch,
FailureType::Failure_InvalidSession,
FailureType::Failure_Busy,
FailureType::Failure_FirmwareError,
];
}
@ -508,7 +513,8 @@ pub mod failure {
FailureType::Failure_PinMismatch => 11,
FailureType::Failure_WipeCodeMismatch => 12,
FailureType::Failure_InvalidSession => 13,
FailureType::Failure_FirmwareError => 14,
FailureType::Failure_Busy => 14,
FailureType::Failure_FirmwareError => 15,
};
Self::enum_descriptor().value_by_index(index)
}
@ -2481,9 +2487,9 @@ impl ::protobuf::reflect::ProtobufValue for HDNodeType {
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x15messages-common.proto\x12\x19hw.trezor.messages.common\x1a\roption\
s.proto\"%\n\x07Success\x12\x1a\n\x07message\x18\x01\x20\x01(\t:\0R\x07m\
essage\"\x8f\x04\n\x07Failure\x12B\n\x04code\x18\x01\x20\x01(\x0e2..hw.t\
essage\"\xa1\x04\n\x07Failure\x12B\n\x04code\x18\x01\x20\x01(\x0e2..hw.t\
rezor.messages.common.Failure.FailureTypeR\x04code\x12\x18\n\x07message\
\x18\x02\x20\x01(\tR\x07message\"\xa5\x03\n\x0bFailureType\x12\x1d\n\x19\
\x18\x02\x20\x01(\tR\x07message\"\xb7\x03\n\x0bFailureType\x12\x1d\n\x19\
Failure_UnexpectedMessage\x10\x01\x12\x1a\n\x16Failure_ButtonExpected\
\x10\x02\x12\x15\n\x11Failure_DataError\x10\x03\x12\x1b\n\x17Failure_Act\
ionCancelled\x10\x04\x12\x17\n\x13Failure_PinExpected\x10\x05\x12\x18\n\
@ -2492,44 +2498,44 @@ static file_descriptor_proto_data: &'static [u8] = b"\
essError\x10\t\x12\x1a\n\x16Failure_NotEnoughFunds\x10\n\x12\x1a\n\x16Fa\
ilure_NotInitialized\x10\x0b\x12\x17\n\x13Failure_PinMismatch\x10\x0c\
\x12\x1c\n\x18Failure_WipeCodeMismatch\x10\r\x12\x1a\n\x16Failure_Invali\
dSession\x10\x0e\x12\x19\n\x15Failure_FirmwareError\x10c\"\xab\x06\n\rBu\
ttonRequest\x12N\n\x04code\x18\x01\x20\x01(\x0e2:.hw.trezor.messages.com\
mon.ButtonRequest.ButtonRequestTypeR\x04code\x12\x14\n\x05pages\x18\x02\
\x20\x01(\rR\x05pages\x12\x12\n\x04name\x18\x04\x20\x01(\tR\x04name\"\
\x99\x05\n\x11ButtonRequestType\x12\x17\n\x13ButtonRequest_Other\x10\x01\
\x12\"\n\x1eButtonRequest_FeeOverThreshold\x10\x02\x12\x1f\n\x1bButtonRe\
quest_ConfirmOutput\x10\x03\x12\x1d\n\x19ButtonRequest_ResetDevice\x10\
\x04\x12\x1d\n\x19ButtonRequest_ConfirmWord\x10\x05\x12\x1c\n\x18ButtonR\
equest_WipeDevice\x10\x06\x12\x1d\n\x19ButtonRequest_ProtectCall\x10\x07\
\x12\x18\n\x14ButtonRequest_SignTx\x10\x08\x12\x1f\n\x1bButtonRequest_Fi\
rmwareCheck\x10\t\x12\x19\n\x15ButtonRequest_Address\x10\n\x12\x1b\n\x17\
ButtonRequest_PublicKey\x10\x0b\x12#\n\x1fButtonRequest_MnemonicWordCoun\
t\x10\x0c\x12\x1f\n\x1bButtonRequest_MnemonicInput\x10\r\x120\n(_Depreca\
ted_ButtonRequest_PassphraseType\x10\x0e\x1a\x02\x08\x01\x12'\n#ButtonRe\
quest_UnknownDerivationPath\x10\x0f\x12\"\n\x1eButtonRequest_RecoveryHom\
epage\x10\x10\x12\x19\n\x15ButtonRequest_Success\x10\x11\x12\x19\n\x15Bu\
ttonRequest_Warning\x10\x12\x12!\n\x1dButtonRequest_PassphraseEntry\x10\
\x13\x12\x1a\n\x16ButtonRequest_PinEntry\x10\x14J\x04\x08\x03\x10\x04\"\
\x0b\n\tButtonAck\"\xbb\x02\n\x10PinMatrixRequest\x12T\n\x04type\x18\x01\
\x20\x01(\x0e2@.hw.trezor.messages.common.PinMatrixRequest.PinMatrixRequ\
estTypeR\x04type\"\xd0\x01\n\x14PinMatrixRequestType\x12\x20\n\x1cPinMat\
rixRequestType_Current\x10\x01\x12!\n\x1dPinMatrixRequestType_NewFirst\
\x10\x02\x12\"\n\x1ePinMatrixRequestType_NewSecond\x10\x03\x12&\n\"PinMa\
trixRequestType_WipeCodeFirst\x10\x04\x12'\n#PinMatrixRequestType_WipeCo\
deSecond\x10\x05\"\x20\n\x0cPinMatrixAck\x12\x10\n\x03pin\x18\x01\x20\
\x02(\tR\x03pin\"5\n\x11PassphraseRequest\x12\x20\n\n_on_device\x18\x01\
\x20\x01(\x08R\x08OnDeviceB\x02\x18\x01\"g\n\rPassphraseAck\x12\x1e\n\np\
assphrase\x18\x01\x20\x01(\tR\npassphrase\x12\x19\n\x06_state\x18\x02\
\x20\x01(\x0cR\x05StateB\x02\x18\x01\x12\x1b\n\ton_device\x18\x03\x20\
\x01(\x08R\x08onDevice\"=\n!Deprecated_PassphraseStateRequest\x12\x14\n\
\x05state\x18\x01\x20\x01(\x0cR\x05state:\x02\x18\x01\"#\n\x1dDeprecated\
_PassphraseStateAck:\x02\x18\x01\"\xc0\x01\n\nHDNodeType\x12\x14\n\x05de\
pth\x18\x01\x20\x02(\rR\x05depth\x12\x20\n\x0bfingerprint\x18\x02\x20\
\x02(\rR\x0bfingerprint\x12\x1b\n\tchild_num\x18\x03\x20\x02(\rR\x08chil\
dNum\x12\x1d\n\nchain_code\x18\x04\x20\x02(\x0cR\tchainCode\x12\x1f\n\
\x0bprivate_key\x18\x05\x20\x01(\x0cR\nprivateKey\x12\x1d\n\npublic_key\
\x18\x06\x20\x02(\x0cR\tpublicKeyB>\n#com.satoshilabs.trezor.lib.protobu\
fB\x13TrezorMessageCommon\x80\xa6\x1d\x01\
dSession\x10\x0e\x12\x10\n\x0cFailure_Busy\x10\x0f\x12\x19\n\x15Failure_\
FirmwareError\x10c\"\xab\x06\n\rButtonRequest\x12N\n\x04code\x18\x01\x20\
\x01(\x0e2:.hw.trezor.messages.common.ButtonRequest.ButtonRequestTypeR\
\x04code\x12\x14\n\x05pages\x18\x02\x20\x01(\rR\x05pages\x12\x12\n\x04na\
me\x18\x04\x20\x01(\tR\x04name\"\x99\x05\n\x11ButtonRequestType\x12\x17\
\n\x13ButtonRequest_Other\x10\x01\x12\"\n\x1eButtonRequest_FeeOverThresh\
old\x10\x02\x12\x1f\n\x1bButtonRequest_ConfirmOutput\x10\x03\x12\x1d\n\
\x19ButtonRequest_ResetDevice\x10\x04\x12\x1d\n\x19ButtonRequest_Confirm\
Word\x10\x05\x12\x1c\n\x18ButtonRequest_WipeDevice\x10\x06\x12\x1d\n\x19\
ButtonRequest_ProtectCall\x10\x07\x12\x18\n\x14ButtonRequest_SignTx\x10\
\x08\x12\x1f\n\x1bButtonRequest_FirmwareCheck\x10\t\x12\x19\n\x15ButtonR\
equest_Address\x10\n\x12\x1b\n\x17ButtonRequest_PublicKey\x10\x0b\x12#\n\
\x1fButtonRequest_MnemonicWordCount\x10\x0c\x12\x1f\n\x1bButtonRequest_M\
nemonicInput\x10\r\x120\n(_Deprecated_ButtonRequest_PassphraseType\x10\
\x0e\x1a\x02\x08\x01\x12'\n#ButtonRequest_UnknownDerivationPath\x10\x0f\
\x12\"\n\x1eButtonRequest_RecoveryHomepage\x10\x10\x12\x19\n\x15ButtonRe\
quest_Success\x10\x11\x12\x19\n\x15ButtonRequest_Warning\x10\x12\x12!\n\
\x1dButtonRequest_PassphraseEntry\x10\x13\x12\x1a\n\x16ButtonRequest_Pin\
Entry\x10\x14J\x04\x08\x03\x10\x04\"\x0b\n\tButtonAck\"\xbb\x02\n\x10Pin\
MatrixRequest\x12T\n\x04type\x18\x01\x20\x01(\x0e2@.hw.trezor.messages.c\
ommon.PinMatrixRequest.PinMatrixRequestTypeR\x04type\"\xd0\x01\n\x14PinM\
atrixRequestType\x12\x20\n\x1cPinMatrixRequestType_Current\x10\x01\x12!\
\n\x1dPinMatrixRequestType_NewFirst\x10\x02\x12\"\n\x1ePinMatrixRequestT\
ype_NewSecond\x10\x03\x12&\n\"PinMatrixRequestType_WipeCodeFirst\x10\x04\
\x12'\n#PinMatrixRequestType_WipeCodeSecond\x10\x05\"\x20\n\x0cPinMatrix\
Ack\x12\x10\n\x03pin\x18\x01\x20\x02(\tR\x03pin\"5\n\x11PassphraseReques\
t\x12\x20\n\n_on_device\x18\x01\x20\x01(\x08R\x08OnDeviceB\x02\x18\x01\"\
g\n\rPassphraseAck\x12\x1e\n\npassphrase\x18\x01\x20\x01(\tR\npassphrase\
\x12\x19\n\x06_state\x18\x02\x20\x01(\x0cR\x05StateB\x02\x18\x01\x12\x1b\
\n\ton_device\x18\x03\x20\x01(\x08R\x08onDevice\"=\n!Deprecated_Passphra\
seStateRequest\x12\x14\n\x05state\x18\x01\x20\x01(\x0cR\x05state:\x02\
\x18\x01\"#\n\x1dDeprecated_PassphraseStateAck:\x02\x18\x01\"\xc0\x01\n\
\nHDNodeType\x12\x14\n\x05depth\x18\x01\x20\x02(\rR\x05depth\x12\x20\n\
\x0bfingerprint\x18\x02\x20\x02(\rR\x0bfingerprint\x12\x1b\n\tchild_num\
\x18\x03\x20\x02(\rR\x08childNum\x12\x1d\n\nchain_code\x18\x04\x20\x02(\
\x0cR\tchainCode\x12\x1f\n\x0bprivate_key\x18\x05\x20\x01(\x0cR\nprivate\
Key\x12\x1d\n\npublic_key\x18\x06\x20\x02(\x0cR\tpublicKeyB>\n#com.satos\
hilabs.trezor.lib.protobufB\x13TrezorMessageCommon\x80\xa6\x1d\x01\
";
/// `FileDescriptorProto` object which was a source for this generated file