Skip to content

Commit 5907bd5

Browse files
committed
rust/hww: disallow api calls according to commander_states
Moving the commander states check calls from C to Rust makes sure that API calls handled in Rust obey the same rules, e.g. that SetDeviceName cannot be called in the middle of a Bitcoin tx signing session.
1 parent ad81783 commit 5907bd5

File tree

6 files changed

+69
-11
lines changed

6 files changed

+69
-11
lines changed

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,8 @@ add_custom_target(rust-bindgen
373373
--whitelist-type commander_error_t
374374
--rustified-enum commander_error_t
375375
--whitelist-function commander
376+
--whitelist-function commander_states_can_call
377+
--whitelist-function commander_states_clear_force_next
376378
--whitelist-type BitBoxBaseRequest
377379
--whitelist-var ".*_tag"
378380
--whitelist-var MAX_LABEL_SIZE

src/commander/commander.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -362,17 +362,8 @@ void commander(const in_buffer_t* in_buf, buffer_t* out_buf)
362362
commander_error_t err =
363363
protobuf_decode(in_buf, &request) ? COMMANDER_OK : COMMANDER_ERR_INVALID_INPUT;
364364
if (err == COMMANDER_OK) {
365-
if (!commander_states_can_call(request.which_request)) {
366-
err = COMMANDER_ERR_INVALID_STATE;
367-
} else {
368-
// Since we will process the call now, so can clear the 'force next' info.
369-
// We do this before processing as the api call can potentially define the next api call
370-
// to be forced.
371-
commander_states_clear_force_next();
372-
373-
err = _api_process(&request, &response);
374-
util_zero(&request, sizeof(request));
375-
}
365+
err = _api_process(&request, &response);
366+
util_zero(&request, sizeof(request));
376367
}
377368
if (err != COMMANDER_OK) {
378369
_report_error(&response, err);

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,41 @@ fn encode(response: Response) -> Vec<u8> {
6767
out
6868
}
6969

70+
/// Returns the field tag number of the request as defined in the .proto file. This is needed for
71+
/// compatibility with commander_states.c, and needed as long as API calls processed in C use
72+
/// `commmander_states_force_next()`.
73+
fn request_tag(request: &Request) -> u32 {
74+
use Request::*;
75+
match request {
76+
RandomNumber(_) => bitbox02::Request_random_number_tag,
77+
DeviceName(_) => bitbox02::Request_device_name_tag,
78+
DeviceLanguage(_) => bitbox02::Request_device_language_tag,
79+
DeviceInfo(_) => bitbox02::Request_device_info_tag,
80+
SetPassword(_) => bitbox02::Request_set_password_tag,
81+
CreateBackup(_) => bitbox02::Request_create_backup_tag,
82+
ShowMnemonic(_) => bitbox02::Request_show_mnemonic_tag,
83+
BtcPub(_) => bitbox02::Request_btc_pub_tag,
84+
BtcSignInit(_) => bitbox02::Request_btc_sign_init_tag,
85+
BtcSignInput(_) => bitbox02::Request_btc_sign_input_tag,
86+
BtcSignOutput(_) => bitbox02::Request_btc_sign_output_tag,
87+
InsertRemoveSdcard(_) => bitbox02::Request_insert_remove_sdcard_tag,
88+
CheckSdcard(_) => bitbox02::Request_check_sdcard_tag,
89+
SetMnemonicPassphraseEnabled(_) => bitbox02::Request_set_mnemonic_passphrase_enabled_tag,
90+
ListBackups(_) => bitbox02::Request_list_backups_tag,
91+
RestoreBackup(_) => bitbox02::Request_restore_backup_tag,
92+
PerformAttestation(_) => bitbox02::Request_perform_attestation_tag,
93+
Reboot(_) => bitbox02::Request_reboot_tag,
94+
CheckBackup(_) => bitbox02::Request_check_backup_tag,
95+
Eth(_) => bitbox02::Request_eth_tag,
96+
Reset(_) => bitbox02::Request_reset_tag,
97+
RestoreFromMnemonic(_) => bitbox02::Request_restore_from_mnemonic_tag,
98+
Bitboxbase(_) => bitbox02::Request_bitboxbase_tag,
99+
Fingerprint(_) => bitbox02::Request_fingerprint_tag,
100+
Btc(_) => bitbox02::Request_btc_tag,
101+
ElectrumEncryptionKey(_) => bitbox02::Request_electrum_encryption_key_tag,
102+
}
103+
}
104+
70105
async fn api_set_device_name(
71106
pb::SetDeviceNameRequest { name }: &pb::SetDeviceNameRequest,
72107
) -> Response {
@@ -114,6 +149,15 @@ pub async fn process(input: Vec<u8>) -> Vec<u8> {
114149
}) => request,
115150
_ => return encode(make_error(Error::COMMANDER_ERR_INVALID_INPUT)),
116151
};
152+
if !bitbox02::commander::states_can_call(request_tag(&request) as u16) {
153+
return encode(make_error(Error::COMMANDER_ERR_INVALID_STATE));
154+
}
155+
156+
// Since we will process the call now, so can clear the 'force next' info.
157+
// We do this before processing as the api call can potentially define the next api call
158+
// to be forced.
159+
bitbox02::commander::states_clear_force_next();
160+
117161
match process_api(&request).await {
118162
Some(response) => encode(response),
119163
// Api call not handled in Rust -> handle it in C.

src/rust/bitbox02-sys/wrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <bitboxbase/bitboxbase_screensaver.h>
1717
#include <bitboxbase/bitboxbase_watchdog.h>
1818
#include <commander/commander.h>
19+
#include <commander/commander_states.h>
1920
#include <keystore.h>
2021
#include <memory/memory.h>
2122
#include <platform/bitboxbase/leds.h>

src/rust/bitbox02/src/commander.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,11 @@ pub fn commander(input: Vec<u8>) -> Vec<u8> {
4444
};
4545
output_vec
4646
}
47+
48+
pub fn states_can_call(request_tag: u16) -> bool {
49+
unsafe { bitbox02_sys::commander_states_can_call(request_tag) }
50+
}
51+
52+
pub fn states_clear_force_next() {
53+
unsafe { bitbox02_sys::commander_states_clear_force_next() }
54+
}

src/rust/bitbox02/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ pub const BitBoxBaseRequest_display_status_tag: u16 =
5555
pub const BitBoxBaseRequest_set_config_tag: u16 =
5656
bitbox02_sys::BitBoxBaseRequest_set_config_tag as u16;
5757

58+
pub use bitbox02_sys::{
59+
Request_bitboxbase_tag, Request_btc_pub_tag, Request_btc_sign_init_tag,
60+
Request_btc_sign_input_tag, Request_btc_sign_output_tag, Request_btc_tag,
61+
Request_check_backup_tag, Request_check_sdcard_tag, Request_create_backup_tag,
62+
Request_device_info_tag, Request_device_language_tag, Request_device_name_tag,
63+
Request_electrum_encryption_key_tag, Request_eth_tag, Request_fingerprint_tag,
64+
Request_insert_remove_sdcard_tag, Request_list_backups_tag, Request_perform_attestation_tag,
65+
Request_random_number_tag, Request_reboot_tag, Request_reset_tag, Request_restore_backup_tag,
66+
Request_restore_from_mnemonic_tag, Request_set_mnemonic_passphrase_enabled_tag,
67+
Request_set_password_tag, Request_show_mnemonic_tag,
68+
};
69+
5870
// Use this for functions exported to "C"
5971
#[allow(non_camel_case_types)]
6072
pub type commander_error_t = bitbox02_sys::commander_error_t;

0 commit comments

Comments
 (0)