Skip to content

Commit 8fc3c3c

Browse files
benma's agentbenma
authored andcommitted
keystore: port _verify_seed to Rust
1 parent 42c2ac9 commit 8fc3c3c

File tree

4 files changed

+35
-38
lines changed

4 files changed

+35
-38
lines changed

src/keystore.c

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -194,39 +194,6 @@ static keystore_error_t _get_and_decrypt_seed(
194194
return KEYSTORE_OK;
195195
}
196196

197-
static bool _verify_seed(
198-
const uint8_t* encryption_key,
199-
const uint8_t* expected_seed,
200-
size_t expected_seed_len)
201-
{
202-
uint8_t encrypted_seed_and_hmac[96];
203-
UTIL_CLEANUP_32(encrypted_seed_and_hmac);
204-
uint8_t encrypted_len;
205-
if (!memory_get_encrypted_seed_and_hmac(encrypted_seed_and_hmac, &encrypted_len)) {
206-
return false;
207-
}
208-
if (encrypted_len < 49) {
209-
Abort("_verify_seed: underflow / zero size");
210-
}
211-
size_t decrypted_len = encrypted_len - 48;
212-
uint8_t decrypted[decrypted_len];
213-
bool password_correct = cipher_aes_hmac_decrypt(
214-
encrypted_seed_and_hmac, encrypted_len, decrypted, &decrypted_len, encryption_key);
215-
if (!password_correct) {
216-
return false;
217-
}
218-
if (expected_seed_len != decrypted_len) {
219-
util_zero(decrypted, sizeof(decrypted));
220-
return false;
221-
}
222-
if (!MEMEQ(expected_seed, decrypted, expected_seed_len)) {
223-
util_zero(decrypted, sizeof(decrypted));
224-
return false;
225-
}
226-
util_zero(decrypted, sizeof(decrypted));
227-
return true;
228-
}
229-
230197
static keystore_error_t _hash_seed(const uint8_t* seed, size_t seed_len, uint8_t* out)
231198
{
232199
uint8_t salted_key[32] = {0};
@@ -365,7 +332,9 @@ keystore_error_t keystore_encrypt_and_store_seed(
365332
if (!memory_set_encrypted_seed_and_hmac(encrypted_seed, encrypted_seed_len_u8)) {
366333
return KEYSTORE_ERR_MEMORY;
367334
}
368-
if (!_verify_seed(secret, seed, seed_length)) {
335+
if (!rust_keystore_verify_seed(
336+
rust_util_bytes(secret, sizeof(secret)),
337+
rust_util_bytes(seed, seed_length))) {
369338
if (!memory_reset_hww()) {
370339
return KEYSTORE_ERR_MEMORY;
371340
}

src/rust/bitbox02-rust/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ erc20_params = { path = "../erc20_params", optional = true }
3333
binascii = { version = "0.1.4", default-features = false, features = ["encode"] }
3434
bitbox02-noise = {path = "../bitbox02-noise"}
3535
streaming-silent-payments = { path = "../streaming-silent-payments", optional = true }
36+
bitbox-aes = { path = "../bitbox-aes" }
3637
hex = { workspace = true }
3738
sha2 = { workspace = true }
3839
sha3 = { workspace = true, optional = true }
@@ -65,9 +66,6 @@ version = "0.13.1"
6566
default-features = false
6667
features = ["derive"]
6768

68-
[dev-dependencies]
69-
bitbox-aes = { path = "../bitbox-aes" }
70-
7169
[features]
7270
ed25519 = [
7371
"dep:bip32-ed25519",

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,29 @@ pub fn is_locked() -> bool {
4646
keystore::_is_locked()
4747
}
4848

49+
fn verify_seed(encryption_key: &[u8], expected_seed: &[u8]) -> bool {
50+
if encryption_key.len() != 32 {
51+
return false;
52+
}
53+
54+
let cipher = match bitbox02::memory::get_encrypted_seed_and_hmac() {
55+
Ok(cipher) => cipher,
56+
Err(_) => return false,
57+
};
58+
let decrypted = match bitbox_aes::decrypt_with_hmac(encryption_key, &cipher) {
59+
Ok(decrypted) => decrypted,
60+
Err(_) => return false,
61+
};
62+
if decrypted.len() != expected_seed.len() {
63+
return false;
64+
}
65+
let mut diff = 0u8;
66+
for (expected, actual) in expected_seed.iter().zip(decrypted.as_slice()) {
67+
diff |= expected ^ actual;
68+
}
69+
diff == 0
70+
}
71+
4972
pub fn unlock(password: &str) -> Result<zeroize::Zeroizing<Vec<u8>>, Error> {
5073
keystore::_unlock(password)
5174
}
@@ -291,6 +314,14 @@ pub unsafe extern "C" fn rust_keystore_stretch_retained_seed_encryption_key(
291314
}
292315
}
293316

317+
#[unsafe(no_mangle)]
318+
pub extern "C" fn rust_keystore_verify_seed(
319+
encryption_key: util::bytes::Bytes,
320+
expected_seed: util::bytes::Bytes,
321+
) -> bool {
322+
verify_seed(encryption_key.as_ref(), expected_seed.as_ref())
323+
}
324+
294325
fn bip85_entropy(keypath: &[u32]) -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
295326
let priv_key = secp256k1_get_private_key_twice(keypath)?;
296327

src/rust/bitbox02/src/memory.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ pub fn get_attestation_pubkey_and_certificate(
9898
}
9999
}
100100

101-
#[cfg(feature = "testing")]
102101
pub fn get_encrypted_seed_and_hmac() -> Result<alloc::vec::Vec<u8>, ()> {
103102
let mut out = vec![0u8; 96];
104103
let mut len = 0u8;

0 commit comments

Comments
 (0)