Skip to content

Commit

Permalink
legacy: refactor path_mismatched function and revert its logic
Browse files Browse the repository at this point in the history
  • Loading branch information
prusnak committed Aug 5, 2020
1 parent 8d39ba8 commit 568da98
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 79 deletions.
99 changes: 99 additions & 0 deletions legacy/firmware/crypto.c
Expand Up @@ -507,3 +507,102 @@ int cryptoIdentityFingerprint(const IdentityType *identity, uint8_t *hash) {
sha256_Final(&ctx, hash);
return 1;
}

bool coin_known_path_check(const CoinInfo *coin, InputScriptType script_type,
uint32_t address_n_count, const uint32_t *address_n,
bool full) {
bool valid = true;
// m/44' : BIP44 Legacy
// m / purpose' / coin_type' / account' / change / address_index
if (address_n_count > 0 && address_n[0] == (0x80000000 + 44)) {
valid &= (script_type == InputScriptType_SPENDADDRESS);
if (full) {
valid &= (address_n_count == 5);
} else {
valid &= (address_n_count >= 2);
}
valid &= (address_n[1] == coin->coin_type);
if (full) {
valid &= (address_n[2] & 0x80000000) == 0x80000000;
valid &= (address_n[3] & 0x80000000) == 0;
valid &= (address_n[4] & 0x80000000) == 0;
}
return valid;
}

// m/45' - BIP45 Copay Abandoned Multisig P2SH
// m / purpose' / cosigner_index / change / address_index
if (address_n_count > 0 && address_n[0] == (0x80000000 + 45)) {
valid &= (script_type == InputScriptType_SPENDMULTISIG);
if (full) {
valid &= (address_n_count == 4);
valid &= (address_n[1] & 0x80000000) == 0;
valid &= (address_n[2] & 0x80000000) == 0;
valid &= (address_n[3] & 0x80000000) == 0;
}
return valid;
}

// 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 (address_n_count > 0 && address_n[0] == (0x80000000 + 48)) {
valid &= (script_type == InputScriptType_SPENDMULTISIG) ||
(script_type == InputScriptType_SPENDP2SHWITNESS) ||
(script_type == InputScriptType_SPENDWITNESS);
if (full) {
valid &= (address_n_count == 5) || (address_n_count == 6);
} else {
valid &= (address_n_count >= 2);
}
valid &= (address_n[1] == coin->coin_type);
if (full) {
valid &= (address_n[2] & 0x80000000) == 0x80000000;
valid &= (address_n[4] & 0x80000000) == 0;
}
return valid;
}

// m/49' : BIP49 SegWit
// m / purpose' / coin_type' / account' / change / address_index
if (address_n_count > 0 && address_n[0] == (0x80000000 + 49)) {
valid &= (script_type == InputScriptType_SPENDP2SHWITNESS);
valid &= coin->has_segwit;
if (full) {
valid &= (address_n_count == 5);
} else {
valid &= (address_n_count >= 2);
}
valid &= (address_n[1] == coin->coin_type);
if (full) {
valid &= (address_n[2] & 0x80000000) == 0x80000000;
valid &= (address_n[3] & 0x80000000) == 0;
valid &= (address_n[4] & 0x80000000) == 0;
}
return valid;
}

// m/84' : BIP84 Native SegWit
// m / purpose' / coin_type' / account' / change / address_index
if (address_n_count > 0 && address_n[0] == (0x80000000 + 84)) {
valid &= (script_type == InputScriptType_SPENDWITNESS);
valid &= coin->has_segwit;
valid &= coin->bech32_prefix != NULL;
if (full) {
valid &= (address_n_count == 5);
} else {
valid &= (address_n_count >= 2);
}
valid &= (address_n[1] == coin->coin_type);
if (full) {
valid &= (address_n[2] & 0x80000000) == 0x80000000;
valid &= (address_n[3] & 0x80000000) == 0;
valid &= (address_n[4] & 0x80000000) == 0;
}
return valid;
}

// we don't check unknown paths
return true;
}
4 changes: 4 additions & 0 deletions legacy/firmware/crypto.h
Expand Up @@ -82,4 +82,8 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,

int cryptoIdentityFingerprint(const IdentityType *identity, uint8_t *hash);

bool coin_known_path_check(const CoinInfo *coin, InputScriptType script_type,
uint32_t address_n_count, const uint32_t *address_n,
bool full);

#endif
81 changes: 2 additions & 79 deletions legacy/firmware/fsm_msg_coin.h
Expand Up @@ -121,82 +121,6 @@ void fsm_msgTxAck(TxAck *msg) {
signing_txack(&(msg->tx));
}

static bool path_mismatched(const CoinInfo *coin, const GetAddress *msg) {
bool mismatch = false;

// m : no path
if (msg->address_n_count == 0) {
return false;
}

// m/44' : BIP44 Legacy
// m / purpose' / coin_type' / account' / change / address_index
if (msg->address_n[0] == (0x80000000 + 44)) {
mismatch |= (msg->script_type != InputScriptType_SPENDADDRESS);
mismatch |= (msg->address_n_count != 5);
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;
}

// m/45' - BIP45 Copay Abandoned Multisig P2SH
// m / purpose' / cosigner_index / change / address_index
if (msg->address_n[0] == (0x80000000 + 45)) {
mismatch |= (msg->script_type != InputScriptType_SPENDMULTISIG);
mismatch |= (msg->address_n_count != 4);
mismatch |= (msg->address_n[1] & 0x80000000) == 0x80000000;
mismatch |= (msg->address_n[2] & 0x80000000) == 0x80000000;
mismatch |= (msg->address_n[3] & 0x80000000) == 0x80000000;
return mismatch;
}

// 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) &&
(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[4] & 0x80000000) == 0x80000000;
return mismatch;
}

// m/49' : BIP49 SegWit
// m / purpose' / coin_type' / account' / change / address_index
if (msg->address_n[0] == (0x80000000 + 49)) {
mismatch |= (msg->script_type != InputScriptType_SPENDP2SHWITNESS);
mismatch |= !coin->has_segwit;
mismatch |= (msg->address_n_count != 5);
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;
}

// m/84' : BIP84 Native SegWit
// m / purpose' / coin_type' / account' / change / address_index
if (msg->address_n[0] == (0x80000000 + 84)) {
mismatch |= (msg->script_type != InputScriptType_SPENDWITNESS);
mismatch |= !coin->has_segwit;
mismatch |= !coin->bech32_prefix;
mismatch |= (msg->address_n_count != 5);
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;
}

return false;
}

void fsm_msgGetAddress(const GetAddress *msg) {
RESP_INIT(Address);

Expand Down Expand Up @@ -239,9 +163,8 @@ void fsm_msgGetAddress(const GetAddress *msg) {
strlcpy(desc, _("Address:"), sizeof(desc));
}

bool mismatch = path_mismatched(coin, msg);

if (mismatch) {
if (!coin_known_path_check(coin, msg->script_type, msg->address_n_count,
msg->address_n, true)) {
layoutDialogSwipe(&bmp_icon_warning, _("Abort"), _("Continue"), NULL,
_("Wrong address path"), _("for selected coin."), NULL,
_("Continue at your"), _("own risk!"), NULL);
Expand Down
4 changes: 4 additions & 0 deletions legacy/firmware/signing.c
Expand Up @@ -466,6 +466,10 @@ bool compile_input_script_sig(TxInputType *tinput) {
return false;
}
}
if (!coin_known_path_check(coin, tinput->script_type, tinput->address_n_count,
tinput->address_n, false)) {
return false;
}
memcpy(&node, &root, sizeof(HDNode));
if (hdnode_private_ckd_cached(&node, tinput->address_n,
tinput->address_n_count, NULL) == 0) {
Expand Down

0 comments on commit 568da98

Please sign in to comment.