Skip to content
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
21 changes: 13 additions & 8 deletions src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use util::bip32::HARDENED;

use crate::bip32;
use crate::hal::{Memory, Ui};
use crate::workflow::confirm;
use crate::xpubcache::Bip32XpubCache;

use bitcoin::taproot::{LeafVersion, TapLeafHash, TapTweakHash};
Expand Down Expand Up @@ -395,15 +396,17 @@ impl ParsedPolicy<'_> {
})
.await?;

hal.ui()
.confirm(&ConfirmParams {
confirm::confirm_value(
hal,
&ConfirmParams {
title: "Name",
body: name,
scrollable: true,
accept_is_nextarrow: true,
..Default::default()
})
.await?;
},
)
.await?;

if matches!(mode, Mode::Basic) {
if let Err(crate::hal::ui::UserAbort) = hal
Expand All @@ -419,15 +422,17 @@ impl ParsedPolicy<'_> {
}
}

hal.ui()
.confirm(&ConfirmParams {
confirm::confirm_value(
hal,
&ConfirmParams {
title: "Policy",
body: &policy.policy,
scrollable: true,
accept_is_nextarrow: true,
..Default::default()
})
.await?;
},
)
.await?;

let output_xpub_type = match params.coin {
BtcCoin::Btc | BtcCoin::Ltc => bip32::XPubType::Xpub,
Expand Down
46 changes: 46 additions & 0 deletions src/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ mod tests {
use crate::hal::testing::TestingHal;
use crate::hal::testing::ui::Screen;
use crate::keystore::testing::mock_unlocked;
use crate::workflow::confirm::{MAX_CONFIRM_BODY_SIZE, TRUNCATION_WARNING_BODY};
use alloc::boxed::Box;
use util::bip32::HARDENED;

Expand Down Expand Up @@ -189,6 +190,51 @@ mod tests {
);
}

#[async_test::test]
pub async fn test_p2wpkh_long_message_warning() {
let msg = "m".repeat(MAX_CONFIRM_BODY_SIZE + 1);
let request = pb::BtcSignMessageRequest {
coin: BtcCoin::Btc as _,
script_config: Some(pb::BtcScriptConfigWithKeypath {
script_config: Some(pb::BtcScriptConfig {
config: Some(Config::SimpleType(SimpleType::P2wpkh as _)),
}),
keypath: vec![84 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 0],
}),
msg: msg.as_bytes().to_vec(),
host_nonce_commitment: None,
};

mock_unlocked();
let mut mock_hal = TestingHal::new();
assert!(process(&mut mock_hal, &request).await.is_ok());
assert_eq!(
mock_hal.ui.screens,
vec![
Screen::Confirm {
title: "Sign message".into(),
body: "Coin: Bitcoin".into(),
longtouch: false,
},
Screen::Confirm {
title: "Address".into(),
body: "bc1q k5f9 em9q c8yf pks8 ngfg 3h8h 02n2 e3ye qdyh pt".into(),
longtouch: false,
},
Screen::Confirm {
title: "Warning".into(),
body: TRUNCATION_WARNING_BODY.into(),
longtouch: false,
},
Screen::Confirm {
title: "Sign message".into(),
body: msg,
longtouch: true,
},
]
);
}

#[async_test::test]
pub async fn test_p2wpkh_testnet() {
let request = pb::BtcSignMessageRequest {
Expand Down
4 changes: 1 addition & 3 deletions src/rust/bitbox02-rust/src/hww/api/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ use pb::eth_response::Response;

use core::convert::TryInto;

// Keep this in sync with src/ui/components/label.h:MAX_LABEL_SIZE. `MAX_CONFIRM_BODY_SIZE` is the
// effective confirmation body limit and intentionally matches that UI label size limit.
const MAX_CONFIRM_BODY_SIZE: usize = 640;
use crate::workflow::confirm::MAX_CONFIRM_BODY_SIZE;

/// Returns how many bytes of hex-encoded data to include in a preview body.
///
Expand Down
23 changes: 8 additions & 15 deletions src/rust/bitbox02-rust/src/hww/api/ethereum/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use super::super::payment_request;
use super::Error;
use super::MAX_CONFIRM_BODY_SIZE;
use super::amount::{Amount, calculate_percentage};
use super::params::Params;
use super::pb;
Expand All @@ -13,6 +12,7 @@ use crate::hal::ui::ConfirmParams;
use crate::keystore;

use crate::hal::Ui;
use crate::workflow::confirm;
use crate::workflow::transaction;

use alloc::string::String;
Expand Down Expand Up @@ -452,26 +452,18 @@ async fn verify_standard_transaction(
} else {
(request.data().len(), hex::encode(request.data()))
};
if body.len() > MAX_CONFIRM_BODY_SIZE {
hal.ui()
.confirm(&ConfirmParams {
title: "Warning",
body: "The next value is\ntoo large to display\nin full",
accept_is_nextarrow: true,
..Default::default()
})
.await?;
}
hal.ui()
.confirm(&ConfirmParams {
confirm::confirm_value(
hal,
&ConfirmParams {
title: "Transaction\ndata",
body: &body,
scrollable: true,
display_size,
accept_is_nextarrow: true,
..Default::default()
})
.await?;
},
)
.await?;
}

let address = super::address::from_pubkey_hash(&recipient, request.case()?);
Expand Down Expand Up @@ -659,6 +651,7 @@ mod tests {
use crate::hal::testing::TestingHal;
use crate::hal::testing::ui::Screen;
use crate::keystore::testing::mock_unlocked;
use crate::workflow::confirm::MAX_CONFIRM_BODY_SIZE;
use alloc::boxed::Box;
use util::bip32::HARDENED;

Expand Down
23 changes: 8 additions & 15 deletions src/rust/bitbox02-rust/src/hww/api/ethereum/sign_typed_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
//! using SignTypedDataVersion.V4.

use super::Error;
use super::MAX_CONFIRM_BODY_SIZE;
use super::pb;
use super::sighash::DataProducer;
use super::truncating_hex_preview_byte_cap;

use crate::hal::Ui;
use crate::hal::ui::ConfirmParams;
use crate::keystore;
use crate::workflow::confirm;

use pb::eth_request::Request;
use pb::eth_response::Response;
Expand Down Expand Up @@ -427,18 +427,9 @@ async fn encode_member<U: sha3::digest::Update>(
let lines: Vec<&str> = value_formatted.split('\n').collect();
for (i, &line) in lines.iter().enumerate() {
let body = format_display_line_body(&display_path, i, lines.len(), line);
if body.len() > MAX_CONFIRM_BODY_SIZE {
hal.ui()
.confirm(&ConfirmParams {
title: "Warning",
body: "The next value is\ntoo large to display\nin full",
accept_is_nextarrow: true,
..Default::default()
})
.await?;
}
hal.ui()
.confirm(&ConfirmParams {
confirm::confirm_value(
hal,
&ConfirmParams {
title: &format!(
"{}{}",
confirm_title(context.root_object),
Expand All @@ -449,8 +440,9 @@ async fn encode_member<U: sha3::digest::Update>(
display_size,
accept_is_nextarrow: true,
..Default::default()
})
.await?;
},
)
.await?;
}
}
Ok(())
Expand Down Expand Up @@ -741,6 +733,7 @@ mod tests {
use crate::hal::testing::TestingHal;
use crate::hal::testing::ui::Screen;
use crate::keystore::testing::mock_unlocked;
use crate::workflow::confirm::MAX_CONFIRM_BODY_SIZE;
use util::bip32::HARDENED;

use alloc::boxed::Box;
Expand Down
43 changes: 43 additions & 0 deletions src/rust/bitbox02-rust/src/hww/api/ethereum/signmsg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ mod tests {
use crate::hal::testing::TestingHal;
use crate::hal::testing::ui::Screen;
use crate::keystore::testing::mock_unlocked;
use crate::workflow::confirm::{MAX_CONFIRM_BODY_SIZE, TRUNCATION_WARNING_BODY};
use alloc::boxed::Box;
use hex_lit::hex;
use util::bip32::HARDENED;
Expand Down Expand Up @@ -143,6 +144,48 @@ mod tests {
);
}

#[async_test::test]
pub async fn test_process_long_message_warning() {
let msg = "m".repeat(MAX_CONFIRM_BODY_SIZE + 1);

mock_unlocked();
let mut mock_hal = TestingHal::new();
assert!(
process(
&mut mock_hal,
&pb::EthSignMessageRequest {
coin: pb::EthCoin::Eth as _,
keypath: KEYPATH.to_vec(),
msg: msg.as_bytes().to_vec(),
host_nonce_commitment: None,
chain_id: 0,
},
)
.await
.is_ok()
);
assert_eq!(
mock_hal.ui.screens,
vec![
Screen::Confirm {
title: "Ethereum".into(),
body: EXPECTED_ADDRESS.into(),
longtouch: false,
},
Screen::Confirm {
title: "Warning".into(),
body: TRUNCATION_WARNING_BODY.into(),
longtouch: false,
},
Screen::Confirm {
title: "Sign message".into(),
body: msg,
longtouch: true,
},
]
);
}

#[async_test::test]
pub async fn test_process_warn_unusual_keypath() {
const SIGNATURE: [u8; 64] = [b'1'; 64];
Expand Down
1 change: 1 addition & 0 deletions src/rust/bitbox02-rust/src/workflow.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: Apache-2.0

pub mod confirm;
#[cfg_attr(
all(feature = "c-unit-testing", not(feature = "testing")),
path = "workflow/mnemonic_c_unit_tests.rs"
Expand Down
31 changes: 31 additions & 0 deletions src/rust/bitbox02-rust/src/workflow/confirm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: Apache-2.0

use crate::hal::Ui;
use crate::hal::ui::{ConfirmParams, UserAbort};

// Keep this in sync with src/ui/components/label.h:MAX_LABEL_SIZE. `MAX_CONFIRM_BODY_SIZE` is the
// effective confirmation body limit and intentionally matches that UI label size limit.
pub(crate) const MAX_CONFIRM_BODY_SIZE: usize = 640;

pub(crate) const TRUNCATION_WARNING_BODY: &str = "The next value is\ntoo large to display\nin full";

/// Confirm a potentially long value.
///
/// If the value exceeds the UI label limit, the UI will truncate it with `...`, so warn the user
/// before showing it.
pub(crate) async fn confirm_value(
hal: &mut impl crate::hal::Hal,
params: &ConfirmParams<'_>,
) -> Result<(), UserAbort> {
if params.body.len() > MAX_CONFIRM_BODY_SIZE {
hal.ui()
.confirm(&ConfirmParams {
title: "Warning",
body: TRUNCATION_WARNING_BODY,
accept_is_nextarrow: true,
..Default::default()
})
.await?;
}
hal.ui().confirm(params).await
}
Loading
Loading