From 18d844389141c6e43762fe180d5446fca864a761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hlusi=C4=8Dka?= Date: Sun, 1 Mar 2026 01:10:52 +0100 Subject: [PATCH] Fix crashes when entering an empty or incorrect password --- firmware/acid-firmware/src/ui/mod.rs | 74 ++++++++++++++++++---------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/firmware/acid-firmware/src/ui/mod.rs b/firmware/acid-firmware/src/ui/mod.rs index 1238799..d608272 100644 --- a/firmware/acid-firmware/src/ui/mod.rs +++ b/firmware/acid-firmware/src/ui/mod.rs @@ -55,11 +55,18 @@ pub mod window_adapter; slint::include_modules!(); +#[derive(Clone, Copy)] +struct EmptyPassword; + fn spectre_derive_user_key( username: &CStr, password: &CStr, encrypted_key: Option, -) -> SpectreUserKey { +) -> Result { + if password.is_empty() { + return Err(EmptyPassword); + } + if let Some(encrypted_key) = encrypted_key { ACTIVE_ENCRYPTED_USER_KEY.lock(|user_key| { user_key.set(encrypted_key); @@ -84,7 +91,7 @@ fn spectre_derive_user_key( // TODO: Erase memory before freeing __spre_free(user_key as *const _ as *mut _); - user_key_stack + Ok(user_key_stack) } } @@ -338,14 +345,16 @@ impl State { fn process_callback_message( state_rc: &Rc, PsramAllocator>, - message: CallbackMessage, + mut message: CallbackMessage, ) { let view = state_rc.borrow().view; - match view { + while let Some(next_message) = match view { AppState::Login => StateLogin::process_callback_message(state_rc, message), AppState::Users => StateUsers::process_callback_message(state_rc, message), AppState::UserEdit => StateUserEdit::process_callback_message(state_rc, message), AppState::UserSites => StateUserSites::process_callback_message(state_rc, message), + } { + message = next_message } } @@ -392,7 +401,8 @@ trait AppViewTrait { fn process_callback_message( _state_rc: &Rc, PsramAllocator>, _message: CallbackMessage, - ) { + ) -> Option { + None } } @@ -403,7 +413,7 @@ impl AppViewTrait for StateLogin { fn process_callback_message( state_rc: &Rc, PsramAllocator>, message: CallbackMessage, - ) { + ) -> Option { let mut state = state_rc.borrow_mut(); match message { CallbackMessage::Login(CallbackMessageLogin::PwAccepted { @@ -413,14 +423,18 @@ impl AppViewTrait for StateLogin { }) => { let Some(user) = state.users.users.row_data(user_index as usize) else { error!("Failed to find a user with index {user_index}."); - return; + return None; }; let username_c = CString::new(&*user.username) .expect("Username cannot be converted to a C string."); let password_c = CString::new(&*password).expect("Password cannot be converted to a C string."); - let user_key = - spectre_derive_user_key(&username_c, &password_c, Some(user.encrypted_key)); + let Ok(user_key) = + spectre_derive_user_key(&username_c, &password_c, Some(user.encrypted_key)) + else { + error!("Password empty."); + return None; + }; // { // let mut write = db.write_transaction().await; @@ -459,14 +473,10 @@ impl AppViewTrait for StateLogin { // } if user.key_id != user_key.keyID.bytes { - State::process_callback_message( - state_rc, - CallbackMessage::Login(CallbackMessageLogin::LoginResult { - username: user.username, - result: LoginResult::Failure, - }), - ); - return; + return Some(CallbackMessage::Login(CallbackMessageLogin::LoginResult { + username: user.username, + result: LoginResult::Failure, + })); } slint::spawn_local({ @@ -549,6 +559,8 @@ impl AppViewTrait for StateLogin { } _ => (), } + + None } } @@ -559,7 +571,7 @@ impl AppViewTrait for StateUsers { fn process_callback_message( state_rc: &Rc, PsramAllocator>, message: CallbackMessage, - ) { + ) -> Option { let mut state = state_rc.borrow_mut(); match message { CallbackMessage::Escape => { @@ -577,6 +589,8 @@ impl AppViewTrait for StateUsers { } _ => (), } + + None } } @@ -592,7 +606,7 @@ impl AppViewTrait for StateUserEdit { fn process_callback_message( state_rc: &Rc, PsramAllocator>, message: CallbackMessage, - ) { + ) -> Option { let state = state_rc.clone(); let mut state = state.borrow_mut(); match message { @@ -630,7 +644,7 @@ impl AppViewTrait for StateUserEdit { }) => { let Some(password) = state.state_user_edit.password.as_ref() else { warn!("Attempted to compute a key ID when no password has been entered."); - return; + return None; }; let mut key: Key = [0; _]; @@ -654,14 +668,18 @@ impl AppViewTrait for StateUserEdit { } }; state.window.set_user_edit_key_error(message); - return; + return None; } let username_c = CString::new(&*state.state_user_edit.username) .expect("Username cannot be converted to a C string."); let password_c = CString::new(&**password).expect("Password cannot be converted to a C string."); - let user_key = spectre_derive_user_key(&username_c, &password_c, Some(key)); + let Ok(user_key) = spectre_derive_user_key(&username_c, &password_c, Some(key)) + else { + error!("Password empty."); + return None; + }; state.window.set_user_edit_key_error(SharedString::new()); state.window.set_user_edit_key_id( @@ -683,7 +701,7 @@ impl AppViewTrait for StateUserEdit { )) = state.state_user_edit.encrypted_key.take() else { warn!("Encrypted key is not set."); - return; + return None; }; // If a user with that username already exists, overwrite it. @@ -730,6 +748,8 @@ impl AppViewTrait for StateUserEdit { } _ => (), } + + None } } @@ -745,7 +765,7 @@ impl AppViewTrait for StateUserSites { fn process_callback_message( state_rc: &Rc, PsramAllocator>, message: CallbackMessage, - ) { + ) -> Option { let state = state_rc.clone(); let mut state = state.borrow_mut(); match message { @@ -763,12 +783,12 @@ impl AppViewTrait for StateUserSites { }) => { let Some(user_sites) = state.state_user_sites.as_mut() else { error!("User sites uninitialized."); - return; + return None; }; let Some(site_list_entry) = user_sites.site_list.row_data(site_list_index as usize) else { error!("Invalid site list entry index: {site_list_index}"); - return; + return None; }; warn!("Site name accepted: {site_list_entry:?}"); let site_name = match site_list_entry { @@ -809,6 +829,8 @@ impl AppViewTrait for StateUserSites { } _ => (), } + + None } }