Skip to content

Commit 368a6ea

Browse files
committed
rust/hww: protobuf plumbing and set device name call in Rust
1 parent b581845 commit 368a6ea

File tree

7 files changed

+127
-89
lines changed

7 files changed

+127
-89
lines changed

src/commander/commander.c

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -123,22 +123,6 @@ static commander_error_t _api_get_info(DeviceInfoResponse* device_info)
123123
return COMMANDER_OK;
124124
}
125125

126-
static commander_error_t _api_set_device_name(const SetDeviceNameRequest* request)
127-
{
128-
const confirm_params_t params = {
129-
.title = "Name",
130-
.body = request->name,
131-
.scrollable = true,
132-
};
133-
if (!workflow_confirm_blocking(&params)) {
134-
return COMMANDER_ERR_USER_ABORT;
135-
}
136-
if (!memory_set_device_name(request->name)) {
137-
return COMMANDER_ERR_MEMORY;
138-
}
139-
return COMMANDER_OK;
140-
}
141-
142126
static commander_error_t _api_set_password(const SetPasswordRequest* request)
143127
{
144128
if (!workflow_create_seed(request->entropy)) {
@@ -282,9 +266,6 @@ static commander_error_t _api_process(const Request* request, Response* response
282266
case Request_device_info_tag:
283267
response->which_response = Response_device_info_tag;
284268
return _api_get_info(&(response->response.device_info));
285-
case Request_device_name_tag:
286-
response->which_response = Response_success_tag;
287-
return _api_set_device_name(&(request->request.device_name));
288269
case Request_set_password_tag:
289270
response->which_response = Response_success_tag;
290271
return _api_set_password(&(request->request.set_password));
@@ -401,10 +382,6 @@ void commander(const in_buffer_t* in_buf, buffer_t* out_buf)
401382
}
402383

403384
#ifdef TESTING
404-
commander_error_t commander_api_set_device_name(const SetDeviceNameRequest* request)
405-
{
406-
return _api_set_device_name(request);
407-
}
408385
commander_error_t commander_api_set_mnemonic_passphrase_enabled(
409386
const SetMnemonicPassphraseEnabledRequest* request)
410387
{
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright 2020 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+
use alloc::vec::Vec;
16+
17+
use super::pb;
18+
use super::pb::request::Request;
19+
use super::pb::response::Response;
20+
use bitbox02::commander::Error;
21+
22+
/// Creates an Error response. Corresponds to commander.c:_report_error().
23+
fn make_error(err: bitbox02::commander::Error) -> Response {
24+
use Error::*;
25+
let err = match err {
26+
COMMANDER_OK => panic!("can't call this function with COMMANDER_OK"),
27+
COMMANDER_ERR_INVALID_INPUT => pb::Error {
28+
code: 101,
29+
message: "invalid input".into(),
30+
},
31+
COMMANDER_ERR_MEMORY => pb::Error {
32+
code: 102,
33+
message: "memory".into(),
34+
},
35+
COMMANDER_ERR_GENERIC => pb::Error {
36+
code: 103,
37+
message: "generic error".into(),
38+
},
39+
COMMANDER_ERR_USER_ABORT => pb::Error {
40+
code: 104,
41+
message: "aborted by the user".into(),
42+
},
43+
COMMANDER_ERR_INVALID_STATE => pb::Error {
44+
code: 105,
45+
message: "can't call this endpoint: wrong state".into(),
46+
},
47+
COMMANDER_ERR_DISABLED => pb::Error {
48+
code: 106,
49+
message: "function disabled".into(),
50+
},
51+
COMMANDER_ERR_DUPLICATE => pb::Error {
52+
code: 107,
53+
message: "duplicate entry".into(),
54+
},
55+
};
56+
Response::Error(err)
57+
}
58+
59+
/// Encodes a protobuf Response message.
60+
fn encode(response: Response) -> Vec<u8> {
61+
use prost::Message;
62+
let response = pb::Response {
63+
response: Some(response),
64+
};
65+
let mut out = Vec::<u8>::new();
66+
response.encode(&mut out).unwrap();
67+
out
68+
}
69+
70+
async fn api_set_device_name(
71+
pb::SetDeviceNameRequest { name }: &pb::SetDeviceNameRequest,
72+
) -> Response {
73+
use crate::workflow::confirm;
74+
let params = confirm::Params {
75+
title: "Name",
76+
body: &name,
77+
scrollable: true,
78+
..Default::default()
79+
};
80+
81+
if !confirm::confirm(&params).await {
82+
return make_error(Error::COMMANDER_ERR_USER_ABORT);
83+
}
84+
85+
if bitbox02::memory::set_device_name(&name).is_err() {
86+
return make_error(Error::COMMANDER_ERR_MEMORY);
87+
}
88+
89+
Response::Success(pb::Success {})
90+
}
91+
92+
/// Handle a protobuf api call.
93+
///
94+
/// Returns `None` if the call was not handled by Rust, in which case
95+
/// it should be handled by the C commander.
96+
async fn process_api(request: &Request) -> Option<Response> {
97+
match request {
98+
Request::DeviceName(ref request) => Some(api_set_device_name(request).await),
99+
_ => None,
100+
}
101+
}
102+
103+
/// Handle a protobuf api call. API calls not handled by Rust are
104+
/// handled by the C commander, which allows us to use Rust for new
105+
/// api calls and port the old calls step by step.
106+
///
107+
/// `input` is a hww.proto Request message, protobuf encoded.
108+
/// Returns a protobuf encoded hww.proto Response message.
109+
pub async fn process(input: Vec<u8>) -> Vec<u8> {
110+
use prost::Message;
111+
let request = match pb::Request::decode(&input[..]) {
112+
Ok(pb::Request {
113+
request: Some(request),
114+
}) => request,
115+
_ => return encode(make_error(Error::COMMANDER_ERR_INVALID_INPUT)),
116+
};
117+
match process_api(&request).await {
118+
Some(response) => encode(response),
119+
// Api call not handled in Rust -> handle it in C.
120+
_ => bitbox02::commander::commander(input),
121+
}
122+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@
1515
mod pb {
1616
include!("./shiftcrypto.bitbox02.rs");
1717
}
18+
19+
mod api;
20+
pub use api::process;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ pub(crate) async fn process(usb_in: Vec<u8>, usb_out: &mut Vec<u8>) -> Result<()
117117
}
118118
Some((&OP_NOISE_MSG, encrypted_msg)) => {
119119
let decrypted_msg = state.decrypt(encrypted_msg)?;
120-
let response = bitbox02::commander::commander(decrypted_msg);
120+
let response = super::api::process(decrypted_msg).await;
121121
state.encrypt(&response, usb_out)?;
122122
Ok(())
123123
}

src/rust/bitbox02/src/commander.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
pub type Error = bitbox02_sys::commander_error_t;
16+
pub use bitbox02_sys::commander_error_t as Error;
1717

1818
extern crate alloc;
1919
use alloc::vec::Vec;

test/unit-test/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,6 @@ set(TEST_LIST
220220
"-Wl,--wrap=usb_processing_enqueue"
221221
util
222222
""
223-
commander_set_device_name
224-
"-Wl,--wrap=workflow_confirm_blocking,--wrap=memory_set_device_name"
225223
commander_set_mnemonic_passphrase_enabled
226224
"-Wl,--wrap=workflow_confirm_blocking,--wrap=memory_set_mnemonic_passphrase_enabled"
227225
workflow_blocking

test/unit-test/test_commander_set_device_name.c

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)