bitbox02/ui: use ConfirmResponse also in confirm()
What changed, and why it matters
This commit is a straightforward internal code cleanup: it replaces a plain true/false return value from the device's on-screen confirmation prompt with a named 'Approved'/'Cancelled' response type. There is no change to what the device does or to any security behavior; it only makes the code easier to read and maintain.
No security action required; treat as normal refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors bitbox02::ui::confirm() and its callers to use the existing ConfirmResponse enum (Approved/Cancelled) instead of a raw bool. The async state machine, C callback mapping, and menu cancel-confirmation logic are updated to match, but the underlying behavior (approve => Ok, cancel => UserAbort, menu cancel confirmation flow) is preserved. Stubs and unit-test mocks are updated accordingly. No functional or security logic is altered.
Changed components
src/rust/bitbox02-rust/src/workflow/confirm.rssrc/rust/bitbox02/src/ui/ui.rssrc/rust/bitbox02/src/ui/ui_stub.rssrc/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rsInspect captured patch +21 / −16
diff --git a/src/rust/bitbox02-rust/src/workflow/confirm.rs b/src/rust/bitbox02-rust/src/workflow/confirm.rs
index dd53b23..95c9628 100644
--- a/src/rust/bitbox02-rust/src/workflow/confirm.rs
+++ b/src/rust/bitbox02-rust/src/workflow/confirm.rs
@@ -6,9 +6,8 @@ pub struct UserAbort;
/// Returns `Ok(())` if the user accepts, `Err(UserAbort)` if the user rejects.
pub async fn confirm(params: &Params<'_>) -> Result<(), UserAbort> {
- if bitbox02::ui::confirm(params).await {
- Ok(())
- } else {
- Err(UserAbort)
+ match bitbox02::ui::confirm(params).await {
+ bitbox02::ui::ConfirmResponse::Approved => Ok(()),
+ bitbox02::ui::ConfirmResponse::Cancelled => Err(UserAbort),
}
}
diff --git a/src/rust/bitbox02/src/ui/ui.rs b/src/rust/bitbox02/src/ui/ui.rs
index 51a9c5a..333b545 100644
--- a/src/rust/bitbox02/src/ui/ui.rs
+++ b/src/rust/bitbox02/src/ui/ui.rs
@@ -170,14 +170,15 @@ pub async fn trinary_input_string(
.await
}
-/// Returns true if the user accepts, false if the user rejects.
-pub async fn confirm(params: &ConfirmParams<'_>) -> bool {
+/// Returns `ConfirmResponse::Approved` if the user accepts,
+/// `ConfirmResponse::Cancelled` if the user rejects.
+pub async fn confirm(params: &ConfirmParams<'_>) -> ConfirmResponse {
let _no_screensaver = crate::screen_saver::ScreensaverInhibitor::new();
// Shared between the async context and the c callback
struct SharedState {
waker: Option<Waker>,
- result: Option<bool>,
+ result: Option<ConfirmResponse>,
}
let shared_state = Box::new(RefCell::new(SharedState {
waker: None,
@@ -189,7 +190,11 @@ pub async fn confirm(params: &ConfirmParams<'_>) -> bool {
let shared_state = unsafe { &*(user_data as *mut RefCell<SharedState>) };
let mut shared_state = shared_state.borrow_mut();
if shared_state.result.is_none() {
- shared_state.result = Some(result);
+ shared_state.result = Some(if result {
+ ConfirmResponse::Approved
+ } else {
+ ConfirmResponse::Cancelled
+ });
if let Some(waker) = shared_state.waker.as_ref() {
waker.wake_by_ref();
}
@@ -237,7 +242,7 @@ pub async fn confirm(params: &ConfirmParams<'_>) -> bool {
move |cx| {
let mut shared_state = shared_state.borrow_mut();
- if let Some(result) = shared_state.result {
+ if let Some(result) = shared_state.result.take() {
Poll::Ready(result)
} else {
// Store the waker so the callback can wake up this task
@@ -459,17 +464,18 @@ pub async fn menu(params: MenuParams<'_>) -> MenuResponse {
MenuResponse::Cancel => match cancel_confirm_title {
None => return MenuResponse::Cancel,
Some(title) => {
- // false means _do not cancel_, stay in the same menu component.
- if !confirm(&ConfirmParams {
+ // `ConfirmResponse::Cancelled` means _do not cancel_,
+ // stay in the same menu component.
+ match confirm(&ConfirmParams {
title,
body: "Do you really\nwant to cancel?",
..Default::default()
})
.await
{
- continue;
+ ConfirmResponse::Approved => return MenuResponse::Cancel,
+ ConfirmResponse::Cancelled => continue,
}
- return MenuResponse::Cancel;
}
},
}
diff --git a/src/rust/bitbox02/src/ui/ui_stub.rs b/src/rust/bitbox02/src/ui/ui_stub.rs
index 3549430..04a7e23 100644
--- a/src/rust/bitbox02/src/ui/ui_stub.rs
+++ b/src/rust/bitbox02/src/ui/ui_stub.rs
@@ -47,7 +47,7 @@ pub async fn trinary_input_string(
panic!("not used");
}
-pub async fn confirm(_params: &ConfirmParams<'_>) -> bool {
+pub async fn confirm(_params: &ConfirmParams<'_>) -> ConfirmResponse {
panic!("not used");
}
diff --git a/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs b/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs
index 9ca6213..95c2e60 100644
--- a/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs
+++ b/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs
@@ -49,13 +49,13 @@ pub async fn trinary_input_string(
Ok(zeroize::Zeroizing::new("".into()))
}
-pub async fn confirm(params: &ConfirmParams<'_>) -> bool {
+pub async fn confirm(params: &ConfirmParams<'_>) -> ConfirmResponse {
crate::print_stdout(&format!(
"CONFIRM SCREEN START\nTITLE: {}\nBODY: {}\nCONFIRM SCREEN END\n",
params.title, params.body
));
- true
+ ConfirmResponse::Approved
}
pub fn screen_process() {}
Why this scored 15/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.