From def96032d2b4e168a017b3f8a9c00dd5ce6a4a82 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 23 Apr 2019 18:16:37 +0200 Subject: [PATCH] core+legacy: make path checks more benevolent (#84) Non-existing BIP-48 is causing mess among implementations --- core/src/apps/wallet/sign_tx/addresses.py | 42 ++++++++++++++--------- legacy/firmware/fsm_msg_coin.h | 9 +++-- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/core/src/apps/wallet/sign_tx/addresses.py b/core/src/apps/wallet/sign_tx/addresses.py index ff6e93c3a..d9d44d3f0 100644 --- a/core/src/apps/wallet/sign_tx/addresses.py +++ b/core/src/apps/wallet/sign_tx/addresses.py @@ -204,7 +204,7 @@ def validate_full_path( See docs/coins for what paths are allowed. Please note that this is not a comprehensive check, some nuances are omitted for simplification. """ - if len(path) != 5: + if len(path) not in (4, 5, 6): return False if not validate_purpose(path[0], coin): @@ -214,21 +214,29 @@ def validate_full_path( ): return False - if path[1] != coin.slip44 | HARDENED: + if path[1] > 20 and path[1] != coin.slip44 | HARDENED: return False - if path[2] < HARDENED or path[2] > 20 | HARDENED: + if (path[2] > 20 and path[2] < HARDENED) or path[2] > 20 | HARDENED: + return False + if path[3] not in (0, 1, 0 | HARDENED, 1 | HARDENED, 2 | HARDENED): return False - if path[3] not in [0, 1]: + if len(path) > 4 and path[4] > 1000000: return False - if path[4] > 1000000: + if len(path) > 5 and path[5] > 1000000: return False return True def validate_purpose(purpose: int, coin: CoinInfo) -> bool: - if purpose not in (44 | HARDENED, 48 | HARDENED, 49 | HARDENED, 84 | HARDENED): + if purpose not in ( + 44 | HARDENED, + 45 | HARDENED, + 48 | HARDENED, + 49 | HARDENED, + 84 | HARDENED, + ): return False - if not coin.segwit and purpose not in (44 | HARDENED, 48 | HARDENED): + if not coin.segwit and purpose not in (44 | HARDENED, 45 | HARDENED, 48 | HARDENED): return False return True @@ -239,21 +247,23 @@ def validate_purpose_against_script_type( """ Validates purpose against provided input's script type: - 44 for spending address (script_type == SPENDADDRESS) - - 48 for multisig (script_type == SPENDMULTISIG) - - 49 for p2sh-segwit spend (script_type == SPENDP2SHWITNESS) - - 84 for native segwit spend (script_type == SPENDWITNESS) + - 45, 48 for multisig (script_type == SPENDMULTISIG) + - 49 for p2wsh-nested-in-p2sh spend (script_type == SPENDP2SHWITNESS) + - 84 for p2wsh native segwit spend (script_type == SPENDWITNESS) """ if purpose == 44 | HARDENED and script_type != InputScriptType.SPENDADDRESS: return False - if purpose == 48 | HARDENED and script_type != InputScriptType.SPENDMULTISIG: + if purpose == 45 | HARDENED and script_type != InputScriptType.SPENDMULTISIG: return False - if ( # p2wsh-nested-in-p2sh - purpose == 49 | HARDENED and script_type != InputScriptType.SPENDP2SHWITNESS + if purpose == 48 | HARDENED and script_type not in ( + InputScriptType.SPENDMULTISIG, + InputScriptType.SPENDP2SHWITNESS, + InputScriptType.SPENDWITNESS, ): return False - if ( # p2wsh - purpose == 84 | HARDENED and script_type != InputScriptType.SPENDWITNESS - ): + if purpose == 49 | HARDENED and script_type != InputScriptType.SPENDP2SHWITNESS: + return False + if purpose == 84 | HARDENED and script_type != InputScriptType.SPENDWITNESS: return False return True diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index 30b5e1747..dc3a94e52 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -147,12 +147,15 @@ static bool path_mismatched(const CoinInfo *coin, const GetAddress *msg) { // m/48' - BIP48 Copay Multisig P2SH // m / purpose' / coin_type' / account' / change / address_index + // Electrum: + // m / purpose' / coin_type' / account' / type' / change / address_index if (msg->address_n[0] == (0x80000000 + 48)) { - mismatch |= (msg->script_type != InputScriptType_SPENDMULTISIG); - mismatch |= (msg->address_n_count != 5); + mismatch |= (msg->script_type != InputScriptType_SPENDMULTISIG) && + (msg->script_type != InputScriptType_SPENDP2SHWITNESS) && + (msg->script_type != InputScriptType_SPENDWITNESS); + mismatch |= (msg->address_n_count != 5) && (msg->address_n_count != 6); mismatch |= (msg->address_n[1] != coin->coin_type); mismatch |= (msg->address_n[2] & 0x80000000) == 0; - mismatch |= (msg->address_n[3] & 0x80000000) == 0x80000000; mismatch |= (msg->address_n[4] & 0x80000000) == 0x80000000; return mismatch; }