hal: move TestingRandom to platform host
What changed, and why it matters
This commit simply moves a test-only fake random number generator from one internal Rust module to another. The code is identical and is only used in automated tests running on a developer's computer, not in the real BitBox02 hardware wallet firmware. There is no security issue.
No action required. This is a refactoring of test infrastructure with no security relevance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change relocates TestingRandom from bitbox02-rust/src/hal/testing/random.rs to bitbox-platform-host/src/random.rs and re-exports it. The implementation, including the deterministic counter-based fallback and fixed FACTORY_RANDOMNESS, is unchanged. TestingRandom implements the bitbox_hal::Random trait for host-side unit/integration tests; it is not compiled into the device firmware. References in testing/ui.rs are updated from super::random::TestingRandom to super::TestingRandom.
Changed components
bitbox-platform-host/src/random.rs (new test helper)bitbox02-rust/src/hal/testing.rs (re-export update)bitbox02-rust/src/hal/testing/random.rs (removed)bitbox02-rust/src/hal/testing/ui.rs (path update)Inspect captured patch +84 / −84
diff --git a/src/rust/bitbox-platform-host/src/lib.rs b/src/rust/bitbox-platform-host/src/lib.rs
index d12d0dc..d9b8817 100644
--- a/src/rust/bitbox-platform-host/src/lib.rs
+++ b/src/rust/bitbox-platform-host/src/lib.rs
@@ -8,6 +8,7 @@ extern crate std;
pub mod eeprom;
pub mod memory;
+pub mod random;
pub mod sd;
pub mod securechip;
pub mod timer;
diff --git a/src/rust/bitbox-platform-host/src/random.rs b/src/rust/bitbox-platform-host/src/random.rs
new file mode 100644
index 0000000..9ef37ac
--- /dev/null
+++ b/src/rust/bitbox-platform-host/src/random.rs
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: Apache-2.0
+use alloc::collections::VecDeque;
+
+use bitcoin::hashes::{Hash, sha256};
+use hex_lit::hex;
+
+pub struct TestingRandom {
+ mock_next_values: VecDeque<[u8; 32]>,
+ counter: u32,
+}
+
+impl TestingRandom {
+ pub const FACTORY_RANDOMNESS: [u8; 32] =
+ hex!("f71df5932e61dbaab9b9eca90e59c4b45ec91fadf803db15578c260c608eb46b");
+
+ pub fn new() -> Self {
+ Self {
+ mock_next_values: VecDeque::new(),
+ counter: 0,
+ }
+ }
+
+ pub fn mock_next(&mut self, value: [u8; 32]) {
+ self.mock_next_values.push_back(value)
+ }
+
+ fn next_value(&mut self) -> [u8; 32] {
+ self.counter += 1;
+ if let Some(value) = self.mock_next_values.pop_front() {
+ value
+ } else {
+ let hash = sha256::Hash::hash(&self.counter.to_be_bytes());
+ hash.to_byte_array()
+ }
+ }
+}
+
+impl bitbox_hal::Random for TestingRandom {
+ fn factory_randomness(&mut self) -> &'static [u8; 32] {
+ &Self::FACTORY_RANDOMNESS
+ }
+
+ fn mcu_32_bytes(&mut self, out: &mut [u8; 32]) {
+ *out = self.next_value();
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use bitbox_hal::Random;
+ use hex_lit::hex;
+
+ #[test]
+ fn test_mcu_32_bytes() {
+ let mut random = TestingRandom::new();
+ let mut first = [0u8; 32];
+ let mut second = [0u8; 32];
+ random.mcu_32_bytes(&mut first);
+ random.mcu_32_bytes(&mut second);
+ assert_eq!(
+ first,
+ hex!("b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d"),
+ );
+ assert_eq!(
+ second,
+ hex!("433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a"),
+ );
+ }
+
+ #[test]
+ fn test_factory_randomness() {
+ let mut random = TestingRandom::new();
+ let first = random.factory_randomness();
+ let second = random.factory_randomness();
+ assert_eq!(first, &TestingRandom::FACTORY_RANDOMNESS);
+ assert_eq!(second, &TestingRandom::FACTORY_RANDOMNESS);
+ }
+}
diff --git a/src/rust/bitbox02-rust/src/hal/testing.rs b/src/rust/bitbox02-rust/src/hal/testing.rs
index c3ddeaf..c35971a 100644
--- a/src/rust/bitbox02-rust/src/hal/testing.rs
+++ b/src/rust/bitbox02-rust/src/hal/testing.rs
@@ -1,14 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
-pub mod random;
pub mod system;
pub mod ui;
pub use bitbox_platform_host::eeprom::FakeEeprom as TestingEeprom;
pub use bitbox_platform_host::memory::FakeMemory as TestingMemory;
+pub use bitbox_platform_host::random::TestingRandom;
pub use bitbox_platform_host::sd::FakeSd as TestingSd;
pub use bitbox_platform_host::securechip::FakeSecureChip as TestingSecureChip;
-pub use random::TestingRandom;
pub use system::TestingSystem;
pub use ui::{Screen, TestingUi};
diff --git a/src/rust/bitbox02-rust/src/hal/testing/random.rs b/src/rust/bitbox02-rust/src/hal/testing/random.rs
deleted file mode 100644
index 1304d3e..0000000
--- a/src/rust/bitbox02-rust/src/hal/testing/random.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-use alloc::collections::VecDeque;
-
-use bitcoin::hashes::{Hash, sha256};
-use hex_lit::hex;
-
-pub struct TestingRandom {
- mock_next_values: VecDeque<[u8; 32]>,
- counter: u32,
-}
-
-impl TestingRandom {
- pub const FACTORY_RANDOMNESS: [u8; 32] =
- hex!("f71df5932e61dbaab9b9eca90e59c4b45ec91fadf803db15578c260c608eb46b");
-
- pub fn new() -> Self {
- Self {
- mock_next_values: VecDeque::new(),
- counter: 0,
- }
- }
-
- pub fn mock_next(&mut self, value: [u8; 32]) {
- self.mock_next_values.push_back(value)
- }
-
- fn next_value(&mut self) -> [u8; 32] {
- self.counter += 1;
- if let Some(value) = self.mock_next_values.pop_front() {
- value
- } else {
- let hash = sha256::Hash::hash(&self.counter.to_be_bytes());
- hash.to_byte_array()
- }
- }
-}
-
-impl crate::hal::Random for TestingRandom {
- fn factory_randomness(&mut self) -> &'static [u8; 32] {
- &Self::FACTORY_RANDOMNESS
- }
-
- fn mcu_32_bytes(&mut self, out: &mut [u8; 32]) {
- *out = self.next_value();
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::hal::Random;
- use hex_lit::hex;
-
- #[test]
- fn test_mcu_32_bytes() {
- let mut random = TestingRandom::new();
- let mut first = [0u8; 32];
- let mut second = [0u8; 32];
- random.mcu_32_bytes(&mut first);
- random.mcu_32_bytes(&mut second);
- assert_eq!(
- first,
- hex!("b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d"),
- );
- assert_eq!(
- second,
- hex!("433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a"),
- );
- }
-
- #[test]
- fn test_factory_randomness() {
- let mut random = TestingRandom::new();
- let first = random.factory_randomness();
- let second = random.factory_randomness();
- assert_eq!(first, &TestingRandom::FACTORY_RANDOMNESS);
- assert_eq!(second, &TestingRandom::FACTORY_RANDOMNESS);
- }
-}
diff --git a/src/rust/bitbox02-rust/src/hal/testing/ui.rs b/src/rust/bitbox02-rust/src/hal/testing/ui.rs
index 7b4733c..ae1823c 100644
--- a/src/rust/bitbox02-rust/src/hal/testing/ui.rs
+++ b/src/rust/bitbox02-rust/src/hal/testing/ui.rs
@@ -306,13 +306,13 @@ impl<'a> TestingUi<'a> {
/// Push one mocked 16-bit random value in the format consumed by
/// `workflow::mnemonic::create_random_unique_words()` (its local `rand16`
/// helper reads the first two bytes big-endian).
- pub fn mock_next_u16(random: &mut super::random::TestingRandom, value: u16) {
+ pub fn mock_next_u16(random: &mut super::TestingRandom, value: u16) {
random.mock_next(Self::u16_to_rand(value));
}
/// Configure random values for one `create_random_unique_words()` call so that
/// the correct answer is placed at choice index 2 in a 5-entry list.
- pub fn prepare_mnemonic_quiz_word_random(random: &mut super::random::TestingRandom) {
+ pub fn prepare_mnemonic_quiz_word_random(random: &mut super::TestingRandom) {
for value in [2u16, 0, 1, 2, 3] {
Self::mock_next_u16(random, value);
}
@@ -323,7 +323,7 @@ impl<'a> TestingUi<'a> {
/// This prepares the quiz so the correct answer is always at choice index 2.
pub fn prepare_show_and_confirm_mnemonic(
&mut self,
- random: &mut super::random::TestingRandom,
+ random: &mut super::TestingRandom,
num_words: usize,
) {
for _ in 0..num_words {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.