Skip to content

Commit 2b6097e

Browse files
committed
keystore: port create_and_store_seed to Rust
1 parent b153b88 commit 2b6097e

File tree

5 files changed

+23
-68
lines changed

5 files changed

+23
-68
lines changed

src/keystore.c

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -381,43 +381,6 @@ keystore_error_t keystore_encrypt_and_store_seed(
381381
return KEYSTORE_OK;
382382
}
383383

384-
keystore_error_t keystore_create_and_store_seed(
385-
const char* password,
386-
const uint8_t* host_entropy,
387-
size_t host_entropy_size)
388-
{
389-
if (host_entropy_size != 16 && host_entropy_size != 32) {
390-
return KEYSTORE_ERR_SEED_SIZE;
391-
}
392-
if (KEYSTORE_MAX_SEED_LENGTH != RANDOM_NUM_SIZE) {
393-
Abort("keystore create: size mismatch");
394-
}
395-
uint8_t seed[KEYSTORE_MAX_SEED_LENGTH];
396-
UTIL_CLEANUP_32(seed);
397-
random_32_bytes(seed);
398-
399-
// Mix in Host entropy.
400-
for (size_t i = 0; i < host_entropy_size; i++) {
401-
seed[i] ^= host_entropy[i];
402-
}
403-
404-
// Mix in entropy derived from the user password.
405-
uint8_t password_salted_hashed[KEYSTORE_MAX_SEED_LENGTH] = {0};
406-
UTIL_CLEANUP_32(password_salted_hashed);
407-
if (!salt_hash_data(
408-
(const uint8_t*)password,
409-
strlen(password),
410-
"keystore_seed_generation",
411-
password_salted_hashed)) {
412-
return KEYSTORE_ERR_SALT;
413-
}
414-
415-
for (size_t i = 0; i < host_entropy_size; i++) {
416-
seed[i] ^= password_salted_hashed[i];
417-
}
418-
return keystore_encrypt_and_store_seed(seed, host_entropy_size, password);
419-
}
420-
421384
// Checks if the retained seed matches the passed seed.
422385
static bool _check_retained_seed(const uint8_t* seed, size_t seed_length)
423386
{

src/keystore.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,6 @@ USE_RESULT bool keystore_copy_bip39_seed(uint8_t* bip32_seed_out);
7272
USE_RESULT keystore_error_t
7373
keystore_encrypt_and_store_seed(const uint8_t* seed, size_t seed_length, const char* password);
7474

75-
/**
76-
Generates the seed, mixes it with host_entropy, and stores it encrypted with the
77-
password. The size of the host entropy determines the size of the seed. Can be either 16 or 32
78-
bytes, resulting in 12 or 24 BIP39 recovery words.
79-
This also unlocks the keystore with the new seed.
80-
@param[in] host_entropy bytes of entropy to be mixed in.
81-
@param[in] host_entropy_size must be 16 or 32.
82-
*/
83-
USE_RESULT keystore_error_t keystore_create_and_store_seed(
84-
const char* password,
85-
const uint8_t* host_entropy,
86-
size_t host_entropy_size);
87-
8875
/** Unlocks the keystore seed or checks the password:
8976
* If the keystore is locked, it decrypts and loads the seed, unlocking the keystore:
9077
* 1) loads the stored seed and tries to decrypt using password.

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,29 @@ pub fn encrypt_and_store_seed(seed: &[u8], password: &str) -> Result<(), Error>
9999
/// bytes, resulting in 12 or 24 BIP39 recovery words.
100100
/// This also unlocks the keystore with the new seed.
101101
pub fn create_and_store_seed(password: &str, host_entropy: &[u8]) -> Result<(), Error> {
102-
keystore::_create_and_store_seed(password, host_entropy)
102+
let seed_len = host_entropy.len();
103+
if !matches!(seed_len, 16 | 32) {
104+
return Err(Error::SeedSize);
105+
}
106+
107+
let mut seed_vec = bitbox02::random::random_32_bytes();
108+
let seed = &mut seed_vec[..seed_len];
109+
110+
// Mix in host entropy.
111+
for (i, &entropy_byte) in host_entropy.iter().enumerate() {
112+
seed[i] ^= entropy_byte;
113+
}
114+
115+
// Mix in entropy derived from the user password.
116+
let password_salted_hashed =
117+
crate::salt::hash_data(password.as_bytes(), "keystore_seed_generation")
118+
.map_err(|_| Error::Salt)?;
119+
120+
for (i, &hash_byte) in password_salted_hashed.iter().take(seed_len).enumerate() {
121+
seed[i] ^= hash_byte;
122+
}
123+
124+
encrypt_and_store_seed(seed, password)
103125
}
104126

105127
/// Returns the keystore's seed encoded as a BIP-39 mnemonic.

src/rust/bitbox02-sys/build.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ const ALLOWLIST_FNS: &[&str] = &[
7272
"keystore_bip39_mnemonic_to_seed",
7373
"keystore_copy_seed",
7474
"keystore_copy_bip39_seed",
75-
"keystore_create_and_store_seed",
7675
"keystore_encrypt_and_store_seed",
7776
"keystore_get_bip39_word",
7877
"keystore_is_locked",

src/rust/bitbox02/src/keystore.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,22 +129,6 @@ pub fn test_get_retained_bip39_seed_encrypted() -> &'static [u8] {
129129
}
130130
}
131131

132-
pub fn _create_and_store_seed(password: &str, host_entropy: &[u8]) -> Result<(), Error> {
133-
match unsafe {
134-
bitbox02_sys::keystore_create_and_store_seed(
135-
crate::util::str_to_cstr_vec(password)
136-
.unwrap()
137-
.as_ptr()
138-
.cast(),
139-
host_entropy.as_ptr(),
140-
host_entropy.len() as _,
141-
)
142-
} {
143-
keystore_error_t::KEYSTORE_OK => Ok(()),
144-
err => Err(err.into()),
145-
}
146-
}
147-
148132
pub fn _copy_seed() -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
149133
let mut seed = zeroize::Zeroizing::new([0u8; MAX_SEED_LENGTH].to_vec());
150134
let mut seed_len: usize = 0;

0 commit comments

Comments
 (0)