feat(nordic/ble): request specific connection interval and phy
What changed, and why it matters
This commit tunes the Bluetooth Low Energy settings on Trezor's Nordic BLE firmware. It asks for a faster connection interval, switches to the 2 Mbps physical layer, and adds suspend/resume functions that slow the connection when the device is idle. There is no direct security bug visible in the diff, but changing connection parameters can affect power, stability, and the attack surface for Bluetooth side-channel or denial-of-service attacks.
Treat as a normal feature commit. Review whether the chosen supervision timeout and interval are robust against connection hijacking or denial-of-service attempts, and verify that bt_conn_le_param_update/phy_update return values are checked in future hardening. No immediate patch or incident response is indicated by this diff alone.
Security signals we found
BLE connection parameter change (interval/timeout/PHY)
New suspend/resume connection state helpers
No input validation or memory safety changes visible
No vendor security disclosure or CVE references present
Evidence from the diff
The patch configures the Zephyr BLE stack to request a fixed 7.5 ms connection interval (6 * 1.25 ms), a 4 s supervision timeout, and 2M PHY in both directions. It adds connection_suspend()/connection_resume() helpers that relax the interval to 500 ms–1 s and 4 s–8 s timeout when suspended. The changes are functional/performance tuning rather than a vulnerability fix; no input validation, cryptographic, or memory-safety issues are introduced in the diff.
Changed components
nordic/trezor/trezor-ble/prj.confnordic/trezor/trezor-ble/src/ble/connection.cnordic/trezor/trezor-ble/src/ble/inc/ble/ble.hnordic/trezor/trezor-ble/src/management/management.cInspect captured patch +68 / −1
diff --git a/nordic/trezor/trezor-ble/prj.conf b/nordic/trezor/trezor-ble/prj.conf
index 61e97a577..1c5756226 100644
--- a/nordic/trezor/trezor-ble/prj.conf
+++ b/nordic/trezor/trezor-ble/prj.conf
@@ -53,7 +53,12 @@ CONFIG_BT_PRIVACY=y
CONFIG_BT_TINYCRYPT_ECC=y
CONFIG_BT_LL_SW_SPLIT=y
CONFIG_BT_CTLR_TX_PWR_PLUS_4=y
-
+CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=y
+CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6
+CONFIG_BT_PERIPHERAL_PREF_MAX_INT=6
+CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=400
+CONFIG_BT_CTLR_PHY_2M=y
+CONFIG_BT_USER_PHY_UPDATE=y
#PHY update needed for updating PHY request
CONFIG_BT_PHY_UPDATE=y
diff --git a/nordic/trezor/trezor-ble/src/ble/connection.c b/nordic/trezor/trezor-ble/src/ble/connection.c
index c581f09ee..1cdcbdde2 100644
--- a/nordic/trezor/trezor-ble/src/ble/connection.c
+++ b/nordic/trezor/trezor-ble/src/ble/connection.c
@@ -35,6 +35,27 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
static struct bt_conn *current_conn = NULL;
static struct bt_conn *next_conn = NULL;
+static void show_params(struct bt_conn *conn) {
+ struct bt_conn_info info;
+ if (bt_conn_get_info(conn, &info) == 0 && info.type == BT_CONN_TYPE_LE) {
+ const struct bt_conn_le_info *le = &info.le;
+ /* Bluetooth units: interval = 1.25 ms, timeout = 10 ms */
+ uint32_t interval_ms = le->interval * 125 / 100; // 1.25 ms units → ms
+ uint32_t timeout_ms = le->timeout * 10; // 10 ms units → ms
+ LOG_INF("Conn params: interval=%u.%02u ms, latency=%u, timeout=%u ms",
+ interval_ms, (le->interval * 125) % 100, le->latency, timeout_ms);
+ }
+}
+
+/* Called when central updates params */
+static void le_param_updated(struct bt_conn *conn, uint16_t interval,
+ uint16_t latency, uint16_t timeout) {
+ uint32_t interval_ms = interval * 125 / 100;
+ uint32_t timeout_ms = timeout * 10;
+ LOG_INF("Params updated: interval=%u.%02u ms, latency=%u, timeout=%u ms",
+ interval_ms, (interval * 125) % 100, latency, timeout_ms);
+}
+
void connected(struct bt_conn *conn, uint8_t err) {
char addr[BT_ADDR_LE_STR_LEN];
@@ -43,6 +64,20 @@ void connected(struct bt_conn *conn, uint8_t err) {
return;
}
+ show_params(conn);
+
+ const struct bt_le_conn_param *param = BT_LE_CONN_PARAM(6, 6, 0, 400);
+ bt_conn_le_param_update(conn, param);
+
+ // Prefer 2M both directions; 0 options = no specific constraints
+ const struct bt_conn_le_phy_param phy_2m = {
+ .options = 0,
+ .pref_tx_phy = BT_GAP_LE_PHY_2M,
+ .pref_rx_phy = BT_GAP_LE_PHY_2M,
+ };
+
+ bt_conn_le_phy_update(conn, &phy_2m);
+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Connected %s", addr);
@@ -106,6 +141,7 @@ BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
.security_changed = security_changed,
+ .le_param_updated = le_param_updated,
};
bool connection_init(void) { return true; }
@@ -120,3 +156,21 @@ void connection_disconnect(void) {
}
struct bt_conn *connection_get_current(void) { return current_conn; }
+
+void connection_suspend(void) {
+ struct bt_conn *conn = connection_get_current();
+
+ if (conn != NULL) {
+ const struct bt_le_conn_param *param = BT_LE_CONN_PARAM(400, 800, 0, 500);
+ bt_conn_le_param_update(conn, param);
+ }
+}
+
+void connection_resume(void) {
+ struct bt_conn *conn = connection_get_current();
+
+ if (conn != NULL) {
+ const struct bt_le_conn_param *param = BT_LE_CONN_PARAM(6, 6, 0, 400);
+ bt_conn_le_param_update(conn, param);
+ }
+}
diff --git a/nordic/trezor/trezor-ble/src/ble/inc/ble/ble.h b/nordic/trezor/trezor-ble/src/ble/inc/ble/ble.h
index 0d48d9803..90a89fa3a 100644
--- a/nordic/trezor/trezor-ble/src/ble/inc/ble/ble.h
+++ b/nordic/trezor/trezor-ble/src/ble/inc/ble/ble.h
@@ -26,3 +26,9 @@ bool ble_init(void);
// Stop advertising
void advertising_stop(void);
+
+// Set connection to suspended state- slower interval and so
+void connection_suspend(void);
+
+// Resume connection - faster interval
+void connection_resume(void);
diff --git a/nordic/trezor/trezor-ble/src/management/management.c b/nordic/trezor/trezor-ble/src/management/management.c
index fd267d86a..fd300beb6 100644
--- a/nordic/trezor/trezor-ble/src/management/management.c
+++ b/nordic/trezor/trezor-ble/src/management/management.c
@@ -194,10 +194,12 @@ static void process_command(uint8_t *data, uint16_t len) {
LOG_INF("Suspend");
trz_comm_suspend();
advertising_stop();
+ connection_suspend();
break;
case MGMT_CMD_RESUME:
LOG_INF("Resume");
trz_comm_resume();
+ connection_resume();
break;
case MGMT_CMD_AUTH_CHALLENGE:
LOG_INF("Challenge command");
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.