Skip to content
This repository has been archived by the owner on Aug 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #4 from dj8yfo/get_pub_key_get_wallet_id
Browse files Browse the repository at this point in the history
feat: `display` p1 flag in `INS_GET_PUBLIC_KEY`, add `INS_GET_WALLET_ID`
  • Loading branch information
dj8yfo authored Jan 18, 2024
2 parents 2ede498 + bce295b commit 014b617
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 36 deletions.
27 changes: 24 additions & 3 deletions src/app_ui/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ use crate::utils::types::fmt_buffer::FmtBuffer;
use ledger_device_sdk::ui::bitmaps::{CROSSMARK, EYE, VALIDATE_14};
use ledger_device_sdk::ui::gadgets::{Field, MultiFieldReview};

pub fn ui_display_pk(public_key: &crypto::PublicKeyBe) -> Result<bool, AppSW> {
pub fn ui_display_pk_base58(public_key: &crypto::PublicKeyBe) -> Result<bool, AppSW> {
let mut out_buf = FmtBuffer::<60>::new();
public_key.display_str(&mut out_buf)?;
public_key.display_str_base58(&mut out_buf)?;

let my_field = [Field {
name: "Address",
name: "Public Key",
value: out_buf.as_str(),
}];

Expand All @@ -42,3 +42,24 @@ pub fn ui_display_pk(public_key: &crypto::PublicKeyBe) -> Result<bool, AppSW> {

Ok(my_review.show())
}

pub fn ui_display_hex(public_key: &crypto::PublicKeyBe) -> Result<bool, AppSW> {
let mut out_buf = [0u8; 64];

let my_field = [Field {
name: "Wallet ID",
value: public_key.display_str_hex(&mut out_buf),
}];

let my_review = MultiFieldReview::new(
&my_field,
&["Confirm Address"],
Some(&EYE),
"Approve",
Some(&VALIDATE_14),
"Reject",
Some(&CROSSMARK),
);

Ok(my_review.show())
}
6 changes: 3 additions & 3 deletions src/handlers/get_public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
* limitations under the License.
*****************************************************************************/

use crate::app_ui::address::ui_display_pk;
use crate::app_ui::address;
use crate::utils::crypto;
use crate::AppSW;
use ledger_device_sdk::io::Comm;


pub fn handler_get_public_key(comm: &mut Comm, display: bool) -> Result<(), AppSW> {
pub fn handler(comm: &mut Comm, display: bool) -> Result<(), AppSW> {
let data = comm.get_data().map_err(|_| AppSW::WrongApduLength)?;
let path = crypto::PathBip32::parse(data).map_err(|_| AppSW::Bip32PathParsingFail)?;

Expand All @@ -38,7 +38,7 @@ pub fn handler_get_public_key(comm: &mut Comm, display: bool) -> Result<(), AppS
pk.debug_print()?;

if display {
if !ui_display_pk(&pk)? {
if !address::ui_display_pk_base58(&pk)? {
return Err(AppSW::Deny);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/get_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use ledger_device_sdk::io;
use ledger_device_sdk::testing;


pub fn handler_get_version(comm: &mut io::Comm) -> Result<(), AppSW> {
pub fn handler(comm: &mut io::Comm) -> Result<(), AppSW> {
#[cfg(feature = "speculos")]
testing::debug_print("enter `handler_get_version` fn\n");
if let Some((major, minor, patch)) = parse_version_string(env!("CARGO_PKG_VERSION")) {
Expand Down
30 changes: 30 additions & 0 deletions src/handlers/get_wallet_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::app_ui::address;
use crate::utils::crypto;
use crate::AppSW;
use ledger_device_sdk::io::Comm;


pub fn handler(comm: &mut Comm) -> Result<(), AppSW> {
let data = comm.get_data().map_err(|_| AppSW::WrongApduLength)?;
let path = crypto::PathBip32::parse(data).map_err(|_| AppSW::Bip32PathParsingFail)?;

#[cfg(feature = "speculos")]
path.debug_print();

let pk = crypto::bip32_derive(&path.0)
.public_key()
.map_err(|_| AppSW::KeyDeriveFail)?;

let pk = crypto::PublicKeyBe::from_little_endian(pk);

#[cfg(feature = "speculos")]
pk.debug_print()?;

if !address::ui_display_hex(&pk)? {
return Err(AppSW::Deny);
}

comm.append(&pk.0);

Ok(())
}
2 changes: 1 addition & 1 deletion src/handlers/sign_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fn popup_action(stream: &mut HashingStream<SingleTxStream<'_>>, ordinal_action:

}

pub fn handler_sign_tx(mut stream: SingleTxStream<'_>) -> Result<Signature, AppSW> {
pub fn handler(mut stream: SingleTxStream<'_>) -> Result<Signature, AppSW> {
sign_ui::widgets::display_receiving();
let path = <crypto::PathBip32 as BorshDeserialize>::deserialize_reader(&mut stream)
.map_err(|_| AppSW::Bip32PathParsingFail)?;
Expand Down
52 changes: 26 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,17 @@ mod app_ui {
pub mod fields_writer;
pub mod menu;
pub mod sign {
pub mod action;
pub mod transaction_prefix;
pub mod widgets;
pub mod action;
}
}
pub use app_ui::sign as sign_ui;

mod handlers {
pub mod get_public_key;
pub mod get_version;
pub mod get_wallet_id;
pub mod sign_tx;
}

Expand All @@ -54,21 +55,18 @@ pub mod parsing {
pub mod borsh;
pub mod transaction_stream_reader;
pub mod types {
pub mod transaction_prefix;
pub mod action;
pub mod transaction_prefix;

pub use action::{Action, TransferAction};
pub use transaction_prefix::TransactionPrefix;
pub use action::{TransferAction, Action};
}

pub use transaction_stream_reader::{HashingStream, SingleTxStream};
}

use app_ui::menu::ui_menu_main;
use handlers::{
get_public_key::handler_get_public_key, get_version::handler_get_version,
sign_tx::handler_sign_tx,
};
use handlers::{get_public_key, get_version, get_wallet_id, sign_tx};
use ledger_device_sdk::io::{ApduHeader, Comm, Event, Reply, StatusWords};
#[cfg(feature = "speculos")]
use ledger_device_sdk::testing;
Expand All @@ -80,10 +78,14 @@ ledger_device_sdk::set_panic!(ledger_device_sdk::exiting_panic);
const CLA: u8 = 0x80;
const INS_GET_VERSION: u8 = 6; // Instruction code to get app version from the Ledger
const INS_GET_PUBLIC_KEY: u8 = 4; // Instruction code to get public key
const INS_GET_WALLET_ID: u8 = 0x05; // Get Wallet ID
const INS_SIGN_TRANSACTION: u8 = 2; // Instruction code to sign a transaction on the Ledger

const P1_SIGN_NORMAL: u8 = 0;
const P1_SIGN_NORMAL_LAST_CHUNK: u8 = 0x80;
const P1_SIGN_LAST_CHUNK: u8 = 0x80;

const P1_GET_PUB_DISPLAY: u8 = 0;
const P1_GET_PUB_SILENT: u8 = 1;

// Application status words.
#[repr(u16)]
Expand Down Expand Up @@ -114,8 +116,8 @@ impl From<AppSW> for Reply {
/// Possible input commands received through APDUs.
pub enum Instruction {
GetVersion,
// GetAppName,
GetPubkey,
GetWalletID,
GetPubkey { display: bool },
SignTx { is_last_chunk: bool },
}

Expand All @@ -131,22 +133,19 @@ impl TryFrom<ApduHeader> for Instruction {

fn try_from(value: ApduHeader) -> Result<Self, Self::Error> {
match (value.cla, value.ins, value.p1, value.p2) {
(CLA, INS_GET_VERSION, 0, 0) => Ok(Instruction::GetVersion),
(CLA, INS_GET_PUBLIC_KEY, 0, _) => Ok(Instruction::GetPubkey),
(CLA, INS_SIGN_TRANSACTION, P1_SIGN_NORMAL | P1_SIGN_NORMAL_LAST_CHUNK, _) => {
(CLA, INS_GET_VERSION, _, _) => Ok(Instruction::GetVersion),
(CLA, INS_GET_WALLET_ID, _, _) => Ok(Instruction::GetWalletID),
(CLA, INS_GET_PUBLIC_KEY, P1_GET_PUB_DISPLAY | P1_GET_PUB_SILENT, _) => {
Ok(Instruction::GetPubkey {
display: value.p1 == P1_GET_PUB_DISPLAY,
})
}
(CLA, INS_SIGN_TRANSACTION, P1_SIGN_NORMAL | P1_SIGN_LAST_CHUNK, _) => {
Ok(Instruction::SignTx {
is_last_chunk: value.p1 == P1_SIGN_NORMAL_LAST_CHUNK,
is_last_chunk: value.p1 == P1_SIGN_LAST_CHUNK,
})
}
// (CLA, 4, 0, 0) => Ok(Instruction::GetAppName),
// (CLA, 6, P1_SIGN_TX_START, P2_SIGN_TX_MORE)
// | (CLA, 6, 1..=P1_SIGN_TX_MAX, P2_SIGN_TX_LAST | P2_SIGN_TX_MORE) => {
// Ok(Instruction::SignTx {
// chunk: value.p1,
// more: value.p2 == P2_SIGN_TX_MORE,
// })
// }
// (CLA, 3..=6, _, _) => Err(AppSW::WrongP1P2),
(CLA, INS_GET_PUBLIC_KEY | INS_SIGN_TRANSACTION, _, _) => Err(AppSW::WrongP1P2),
(CLA, _, _, _) => Err(AppSW::InsNotSupported),
(_, _, _, _) => Err(AppSW::ClaNotSupported),
}
Expand All @@ -173,11 +172,12 @@ extern "C" fn sample_main() {

fn handle_apdu(comm: &mut Comm, ins: Instruction) -> Result<(), AppSW> {
match ins {
Instruction::GetVersion => handler_get_version(comm),
Instruction::GetPubkey => handler_get_public_key(comm, true),
Instruction::GetVersion => get_version::handler(comm),
Instruction::GetWalletID => get_wallet_id::handler(comm),
Instruction::GetPubkey { display } => get_public_key::handler(comm, display),
Instruction::SignTx { is_last_chunk } => {
let stream = SingleTxStream::new(comm, is_last_chunk);
let signature = handler_sign_tx(stream)?;
let signature = sign_tx::handler(stream)?;
comm.append(&signature.0);
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/parsing/transaction_stream_reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl<'a> io::Read for SingleTxStream<'a> {
}
},
Event::Command(Instruction::GetVersion)
| Event::Command(Instruction::GetPubkey) => {
| Event::Command(Instruction::GetPubkey { .. }) => {
return Err(io::Error::from(io::ErrorKind::InvalidData))
}
Event::Command(Instruction::SignTx { is_last_chunk }) => break is_last_chunk,
Expand Down
8 changes: 7 additions & 1 deletion src/utils/crypto/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl PublicKeyBe {
PublicKeyBe(out)
}

pub fn display_str(&self, buffer: &mut FmtBuffer<60>) -> Result<(), AppSW> {
pub fn display_str_base58(&self, buffer: &mut FmtBuffer<60>) -> Result<(), AppSW> {
let mut out = [0u8; 50];
let len = bs58::encode(&self.0)
.onto(&mut out[..])
Expand All @@ -64,6 +64,12 @@ impl PublicKeyBe {
Ok(())
}

pub fn display_str_hex<'a, 'b>(&'a self, buffer: &'b mut [u8; 64]) -> &'b str {
hex::encode_to_slice(&self.0, buffer).unwrap();

core::str::from_utf8(buffer).unwrap()
}

#[cfg(feature = "speculos")]
pub fn debug_print(&self) -> Result<(), AppSW> {
testing::debug_print("debug printing pub key:\n");
Expand Down

0 comments on commit 014b617

Please sign in to comment.