Skip to content

Commit b8ec18e

Browse files
committed
Merge branch 'simulator'
2 parents 520f71f + a1c553b commit b8ec18e

File tree

15 files changed

+444
-8
lines changed

15 files changed

+444
-8
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
.ccls-cache
1010
compile_commands.json
1111
compile_flags.txt
12+
.vscode
13+
.DS_Store
1214

1315
# gnu global
1416
/src/GPATH

py/send_message.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# pylint: disable=too-many-lines
1919

2020
import argparse
21+
import socket
2122
import pprint
2223
import sys
2324
from typing import List, Any, Optional, Callable, Union, Tuple, Sequence
@@ -41,6 +42,7 @@
4142
FirmwareVersionOutdatedException,
4243
u2fhid,
4344
bitbox_api_protocol,
45+
PhysicalLayer,
4446
)
4547

4648
import u2f
@@ -1556,6 +1558,65 @@ def run(self) -> int:
15561558
return 0
15571559

15581560

1561+
def connect_to_simulator_bitbox(debug: bool) -> int:
1562+
"""
1563+
Connects and runs the main menu on host computer,
1564+
simulating a BitBox02 connected over USB.
1565+
"""
1566+
1567+
class Simulator(PhysicalLayer):
1568+
"""
1569+
Simulator class handles the communication
1570+
with the firmware simulator
1571+
"""
1572+
1573+
def __init__(self) -> None:
1574+
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1575+
port = 15423
1576+
self.client_socket.bind(("", port))
1577+
self.client_socket.listen(50)
1578+
print(f"Waiting for connection on port {port}")
1579+
self.connection, addr = self.client_socket.accept()
1580+
print(f"Connected to {addr}")
1581+
1582+
def write(self, data: bytes) -> None:
1583+
self.connection.send(data[1:])
1584+
if debug:
1585+
print(f"Written to the simulator:\n{data.hex()[2:]}")
1586+
1587+
def read(self, size: int, timeout_ms: int) -> bytes:
1588+
res = self.connection.recv(64)
1589+
if debug:
1590+
print(f"Read from the simulator:\n{res.hex()}")
1591+
return res
1592+
1593+
def __del__(self) -> None:
1594+
print("Simulator quit")
1595+
if self.connection:
1596+
self.connection.shutdown(socket.SHUT_RDWR)
1597+
self.connection.close()
1598+
1599+
simulator = Simulator()
1600+
1601+
device_info: devices.DeviceInfo = {
1602+
"serial_number": "v9.16.0",
1603+
"path": b"",
1604+
"product_string": "BitBox02BTC",
1605+
}
1606+
noise_config = bitbox_api_protocol.BitBoxNoiseConfig()
1607+
bitbox_connection = bitbox02.BitBox02(
1608+
transport=u2fhid.U2FHid(simulator),
1609+
device_info=device_info,
1610+
noise_config=noise_config,
1611+
)
1612+
try:
1613+
bitbox_connection.check_min_version()
1614+
except FirmwareVersionOutdatedException as exc:
1615+
print("WARNING: ", exc)
1616+
1617+
return SendMessage(bitbox_connection, debug).run()
1618+
1619+
15591620
def connect_to_usb_bitbox(debug: bool, use_cache: bool) -> int:
15601621
"""
15611622
Connects and runs the main menu on a BitBox02 connected
@@ -1643,6 +1704,11 @@ def main() -> int:
16431704
parser = argparse.ArgumentParser(description="Tool for communicating with bitbox device")
16441705
parser.add_argument("--debug", action="store_true", help="Print messages sent and received")
16451706
parser.add_argument("--u2f", action="store_true", help="Use u2f menu instead")
1707+
parser.add_argument(
1708+
"--simulator",
1709+
action="store_true",
1710+
help="Connect to the BitBox02 simulator instead of a real BitBox02",
1711+
)
16461712
parser.add_argument(
16471713
"--no-cache", action="store_true", help="Don't use cached or store noise keys"
16481714
)
@@ -1663,6 +1729,9 @@ def main() -> int:
16631729
return u2fapp.run()
16641730
return 1
16651731

1732+
if args.simulator:
1733+
return connect_to_simulator_bitbox(args.debug)
1734+
16661735
return connect_to_usb_bitbox(args.debug, not args.no_cache)
16671736

16681737

src/rust/bitbox02-rust/src/workflow.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
pub mod cancel;
1616
pub mod confirm;
1717
pub mod menu;
18+
#[cfg_attr(feature = "c-unit-testing", path = "workflow/mnemonic_c_unit_tests.rs")]
1819
pub mod mnemonic;
1920
pub mod pairing;
2021
pub mod password;

src/rust/bitbox02-rust/src/workflow/confirm.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,7 @@ pub async fn confirm(params: &Params<'_>) -> Result<(), UserAbort> {
3131
};
3232
});
3333
component.screen_stack_push();
34+
#[cfg(feature = "c-unit-testing")]
35+
bitbox02::print_stdout(&format!("CONFIRM SCREEN START\nTITLE: {}\nBODY: {}\nCONFIRM SCREEN END\n", params.title, params.body));
3436
option_no_screensaver(&result).await
3537
}

src/rust/bitbox02-rust/src/workflow/mnemonic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,4 +502,4 @@ mod tests {
502502
&bruteforce_lastword(&mnemonic)
503503
);
504504
}
505-
}
505+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2024 Shift Crypto AG
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
pub use super::cancel::Error as CancelError;
16+
17+
use alloc::string::String;
18+
use alloc::string::ToString;
19+
20+
pub async fn show_and_confirm_mnemonic(words: &[&str]) -> Result<(), CancelError> {
21+
for word in words.iter() {
22+
bitbox02::println_stdout(word);
23+
}
24+
bitbox02::println_stdout("Words confirmed");
25+
26+
Ok(())
27+
}
28+
29+
pub async fn get() -> Result<zeroize::Zeroizing<String>, CancelError> {
30+
let words = "boring mistake dish oyster truth pigeon viable emerge sort crash wire portion cannon couple enact box walk height pull today solid off enable tide";
31+
bitbox02::println_stdout("Restored from recovery words below:");
32+
bitbox02::println_stdout(words);
33+
34+
Ok(zeroize::Zeroizing::new(
35+
words
36+
.to_string()
37+
))
38+
}

src/rust/bitbox02-rust/src/workflow/status.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,7 @@ pub async fn status(title: &str, status_success: bool) {
2121
*result.borrow_mut() = Some(());
2222
});
2323
component.screen_stack_push();
24+
#[cfg(feature = "c-unit-testing")]
25+
bitbox02::print_stdout(&format!("STATUS SCREEN START\nTITLE: {}\nSTATUS SCREEN END\n", title));
2426
option_no_screensaver(&result).await
2527
}

src/rust/bitbox02-rust/src/workflow/trinary_input_string.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub async fn enter(
4949
bitbox02::ui::trinary_input_string_set_input(&mut component, preset);
5050
}
5151
component.screen_stack_push();
52+
#[cfg(feature = "c-unit-testing")]
53+
bitbox02::print_stdout(&format!("ENTER SCREEN START\nTITLE: {}\nENTER SCREEN END\n", params.title));
5254
option(&result)
5355
.await
5456
.or(Err(super::cancel::Error::Cancelled))

src/rust/bitbox02/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ pub fn print_stdout(msg: &str) {
183183
}
184184
}
185185

186+
#[cfg(any(feature = "testing", feature = "c-unit-testing"))]
187+
pub fn println_stdout(msg: &str) {
188+
unsafe {
189+
bitbox02_sys::printf(crate::util::str_to_cstr_vec(msg).unwrap().as_ptr());
190+
bitbox02_sys::printf(crate::util::str_to_cstr_vec("\n").unwrap().as_ptr());
191+
}
192+
}
193+
186194
#[cfg(test)]
187195
mod tests {
188196
use super::*;

src/rust/bitbox02/src/ui.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
mod types;
1717

1818
#[cfg_attr(feature = "testing", path = "ui/ui_stub.rs")]
19+
#[cfg_attr(not(feature = "testing"), cfg_attr(feature = "c-unit-testing", path = "ui/ui_stub_c_unit_tests.rs"))]
1920
// We don't actually use ui::ui anywhere, we re-export below.
2021
#[allow(clippy::module_inception)]
2122
mod ui;

0 commit comments

Comments
 (0)