Skip to content

Commit 56533c7

Browse files
committed
rust: remove SafeInputString
This was a custom C string wrapper with auto-zeroing, but it is much easier to simply use zeroize and CStr (which were both introduced to the codebase after SafeInputString). This also allows us to call bip39 unlock more easily with a Rust string in the future (see testing.rs for example).
1 parent d1ebf2c commit 56533c7

File tree

11 files changed

+45
-169
lines changed

11 files changed

+45
-169
lines changed

src/rust/bitbox02-rust/src/workflow/mnemonic.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,7 @@ async fn get_12th_18th_word(
272272
trinary_input_string::CanCancel::Yes,
273273
"",
274274
)
275-
.await
276-
.map(|s| s.as_string())?;
275+
.await?;
277276

278277
// Confirm word picked again, as a typo here would be extremely annoying. Double checking
279278
// is also safer, as the user might not even realize they made a typo.
@@ -344,7 +343,7 @@ pub async fn get() -> Result<zeroize::Zeroizing<String>, CancelError> {
344343
preset,
345344
)
346345
.await
347-
.map(|s| s.as_string())
346+
.into()
348347
};
349348

350349
match user_entry {

src/rust/bitbox02-rust/src/workflow/password.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
// limitations under the License.
1414

1515
use super::{confirm, status, trinary_input_string};
16-
use bitbox02::input::SafeInputString;
1716

1817
pub use trinary_input_string::{CanCancel, Error};
1918

19+
use alloc::string::String;
20+
2021
async fn prompt_cancel() -> Result<(), confirm::UserAbort> {
2122
confirm::confirm(&confirm::Params {
2223
body: "Do you really\nwant to cancel?",
@@ -37,7 +38,7 @@ pub async fn enter(
3738
title: &str,
3839
special_chars: bool,
3940
can_cancel: CanCancel,
40-
) -> Result<SafeInputString, Error> {
41+
) -> Result<zeroize::Zeroizing<String>, Error> {
4142
let params = trinary_input_string::Params {
4243
title,
4344
hide: true,
@@ -78,7 +79,7 @@ impl core::convert::From<Error> for EnterTwiceError {
7879
/// ```no_run
7980
/// let pw = enter_twice().await.unwrap();
8081
/// // use pw.
81-
pub async fn enter_twice() -> Result<SafeInputString, EnterTwiceError> {
82+
pub async fn enter_twice() -> Result<zeroize::Zeroizing<String>, EnterTwiceError> {
8283
let password = enter("Set password", false, CanCancel::Yes).await?;
8384
let password_repeat = enter("Repeat password", false, CanCancel::Yes).await?;
8485
if password.as_str() != password_repeat.as_str() {

src/rust/bitbox02-rust/src/workflow/trinary_input_string.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ pub use super::cancel::{cancel, set_result, Error};
1616
pub use bitbox02::ui::TrinaryInputStringParams as Params;
1717

1818
use crate::bb02_async::option;
19-
use bitbox02::input::SafeInputString;
2019
use core::cell::RefCell;
2120

2221
use alloc::boxed::Box;
22+
use alloc::string::String;
2323

2424
#[derive(Copy, Clone)]
2525
pub enum CanCancel {
@@ -35,7 +35,7 @@ pub async fn enter(
3535
params: &Params<'_>,
3636
can_cancel: CanCancel,
3737
preset: &str,
38-
) -> Result<SafeInputString, Error> {
38+
) -> Result<zeroize::Zeroizing<String>, Error> {
3939
let result = RefCell::new(None);
4040
let mut component = bitbox02::ui::trinary_input_string_create(
4141
params,

src/rust/bitbox02-rust/src/workflow/unlock.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use crate::general::abort;
1616
use crate::workflow::confirm;
1717
use crate::workflow::password;
1818
use crate::workflow::status::status;
19-
use bitbox02::input::SafeInputString;
2019
use bitbox02::keystore;
2120

2221
pub use password::CanCancel;
@@ -98,7 +97,7 @@ pub async fn unlock_keystore(
9897
/// feature is enabled, the user will be asked for the passphrase.
9998
pub async fn unlock_bip39() {
10099
// Empty passphrase by default.
101-
let mut mnemonic_passphrase = SafeInputString::new();
100+
let mut mnemonic_passphrase = zeroize::Zeroizing::new("".into());
102101

103102
// If setting activated, get the passphrase from the user.
104103
if bitbox02::memory::is_mnemonic_passphrase_enabled() {

src/rust/bitbox02/src/input.rs

Lines changed: 0 additions & 125 deletions
This file was deleted.

src/rust/bitbox02/src/keystore.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use alloc::vec::Vec;
1919

2020
use core::convert::TryInto;
2121

22-
use crate::input::SafeInputString;
2322
use bitbox02_sys::keystore_error_t;
2423

2524
pub const BIP39_WORDLIST_LEN: u16 = bitbox02_sys::BIP39_WORDLIST_LEN as u16;
@@ -62,12 +61,12 @@ impl core::convert::From<keystore_error_t> for Error {
6261
}
6362
}
6463

65-
pub fn unlock(password: &SafeInputString) -> Result<(), Error> {
64+
pub fn unlock(password: &str) -> Result<(), Error> {
6665
let mut remaining_attempts: u8 = 0;
6766
let mut securechip_result: i32 = 0;
6867
match unsafe {
6968
bitbox02_sys::keystore_unlock(
70-
password.as_cstr(),
69+
crate::util::str_to_cstr_vec(password).unwrap().as_ptr(),
7170
&mut remaining_attempts,
7271
&mut securechip_result,
7372
)
@@ -85,18 +84,24 @@ pub fn lock() {
8584
unsafe { bitbox02_sys::keystore_lock() }
8685
}
8786

88-
pub fn unlock_bip39(mnemonic_passphrase: &SafeInputString) -> Result<(), Error> {
89-
if unsafe { bitbox02_sys::keystore_unlock_bip39(mnemonic_passphrase.as_cstr()) } {
87+
pub fn unlock_bip39(mnemonic_passphrase: &str) -> Result<(), Error> {
88+
if unsafe {
89+
bitbox02_sys::keystore_unlock_bip39(
90+
crate::util::str_to_cstr_vec(mnemonic_passphrase)
91+
.unwrap()
92+
.as_ptr(),
93+
)
94+
} {
9095
Ok(())
9196
} else {
9297
Err(Error::CannotUnlockBIP39)
9398
}
9499
}
95100

96-
pub fn create_and_store_seed(password: &SafeInputString, host_entropy: &[u8]) -> Result<(), Error> {
101+
pub fn create_and_store_seed(password: &str, host_entropy: &[u8]) -> Result<(), Error> {
97102
match unsafe {
98103
bitbox02_sys::keystore_create_and_store_seed(
99-
password.as_cstr(),
104+
crate::util::str_to_cstr_vec(password).unwrap().as_ptr(),
100105
host_entropy.as_ptr(),
101106
host_entropy.len() as _,
102107
)
@@ -304,9 +309,13 @@ pub fn bip39_mnemonic_to_seed(mnemonic: &str) -> Result<zeroize::Zeroizing<Vec<u
304309
}
305310
}
306311

307-
pub fn encrypt_and_store_seed(seed: &[u8], password: &SafeInputString) -> Result<(), Error> {
312+
pub fn encrypt_and_store_seed(seed: &[u8], password: &str) -> Result<(), Error> {
308313
match unsafe {
309-
bitbox02_sys::keystore_encrypt_and_store_seed(seed.as_ptr(), seed.len(), password.as_cstr())
314+
bitbox02_sys::keystore_encrypt_and_store_seed(
315+
seed.as_ptr(),
316+
seed.len(),
317+
crate::util::str_to_cstr_vec(password).unwrap().as_ptr(),
318+
)
310319
} {
311320
keystore_error_t::KEYSTORE_OK => Ok(()),
312321
err => Err(err.into()),

src/rust/bitbox02/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use alloc::string::String;
3434
pub mod testing;
3535

3636
pub mod bip32;
37-
pub mod input;
3837
pub mod keystore;
3938
pub mod memory;
4039
pub mod random;

src/rust/bitbox02/src/testing.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,7 @@ pub fn mock_unlocked_using_mnemonic(mnemonic: &str, passphrase: &str) {
5656
unsafe {
5757
bitbox02_sys::keystore_mock_unlocked(seed.as_ptr(), seed.len() as _, core::ptr::null())
5858
}
59-
keystore::unlock_bip39(&crate::input::SafeInputString::from_buf(
60-
passphrase.as_bytes(),
61-
))
62-
.unwrap();
59+
keystore::unlock_bip39(passphrase).unwrap();
6360
}
6461

6562
pub const TEST_MNEMONIC: &str = "purity concert above invest pigeon category peace tuition hazard vivid latin since legal speak nation session onion library travel spell region blast estate stay";

src/rust/bitbox02/src/ui/ui.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub use super::types::{
2121
use util::c_types::{c_char, c_void};
2222

2323
extern crate alloc;
24-
use crate::input::SafeInputString;
2524
use alloc::boxed::Box;
25+
use alloc::string::String;
2626
use alloc::vec::Vec;
2727

2828
use core::marker::PhantomData;
@@ -71,21 +71,21 @@ pub fn trinary_input_string_create<'a, F>(
7171
) -> Component<'a>
7272
where
7373
// Callback must outlive component.
74-
F: FnMut(SafeInputString) + 'a,
74+
F: FnMut(zeroize::Zeroizing<String>) + 'a,
7575
{
7676
unsafe extern "C" fn c_confirm_callback<F2>(password: *const c_char, param: *mut c_void)
7777
where
78-
F2: FnMut(SafeInputString),
78+
F2: FnMut(zeroize::Zeroizing<String>),
7979
{
80-
let mut password_out = SafeInputString::new();
81-
let cap = password_out.cap();
82-
password_out
83-
.as_mut()
84-
.copy_from_slice(core::slice::from_raw_parts(password, cap));
80+
let pw: zeroize::Zeroizing<String> = zeroize::Zeroizing::new(
81+
crate::util::str_from_null_terminated_ptr(password)
82+
.unwrap()
83+
.into(),
84+
);
8585
// The callback is dropped afterwards. This is safe because
8686
// this C callback is guaranteed to be called only once.
8787
let mut callback = Box::from_raw(param as *mut F2);
88-
callback(password_out);
88+
callback(pw);
8989
}
9090

9191
unsafe extern "C" fn c_cancel_callback(param: *mut c_void) {

src/rust/bitbox02/src/ui/ui_stub.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ pub use super::types::{
1919
TrinaryChoiceCb, TrinaryInputStringParams,
2020
};
2121

22-
use crate::input::SafeInputString;
23-
2422
use core::marker::PhantomData;
2523

2624
extern crate alloc;
2725

26+
use alloc::string::String;
27+
2828
pub struct Component<'a> {
2929
is_pushed: bool,
3030
_p: PhantomData<&'a ()>,
@@ -53,14 +53,11 @@ pub fn trinary_input_string_create<'a, F>(
5353
_cancel_callback: Option<ContinueCancelCb<'a>>,
5454
) -> Component<'a>
5555
where
56-
F: FnMut(SafeInputString) + 'a,
56+
F: FnMut(zeroize::Zeroizing<String>) + 'a,
5757
{
5858
let data = crate::testing::DATA.0.borrow();
5959
let input_string = data.ui_trinary_input_string_create.as_ref().unwrap()(params);
60-
let input_buf = input_string.as_bytes();
61-
let mut input = SafeInputString::new();
62-
input.as_mut()[..input_buf.len()].copy_from_slice(input_buf);
63-
confirm_callback(input);
60+
confirm_callback(zeroize::Zeroizing::new(input_string));
6461
Component {
6562
is_pushed: false,
6663
_p: PhantomData,

0 commit comments

Comments
 (0)