What changed, and why it matters
This commit is a routine internal refactoring: it moves three existing device-control functions (reboot, reset Bluetooth chip, and disable SmartEEPROM) behind a common Rust 'system' interface so different parts of the firmware call them through a hardware-abstraction layer instead of directly. The actual device behavior does not change; it is not a security fix and does not introduce a known vulnerability.
No security action required. Treat as normal code-quality/architecture refactoring. Continue standard review and testing.
Security signals we found
No new unsafe code introduced; existing unsafe FFI calls are only relocated.
No change to access-control, authentication, or authorization logic.
No change to cryptographic, memory, or Bluetooth protocol handling.
No bug fix, bounds check, or input validation added.
No vendor statement or external advisory links security relevance to this commit.
Evidence from the diff
The patch refactors system-level operations into the System trait in bitbox-hal and provides implementations for the real BitBox02 device (bitbox02/src/hal/system.rs) and the test mock (bitbox02-rust/src/hal/testing/system.rs). Call sites in reset.rs and bluetooth.rs are updated from direct bitbox02::reboot(), bitbox02::reset_ble(), and bitbox02::smarteeprom::disable() calls to hal.system().reboot(), hal.system().reset_ble(), and hal.system().smarteeprom_disable(). The underlying unsafe FFI calls to bitbox02_sys::reboot(), bitbox02_sys::reset_ble(), and bitbox02_sys::smarteeprom_disable() remain unchanged. The removed reboot() and smarteeprom::disable()/is_enabled() free functions are simply relocated, not eliminated.
Changed components
src/rust/bitbox-hal/src/system.rssrc/rust/bitbox02/src/hal/system.rssrc/rust/bitbox02-rust/src/hal/testing/system.rssrc/rust/bitbox02-rust/src/reset.rssrc/rust/bitbox02-rust/src/hww/api/bluetooth.rssrc/rust/bitbox02/src/lib.rssrc/rust/bitbox02/src/smarteeprom.rsInspect captured patch +73 / −24
diff --git a/src/rust/bitbox-hal/src/system.rs b/src/rust/bitbox-hal/src/system.rs
index c04a0f1..91c12dc 100644
--- a/src/rust/bitbox-hal/src/system.rs
+++ b/src/rust/bitbox-hal/src/system.rs
@@ -5,5 +5,8 @@ pub trait System {
/// Runs device-specific startup UI/initialization before regular operation.
async fn startup();
+ fn reboot(&mut self) -> !;
fn reboot_to_bootloader(&mut self) -> !;
+ fn reset_ble(&mut self);
+ fn smarteeprom_disable(&mut self);
}
diff --git a/src/rust/bitbox02-rust/src/hal/testing/system.rs b/src/rust/bitbox02-rust/src/hal/testing/system.rs
index 804bbd9..c57f50e 100644
--- a/src/rust/bitbox02-rust/src/hal/testing/system.rs
+++ b/src/rust/bitbox02-rust/src/hal/testing/system.rs
@@ -1,17 +1,63 @@
// SPDX-License-Identifier: Apache-2.0
-pub struct TestingSystem;
+pub struct TestingSystem {
+ pub(crate) smarteeprom_enabled: bool,
+ ble_reset_count: u32,
+}
impl TestingSystem {
pub fn new() -> Self {
- Self
+ Self {
+ smarteeprom_enabled: true,
+ ble_reset_count: 0,
+ }
+ }
+
+ pub fn ble_reset_count(&self) -> u32 {
+ self.ble_reset_count
}
}
impl crate::hal::System for TestingSystem {
async fn startup() {}
+ fn reboot(&mut self) -> ! {
+ panic!("reboot called")
+ }
+
fn reboot_to_bootloader(&mut self) -> ! {
panic!("reboot_to_bootloader called")
}
+
+ fn reset_ble(&mut self) {
+ self.ble_reset_count += 1;
+ }
+
+ fn smarteeprom_disable(&mut self) {
+ self.smarteeprom_enabled = false;
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use crate::hal::System;
+
+ #[test]
+ fn test_smarteeprom_disable() {
+ let mut system = TestingSystem::new();
+ assert!(system.smarteeprom_enabled);
+ system.smarteeprom_disable();
+ assert!(!system.smarteeprom_enabled);
+ }
+
+ #[test]
+ fn test_reset_ble() {
+ let mut system = TestingSystem::new();
+ assert_eq!(system.ble_reset_count(), 0);
+ system.reset_ble();
+ system.reset_ble();
+ assert_eq!(system.ble_reset_count(), 2);
+ }
}
diff --git a/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs b/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs
index 0721f0b..79c8df6 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs
@@ -11,7 +11,7 @@ use pb::bluetooth_response::Response;
use sha2::{Digest, Sha256};
-use crate::hal::{Memory, Ui, memory as hal_memory};
+use crate::hal::{Memory, System, Ui, memory as hal_memory};
use alloc::vec::Vec;
@@ -149,7 +149,7 @@ async fn process_upgrade(
if response.is_ok() {
hal.ui().status("Upgrade\nsuccessful", true).await;
- bitbox02::reset_ble();
+ hal.system().reset_ble();
if crate::communication_mode::ble_enabled(hal) {
// Since the Bluetooth host will not be there anymore to read this response, this task
// will not be cleared by the executor. We do it manually to make space for the next
diff --git a/src/rust/bitbox02-rust/src/reset.rs b/src/rust/bitbox02-rust/src/reset.rs
index 04ad1cc..e63b866 100644
--- a/src/rust/bitbox02-rust/src/reset.rs
+++ b/src/rust/bitbox02-rust/src/reset.rs
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::general::abort;
-use crate::hal::{Memory, SecureChip, Ui, memory};
+use crate::hal::{Memory, SecureChip, System, Ui, memory};
/// Resets the device:
/// - Updates secure chip KDF keys.
@@ -51,7 +51,7 @@ pub(crate) async fn reset(hal: &mut impl crate::hal::Hal, status: bool) {
}
// Disable SmartEEPROM so it will be erased on next reboot.
- bitbox02::smarteeprom::disable();
+ hal.system().smarteeprom_disable();
// Show "Device reset" status using the UI workflow.
hal.ui().status("Device reset", status).await;
@@ -61,11 +61,11 @@ pub(crate) async fn reset(hal: &mut impl crate::hal::Hal, status: bool) {
hal.memory().get_platform(),
Ok(memory::Platform::BitBox02Plus)
) {
- bitbox02::reset_ble();
+ hal.system().reset_ble();
}
#[cfg(not(feature = "testing"))]
- bitbox02::reboot();
+ hal.system().reboot();
}
#[cfg(test)]
@@ -89,7 +89,7 @@ mod tests {
mock_unlocked();
hal.memory.set_device_name("Custom name").unwrap();
assert!(!keystore::is_locked());
- assert!(bitbox02::smarteeprom::is_enabled());
+ assert!(hal.system.smarteeprom_enabled);
// Make the reset keys call fail once, to test that it is retried.
hal.securechip.mock_reset_keys_fails();
@@ -110,7 +110,7 @@ mod tests {
assert_eq!(hal.memory.get_device_name().as_str(), "My BitBox");
// SmartEEPROM was disabled as part of the reset.
- assert!(!bitbox02::smarteeprom::is_enabled());
+ assert!(!hal.system.smarteeprom_enabled);
assert_eq!(hal.securechip.get_u2f_counter(), 0);
diff --git a/src/rust/bitbox02/src/hal/system.rs b/src/rust/bitbox02/src/hal/system.rs
index a81efdc..83ae393 100644
--- a/src/rust/bitbox02/src/hal/system.rs
+++ b/src/rust/bitbox02/src/hal/system.rs
@@ -19,7 +19,21 @@ impl System for BitBox02System {
crate::ui::screen_process_waiting_switch_to_lockscreen();
}
+ #[allow(clippy::empty_loop)]
+ fn reboot(&mut self) -> ! {
+ unsafe { bitbox02_sys::reboot() }
+ loop {}
+ }
+
fn reboot_to_bootloader(&mut self) -> ! {
crate::reboot_to_bootloader()
}
+
+ fn reset_ble(&mut self) {
+ crate::reset_ble()
+ }
+
+ fn smarteeprom_disable(&mut self) {
+ unsafe { bitbox02_sys::smarteeprom_disable() }
+ }
}
diff --git a/src/rust/bitbox02/src/lib.rs b/src/rust/bitbox02/src/lib.rs
index b37ec3a..3b24799 100644
--- a/src/rust/bitbox02/src/lib.rs
+++ b/src/rust/bitbox02/src/lib.rs
@@ -126,11 +126,6 @@ pub fn reset_ble() {
unsafe { bitbox02_sys::reset_ble() }
}
-#[cfg(not(feature = "testing"))]
-pub fn reboot() {
- unsafe { bitbox02_sys::reboot() }
-}
-
#[allow(clippy::empty_loop)]
pub fn reboot_to_bootloader() -> ! {
unsafe { bitbox02_sys::reboot_to_bootloader() }
diff --git a/src/rust/bitbox02/src/smarteeprom.rs b/src/rust/bitbox02/src/smarteeprom.rs
index 2a7bbe9..f511c62 100644
--- a/src/rust/bitbox02/src/smarteeprom.rs
+++ b/src/rust/bitbox02/src/smarteeprom.rs
@@ -9,12 +9,3 @@ pub fn bb02_config() {
pub fn init() {
unsafe { bitbox02_sys::bitbox02_smarteeprom_init() };
}
-
-pub fn disable() {
- unsafe { bitbox02_sys::smarteeprom_disable() };
-}
-
-#[cfg(feature = "testing")]
-pub fn is_enabled() -> bool {
- unsafe { bitbox02_sys::smarteeprom_is_enabled() }
-}
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.