@@ -16,5 +16,154 @@ mod pb {
16
16
include ! ( "./shiftcrypto.bitbox02.rs" ) ;
17
17
}
18
18
19
- mod api;
20
- pub use api:: process;
19
+ use alloc:: vec:: Vec ;
20
+
21
+ use bitbox02:: commander:: Error ;
22
+ use pb:: request:: Request ;
23
+ use pb:: response:: Response ;
24
+
25
+ /// Creates an Error response. Corresponds to commander.c:_report_error().
26
+ fn make_error ( err : bitbox02:: commander:: Error ) -> Response {
27
+ use Error :: * ;
28
+ let err = match err {
29
+ COMMANDER_OK => panic ! ( "can't call this function with COMMANDER_OK" ) ,
30
+ COMMANDER_ERR_INVALID_INPUT => pb:: Error {
31
+ code : 101 ,
32
+ message : "invalid input" . into ( ) ,
33
+ } ,
34
+ COMMANDER_ERR_MEMORY => pb:: Error {
35
+ code : 102 ,
36
+ message : "memory" . into ( ) ,
37
+ } ,
38
+ COMMANDER_ERR_GENERIC => pb:: Error {
39
+ code : 103 ,
40
+ message : "generic error" . into ( ) ,
41
+ } ,
42
+ COMMANDER_ERR_USER_ABORT => pb:: Error {
43
+ code : 104 ,
44
+ message : "aborted by the user" . into ( ) ,
45
+ } ,
46
+ COMMANDER_ERR_INVALID_STATE => pb:: Error {
47
+ code : 105 ,
48
+ message : "can't call this endpoint: wrong state" . into ( ) ,
49
+ } ,
50
+ COMMANDER_ERR_DISABLED => pb:: Error {
51
+ code : 106 ,
52
+ message : "function disabled" . into ( ) ,
53
+ } ,
54
+ COMMANDER_ERR_DUPLICATE => pb:: Error {
55
+ code : 107 ,
56
+ message : "duplicate entry" . into ( ) ,
57
+ } ,
58
+ } ;
59
+ Response :: Error ( err)
60
+ }
61
+
62
+ /// Encodes a protobuf Response message.
63
+ fn encode ( response : Response ) -> Vec < u8 > {
64
+ use prost:: Message ;
65
+ let response = pb:: Response {
66
+ response : Some ( response) ,
67
+ } ;
68
+ let mut out = Vec :: < u8 > :: new ( ) ;
69
+ response. encode ( & mut out) . unwrap ( ) ;
70
+ out
71
+ }
72
+
73
+ /// Returns the field tag number of the request as defined in the .proto file. This is needed for
74
+ /// compatibility with commander_states.c, and needed as long as API calls processed in C use
75
+ /// `commmander_states_force_next()`.
76
+ fn request_tag ( request : & Request ) -> u32 {
77
+ use Request :: * ;
78
+ match request {
79
+ RandomNumber ( _) => bitbox02:: Request_random_number_tag ,
80
+ DeviceName ( _) => bitbox02:: Request_device_name_tag ,
81
+ DeviceLanguage ( _) => bitbox02:: Request_device_language_tag ,
82
+ DeviceInfo ( _) => bitbox02:: Request_device_info_tag ,
83
+ SetPassword ( _) => bitbox02:: Request_set_password_tag ,
84
+ CreateBackup ( _) => bitbox02:: Request_create_backup_tag ,
85
+ ShowMnemonic ( _) => bitbox02:: Request_show_mnemonic_tag ,
86
+ BtcPub ( _) => bitbox02:: Request_btc_pub_tag ,
87
+ BtcSignInit ( _) => bitbox02:: Request_btc_sign_init_tag ,
88
+ BtcSignInput ( _) => bitbox02:: Request_btc_sign_input_tag ,
89
+ BtcSignOutput ( _) => bitbox02:: Request_btc_sign_output_tag ,
90
+ InsertRemoveSdcard ( _) => bitbox02:: Request_insert_remove_sdcard_tag ,
91
+ CheckSdcard ( _) => bitbox02:: Request_check_sdcard_tag ,
92
+ SetMnemonicPassphraseEnabled ( _) => bitbox02:: Request_set_mnemonic_passphrase_enabled_tag ,
93
+ ListBackups ( _) => bitbox02:: Request_list_backups_tag ,
94
+ RestoreBackup ( _) => bitbox02:: Request_restore_backup_tag ,
95
+ PerformAttestation ( _) => bitbox02:: Request_perform_attestation_tag ,
96
+ Reboot ( _) => bitbox02:: Request_reboot_tag ,
97
+ CheckBackup ( _) => bitbox02:: Request_check_backup_tag ,
98
+ Eth ( _) => bitbox02:: Request_eth_tag ,
99
+ Reset ( _) => bitbox02:: Request_reset_tag ,
100
+ RestoreFromMnemonic ( _) => bitbox02:: Request_restore_from_mnemonic_tag ,
101
+ Bitboxbase ( _) => bitbox02:: Request_bitboxbase_tag ,
102
+ Fingerprint ( _) => bitbox02:: Request_fingerprint_tag ,
103
+ Btc ( _) => bitbox02:: Request_btc_tag ,
104
+ ElectrumEncryptionKey ( _) => bitbox02:: Request_electrum_encryption_key_tag ,
105
+ }
106
+ }
107
+
108
+ async fn api_set_device_name (
109
+ pb:: SetDeviceNameRequest { name } : & pb:: SetDeviceNameRequest ,
110
+ ) -> Response {
111
+ use crate :: workflow:: confirm;
112
+ let params = confirm:: Params {
113
+ title : "Name" ,
114
+ body : & name,
115
+ scrollable : true ,
116
+ ..Default :: default ( )
117
+ } ;
118
+
119
+ if !confirm:: confirm ( & params) . await {
120
+ return make_error ( Error :: COMMANDER_ERR_USER_ABORT ) ;
121
+ }
122
+
123
+ if bitbox02:: memory:: set_device_name ( & name) . is_err ( ) {
124
+ return make_error ( Error :: COMMANDER_ERR_MEMORY ) ;
125
+ }
126
+
127
+ Response :: Success ( pb:: Success { } )
128
+ }
129
+
130
+ /// Handle a protobuf api call.
131
+ ///
132
+ /// Returns `None` if the call was not handled by Rust, in which case
133
+ /// it should be handled by the C commander.
134
+ async fn process_api ( request : & Request ) -> Option < Response > {
135
+ match request {
136
+ Request :: DeviceName ( ref request) => Some ( api_set_device_name ( request) . await ) ,
137
+ _ => None ,
138
+ }
139
+ }
140
+
141
+ /// Handle a protobuf api call. API calls not handled by Rust are
142
+ /// handled by the C commander, which allows us to use Rust for new
143
+ /// api calls and port the old calls step by step.
144
+ ///
145
+ /// `input` is a hww.proto Request message, protobuf encoded.
146
+ /// Returns a protobuf encoded hww.proto Response message.
147
+ pub async fn process ( input : Vec < u8 > ) -> Vec < u8 > {
148
+ use prost:: Message ;
149
+ let request = match pb:: Request :: decode ( & input[ ..] ) {
150
+ Ok ( pb:: Request {
151
+ request : Some ( request) ,
152
+ } ) => request,
153
+ _ => return encode ( make_error ( Error :: COMMANDER_ERR_INVALID_INPUT ) ) ,
154
+ } ;
155
+ if !bitbox02:: commander:: states_can_call ( request_tag ( & request) as u16 ) {
156
+ return encode ( make_error ( Error :: COMMANDER_ERR_INVALID_STATE ) ) ;
157
+ }
158
+
159
+ // Since we will process the call now, so can clear the 'force next' info.
160
+ // We do this before processing as the api call can potentially define the next api call
161
+ // to be forced.
162
+ bitbox02:: commander:: states_clear_force_next ( ) ;
163
+
164
+ match process_api ( & request) . await {
165
+ Some ( response) => encode ( response) ,
166
+ // Api call not handled in Rust -> handle it in C.
167
+ _ => bitbox02:: commander:: commander ( input) ,
168
+ }
169
+ }
0 commit comments