Skip to content

Commit c8c4607

Browse files
committed
keystore: expose copy_bip39_seed to Rust
Will be needed to implement bip32 functionality, whose derivations begins with the bip39 seed.
1 parent b502903 commit c8c4607

File tree

4 files changed

+30
-13
lines changed

4 files changed

+30
-13
lines changed

src/keystore.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static bool _is_unlocked_bip39 = false;
4545
// Stores a random keyy after bip39-unlock which, after stretching, is used to encrypt the retained
4646
// bip39 seed.
4747
static uint8_t _unstretched_retained_bip39_seed_encryption_key[32] = {0};
48-
// Must be defined if _is_unlocked is true. ONLY ACCESS THIS WITH _copy_bip39_seed().
48+
// Must be defined if _is_unlocked is true. ONLY ACCESS THIS WITH keystore_copy_bip39_seed().
4949
// Stores the encrypted BIP-39 seed after bip39-unlock.
5050
static uint8_t _retained_bip39_seed_encrypted[64 + 64] = {0};
5151
static size_t _retained_bip39_seed_encrypted_len = 0;
@@ -115,14 +115,7 @@ bool keystore_copy_seed(uint8_t* seed_out, size_t* length_out)
115115
return true;
116116
}
117117

118-
/**
119-
* Copies the retained bip39 seed into the given buffer. The caller must
120-
* zero the seed with util_zero once it is no longer needed.
121-
* @param[out] bip39_seed_out The seed bytes copied from the retained bip39 seed.
122-
* The buffer must be 64 bytes long.
123-
* @return true if the bip39 seed is available.
124-
*/
125-
static bool _copy_bip39_seed(uint8_t* bip39_seed_out)
118+
bool keystore_copy_bip39_seed(uint8_t* bip39_seed_out)
126119
{
127120
if (!_is_unlocked_bip39) {
128121
return false;
@@ -537,7 +530,7 @@ static bool _get_xprv(const uint32_t* keypath, const size_t keypath_len, struct
537530

538531
uint8_t bip39_seed[64] = {0};
539532
UTIL_CLEANUP_64(bip39_seed);
540-
if (!_copy_bip39_seed(bip39_seed)) {
533+
if (!keystore_copy_bip39_seed(bip39_seed)) {
541534
return false;
542535
}
543536
struct ext_key xprv_master __attribute__((__cleanup__(keystore_zero_xkey))) = {0};
@@ -698,7 +691,7 @@ bool keystore_get_u2f_seed(uint8_t* seed_out)
698691
}
699692
uint8_t bip39_seed[64] = {0};
700693
UTIL_CLEANUP_64(bip39_seed);
701-
if (!_copy_bip39_seed(bip39_seed)) {
694+
if (!keystore_copy_bip39_seed(bip39_seed)) {
702695
return false;
703696
}
704697
const uint8_t message[] = "u2f";
@@ -713,7 +706,7 @@ bool keystore_get_ed25519_seed(uint8_t* seed_out)
713706
{
714707
uint8_t bip39_seed[64] = {0};
715708
UTIL_CLEANUP_64(bip39_seed);
716-
if (!_copy_bip39_seed(bip39_seed)) {
709+
if (!keystore_copy_bip39_seed(bip39_seed)) {
717710
return false;
718711
}
719712

src/keystore.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ typedef enum {
5656
*/
5757
USE_RESULT bool keystore_copy_seed(uint8_t* seed_out, size_t* length_out);
5858

59+
/**
60+
* Copies the retained bip39 seed into the given buffer. The caller must
61+
* zero the seed once it is no longer needed.
62+
* @param[out] bip39_seed_out The seed bytes copied from the retained bip39 seed.
63+
* The buffer must be 64 bytes long.
64+
* @return true if the bip39 seed is available.
65+
*/
66+
USE_RESULT bool keystore_copy_bip39_seed(uint8_t* bip32_seed_out);
67+
5968
/**
6069
* Restores a seed.
6170
* @param[in] seed The seed that is to be restored.

src/rust/bitbox02-sys/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const ALLOWLIST_FNS: &[&str] = &[
6969
"empty_create",
7070
"keystore_bip39_mnemonic_to_seed",
7171
"keystore_copy_seed",
72+
"keystore_copy_bip39_seed",
7273
"keystore_create_and_store_seed",
7374
"keystore_encode_xpub_at_keypath",
7475
"keystore_encrypt_and_store_seed",

src/rust/bitbox02/src/keystore.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ pub fn copy_seed() -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
122122
}
123123
}
124124

125+
pub fn copy_bip39_seed() -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
126+
let mut bip39_seed = zeroize::Zeroizing::new(vec![0u8; 64]);
127+
match unsafe { bitbox02_sys::keystore_copy_bip39_seed(bip39_seed.as_mut_ptr()) } {
128+
true => Ok(bip39_seed),
129+
false => Err(()),
130+
}
131+
}
132+
125133
pub fn bip39_mnemonic_from_seed(seed: &[u8]) -> Result<zeroize::Zeroizing<String>, ()> {
126134
let mut mnemonic = zeroize::Zeroizing::new([0u8; 256]);
127135
match unsafe {
@@ -703,6 +711,13 @@ mod tests {
703711
assert!(unlock("password").is_ok());
704712
assert!(unlock_bip39("foo").is_ok());
705713

714+
let expected_bip39_seed = hex::decode("2b3c63de86f0f2b13cc6a36c1ba2314fbc1b40c77ab9cb64e96ba4d5c62fc204748ca6626a9f035e7d431bce8c9210ec0bdffc2e7db873dee56c8ac2153eee9a").unwrap();
715+
716+
assert_eq!(
717+
copy_bip39_seed().unwrap().as_slice(),
718+
expected_bip39_seed.as_slice()
719+
);
720+
706721
// Check that the retained bip39 seed was encrypted with the expected encryption key.
707722
let decrypted = {
708723
let retained_bip39_seed_encrypted: &[u8] = unsafe {
@@ -719,7 +734,6 @@ mod tests {
719734
)
720735
.unwrap()
721736
};
722-
let expected_bip39_seed = hex::decode("2b3c63de86f0f2b13cc6a36c1ba2314fbc1b40c77ab9cb64e96ba4d5c62fc204748ca6626a9f035e7d431bce8c9210ec0bdffc2e7db873dee56c8ac2153eee9a").unwrap();
723737
assert_eq!(decrypted.as_slice(), expected_bip39_seed.as_slice());
724738
}
725739

0 commit comments

Comments
 (0)