Skip to content

Commit 1c787d4

Browse files
benma's agentbenma
authored andcommitted
rust/hal: add Random to HAL
Will allow to input different implementations in bb02, future bitboxes, unit tests, simulator, etc. The two Taproot signature checks are adjusted, as they changed due to using the new testing random numbers.
1 parent d3a42f2 commit 1c787d4

File tree

3 files changed

+75
-8
lines changed

3 files changed

+75
-8
lines changed

src/rust/bitbox02-rust/src/hal.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use crate::workflow::RealWorkflows;
1616
pub use crate::workflow::Workflows as Ui;
1717

18+
use alloc::boxed::Box;
1819
use alloc::string::String;
1920
use alloc::vec::Vec;
2021

@@ -33,10 +34,15 @@ pub trait Sd {
3334
async fn write_bin(&mut self, filename: &str, dir: &str, data: &[u8]) -> Result<(), ()>;
3435
}
3536

37+
pub trait Random {
38+
fn random_32_bytes(&mut self) -> Box<zeroize::Zeroizing<[u8; 32]>>;
39+
}
40+
3641
/// Hardware abstraction layer for BitBox devices.
3742
pub trait Hal {
3843
fn ui(&mut self) -> &mut impl Ui;
3944
fn sd(&mut self) -> &mut impl Sd;
45+
fn random(&mut self) -> &mut impl Random;
4046
}
4147

4248
pub struct BitBox02Sd;
@@ -82,16 +88,27 @@ impl Sd for BitBox02Sd {
8288
}
8389
}
8490

91+
pub struct BitBox02Random;
92+
93+
impl Random for BitBox02Random {
94+
#[inline(always)]
95+
fn random_32_bytes(&mut self) -> Box<zeroize::Zeroizing<[u8; 32]>> {
96+
bitbox02::random::random_32_bytes()
97+
}
98+
}
99+
85100
pub struct BitBox02Hal {
86101
ui: RealWorkflows,
87102
sd: BitBox02Sd,
103+
random: BitBox02Random,
88104
}
89105

90106
impl BitBox02Hal {
91107
pub const fn new() -> Self {
92108
Self {
93109
ui: crate::workflow::RealWorkflows,
94110
sd: BitBox02Sd,
111+
random: BitBox02Random,
95112
}
96113
}
97114
}
@@ -103,14 +120,38 @@ impl Hal for BitBox02Hal {
103120
fn sd(&mut self) -> &mut impl Sd {
104121
&mut self.sd
105122
}
123+
fn random(&mut self) -> &mut impl Random {
124+
&mut self.random
125+
}
106126
}
107127

108128
#[cfg(feature = "testing")]
109129
pub mod testing {
130+
use alloc::boxed::Box;
110131
use alloc::collections::BTreeMap;
111132
use alloc::string::String;
112133
use alloc::vec::Vec;
113134

135+
use bitcoin::hashes::{Hash, sha256};
136+
137+
pub struct TestingRandom {
138+
counter: u32,
139+
}
140+
141+
impl TestingRandom {
142+
pub fn new() -> Self {
143+
Self { counter: 0 }
144+
}
145+
}
146+
147+
impl super::Random for TestingRandom {
148+
fn random_32_bytes(&mut self) -> Box<zeroize::Zeroizing<[u8; 32]>> {
149+
self.counter += 1;
150+
let hash = sha256::Hash::hash(&self.counter.to_be_bytes());
151+
Box::new(zeroize::Zeroizing::new(hash.to_byte_array()))
152+
}
153+
}
154+
114155
pub struct TestingSd {
115156
pub inserted: Option<bool>,
116157
files: BTreeMap<String, BTreeMap<String, Vec<u8>>>,
@@ -172,13 +213,15 @@ pub mod testing {
172213
pub struct TestingHal<'a> {
173214
pub ui: crate::workflow::testing::TestingWorkflows<'a>,
174215
pub sd: TestingSd,
216+
pub random: TestingRandom,
175217
}
176218

177219
impl TestingHal<'_> {
178220
pub fn new() -> Self {
179221
Self {
180222
ui: crate::workflow::testing::TestingWorkflows::new(),
181223
sd: TestingSd::new(),
224+
random: TestingRandom::new(),
182225
}
183226
}
184227
}
@@ -190,12 +233,16 @@ pub mod testing {
190233
fn sd(&mut self) -> &mut impl super::Sd {
191234
&mut self.sd
192235
}
236+
fn random(&mut self) -> &mut impl super::Random {
237+
&mut self.random
238+
}
193239
}
194240

195241
#[cfg(test)]
196242
mod tests {
197243
use super::*;
198-
use crate::hal::Sd;
244+
use crate::hal::{Random, Sd};
245+
use hex_lit::hex;
199246

200247
use util::bb02_async::block_on;
201248

@@ -230,5 +277,20 @@ pub mod testing {
230277
assert!(block_on(sd.erase_file_in_subdir("file1.txt", "dir1")).is_ok());
231278
assert_eq!(block_on(sd.list_subdir(Some("dir1"))), Ok(vec![]));
232279
}
280+
281+
#[test]
282+
fn test_random() {
283+
let mut random = TestingRandom::new();
284+
let first = random.random_32_bytes();
285+
let second = random.random_32_bytes();
286+
assert_eq!(
287+
first.as_slice(),
288+
&hex!("b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d"),
289+
);
290+
assert_eq!(
291+
second.as_slice(),
292+
&hex!("433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a"),
293+
);
294+
}
233295
}
234296
}

src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ async fn _process(
11951195

11961196
next_response.next.has_signature = true;
11971197
next_response.next.signature = crate::keystore::secp256k1_schnorr_sign(
1198+
hal.random(),
11981199
&tx_input.keypath,
11991200
&sighash,
12001201
if let TaprootSpendInfo::KeySpend(tweak_hash) = &spend_info {
@@ -2155,7 +2156,6 @@ mod tests {
21552156
}));
21562157

21572158
mock_unlocked();
2158-
bitbox02::random::fake_reset();
21592159
let mut init_request = transaction.borrow().init_request();
21602160
init_request.script_configs[0] = pb::BtcScriptConfigWithKeypath {
21612161
script_config: Some(pb::BtcScriptConfig {
@@ -2172,7 +2172,7 @@ mod tests {
21722172
assert_eq!(
21732173
next.signature,
21742174
hex!(
2175-
"472ef2aa293d5697649a5364d40567d6eaf508fca9e51321c5a48de42c32b4bbc2d0cee4ab6fea1f3b137a1cbca2abe72aa945c50e95e02fa8ac354fddf2ca10"
2175+
"74fa05435a838a76ab34105f783d8d69136977b85df4644dec6afc85bba669ddb7c127d7a5a6d3cb406843b6e4366a276872228bb9efa4e3c22cfd07be3198b5"
21762176
)
21772177
);
21782178
}
@@ -3350,7 +3350,6 @@ mod tests {
33503350
"sudden tenant fault inject concert weather maid people chunk youth stumble grit",
33513351
"",
33523352
);
3353-
bitbox02::random::fake_reset();
33543353
// For the policy registration below.
33553354
mock_memory();
33563355

@@ -3388,7 +3387,7 @@ mod tests {
33883387
assert_eq!(
33893388
next.signature,
33903389
hex!(
3391-
"f4b760fa7f1ca8a00149bf439c07dcd3aafe4c98111607cece4b80066f7ef2e4406d18831990def0bf4a5b5647dc426ef1f749524adf0a6896844cd90b796031"
3390+
"63bb140c52b30f8625219dac0951cad4a6c1c2c5c6a014be40fd46a80ab77207780626f7d568e885f26484bbc3624714a26234a0da5236775cbfae5ed7a6ad8d"
33923391
)
33933392
);
33943393
}

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ pub fn secp256k1_nonce_commit(
406406
/// Sign a message using the private key at the keypath, which is optionally tweaked with the given
407407
/// tweak.
408408
pub fn secp256k1_schnorr_sign(
409+
random: &mut impl crate::hal::Random,
409410
keypath: &[u32],
410411
msg: &[u8; 32],
411412
tweak: Option<&[u8; 32]>,
@@ -423,10 +424,11 @@ pub fn secp256k1_schnorr_sign(
423424
.map_err(|_| ())?;
424425
}
425426

427+
let aux_rand = random.random_32_bytes();
426428
let sig = SECP256K1.sign_schnorr_with_aux_rand(
427429
&bitcoin::secp256k1::Message::from_digest(*msg),
428430
&keypair,
429-
&bitbox02::random::random_32_bytes(),
431+
&aux_rand,
430432
);
431433
Ok(sig.serialize())
432434
}
@@ -497,6 +499,7 @@ pub mod testing {
497499
mod tests {
498500
use super::*;
499501

502+
use crate::hal::{Random, testing::TestingRandom};
500503
use hex_lit::hex;
501504

502505
use bitbox02::testing::mock_memory;
@@ -1285,7 +1288,8 @@ mod tests {
12851288
// Test without tweak
12861289

12871290
bitbox02::securechip::fake_event_counter_reset();
1288-
let sig = secp256k1_schnorr_sign(&keypath, &msg, None).unwrap();
1291+
let mut random = crate::hal::testing::TestingRandom::new();
1292+
let sig = secp256k1_schnorr_sign(&mut random, &keypath, &msg, None).unwrap();
12891293
assert_eq!(bitbox02::securechip::fake_event_counter(), 1);
12901294

12911295
assert!(
@@ -1304,7 +1308,9 @@ mod tests {
13041308
))
13051309
.unwrap();
13061310
let (tweaked_pubkey, _) = expected_pubkey.add_tweak(SECP256K1, &tweak).unwrap();
1307-
let sig = secp256k1_schnorr_sign(&keypath, &msg, Some(&tweak.to_be_bytes())).unwrap();
1311+
let mut random = crate::hal::testing::TestingRandom::new();
1312+
let sig = secp256k1_schnorr_sign(&mut random, &keypath, &msg, Some(&tweak.to_be_bytes()))
1313+
.unwrap();
13081314
assert!(
13091315
SECP256K1
13101316
.verify_schnorr(

0 commit comments

Comments
 (0)