Skip to content

Commit f538988

Browse files
committed
HAL: add stretch_password to SecureChip HAL
1 parent 3ba8248 commit f538988

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

src/rust/bitbox02-rust/src/hal.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ pub trait Random {
4040

4141
pub trait SecureChip {
4242
fn init_new_password(&mut self, password: &str) -> Result<(), bitbox02::securechip::Error>;
43+
fn stretch_password(
44+
&mut self,
45+
password: &str,
46+
) -> Result<zeroize::Zeroizing<Vec<u8>>, bitbox02::securechip::Error>;
4347
}
4448

4549
/// Hardware abstraction layer for BitBox devices.
@@ -108,6 +112,13 @@ impl SecureChip for BitBox02SecureChip {
108112
fn init_new_password(&mut self, password: &str) -> Result<(), bitbox02::securechip::Error> {
109113
bitbox02::securechip::init_new_password(password)
110114
}
115+
116+
fn stretch_password(
117+
&mut self,
118+
password: &str,
119+
) -> Result<zeroize::Zeroizing<Vec<u8>>, bitbox02::securechip::Error> {
120+
bitbox02::securechip::stretch_password(password)
121+
}
111122
}
112123

113124
pub struct BitBox02Hal {
@@ -275,6 +286,21 @@ pub mod testing {
275286
self.event_counter += 1;
276287
Ok(())
277288
}
289+
290+
fn stretch_password(
291+
&mut self,
292+
password: &str,
293+
) -> Result<zeroize::Zeroizing<Vec<u8>>, bitbox02::securechip::Error> {
294+
self.event_counter += 5;
295+
296+
use bitcoin::hashes::{HashEngine, Hmac, HmacEngine, sha256};
297+
let mut engine = HmacEngine::<sha256::Hash>::new(b"unit-test");
298+
engine.input(password.as_bytes());
299+
let hmac_result: Hmac<sha256::Hash> = Hmac::from_engine(engine);
300+
Ok(zeroize::Zeroizing::new(
301+
hmac_result.to_byte_array().to_vec(),
302+
))
303+
}
278304
}
279305

280306
pub struct TestingHal<'a> {

src/rust/bitbox02-rust/src/keystore.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ pub fn encrypt_and_store_seed(
213213

214214
hal.securechip().init_new_password(password)?;
215215

216-
let secret = securechip::stretch_password(password)?;
216+
let secret = hal.securechip().stretch_password(password)?;
217+
217218
let iv_rand = hal.random().random_32_bytes();
218219
let iv: &[u8; 16] = iv_rand.first_chunk::<16>().unwrap();
219220
let encrypted = bitbox_aes::encrypt_with_hmac(iv, &secret, seed);
@@ -243,13 +244,16 @@ fn check_retained_seed(seed: &[u8]) -> Result<(), ()> {
243244
Ok(())
244245
}
245246

246-
fn get_and_decrypt_seed(password: &str) -> Result<zeroize::Zeroizing<Vec<u8>>, Error> {
247+
fn get_and_decrypt_seed(
248+
hal: &mut impl crate::hal::Hal,
249+
password: &str,
250+
) -> Result<zeroize::Zeroizing<Vec<u8>>, Error> {
247251
let encrypted = bitbox02::memory::get_encrypted_seed_and_hmac().map_err(|_| Error::Memory)?;
248252
// Our Optiga securechip implementation fails password stretching if the password is
249253
// wrong, so it already returns an error here. The ATECC stretches the password without checking
250254
// if the password is correct, and we determine if it is correct in the seed decryption
251255
// step below.
252-
let secret = securechip::stretch_password(password)?;
256+
let secret = hal.securechip().stretch_password(password)?;
253257
let seed = match bitbox_aes::decrypt_with_hmac(&secret, &encrypted) {
254258
Ok(seed) => seed,
255259
Err(()) => return Err(Error::IncorrectPassword),
@@ -279,7 +283,7 @@ pub fn unlock(
279283
}
280284
bitbox02::usb_processing::timeout_reset(LONG_TIMEOUT);
281285
bitbox02::memory::smarteeprom_increment_unlock_attempts();
282-
let seed = match get_and_decrypt_seed(password) {
286+
let seed = match get_and_decrypt_seed(hal, password) {
283287
Ok(seed) => seed,
284288
err @ Err(_) => {
285289
if get_remaining_unlock_attempts() == 0 {

0 commit comments

Comments
 (0)