mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-28 02:42:34 +00:00
Fix checking change address
There was a signed/unsigned problem: size_t is unsigned, but we use -1 to indicate mismatch. The problem was that when checking the input address path, it still did this unintentionally when a mismatch was detected, forbidding to sign with mismatched inputs, even when there is no change address. We now use 1 for mismatch. Also we don't allow change address anymore if the inputs have a path of length 1. This simplifies the code a bit.
This commit is contained in:
parent
5e98b0ffd6
commit
4805f27e8c
@ -68,6 +68,12 @@ static uint8_t multisig_fp[32];
|
|||||||
static uint32_t in_address_n[8];
|
static uint32_t in_address_n[8];
|
||||||
static size_t in_address_n_count;
|
static size_t in_address_n_count;
|
||||||
|
|
||||||
|
/* marker for in_address_n_count to indicate a mismatch in bip32 paths in
|
||||||
|
input */
|
||||||
|
#define BIP32_NOCHANGEALLOWED 1
|
||||||
|
/* maximum allowed change index */
|
||||||
|
#define MAX_BIP32_LAST_ELEMENT 1000000
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SIGHASH_ALL = 1,
|
SIGHASH_ALL = 1,
|
||||||
SIGHASH_FORKID = 0x40,
|
SIGHASH_FORKID = 0x40,
|
||||||
@ -328,61 +334,45 @@ void phase2_request_next_input(void)
|
|||||||
|
|
||||||
void extract_input_bip32_path(const TxInputType *tinput)
|
void extract_input_bip32_path(const TxInputType *tinput)
|
||||||
{
|
{
|
||||||
if (in_address_n_count == (size_t) -1) {
|
if (in_address_n_count == BIP32_NOCHANGEALLOWED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t count = tinput->address_n_count;
|
size_t count = tinput->address_n_count;
|
||||||
if (count < 1) {
|
if (count < 2) {
|
||||||
// no change address allowed
|
// no change address allowed
|
||||||
in_address_n_count = (size_t) -1;
|
in_address_n_count = BIP32_NOCHANGEALLOWED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (in_address_n_count == 0) {
|
if (in_address_n_count == 0) {
|
||||||
// initialize in_address_n on first input seen
|
// initialize in_address_n on first input seen
|
||||||
in_address_n_count = count;
|
in_address_n_count = count;
|
||||||
if (count > 2) { // if longer than 2 elements, store first N - 2
|
// store first N - 2
|
||||||
memcpy(in_address_n, tinput->address_n, (count - 2) * sizeof(uint32_t));
|
memcpy(in_address_n, tinput->address_n, (count - 2) * sizeof(uint32_t));
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// check whether they are same length
|
// check whether they are same length
|
||||||
if (in_address_n_count != count) {
|
if (in_address_n_count != count) {
|
||||||
in_address_n_count = (size_t) -1;
|
in_address_n_count = BIP32_NOCHANGEALLOWED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (count > 2 && memcmp(in_address_n, tinput->address_n, (count - 2) * sizeof(uint32_t)) != 0) {
|
if (memcmp(in_address_n, tinput->address_n, (count - 2) * sizeof(uint32_t)) != 0) {
|
||||||
// mismatch -> no change address allowed
|
// mismatch -> no change address allowed
|
||||||
in_address_n_count = (size_t) -1;
|
in_address_n_count = BIP32_NOCHANGEALLOWED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_BIP32_LAST_ELEMENT 1000000
|
|
||||||
|
|
||||||
bool check_change_bip32_path(const TxOutputType *toutput)
|
bool check_change_bip32_path(const TxOutputType *toutput)
|
||||||
{
|
{
|
||||||
size_t count = toutput->address_n_count;
|
size_t count = toutput->address_n_count;
|
||||||
|
|
||||||
if (count < 1 || in_address_n_count < 1) {
|
// Note: count >= 2 and count == in_address_n_count
|
||||||
return 0;
|
// imply that in_address_n_count != BIP32_NOCHANGEALLOWED
|
||||||
}
|
return (count >= 2
|
||||||
|
&& count == in_address_n_count
|
||||||
if (count != in_address_n_count) {
|
&& 0 == memcmp(in_address_n, toutput->address_n, (count - 2) * sizeof(uint32_t))
|
||||||
return 0;
|
&& toutput->address_n[count - 2] == 1
|
||||||
}
|
&& toutput->address_n[count - 1] <= MAX_BIP32_LAST_ELEMENT);
|
||||||
|
|
||||||
if (toutput->address_n[count - 1] > MAX_BIP32_LAST_ELEMENT) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count >= 2) {
|
|
||||||
if (0 != memcmp(in_address_n, toutput->address_n, (count - 2) * sizeof(uint32_t)) ||
|
|
||||||
toutput->address_n[count - 2] != 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compile_input_script_sig(TxInputType *tinput)
|
bool compile_input_script_sig(TxInputType *tinput)
|
||||||
@ -397,14 +387,12 @@ bool compile_input_script_sig(TxInputType *tinput)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (in_address_n_count >= 1) {
|
if (in_address_n_count != BIP32_NOCHANGEALLOWED) {
|
||||||
// check that input address didn't change
|
// check that input address didn't change
|
||||||
size_t count = tinput->address_n_count;
|
size_t count = tinput->address_n_count;
|
||||||
if (count != in_address_n_count) {
|
if (count < 2
|
||||||
return false;
|
|| count != in_address_n_count
|
||||||
}
|
|| 0 != memcmp(in_address_n, tinput->address_n, (count - 2) * sizeof(uint32_t))) {
|
||||||
if (count >= 2
|
|
||||||
&& 0 != memcmp(in_address_n, tinput->address_n, (count - 2) * sizeof(uint32_t))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user