mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
fix(legacy): Stricter Bitcoin transaction checks.
[no changelog]
This commit is contained in:
parent
09d143079b
commit
181fd1c601
@ -1370,7 +1370,12 @@ static void tx_info_finish(TxInfo *tx_info) {
|
|||||||
|
|
||||||
static bool signing_add_input(TxInputType *txinput) {
|
static bool signing_add_input(TxInputType *txinput) {
|
||||||
// hash all input data to check it later (relevant for fee computation)
|
// hash all input data to check it later (relevant for fee computation)
|
||||||
tx_input_check_hash(&hasher_check, txinput);
|
if (!tx_input_check_hash(&hasher_check, txinput)) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_ProcessError,
|
||||||
|
_("Failed to hash input"));
|
||||||
|
signing_abort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fsm_checkCoinPath(coin, txinput->script_type, txinput->address_n_count,
|
if (!fsm_checkCoinPath(coin, txinput->script_type, txinput->address_n_count,
|
||||||
txinput->address_n, txinput->has_multisig, true)) {
|
txinput->address_n, txinput->has_multisig, true)) {
|
||||||
@ -1634,8 +1639,13 @@ static bool signing_add_orig_input(TxInputType *orig_input) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first original input that has address_n set and a signature gets chosen
|
// The first original non-multisig input that has address_n set and a
|
||||||
// as the verification input. Set script_sig for legacy digest computation.
|
// signature gets chosen as the verification input. Set script_sig for legacy
|
||||||
|
// digest computation.
|
||||||
|
// NOTE: Supporting replacement transactions where all internal inputs are
|
||||||
|
// multisig would require checking the signatures of all of the original
|
||||||
|
// internal inputs or not allowing unverified external inputs in transactions
|
||||||
|
// where multisig inputs are present.
|
||||||
if (!have_orig_verif_input && orig_input->address_n_count != 0 &&
|
if (!have_orig_verif_input && orig_input->address_n_count != 0 &&
|
||||||
!orig_input->has_multisig &&
|
!orig_input->has_multisig &&
|
||||||
((orig_input->has_script_sig && orig_input->script_sig.size != 0) ||
|
((orig_input->has_script_sig && orig_input->script_sig.size != 0) ||
|
||||||
@ -2736,7 +2746,12 @@ void signing_txack(TransactionType *tx) {
|
|||||||
if (idx1 == 0) {
|
if (idx1 == 0) {
|
||||||
hasher_Reset(&hasher_check);
|
hasher_Reset(&hasher_check);
|
||||||
}
|
}
|
||||||
tx_input_check_hash(&hasher_check, tx->inputs);
|
if (!tx_input_check_hash(&hasher_check, tx->inputs)) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_ProcessError,
|
||||||
|
_("Failed to hash input"));
|
||||||
|
signing_abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&input, tx->inputs, sizeof(TxInputType));
|
memcpy(&input, tx->inputs, sizeof(TxInputType));
|
||||||
|
|
||||||
@ -2943,7 +2958,12 @@ void signing_txack(TransactionType *tx) {
|
|||||||
hasher_Reset(&hasher_check);
|
hasher_Reset(&hasher_check);
|
||||||
}
|
}
|
||||||
// check inputs are the same as those in phase 1
|
// check inputs are the same as those in phase 1
|
||||||
tx_input_check_hash(&hasher_check, tx->inputs);
|
if (!tx_input_check_hash(&hasher_check, tx->inputs)) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_ProcessError,
|
||||||
|
_("Failed to hash input"));
|
||||||
|
signing_abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (idx2 == idx1) {
|
if (idx2 == idx1) {
|
||||||
if (!tx_info_check_input(&info, &tx->inputs[0]) ||
|
if (!tx_info_check_input(&info, &tx->inputs[0]) ||
|
||||||
!derive_node(&tx->inputs[0]) ||
|
!derive_node(&tx->inputs[0]) ||
|
||||||
|
@ -556,22 +556,37 @@ uint32_t serialize_script_multisig(const CoinInfo *coin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tx methods
|
// tx methods
|
||||||
void tx_input_check_hash(Hasher *hasher, const TxInputType *input) {
|
bool tx_input_check_hash(Hasher *hasher, const TxInputType *input) {
|
||||||
hasher_Update(hasher, input->prev_hash.bytes, sizeof(input->prev_hash.bytes));
|
|
||||||
hasher_Update(hasher, (const uint8_t *)&input->prev_index,
|
|
||||||
sizeof(input->prev_index));
|
|
||||||
hasher_Update(hasher, (const uint8_t *)&input->script_type,
|
|
||||||
sizeof(input->script_type));
|
|
||||||
hasher_Update(hasher, (const uint8_t *)&input->address_n_count,
|
hasher_Update(hasher, (const uint8_t *)&input->address_n_count,
|
||||||
sizeof(input->address_n_count));
|
sizeof(input->address_n_count));
|
||||||
for (int i = 0; i < input->address_n_count; ++i)
|
for (int i = 0; i < input->address_n_count; ++i)
|
||||||
hasher_Update(hasher, (const uint8_t *)&input->address_n[i],
|
hasher_Update(hasher, (const uint8_t *)&input->address_n[i],
|
||||||
sizeof(input->address_n[0]));
|
sizeof(input->address_n[0]));
|
||||||
|
hasher_Update(hasher, input->prev_hash.bytes, sizeof(input->prev_hash.bytes));
|
||||||
|
hasher_Update(hasher, (const uint8_t *)&input->prev_index,
|
||||||
|
sizeof(input->prev_index));
|
||||||
|
tx_script_hash(hasher, input->script_sig.size, input->script_sig.bytes);
|
||||||
hasher_Update(hasher, (const uint8_t *)&input->sequence,
|
hasher_Update(hasher, (const uint8_t *)&input->sequence,
|
||||||
sizeof(input->sequence));
|
sizeof(input->sequence));
|
||||||
|
hasher_Update(hasher, (const uint8_t *)&input->script_type,
|
||||||
|
sizeof(input->script_type));
|
||||||
|
uint8_t multisig_fp[32] = {0};
|
||||||
|
if (input->has_multisig) {
|
||||||
|
if (cryptoMultisigFingerprint(&input->multisig, multisig_fp) == 0) {
|
||||||
|
// Invalid multisig parameters.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasher_Update(hasher, multisig_fp, sizeof(multisig_fp));
|
||||||
hasher_Update(hasher, (const uint8_t *)&input->amount, sizeof(input->amount));
|
hasher_Update(hasher, (const uint8_t *)&input->amount, sizeof(input->amount));
|
||||||
|
tx_script_hash(hasher, input->witness.size, input->witness.bytes);
|
||||||
|
hasher_Update(hasher, (const uint8_t *)&input->has_orig_hash,
|
||||||
|
sizeof(input->has_orig_hash));
|
||||||
|
hasher_Update(hasher, input->orig_hash.bytes, sizeof(input->orig_hash.bytes));
|
||||||
|
hasher_Update(hasher, (const uint8_t *)&input->orig_index,
|
||||||
|
sizeof(input->orig_index));
|
||||||
tx_script_hash(hasher, input->script_pubkey.size, input->script_pubkey.bytes);
|
tx_script_hash(hasher, input->script_pubkey.size, input->script_pubkey.bytes);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input) {
|
uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input) {
|
||||||
|
@ -79,7 +79,7 @@ int compile_output(const CoinInfo *coin, AmountUnit amount_unit,
|
|||||||
int fill_input_script_pubkey(const CoinInfo *coin, const HDNode *root,
|
int fill_input_script_pubkey(const CoinInfo *coin, const HDNode *root,
|
||||||
TxInputType *in);
|
TxInputType *in);
|
||||||
|
|
||||||
void tx_input_check_hash(Hasher *hasher, const TxInputType *input);
|
bool tx_input_check_hash(Hasher *hasher, const TxInputType *input);
|
||||||
uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input);
|
uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input);
|
||||||
uint32_t tx_amount_hash(Hasher *hasher, const TxInputType *input);
|
uint32_t tx_amount_hash(Hasher *hasher, const TxInputType *input);
|
||||||
uint32_t tx_script_hash(Hasher *hasher, uint32_t size, const uint8_t *data);
|
uint32_t tx_script_hash(Hasher *hasher, uint32_t size, const uint8_t *data);
|
||||||
|
Loading…
Reference in New Issue
Block a user