Skip to content

Commit 2ef52c6

Browse files
committed
wip
1 parent df216ec commit 2ef52c6

File tree

10 files changed

+113
-18
lines changed

10 files changed

+113
-18
lines changed

src/rust/bitbox02-rust/src/hww/api/restore.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub async fn from_file(
6666
}
6767

6868
let password = password::enter_twice(hal).await?;
69-
if let Err(err) = bitbox02::keystore::encrypt_and_store_seed(data.get_seed(), &password) {
69+
if let Err(err) = crate::keystore::encrypt_and_store_seed(data.get_seed(), &password) {
7070
hal.ui()
7171
.status(&format!("Could not\nrestore backup\n{:?}", err), false)
7272
.await;
@@ -145,7 +145,7 @@ pub async fn from_mnemonic(
145145
}
146146
};
147147

148-
if let Err(err) = bitbox02::keystore::encrypt_and_store_seed(&seed, &password) {
148+
if let Err(err) = crate::keystore::encrypt_and_store_seed(&seed, &password) {
149149
hal.ui()
150150
.status(&format!("Could not\nrestore backup\n{:?}", err), false)
151151
.await;

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

+33-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,39 @@ pub mod ed25519;
1818
use alloc::vec::Vec;
1919

2020
use crate::bip32;
21-
use bitbox02::keystore;
21+
use bitbox02::{cipher, keystore, memory, securechip};
22+
23+
#[derive(Debug)]
24+
pub enum Error {
25+
AlreadyInitialized,
26+
Memory,
27+
SeedSize,
28+
SecureChip,
29+
Encrypt,
30+
}
31+
32+
fn validate_seed_length(len: usize) -> Result<(), Error> {
33+
match len {
34+
16 | 24 | 32 => Ok(()),
35+
_ => Err(Error::SeedSize),
36+
}
37+
}
38+
39+
pub fn encrypt_and_store_seed(seed: &[u8], password: &str) -> Result<(), Error> {
40+
if memory::is_initialized() {
41+
return Err(Error::AlreadyInitialized);
42+
}
43+
keystore::lock();
44+
validate_seed_length(seed.len())?;
45+
securechip::init_new_password(password).map_err(|_| Error::SecureChip)?;
46+
let secret: zeroize::Zeroizing<Vec<u8>> =
47+
securechip::stretch_password(password).map_err(|_| Error::SecureChip)?;
48+
let encrypted_seed: Vec<u8> =
49+
cipher::aes_hmac_encrypt(seed, secret.as_slice()).map_err(|_| Error::Encrypt)?;
50+
memory::set_encrypted_seed_and_hmac(&encrypted_seed).map_err(|_| Error::Memory)?;
51+
// TODO: verify seed
52+
Ok(())
53+
}
2254

2355
/// Derives an xpub from the keystore seed at the given keypath.
2456
pub fn get_xpub(keypath: &[u32]) -> Result<bip32::Xpub, ()> {

src/rust/bitbox02-sys/build.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ const ALLOWLIST_FNS: &[&str] = &[
6565
"keystore_copy_seed",
6666
"keystore_create_and_store_seed",
6767
"keystore_encode_xpub_at_keypath",
68-
"keystore_encrypt_and_store_seed",
6968
"keystore_get_bip39_mnemonic",
7069
"keystore_get_bip39_word",
7170
"keystore_get_ed25519_seed",
@@ -99,6 +98,7 @@ const ALLOWLIST_FNS: &[&str] = &[
9998
"memory_set_initialized",
10099
"memory_set_mnemonic_passphrase_enabled",
101100
"memory_set_seed_birthdate",
101+
"memory_set_encrypted_seed_and_hmac",
102102
"memory_setup",
103103
"menu_create",
104104
"mock_memory_factoryreset",
@@ -127,6 +127,8 @@ const ALLOWLIST_FNS: &[&str] = &[
127127
"securechip_model",
128128
"securechip_monotonic_increments_remaining",
129129
"securechip_u2f_counter_set",
130+
"securechip_init_new_password",
131+
"securechip_stretch_password",
130132
"smarteeprom_bb02_config",
131133
"status_create",
132134
"trinary_choice_create",
@@ -139,6 +141,7 @@ const ALLOWLIST_FNS: &[&str] = &[
139141
"wally_free_string",
140142
"wally_get_secp_context",
141143
"wally_sha512",
144+
"cipher_aes_hmac_encrypt",
142145
];
143146

144147
const RUSTIFIED_ENUMS: &[&str] = &[

src/rust/bitbox02-sys/wrapper.h

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <reset.h>
2323
#include <screen.h>
2424
#include <sd.h>
25+
#include <cipher/cipher.h>
2526
#include <secp256k1_ecdsa_adaptor.h>
2627
#include <secp256k1_ecdsa_s2c.h>
2728
#include <securechip/securechip.h>

src/rust/bitbox02/src/cipher.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2020 Shift Crypto AG
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use alloc::vec::Vec;
16+
17+
pub fn aes_hmac_encrypt(input: &[u8], key: &[u8]) -> Result<Vec<u8>, ()> {
18+
let mut output = vec![0u8; input.len() + 64];
19+
let mut output_size: usize = output.len();
20+
match unsafe {
21+
bitbox02_sys::cipher_aes_hmac_encrypt(
22+
input.as_ptr(),
23+
input.len() as _,
24+
output.as_mut_ptr(),
25+
&mut output_size,
26+
key.as_ptr(),
27+
)
28+
} {
29+
true => {
30+
output.truncate(output_size);
31+
Ok(output)
32+
}
33+
false => Err(()),
34+
}
35+
}

src/rust/bitbox02/src/keystore.rs

-13
Original file line numberDiff line numberDiff line change
@@ -293,19 +293,6 @@ pub fn bip39_mnemonic_to_seed(mnemonic: &str) -> Result<zeroize::Zeroizing<Vec<u
293293
}
294294
}
295295

296-
pub fn encrypt_and_store_seed(seed: &[u8], password: &str) -> Result<(), Error> {
297-
match unsafe {
298-
bitbox02_sys::keystore_encrypt_and_store_seed(
299-
seed.as_ptr(),
300-
seed.len(),
301-
crate::util::str_to_cstr_vec(password).unwrap().as_ptr(),
302-
)
303-
} {
304-
keystore_error_t::KEYSTORE_OK => Ok(()),
305-
err => Err(err.into()),
306-
}
307-
}
308-
309296
pub fn get_ed25519_seed() -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
310297
let mut seed = zeroize::Zeroizing::new([0u8; 96].to_vec());
311298
match unsafe { bitbox02_sys::keystore_get_ed25519_seed(seed.as_mut_ptr()) } {

src/rust/bitbox02/src/lib.rs

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

3636
pub mod bip32;
37+
pub mod cipher;
3738
pub mod keystore;
3839
pub mod memory;
3940
pub mod random;

src/rust/bitbox02/src/memory.rs

+12
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,18 @@ pub fn multisig_get_by_hash(hash: &[u8]) -> Option<String> {
160160
}
161161
}
162162

163+
pub fn set_encrypted_seed_and_hmac(encrypted_seed_and_hmac: &[u8]) -> Result<(), ()> {
164+
match unsafe {
165+
bitbox02_sys::memory_set_encrypted_seed_and_hmac(
166+
encrypted_seed_and_hmac.as_ptr(),
167+
encrypted_seed_and_hmac.len().try_into().unwrap(),
168+
)
169+
} {
170+
true => Ok(()),
171+
false => Err(()),
172+
}
173+
}
174+
163175
#[cfg(test)]
164176
mod tests {
165177
use super::*;

src/rust/bitbox02/src/securechip.rs

+24
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
pub use bitbox02_sys::securechip_model_t as Model;
1616

17+
use alloc::vec::Vec;
18+
1719
pub fn attestation_sign(challenge: &[u8; 32], signature: &mut [u8; 64]) -> Result<(), ()> {
1820
match unsafe {
1921
bitbox02_sys::securechip_attestation_sign(challenge.as_ptr(), signature.as_mut_ptr())
@@ -46,6 +48,28 @@ pub fn u2f_counter_set(_counter: u32) -> Result<(), ()> {
4648
Ok(())
4749
}
4850

51+
pub fn init_new_password(password: &str) -> Result<(), ()> {
52+
match unsafe {
53+
bitbox02_sys::securechip_init_new_password(crate::util::str_to_cstr_vec(password)?.as_ptr())
54+
} {
55+
0 => Ok(()),
56+
_ => Err(()),
57+
}
58+
}
59+
60+
pub fn stretch_password(password: &str) -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
61+
let mut out = zeroize::Zeroizing::new(vec![0u8; 32]);
62+
match unsafe {
63+
bitbox02_sys::securechip_stretch_password(
64+
crate::util::str_to_cstr_vec(password)?.as_ptr(),
65+
out.as_mut_ptr(),
66+
)
67+
} {
68+
0 => Ok(out),
69+
_ => Err(()),
70+
}
71+
}
72+
4973
pub fn model() -> Result<Model, ()> {
5074
let mut ver = core::mem::MaybeUninit::uninit();
5175
match unsafe { bitbox02_sys::securechip_model(ver.as_mut_ptr()) } {

src/rust/bitbox02/src/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub fn truncate_str(s: &str, len: usize) -> &str {
4444
}
4545

4646
/// Converts a Rust string to a null terminated C string by appending a null
47-
/// terminator. Returns `Err(())` if the input already contians a null byte.
47+
/// terminator. Returns `Err(())` if the input already contains a null byte.
4848
pub fn str_to_cstr_vec(input: &str) -> Result<Vec<u8>, ()> {
4949
Ok(alloc::ffi::CString::new(input)
5050
.or(Err(()))?

0 commit comments

Comments
 (0)