Skip to content

Commit

Permalink
bitcoin: allow spending UTXOs at very high address indices
Browse files Browse the repository at this point in the history
In a BIP-44 keypath `m/purpose/coin/account/{0,1}/addressIdx`, we
disallow addressIdx >= 10000 when verifying receive addresses to
mitigate ransom attacks (attacker as victim verify an address at a
very high index, so the victim cannot find the funds).

The same check is applied to change outputs in transactions for the
same reason.

We also had the same check for inputs in the transaction, but there,
the check is not necessary. We want to be able to spend UTXOs that
were received on high indices.
  • Loading branch information
benma committed Jun 5, 2024
1 parent 06cc039 commit 01ef5ea
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 156 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ customers cannot upgrade their bootloader, its changes are recorded separately.
### [Unreleased]
- Bitcoin: add support for payment requests
- Bitcoin: allow multisig accounts at arbitrary keypaths
- Bitcoin: allow spendung UTXOs at very high BIP-44 address indices
- Ethereum: allow signing EIP-712 messages containing multi-line strings

### 9.18.0
Expand Down
7 changes: 5 additions & 2 deletions src/rust/bitbox02-rust/src/hww/api/bitcoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ pub fn derive_address_simple(
coin_params.bip44_coin,
simple_type,
coin_params.taproot_support,
keypath::ReceiveSpend::Receive,
)
.or(Err(Error::InvalidInput))?;
Ok(common::Payload::from_simple(
Expand Down Expand Up @@ -194,7 +195,8 @@ pub async fn address_multisig(
display: bool,
) -> Result<Response, Error> {
let coin_params = params::get(coin);
keypath::validate_address_policy(keypath).or(Err(Error::InvalidInput))?;
keypath::validate_address_policy(keypath, keypath::ReceiveSpend::Receive)
.or(Err(Error::InvalidInput))?;
let account_keypath = &keypath[..keypath.len() - 2];
multisig::validate(multisig, account_keypath)?;
let name = match multisig::get_name(coin, multisig, account_keypath)? {
Expand Down Expand Up @@ -233,7 +235,8 @@ async fn address_policy(
) -> Result<Response, Error> {
let coin_params = params::get(coin);

keypath::validate_address_policy(keypath).or(Err(Error::InvalidInput))?;
keypath::validate_address_policy(keypath, keypath::ReceiveSpend::Receive)
.or(Err(Error::InvalidInput))?;

let parsed = policies::parse(policy)?;
parsed.validate(coin)?;
Expand Down
Loading

0 comments on commit 01ef5ea

Please sign in to comment.