diff --git a/src/keystore.c b/src/keystore.c index d2b4fa171..66fe60af6 100644 --- a/src/keystore.c +++ b/src/keystore.c @@ -192,39 +192,6 @@ static keystore_error_t _get_and_decrypt_seed( return KEYSTORE_OK; } -static bool _verify_seed( - const uint8_t* encryption_key, - const uint8_t* expected_seed, - size_t expected_seed_len) -{ - uint8_t encrypted_seed_and_hmac[96]; - UTIL_CLEANUP_32(encrypted_seed_and_hmac); - uint8_t encrypted_len; - if (!memory_get_encrypted_seed_and_hmac(encrypted_seed_and_hmac, &encrypted_len)) { - return false; - } - if (encrypted_len < 49) { - Abort("_verify_seed: underflow / zero size"); - } - size_t decrypted_len = encrypted_len - 48; - uint8_t decrypted[decrypted_len]; - bool password_correct = cipher_aes_hmac_decrypt( - encrypted_seed_and_hmac, encrypted_len, decrypted, &decrypted_len, encryption_key); - if (!password_correct) { - return false; - } - if (expected_seed_len != decrypted_len) { - util_zero(decrypted, sizeof(decrypted)); - return false; - } - if (!MEMEQ(expected_seed, decrypted, expected_seed_len)) { - util_zero(decrypted, sizeof(decrypted)); - return false; - } - util_zero(decrypted, sizeof(decrypted)); - return true; -} - static keystore_error_t _hash_seed(const uint8_t* seed, size_t seed_len, uint8_t* out) { uint8_t salted_key[32] = {0}; @@ -362,7 +329,9 @@ keystore_error_t keystore_encrypt_and_store_seed( if (!memory_set_encrypted_seed_and_hmac(encrypted_seed, encrypted_seed_len_u8)) { return KEYSTORE_ERR_MEMORY; } - if (!_verify_seed(secret, seed, seed_length)) { + if (!rust_keystore_verify_seed( + rust_util_bytes(secret, sizeof(secret)), + rust_util_bytes(seed, seed_length))) { if (!memory_reset_hww()) { return KEYSTORE_ERR_MEMORY; } diff --git a/src/rust/bitbox02-rust/Cargo.toml b/src/rust/bitbox02-rust/Cargo.toml index 7e312b71a..9e60548fa 100644 --- a/src/rust/bitbox02-rust/Cargo.toml +++ b/src/rust/bitbox02-rust/Cargo.toml @@ -33,6 +33,7 @@ erc20_params = { path = "../erc20_params", optional = true } binascii = { version = "0.1.4", default-features = false, features = ["encode"] } bitbox02-noise = {path = "../bitbox02-noise"} streaming-silent-payments = { path = "../streaming-silent-payments", optional = true } +bitbox-aes = { path = "../bitbox-aes" } hex = { workspace = true } sha2 = { workspace = true } sha3 = { workspace = true, optional = true } @@ -65,9 +66,6 @@ version = "0.13.1" default-features = false features = ["derive"] -[dev-dependencies] -bitbox-aes = { path = "../bitbox-aes" } - [features] ed25519 = [ "dep:bip32-ed25519", diff --git a/src/rust/bitbox02-rust/src/keystore.rs b/src/rust/bitbox02-rust/src/keystore.rs index 2b68e5589..3dbf55b5e 100644 --- a/src/rust/bitbox02-rust/src/keystore.rs +++ b/src/rust/bitbox02-rust/src/keystore.rs @@ -46,6 +46,23 @@ pub fn is_locked() -> bool { keystore::_is_locked() } +fn verify_seed(encryption_key: &[u8], expected_seed: &[u8]) -> bool { + if encryption_key.len() != 32 { + return false; + } + + let cipher = match bitbox02::memory::get_encrypted_seed_and_hmac() { + Ok(cipher) => cipher, + Err(_) => return false, + }; + let decrypted = match bitbox_aes::decrypt_with_hmac(encryption_key, &cipher) { + Ok(decrypted) => decrypted, + Err(_) => return false, + }; + + decrypted.as_slice() == expected_seed +} + pub fn unlock(password: &str) -> Result>, Error> { keystore::_unlock(password) } @@ -291,6 +308,14 @@ pub unsafe extern "C" fn rust_keystore_stretch_retained_seed_encryption_key( } } +#[unsafe(no_mangle)] +pub extern "C" fn rust_keystore_verify_seed( + encryption_key: util::bytes::Bytes, + expected_seed: util::bytes::Bytes, +) -> bool { + verify_seed(encryption_key.as_ref(), expected_seed.as_ref()) +} + fn bip85_entropy(keypath: &[u32]) -> Result>, ()> { let priv_key = secp256k1_get_private_key_twice(keypath)?; diff --git a/src/rust/bitbox02/src/memory.rs b/src/rust/bitbox02/src/memory.rs index ff52f6839..0a9232be5 100644 --- a/src/rust/bitbox02/src/memory.rs +++ b/src/rust/bitbox02/src/memory.rs @@ -98,7 +98,6 @@ pub fn get_attestation_pubkey_and_certificate( } } -#[cfg(feature = "testing")] pub fn get_encrypted_seed_and_hmac() -> Result, ()> { let mut out = vec![0u8; 96]; let mut len = 0u8;