Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify different error codes when rejecting signing #31

Merged
merged 4 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions rust-app/Cargo.lock

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

170 changes: 136 additions & 34 deletions rust-app/src/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use core::fmt::Write;
use ledger_crypto_helpers::common::{try_option, Address, HexSlice};
use ledger_crypto_helpers::eddsa::{ed25519_public_key_bytes, eddsa_sign, with_public_keys};
use ledger_crypto_helpers::hasher::{Blake2b, Hasher, HexHash};
use ledger_device_sdk::io::SyscallError;
use ledger_device_sdk::io::{StatusWords, SyscallError};
use ledger_log::trace;
use ledger_parser_combinators::async_parser::*;
use ledger_parser_combinators::bcs::async_parser::*;
Expand Down Expand Up @@ -57,13 +57,13 @@ pub const BIP32_PREFIX: [u32; 5] =
pub async fn get_address_apdu(io: HostIO, prompt: bool) {
let input = match io.get_params::<1>() {
Some(v) => v,
None => reject().await,
None => reject(SyscallError::InvalidParameter as u16).await,
};

let path = BIP_PATH_PARSER.parse(&mut input[0].clone()).await;

if !path.starts_with(&BIP32_PREFIX[0..2]) {
reject::<()>().await;
reject::<()>(SyscallError::InvalidParameter as u16).await;
}

let mut rv = ArrayVec::<u8, 220>::new();
Expand All @@ -90,7 +90,7 @@ pub async fn get_address_apdu(io: HostIO, prompt: bool) {
})
.is_err()
{
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
}

io.result_final(&rv).await;
Expand Down Expand Up @@ -161,13 +161,25 @@ impl<BS: Clone + Readable> AsyncParser<CallArgSchema, BS> for DefaultInterp {
)
.await;
}
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
CallArg::ObjectArg
}
_ => {
trace!("CallArgSchema: Unknown enum: {}", enum_variant);
reject_on(core::file!(), core::line!()).await
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
Expand Down Expand Up @@ -223,7 +235,12 @@ impl<BS: Clone + Readable> AsyncParser<CommandSchema, BS> for DefaultInterp {
}
_ => {
trace!("CommandSchema: Unknown enum: {}", enum_variant);
reject_on(core::file!(), core::line!()).await
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
Expand Down Expand Up @@ -275,7 +292,14 @@ impl<BS: Clone + Readable> AsyncParser<ArgumentSchema, BS> for DefaultInterp {
.await,
)
}
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
}
Expand Down Expand Up @@ -316,13 +340,27 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<ProgrammableTransacti
recipient_index = Some(i);
}
// Reject on multiple RecipientAddress(s)
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
},
CallArg::Amount(amt) =>
{
#[allow(clippy::single_match)]
match amounts.try_push((amt, i)) {
Err(_) => reject_on(core::file!(), core::line!()).await,
Err(_) => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
_ => {}
}
}
Expand All @@ -332,7 +370,12 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<ProgrammableTransacti
}

if recipient_index.is_none() || amounts.is_empty() {
reject_on::<()>(core::file!(), core::line!()).await;
reject_on::<()>(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await;
}

let mut verified_recipient = false;
Expand All @@ -352,23 +395,47 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<ProgrammableTransacti
Command::TransferObject(_nested_results, recipient_input) => {
if verified_recipient {
// Reject more than one TransferObject(s)
reject_on::<()>(core::file!(), core::line!()).await;
reject_on::<()>(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await;
}
match recipient_input {
Argument::Input(inp_index) => {
if Some(inp_index as u32) != recipient_index {
trace!("TransferObject recipient mismatch");
reject_on::<()>(core::file!(), core::line!()).await;
reject_on::<()>(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await;
}
verified_recipient = true;
}
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
Command::SplitCoins(coin, input_indices) => {
match coin {
Argument::GasCoin => {}
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
for arg in &input_indices {
match arg {
Expand All @@ -378,14 +445,25 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<ProgrammableTransacti
match total_amount.checked_add(*amt) {
Some(t) => total_amount = t,
None => {
reject_on(core::file!(), core::line!())
.await
reject_on(
core::file!(),
core::line!(),
SyscallError::InvalidParameter as u16,
)
.await
}
}
}
}
}
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
}
Expand All @@ -394,7 +472,12 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<ProgrammableTransacti
}

if !verified_recipient {
reject_on::<()>(core::file!(), core::line!()).await;
reject_on::<()>(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await;
}

if PROMPT
Expand All @@ -415,7 +498,7 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<ProgrammableTransacti
},
)
{
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
}
}
}
Expand Down Expand Up @@ -444,7 +527,12 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<TransactionKind<PROMP
}
_ => {
trace!("TransactionKind: {}", enum_variant);
reject_on(core::file!(), core::line!()).await
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
Expand Down Expand Up @@ -492,7 +580,14 @@ impl<BS: Clone + Readable> AsyncParser<TransactionExpiration, BS> for DefaultInt
trace!("TransactionExpiration: Epoch");
<DefaultInterp as AsyncParser<EpochId, BS>>::parse(&DefaultInterp, input).await;
}
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
}
Expand Down Expand Up @@ -568,7 +663,14 @@ impl<BS: Clone + Readable, const PROMPT: bool> AsyncParser<TransactionData<PROMP
trace!("TransactionData: V1");
transaction_data_v1_parser::<_, PROMPT>().parse(input).await;
}
_ => reject_on(core::file!(), core::line!()).await,
_ => {
reject_on(
core::file!(),
core::line!(),
SyscallError::NotSupported as u16,
)
.await
}
}
}
}
Expand All @@ -582,7 +684,7 @@ const fn tx_parser<BS: Clone + Readable, const PROMPT: bool>(
pub async fn sign_apdu(io: HostIO, settings: Settings) {
let mut input = match io.get_params::<2>() {
Some(v) => v,
None => reject().await,
None => reject(SyscallError::InvalidParameter as u16).await,
};

// Read length, and move input[0] by one byte
Expand All @@ -601,14 +703,14 @@ pub async fn sign_apdu(io: HostIO, settings: Settings) {

if known_txn {
if scroller("Transfer", |w| Ok(write!(w, "SUI")?)).is_none() {
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
};
{
let mut bs = input[1].clone();
NoinlineFut(async move {
let path = BIP_PATH_PARSER.parse(&mut bs).await;
if !path.starts_with(&BIP32_PREFIX[0..2]) {
reject::<()>().await;
reject::<()>(SyscallError::InvalidParameter as u16).await;
}
if with_public_keys(&path, true, |_, address: &SuiPubKeyAddress| {
try_option(|| -> Option<()> {
Expand All @@ -619,7 +721,7 @@ pub async fn sign_apdu(io: HostIO, settings: Settings) {
.ok()
.is_none()
{
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
}
})
.await
Expand All @@ -635,7 +737,7 @@ pub async fn sign_apdu(io: HostIO, settings: Settings) {
};

if final_accept_prompt(&["Sign Transaction?"]).is_none() {
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
};
} else if settings.get() == 0 {
scroller("WARNING", |w| {
Expand All @@ -644,9 +746,9 @@ pub async fn sign_apdu(io: HostIO, settings: Settings) {
"Transaction not recognized, enable blind signing to sign unknown transactions"
)?)
});
reject::<()>().await;
reject::<()>(SyscallError::NotSupported as u16).await;
} else if scroller("WARNING", |w| Ok(write!(w, "Transaction not recognized")?)).is_none() {
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
}

// By the time we get here, we've approved and just need to do the signature.
Expand All @@ -668,20 +770,20 @@ pub async fn sign_apdu(io: HostIO, settings: Settings) {
let hash: HexHash<32> = hasher.finalize();
if !known_txn {
if scroller("Transaction Hash", |w| Ok(write!(w, "0x{hash}")?)).is_none() {
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
};
if final_accept_prompt(&["Blind Sign Transaction?"]).is_none() {
reject::<()>().await;
reject::<()>(StatusWords::UserCancelled as u16).await;
};
}
let path = BIP_PATH_PARSER.parse(&mut input[1].clone()).await;
if !path.starts_with(&BIP32_PREFIX[0..2]) {
reject::<()>().await;
reject::<()>(SyscallError::InvalidParameter as u16).await;
}
if let Some(sig) = { eddsa_sign(&path, true, &hash.0).ok() } {
io.result_final(&sig.0[0..]).await;
} else {
reject::<()>().await;
reject::<()>(SyscallError::Unspecified as u16).await;
}
})
.await
Expand Down
Loading