mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 09:28:13 +00:00
firmware: implement zip143 overwinter
This commit is contained in:
parent
32a7db423c
commit
b73e18e573
@ -65,6 +65,8 @@ OBJS += ../vendor/trezor-crypto/ripemd160.o
|
||||
OBJS += ../vendor/trezor-crypto/sha2.o
|
||||
OBJS += ../vendor/trezor-crypto/sha3.o
|
||||
OBJS += ../vendor/trezor-crypto/blake256.o
|
||||
OBJS += ../vendor/trezor-crypto/blake2b.o
|
||||
OBJS += ../vendor/trezor-crypto/groestl.o
|
||||
OBJS += ../vendor/trezor-crypto/hasher.o
|
||||
|
||||
OBJS += ../vendor/trezor-crypto/aes/aescrypt.o
|
||||
@ -103,6 +105,7 @@ CFLAGS += -DDEBUG_LOG=$(DEBUG_LOG)
|
||||
CFLAGS += -DSCM_REVISION='"$(shell git rev-parse HEAD | sed 's:\(..\):\\x\1:g')"'
|
||||
CFLAGS += -DUSE_ETHEREUM=1
|
||||
CFLAGS += -DUSE_NEM=1
|
||||
CFLAGS += -DUSE_MONERO=0
|
||||
|
||||
define GENERATE_CODE
|
||||
# $(1) - Basename for script and output header file
|
||||
|
@ -64,6 +64,7 @@ static uint64_t to_spend, authorized_amount, spending, change_spend;
|
||||
static uint32_t version = 1;
|
||||
static uint32_t lock_time = 0;
|
||||
static uint32_t expiry = 0;
|
||||
static bool overwintered = false;
|
||||
static uint32_t next_nonsegwit_input;
|
||||
static uint32_t progress, progress_step, progress_meta_step;
|
||||
static bool multisig_fp_set, multisig_fp_mismatch;
|
||||
@ -479,6 +480,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, const HDNode *_root)
|
||||
version = msg->version;
|
||||
lock_time = msg->lock_time;
|
||||
expiry = msg->expiry;
|
||||
overwintered = msg->has_overwintered && msg->overwintered;
|
||||
|
||||
uint32_t size = TXSIZE_HEADER + TXSIZE_FOOTER + ser_length_size(inputs_count) + ser_length_size(outputs_count);
|
||||
if (coin->decred) {
|
||||
@ -508,22 +510,31 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, const HDNode *_root)
|
||||
multisig_fp_mismatch = false;
|
||||
next_nonsegwit_input = 0xffffffff;
|
||||
|
||||
tx_init(&to, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign);
|
||||
tx_init(&to, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign, overwintered);
|
||||
|
||||
if (coin->decred) {
|
||||
to.version |= (DECRED_SERIALIZE_FULL << 16);
|
||||
to.is_decred = true;
|
||||
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign);
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign, overwintered);
|
||||
ti.version |= (DECRED_SERIALIZE_NO_WITNESS << 16);
|
||||
ti.is_decred = true;
|
||||
}
|
||||
|
||||
hasher_Init(&hasher_prevouts, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_sequence, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_outputs, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_check, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_preimage, coin->curve->hasher_sign);
|
||||
// segwit hashes for hashPrevouts and hashSequence
|
||||
if (overwintered) {
|
||||
hasher_Init(&hasher_prevouts, HASHER_OVERWINTER_PREVOUTS);
|
||||
hasher_Init(&hasher_sequence, HASHER_OVERWINTER_SEQUENCE);
|
||||
hasher_Init(&hasher_outputs, HASHER_OVERWINTER_OUTPUTS);
|
||||
hasher_Init(&hasher_preimage, HASHER_OVERWINTER_PREIMAGE);
|
||||
hasher_Init(&hasher_check, coin->curve->hasher_sign);
|
||||
} else {
|
||||
hasher_Init(&hasher_prevouts, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_sequence, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_outputs, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_preimage, coin->curve->hasher_sign);
|
||||
hasher_Init(&hasher_check, coin->curve->hasher_sign);
|
||||
}
|
||||
|
||||
layoutProgressSwipe(_("Signing transaction"), 0);
|
||||
|
||||
@ -739,16 +750,39 @@ static void phase1_request_next_output(void) {
|
||||
static void signing_hash_bip143(const TxInputType *txinput, uint8_t *hash) {
|
||||
uint32_t hash_type = signing_hash_type();
|
||||
hasher_Reset(&hasher_preimage);
|
||||
hasher_Update(&hasher_preimage, (const uint8_t *)&version, 4);
|
||||
hasher_Update(&hasher_preimage, hash_prevouts, 32);
|
||||
hasher_Update(&hasher_preimage, hash_sequence, 32);
|
||||
tx_prevout_hash(&hasher_preimage, txinput);
|
||||
tx_script_hash(&hasher_preimage, txinput->script_sig.size, txinput->script_sig.bytes);
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*) &txinput->amount, 8);
|
||||
tx_sequence_hash(&hasher_preimage, txinput);
|
||||
hasher_Update(&hasher_preimage, hash_outputs, 32);
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*) &lock_time, 4);
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*) &hash_type, 4);
|
||||
hasher_Update(&hasher_preimage, (const uint8_t *)&version, 4); // nVersion
|
||||
hasher_Update(&hasher_preimage, hash_prevouts, 32); // hashPrevouts
|
||||
hasher_Update(&hasher_preimage, hash_sequence, 32); // hashSequence
|
||||
tx_prevout_hash(&hasher_preimage, txinput); // outpoint
|
||||
tx_script_hash(&hasher_preimage, txinput->script_sig.size, txinput->script_sig.bytes); // scriptCode
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*) &txinput->amount, 8); // amount
|
||||
tx_sequence_hash(&hasher_preimage, txinput); // nSequence
|
||||
hasher_Update(&hasher_preimage, hash_outputs, 32); // hashOutputs
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*)&lock_time, 4); // nLockTime
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*)&hash_type, 4); // nHashType
|
||||
hasher_Final(&hasher_preimage, hash);
|
||||
}
|
||||
|
||||
static void signing_hash_zip143(const TxInputType *txinput, uint8_t *hash) {
|
||||
uint32_t hash_type = signing_hash_type();
|
||||
hasher_Reset(&hasher_preimage);
|
||||
uint32_t ver = version | TX_OVERWINTERED; // 1. nVersion | fOverwintered
|
||||
hasher_Update(&hasher_preimage, (const uint8_t *)&ver, 4);
|
||||
hasher_Update(&hasher_preimage, (const uint8_t *)&coin->version_group_id, 4); // 2. nVersionGroupId
|
||||
hasher_Update(&hasher_preimage, hash_prevouts, 32); // 3. hashPrevouts
|
||||
hasher_Update(&hasher_preimage, hash_sequence, 32); // 4. hashSequence
|
||||
hasher_Update(&hasher_preimage, hash_outputs, 32); // 5. hashOutputs
|
||||
// 6. hashJoinSplits
|
||||
hasher_Update(&hasher_preimage, (const uint8_t *)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32);
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*)&lock_time, 4); // 7. nLockTime
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*)&expiry, 4); // 8. expiryHeight
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*)&hash_type, 4); // 9. nHashType
|
||||
|
||||
tx_prevout_hash(&hasher_preimage, txinput); // 10a. outpoint
|
||||
tx_script_hash(&hasher_preimage, txinput->script_sig.size, txinput->script_sig.bytes); // 10b. scriptCode
|
||||
hasher_Update(&hasher_preimage, (const uint8_t*)&txinput->amount, 8); // 10c. value
|
||||
tx_sequence_hash(&hasher_preimage, txinput); // 10d. nSequence
|
||||
|
||||
hasher_Final(&hasher_preimage, hash);
|
||||
}
|
||||
|
||||
@ -933,9 +967,9 @@ void signing_txack(TransactionType *tx)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (coin->force_bip143) {
|
||||
if (coin->force_bip143 || overwintered) {
|
||||
if (!tx->inputs[0].has_amount) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError, _("BIP 143 input without amount"));
|
||||
fsm_sendFailure(FailureType_Failure_DataError, _("BIP/ZIP 143 input without amount"));
|
||||
signing_abort();
|
||||
return;
|
||||
}
|
||||
@ -1011,7 +1045,7 @@ void signing_txack(TransactionType *tx)
|
||||
signing_abort();
|
||||
return;
|
||||
}
|
||||
tx_init(&tp, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, tx->expiry, tx->extra_data_len, coin->curve->hasher_sign);
|
||||
tx_init(&tp, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, tx->expiry, tx->extra_data_len, coin->curve->hasher_sign, overwintered);
|
||||
if (coin->decred) {
|
||||
tp.version |= (DECRED_SERIALIZE_NO_WITNESS << 16);
|
||||
tp.is_decred = true;
|
||||
@ -1094,7 +1128,7 @@ void signing_txack(TransactionType *tx)
|
||||
case STAGE_REQUEST_4_INPUT:
|
||||
progress = 500 + ((signatures * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION);
|
||||
if (idx2 == 0) {
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign);
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign, overwintered);
|
||||
hasher_Reset(&hasher_check);
|
||||
}
|
||||
// check prevouts and script type
|
||||
@ -1181,7 +1215,7 @@ void signing_txack(TransactionType *tx)
|
||||
resp.serialized.has_serialized_tx = true;
|
||||
if (tx->inputs[0].script_type == InputScriptType_SPENDMULTISIG
|
||||
|| tx->inputs[0].script_type == InputScriptType_SPENDADDRESS) {
|
||||
if (!coin->force_bip143) {
|
||||
if (!(coin->force_bip143 || overwintered)) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing"));
|
||||
signing_abort();
|
||||
return;
|
||||
@ -1199,7 +1233,11 @@ void signing_txack(TransactionType *tx)
|
||||
authorized_amount -= tx->inputs[0].amount;
|
||||
|
||||
uint8_t hash[32];
|
||||
signing_hash_bip143(&tx->inputs[0], hash);
|
||||
if (overwintered) {
|
||||
signing_hash_zip143(&tx->inputs[0], hash);
|
||||
} else {
|
||||
signing_hash_bip143(&tx->inputs[0], hash);
|
||||
}
|
||||
if (!signing_sign_hash(&tx->inputs[0], node.private_key, node.public_key, hash))
|
||||
return;
|
||||
// since this took a longer time, update progress
|
||||
@ -1289,12 +1327,12 @@ void signing_txack(TransactionType *tx)
|
||||
progress = 500 + ((signatures * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION);
|
||||
if (idx1 == 0) {
|
||||
// witness
|
||||
tx_init(&to, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign);
|
||||
tx_init(&to, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign, overwintered);
|
||||
to.is_decred = true;
|
||||
}
|
||||
|
||||
// witness hash
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign);
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign, overwintered);
|
||||
ti.version |= (DECRED_SERIALIZE_WITNESS_SIGNING << 16);
|
||||
ti.is_decred = true;
|
||||
if (!compile_input_script_sig(&tx->inputs[0])) {
|
||||
|
@ -465,10 +465,18 @@ uint32_t tx_serialize_script(uint32_t size, const uint8_t *data, uint8_t *out)
|
||||
uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out)
|
||||
{
|
||||
int r = 4;
|
||||
memcpy(out, &(tx->version), 4);
|
||||
if (tx->is_segwit) {
|
||||
memcpy(out + r, segwit_header, 2);
|
||||
r += 2;
|
||||
if (tx->overwintered) {
|
||||
uint32_t ver = tx->version | TX_OVERWINTERED;
|
||||
memcpy(out, &ver, 4);
|
||||
uint32_t version_group_id = 0x03c48270;
|
||||
memcpy(out + 4, &version_group_id, 4);
|
||||
r += 4;
|
||||
} else {
|
||||
memcpy(out, &(tx->version), 4);
|
||||
if (tx->is_segwit) {
|
||||
memcpy(out + r, segwit_header, 2);
|
||||
r += 2;
|
||||
}
|
||||
}
|
||||
return r + ser_length(tx->inputs_len, out + r);
|
||||
}
|
||||
@ -476,10 +484,18 @@ uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out)
|
||||
uint32_t tx_serialize_header_hash(TxStruct *tx)
|
||||
{
|
||||
int r = 4;
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->version), 4);
|
||||
if (tx->is_segwit) {
|
||||
hasher_Update(&(tx->hasher), segwit_header, 2);
|
||||
r += 2;
|
||||
if (tx->overwintered) {
|
||||
uint32_t ver = tx->version | TX_OVERWINTERED;
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)&ver, 4);
|
||||
uint32_t version_group_id = 0x03c48270;
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)&version_group_id, 4);
|
||||
r += 4;
|
||||
} else {
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->version), 4);
|
||||
if (tx->is_segwit) {
|
||||
hasher_Update(&(tx->hasher), segwit_header, 2);
|
||||
r += 2;
|
||||
}
|
||||
}
|
||||
return r + ser_length_hash(&(tx->hasher), tx->inputs_len);
|
||||
}
|
||||
@ -598,6 +614,11 @@ uint32_t tx_serialize_middle_hash(TxStruct *tx)
|
||||
uint32_t tx_serialize_footer(TxStruct *tx, uint8_t *out)
|
||||
{
|
||||
memcpy(out, &(tx->lock_time), 4);
|
||||
if (tx->overwintered) {
|
||||
memcpy(out + 4, &(tx->expiry), 4);
|
||||
out[8] = 0x00; // nJoinSplit
|
||||
return 9;
|
||||
}
|
||||
if (tx->is_decred) {
|
||||
memcpy(out + 4, &(tx->expiry), 4);
|
||||
return 8;
|
||||
@ -608,6 +629,11 @@ uint32_t tx_serialize_footer(TxStruct *tx, uint8_t *out)
|
||||
uint32_t tx_serialize_footer_hash(TxStruct *tx)
|
||||
{
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->lock_time), 4);
|
||||
if (tx->overwintered) {
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->expiry), 4);
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)"\x00", 1); // nJoinSplit
|
||||
return 9;
|
||||
}
|
||||
if (tx->is_decred) {
|
||||
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->expiry), 4);
|
||||
return 8;
|
||||
@ -688,7 +714,7 @@ uint32_t tx_serialize_extra_data_hash(TxStruct *tx, const uint8_t *data, uint32_
|
||||
return datalen;
|
||||
}
|
||||
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, uint32_t expiry, uint32_t extra_data_len, HasherType hasher_sign)
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, uint32_t expiry, uint32_t extra_data_len, HasherType hasher_sign, bool overwintered)
|
||||
{
|
||||
tx->inputs_len = inputs_len;
|
||||
tx->outputs_len = outputs_len;
|
||||
@ -702,6 +728,7 @@ void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t v
|
||||
tx->size = 0;
|
||||
tx->is_segwit = false;
|
||||
tx->is_decred = false;
|
||||
tx->overwintered = overwintered;
|
||||
hasher_Init(&(tx->hasher), hasher_sign);
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "hasher.h"
|
||||
#include "types.pb.h"
|
||||
|
||||
#define TX_OVERWINTERED 0x80000000
|
||||
|
||||
typedef struct {
|
||||
uint32_t inputs_len;
|
||||
uint32_t outputs_len;
|
||||
@ -41,6 +43,7 @@ typedef struct {
|
||||
uint32_t have_inputs;
|
||||
uint32_t have_outputs;
|
||||
|
||||
bool overwintered;
|
||||
uint32_t extra_data_len;
|
||||
uint32_t extra_data_received;
|
||||
|
||||
@ -68,7 +71,7 @@ uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, uint8_t *out
|
||||
uint32_t tx_serialize_output(TxStruct *tx, const TxOutputBinType *output, uint8_t *out);
|
||||
uint32_t tx_serialize_decred_witness(TxStruct *tx, const TxInputType *input, uint8_t *out);
|
||||
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, uint32_t expiry, uint32_t extra_data_len, HasherType hasher_sign);
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, uint32_t expiry, uint32_t extra_data_len, HasherType hasher_sign, bool overwintered);
|
||||
uint32_t tx_serialize_header_hash(TxStruct *tx);
|
||||
uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input);
|
||||
uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output);
|
||||
|
2
vendor/trezor-crypto
vendored
2
vendor/trezor-crypto
vendored
@ -1 +1 @@
|
||||
Subproject commit e81fb38ab452f2170769e9c454b10caaf8869974
|
||||
Subproject commit dba23617280ea75b434bbca4699abfd1524fdbe2
|
Loading…
Reference in New Issue
Block a user