Skip to content

Commit

Permalink
Adapt NBGL and IO modules for synchronous API
Browse files Browse the repository at this point in the history
  • Loading branch information
agrojean-ledger committed Mar 1, 2024
1 parent 9f60eb5 commit 71cdf3e
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 247 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ runner = "speculos -m nanox --display=headless"
runner = "speculos -m nanosp --display=headless"

[target.stax]
runner = "speculos -a 13 --model stax"
runner = "speculos --model stax"

[unstable]
build-std = ["core"]
Expand Down
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ledger_device_sdk/examples/stax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extern "C" fn sample_main() {
.app_name("Stax Sample\0")
.info_contents(env!("CARGO_PKG_VERSION"), env!("CARGO_PKG_AUTHORS"))
.icon(&BTC_BMP)
.show_home::<Instruction>()
.show::<Instruction>()
{
Event::Command(_) => {
let fields = [
Expand All @@ -57,7 +57,7 @@ extern "C" fn sample_main() {
value: "Value 3\0",
},
];
if NbglReview::new(&mut comm).review_transaction(&fields) {
if NbglReview.review_transaction(&fields) {
debug_print("Validation result: true\n");
} else {
debug_print("Validation result: false\n");
Expand Down
144 changes: 110 additions & 34 deletions ledger_device_sdk/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl From<Infallible> for Reply {
}

/// Possible events returned by [`Comm::next_event`]
#[derive(Eq, PartialEq)]
#[derive(Eq, PartialEq, Clone)]
pub enum Event<T> {
/// APDU event
Command(T),
Expand All @@ -103,6 +103,7 @@ pub struct Comm {
pub apdu_buffer: [u8; 260],
pub rx: usize,
pub tx: usize,
pub event_pending: bool,
buttons: ButtonsState,
/// Expected value for the APDU CLA byte.
/// If defined, [`Comm`] will automatically reply with [`StatusWords::BadCla`] when an APDU
Expand Down Expand Up @@ -137,6 +138,7 @@ impl Comm {
apdu_buffer: [0u8; 260],
rx: 0,
tx: 0,
event_pending: false,
buttons: ButtonsState::new(),
expected_cla: None,
}
Expand Down Expand Up @@ -247,6 +249,13 @@ impl Comm {
T: TryFrom<ApduHeader>,
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
// if self.event_pending {
// self.event_pending = false;
// if let Some(value) = self.check_event() {
// return value;
// }
// }

let mut spi_buffer = [0u8; 128];

unsafe {
Expand All @@ -271,7 +280,80 @@ impl Comm {
}
}

pub fn decode_event<T>(&mut self, spi_buffer: &mut [u8; 128]) -> Option<Event<T>>
pub fn next_event_ahead<T>(&mut self) -> bool
where
T: TryFrom<ApduHeader>,
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
// if self.event_pending {
// let event: Option<Event<T>> = self.check_event();
// if event.is_some() {
// return true;
// }
// }

let mut spi_buffer = [0u8; 128];

// unsafe {
// G_io_app.apdu_state = APDU_IDLE;
// G_io_app.apdu_media = IO_APDU_MEDIA_NONE;
// G_io_app.apdu_length = 0;
// }

// Signal end of command stream from SE to MCU
// And prepare reception
if !sys_seph::is_status_sent() {
sys_seph::send_general_status();
}
// Fetch the next message from the MCU }
let _rx = sys_seph::seph_recv(&mut spi_buffer, 0);
return self.detect_apdu::<T>(&mut spi_buffer);
}

pub fn check_event<T>(&mut self) -> Option<Event<T>>
where
T: TryFrom<ApduHeader>,
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
if self.event_pending {
self.event_pending = false;
// Reject incomplete APDUs
if self.rx < 4 {
self.reply(StatusWords::BadLen);
return None;
}

// Check for data length by using `get_data`
if let Err(sw) = self.get_data() {
self.reply(sw);
return None;
}

// If CLA filtering is enabled, automatically reject APDUs with wrong CLA
if let Some(cla) = self.expected_cla {
if self.apdu_buffer[0] != cla {
self.reply(StatusWords::BadCla);
return None;
}
}

let res = T::try_from(*self.get_apdu_metadata());
match res {
Ok(ins) => {
return Some(Event::Command(ins));
}
Err(sw) => {
// Invalid Ins code. Send automatically an error, mask
// the bad instruction to the application and just
// discard this event.
self.reply(sw);
}
}
}
None
}

pub fn process_event<T>(&mut self, spi_buffer: &mut [u8; 128]) -> Option<Event<T>>
where
T: TryFrom<ApduHeader>,
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
Expand Down Expand Up @@ -332,44 +414,38 @@ impl Comm {

_ => (),
}
None
}

pub fn decode_event<T>(&mut self, spi_buffer: &mut [u8; 128]) -> Option<Event<T>>
where
T: TryFrom<ApduHeader>,
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
if let Some(event) = self.process_event(spi_buffer) {
return Some(event);
}

if unsafe { G_io_app.apdu_state } != APDU_IDLE && unsafe { G_io_app.apdu_length } > 0 {
self.rx = unsafe { G_io_app.apdu_length as usize };
return self.check_event();
}
None
}

// Reject incomplete APDUs
if self.rx < 4 {
self.reply(StatusWords::BadLen);
return None;
}

// Check for data length by using `get_data`
if let Err(sw) = self.get_data() {
self.reply(sw);
return None;
}

// If CLA filtering is enabled, automatically reject APDUs with wrong CLA
if let Some(cla) = self.expected_cla {
if self.apdu_buffer[0] != cla {
self.reply(StatusWords::BadCla);
return None;
}
}
fn detect_apdu<T>(&mut self, spi_buffer: &mut [u8; 128]) -> bool
where
T: TryFrom<ApduHeader>,
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
let _: Option<Event<T>> = self.decode_event(spi_buffer);

let res = T::try_from(*self.get_apdu_metadata());
match res {
Ok(ins) => {
return Some(Event::Command(ins));
}
Err(sw) => {
// Invalid Ins code. Send automatically an error, mask
// the bad instruction to the application and just
// discard this event.
self.reply(sw);
}
}
if unsafe { G_io_app.apdu_state } != APDU_IDLE && unsafe { G_io_app.apdu_length } > 0 {
self.rx = unsafe { G_io_app.apdu_length as usize };
self.event_pending = true;
return true;
}
None
false
}

/// Wait for the next Command event. Discards received button events.
Expand Down
Loading

0 comments on commit 71cdf3e

Please sign in to comment.