Skip to content

Commit

Permalink
rust/hww: protobuf plumbing and set device name call in Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
benma committed Jul 2, 2020
1 parent 7f24136 commit 29cd960
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 2 deletions.
122 changes: 122 additions & 0 deletions src/rust/bitbox02-rust/src/hww/api/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright 2020 Shift Crypto AG
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use alloc::vec::Vec;

use super::pb;
use super::pb::request::Request;
use super::pb::response::Response;
use bitbox02::commander::Error;

/// Creates an Error response. Corresponds to commander.c:_report_error().
fn make_error(err: bitbox02::commander::Error) -> Response {
use Error::*;
let err = match err {
COMMANDER_OK => panic!("can't call this function with COMMANDER_OK"),
COMMANDER_ERR_INVALID_INPUT => pb::Error {
code: 101,
message: "invalid input".into(),
},
COMMANDER_ERR_MEMORY => pb::Error {
code: 102,
message: "memory".into(),
},
COMMANDER_ERR_GENERIC => pb::Error {
code: 103,
message: "generic error".into(),
},
COMMANDER_ERR_USER_ABORT => pb::Error {
code: 104,
message: "aborted by the user".into(),
},
COMMANDER_ERR_INVALID_STATE => pb::Error {
code: 105,
message: "can't call this endpoint: wrong state".into(),
},
COMMANDER_ERR_DISABLED => pb::Error {
code: 106,
message: "function disabled".into(),
},
COMMANDER_ERR_DUPLICATE => pb::Error {
code: 107,
message: "duplicate entry".into(),
},
};
Response::Error(err)
}

/// Encodes a protobuf Response message.
fn encode(response: Response) -> Vec<u8> {
use prost::Message;
let response = pb::Response {
response: Some(response),
};
let mut out = Vec::<u8>::new();
response.encode(&mut out).unwrap();
out
}

async fn api_set_device_name(
pb::SetDeviceNameRequest { name }: &pb::SetDeviceNameRequest,
) -> Response {
use crate::workflow::confirm;
let params = confirm::Params {
title: "Name",
body: &name,
scrollable: true,
..Default::default()
};

if !confirm::confirm(&params).await {
return make_error(Error::COMMANDER_ERR_USER_ABORT);
}

if bitbox02::memory::set_device_name(&name).is_err() {
return make_error(Error::COMMANDER_ERR_MEMORY);
}

Response::Success(pb::Success {})
}

/// Handle a protobuf api call.
///
/// Returns `None` if the call was not handled by Rust, in which case
/// it should be handled by the C commander.
async fn process_api(request: &Request) -> Option<Response> {
match request {
Request::DeviceName(ref request) => Some(api_set_device_name(request).await),
_ => None,
}
}

/// Handle a protobuf api call. API calls not handled by Rust are
/// handled by the C commander, which allows us to use Rust for new
/// api calls and port the old calls step by step.
///
/// `input` is a hww.proto Request message, protobuf encoded.
/// Returns a protobuf encoded hww.proto Response message.
pub async fn process(input: Vec<u8>) -> Vec<u8> {
use prost::Message;
let request = match pb::Request::decode(&input[..]) {
Ok(pb::Request {
request: Some(request),
}) => request,
_ => return encode(make_error(Error::COMMANDER_ERR_INVALID_INPUT)),
};
match process_api(&request).await {
Some(response) => encode(response),
// Api call not handled Rust -> handle it in C.
_ => bitbox02::commander::commander(input),
}
}
3 changes: 3 additions & 0 deletions src/rust/bitbox02-rust/src/hww/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@
mod pb {
include!("./shiftcrypto.bitbox02.rs");
}

mod api;
pub use api::process;
2 changes: 1 addition & 1 deletion src/rust/bitbox02-rust/src/hww/noise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub(crate) async fn process(usb_in: Vec<u8>, usb_out: &mut Vec<u8>) -> Result<()
}
Some((&OP_NOISE_MSG, encrypted_msg)) => {
let decrypted_msg = state.decrypt(encrypted_msg)?;
let response = bitbox02::commander::commander(decrypted_msg);
let response = super::api::process(decrypted_msg).await;
state.encrypt(&response, usb_out)?;
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/rust/bitbox02/src/commander.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

pub type Error = bitbox02_sys::commander_error_t;
pub use bitbox02_sys::commander_error_t as Error;

extern crate alloc;
use alloc::vec::Vec;
Expand Down

0 comments on commit 29cd960

Please sign in to comment.