Skip to content

Commit

Permalink
Merge branch 'master' into y333/update_cargo_ledger
Browse files Browse the repository at this point in the history
  • Loading branch information
yogh333 authored Jul 29, 2024
2 parents fdeeb2c + f8afb3b commit db41fb0
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 21 deletions.
2 changes: 1 addition & 1 deletion ledger_device_sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ledger_device_sdk"
version = "1.12.0"
version = "1.13.0"
authors = ["yhql", "yogh333", "agrojean-ledger", "kingofpayne"]
edition = "2021"
license.workspace = true
Expand Down
51 changes: 51 additions & 0 deletions ledger_device_sdk/examples/nbgl_choice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#![no_std]
#![no_main]

// Force boot section to be embedded in
use ledger_device_sdk as _;

use include_gif::include_gif;
use ledger_device_sdk::io::*;
use ledger_device_sdk::nbgl::{init_comm, NbglChoice, NbglGlyph};
use ledger_secure_sdk_sys::*;

#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
exit_app(1);
}

#[no_mangle]
extern "C" fn sample_main() {
unsafe {
nbgl_refreshReset();
}

let mut comm = Comm::new();
// Initialize reference to Comm instance for NBGL
// API calls.
init_comm(&mut comm);

// Load glyph from 64x64 4bpp gif file with include_gif macro. Creates an NBGL compatible glyph.
const WARNING: NbglGlyph =
NbglGlyph::from_include(include_gif!("icons/Warning_64px.gif", NBGL));

let back_to_safety = NbglChoice::new().glyph(&WARNING)
.status_text(Some("Transaction rejected"),None)
.show(
"Security risk detected",
"It may not be safe to sign this transaction. To continue, you'll need to review the risk.",
"Back to safety",
"Review risk",
);

if !back_to_safety {
NbglChoice::new()
.status_text(Some("Transaction confirmed"), Some("Transaction rejected"))
.show(
"The transaction cannot be trusted",
"Your Ledger cannot decode this transaction. If you sign it, you could be authorizing malicious actions that can drain your wallet.\n\nLearn more: ledger.com/e8",
"I accept the risk",
"Reject transaction"
);
}
}
Binary file added ledger_device_sdk/icons/Warning_64px.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
161 changes: 141 additions & 20 deletions ledger_device_sdk/src/nbgl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use alloc::ffi::CString;
use alloc::vec::Vec;
use core::ffi::{c_char, c_int};
use core::mem::transmute;
use include_gif::include_gif;
use ledger_secure_sdk_sys::*;

#[no_mangle]
Expand Down Expand Up @@ -307,7 +308,7 @@ impl<'a> NbglHomeAndSettings<'a> {
nbContents: if self.nb_settings > 0 { 1 } else { 0 },
};

match ledger_secure_sdk_sys::ux_sync_homeAndSettings(
match ux_sync_homeAndSettings(
info_contents[0],
&icon as *const nbgl_icon_details_t,
core::ptr::null(),
Expand All @@ -316,7 +317,7 @@ impl<'a> NbglHomeAndSettings<'a> {
&info_list as *const nbgl_contentInfoList_t,
core::ptr::null(),
) {
ledger_secure_sdk_sys::UX_SYNC_RET_APDU_RECEIVED => {
UX_SYNC_RET_APDU_RECEIVED => {
if let Some(comm) = COMM_REF.as_mut() {
if let Some(value) = comm.check_event() {
return value;
Expand All @@ -332,6 +333,35 @@ impl<'a> NbglHomeAndSettings<'a> {
}
}

/// Private helper function to display a warning screen when a transaction
/// is reviewed in "blind" mode. The user can choose to go back to safety
/// or review the risk. If the user chooses to review the risk, a second screen
/// is displayed with the option to accept the risk or reject the transaction.
/// Used in NbglReview and NbglStreamingReview.
fn show_blind_warning() -> bool {
const WARNING: NbglGlyph =
NbglGlyph::from_include(include_gif!("icons/Warning_64px.gif", NBGL));

let back_to_safety = NbglChoice::new().glyph(&WARNING).show(
"Security risk detected",
"It may not be safe to sign this transaction. To continue, you'll need to review the risk.",
"Back to safety",
"Review risk",
);

if !back_to_safety {
NbglChoice::new()
.show(
"The transaction cannot be trusted",
"Your Ledger cannot decode this transaction. If you sign it, you could be authorizing malicious actions that can drain your wallet.\n\nLearn more: ledger.com/e8",
"I accept the risk",
"Reject transaction"
)
} else {
false
}
}

/// A wrapper around the synchronous NBGL ux_sync_review C API binding.
/// Used to display transaction review screens.
pub struct NbglReview<'a> {
Expand Down Expand Up @@ -420,8 +450,15 @@ impl<'a> NbglReview<'a> {
None => nbgl_icon_details_t::default(),
};

if self.blind {
if !show_blind_warning() {
ux_sync_reviewStatus(self.tx_type.to_message(false));
return false;
}
}

// Show the review on the device.
let sync_ret = ledger_secure_sdk_sys::ux_sync_review(
let sync_ret = ux_sync_review(
self.tx_type.to_c_type(self.blind, false),
&tag_value_list as *const nbgl_contentTagValueList_t,
&icon as *const nbgl_icon_details_t,
Expand All @@ -432,12 +469,12 @@ impl<'a> NbglReview<'a> {

// Return true if the user approved the transaction, false otherwise.
match sync_ret {
ledger_secure_sdk_sys::UX_SYNC_RET_APPROVED => {
ledger_secure_sdk_sys::ux_sync_reviewStatus(self.tx_type.to_message(true));
UX_SYNC_RET_APPROVED => {
ux_sync_reviewStatus(self.tx_type.to_message(true));
return true;
}
_ => {
ledger_secure_sdk_sys::ux_sync_reviewStatus(self.tx_type.to_message(false));
ux_sync_reviewStatus(self.tx_type.to_message(false));
return false;
}
}
Expand Down Expand Up @@ -870,18 +907,12 @@ impl NbglGenericReview {

// Return true if the user approved the transaction, false otherwise.
match sync_ret {
ledger_secure_sdk_sys::UX_SYNC_RET_APPROVED => {
ledger_secure_sdk_sys::ux_sync_status(
succeed_cstring.as_ptr() as *const c_char,
true,
);
UX_SYNC_RET_APPROVED => {
ux_sync_status(succeed_cstring.as_ptr() as *const c_char, true);
return true;
}
_ => {
ledger_secure_sdk_sys::ux_sync_status(
rejected_cstring.as_ptr() as *const c_char,
false,
);
ux_sync_status(rejected_cstring.as_ptr() as *const c_char, false);
return false;
}
}
Expand Down Expand Up @@ -929,6 +960,13 @@ impl NbglStreamingReview {
let title = CString::new(title).unwrap();
let subtitle = CString::new(subtitle).unwrap();

if self.blind {
if !show_blind_warning() {
ux_sync_reviewStatus(self.tx_type.to_message(false));
return false;
}
}

let sync_ret = ux_sync_reviewStreamingStart(
self.tx_type.to_c_type(self.blind, false),
&self.icon as *const nbgl_icon_details_t,
Expand Down Expand Up @@ -1001,7 +1039,7 @@ impl NbglStreamingReview {

// Return true if the user approved the transaction, false otherwise.
match sync_ret {
ledger_secure_sdk_sys::UX_SYNC_RET_APPROVED => {
UX_SYNC_RET_APPROVED => {
ux_sync_reviewStatus(self.tx_type.to_message(true));
return true;
}
Expand Down Expand Up @@ -1063,12 +1101,12 @@ impl<'a> NbglAddressReview<'a> {

// Return true if the user approved the address, false otherwise.
match sync_ret {
ledger_secure_sdk_sys::UX_SYNC_RET_APPROVED => {
ledger_secure_sdk_sys::ux_sync_reviewStatus(STATUS_TYPE_ADDRESS_VERIFIED);
UX_SYNC_RET_APPROVED => {
ux_sync_reviewStatus(STATUS_TYPE_ADDRESS_VERIFIED);
return true;
}
ledger_secure_sdk_sys::UX_SYNC_RET_REJECTED => {
ledger_secure_sdk_sys::ux_sync_reviewStatus(STATUS_TYPE_ADDRESS_REJECTED);
UX_SYNC_RET_REJECTED => {
ux_sync_reviewStatus(STATUS_TYPE_ADDRESS_REJECTED);
return false;
}
_ => {
Expand All @@ -1079,6 +1117,89 @@ impl<'a> NbglAddressReview<'a> {
}
}

/// A wrapper around the synchronous NBGL ux_sync_status C API binding.
/// Draws a generic choice page, described in a centered info (with configurable icon),
/// thanks to a button and a footer at the bottom of the page.
pub struct NbglChoice<'a> {
glyph: Option<&'a NbglGlyph<'a>>,
confirmed_text: Option<CString>,
cancelled_text: Option<CString>,
}

impl<'a> NbglChoice<'a> {
pub fn new() -> NbglChoice<'a> {
NbglChoice {
glyph: None,
confirmed_text: None,
cancelled_text: None,
}
}

pub fn glyph(self, glyph: &'a NbglGlyph) -> NbglChoice<'a> {
NbglChoice {
glyph: Some(glyph),
..self
}
}

pub fn status_text(
self,
confirmed: Option<&'a str>,
cancelled: Option<&'a str>,
) -> NbglChoice<'a> {
let confirmed_text = confirmed.map(|s| CString::new(s).unwrap());
let cancelled_text = cancelled.map(|s| CString::new(s).unwrap());
NbglChoice {
confirmed_text,
cancelled_text,
..self
}
}

pub fn show(
self,
message: &str,
sub_message: &str,
confirm_text: &str,
cancel_text: &str,
) -> bool {
unsafe {
let icon: nbgl_icon_details_t = match self.glyph {
Some(g) => g.into(),
None => nbgl_icon_details_t::default(),
};
let message = CString::new(message).unwrap();
let sub_message = CString::new(sub_message).unwrap();
let confirm_text = CString::new(confirm_text).unwrap();
let cancel_text = CString::new(cancel_text).unwrap();

let sync_ret = ux_sync_choice(
&icon as *const nbgl_icon_details_t,
message.as_ptr() as *const c_char,
sub_message.as_ptr() as *const c_char,
confirm_text.as_ptr() as *const c_char,
cancel_text.as_ptr() as *const c_char,
);

// Return true if the user approved the transaction, false otherwise.
match sync_ret {
UX_SYNC_RET_APPROVED => {
if let Some(text) = self.confirmed_text {
ux_sync_status(text.as_ptr() as *const c_char, true);
}
return true;
}
_ => {
if let Some(text) = self.cancelled_text {
ux_sync_status(text.as_ptr() as *const c_char, false);
}
return false;
}
}
}
}
}

#[derive(Copy, Clone)]
pub enum TuneIndex {
Reserved,
Expand Down

0 comments on commit db41fb0

Please sign in to comment.