mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-09 06:02:40 +00:00
hashes for segwit signature
This commit is contained in:
parent
1bd4b99f95
commit
5c60be9854
@ -50,7 +50,9 @@ static TxInputType input;
|
|||||||
static TxOutputBinType bin_output;
|
static TxOutputBinType bin_output;
|
||||||
static TxStruct to, tp, ti;
|
static TxStruct to, tp, ti;
|
||||||
static SHA256_CTX tc;
|
static SHA256_CTX tc;
|
||||||
static uint8_t hash[32], hash_check[32], privkey[32], pubkey[33], sig[64];
|
static SHA256_CTX hashers[2];
|
||||||
|
static uint8_t hash_check[32], privkey[32], pubkey[33], sig[64];
|
||||||
|
static uint8_t hash_prevouts[32], hash_sequence[32],hash_outputs[32];
|
||||||
static uint64_t to_spend, spending, change_spend;
|
static uint64_t to_spend, spending, change_spend;
|
||||||
static uint32_t version = 1;
|
static uint32_t version = 1;
|
||||||
static uint32_t lock_time = 0;
|
static uint32_t lock_time = 0;
|
||||||
@ -273,6 +275,9 @@ void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinTyp
|
|||||||
sha256_Update(&tc, (const uint8_t *)&outputs_count, sizeof(outputs_count));
|
sha256_Update(&tc, (const uint8_t *)&outputs_count, sizeof(outputs_count));
|
||||||
sha256_Update(&tc, (const uint8_t *)&version, sizeof(version));
|
sha256_Update(&tc, (const uint8_t *)&version, sizeof(version));
|
||||||
sha256_Update(&tc, (const uint8_t *)&lock_time, sizeof(lock_time));
|
sha256_Update(&tc, (const uint8_t *)&lock_time, sizeof(lock_time));
|
||||||
|
// segwit hashes for hashPrevouts and hashSequence
|
||||||
|
sha256_Init(&hashers[0]);
|
||||||
|
sha256_Init(&hashers[1]);
|
||||||
|
|
||||||
layoutProgressSwipe("Signing transaction", 0);
|
layoutProgressSwipe("Signing transaction", 0);
|
||||||
|
|
||||||
@ -326,6 +331,9 @@ void signing_txack(TransactionType *tx)
|
|||||||
} else { // InputScriptType_SPENDADDRESS
|
} else { // InputScriptType_SPENDADDRESS
|
||||||
multisig_fp_mismatch = true;
|
multisig_fp_mismatch = true;
|
||||||
}
|
}
|
||||||
|
// compute segwit hashPrevouts & hashSequence
|
||||||
|
tx_prevout_hash(&hashers[0], tx->inputs);
|
||||||
|
tx_sequence_hash(&hashers[1], tx->inputs);
|
||||||
sha256_Update(&tc, (const uint8_t *)tx->inputs, sizeof(TxInputType));
|
sha256_Update(&tc, (const uint8_t *)tx->inputs, sizeof(TxInputType));
|
||||||
memcpy(&input, tx->inputs, sizeof(TxInputType));
|
memcpy(&input, tx->inputs, sizeof(TxInputType));
|
||||||
send_req_2_prev_meta();
|
send_req_2_prev_meta();
|
||||||
@ -399,6 +407,8 @@ void signing_txack(TransactionType *tx)
|
|||||||
if (tp.extra_data_received < tp.extra_data_len) { // still some data remanining
|
if (tp.extra_data_received < tp.extra_data_len) { // still some data remanining
|
||||||
send_req_2_prev_extradata(tp.extra_data_received, MIN(1024, tp.extra_data_len - tp.extra_data_received));
|
send_req_2_prev_extradata(tp.extra_data_received, MIN(1024, tp.extra_data_len - tp.extra_data_received));
|
||||||
} else {
|
} else {
|
||||||
|
/* Check next output */
|
||||||
|
uint8_t hash[32];
|
||||||
tx_hash_final(&tp, hash, true);
|
tx_hash_final(&tp, hash, true);
|
||||||
if (memcmp(hash, input.prev_hash.bytes, 32) != 0) {
|
if (memcmp(hash, input.prev_hash.bytes, 32) != 0) {
|
||||||
fsm_sendFailure(FailureType_Failure_Other, "Encountered invalid prevhash");
|
fsm_sendFailure(FailureType_Failure_Other, "Encountered invalid prevhash");
|
||||||
@ -409,6 +419,13 @@ void signing_txack(TransactionType *tx)
|
|||||||
idx1++;
|
idx1++;
|
||||||
send_req_1_input();
|
send_req_1_input();
|
||||||
} else {
|
} else {
|
||||||
|
// compute segwit hashPrevouts & hashSequence
|
||||||
|
sha256_Final(&hashers[0], hash_prevouts);
|
||||||
|
sha256_Raw(hash_prevouts, 32, hash_prevouts);
|
||||||
|
sha256_Final(&hashers[1], hash_sequence);
|
||||||
|
sha256_Raw(hash_sequence, 32, hash_sequence);
|
||||||
|
// init hashOutputs
|
||||||
|
sha256_Init(&hashers[0]);
|
||||||
idx1 = 0;
|
idx1 = 0;
|
||||||
send_req_3_output();
|
send_req_3_output();
|
||||||
}
|
}
|
||||||
@ -463,11 +480,15 @@ void signing_txack(TransactionType *tx)
|
|||||||
signing_abort();
|
signing_abort();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// compute segwit hashOuts
|
||||||
|
tx_output_hash(&hashers[0], &bin_output);
|
||||||
sha256_Update(&tc, (const uint8_t *)&bin_output, sizeof(TxOutputBinType));
|
sha256_Update(&tc, (const uint8_t *)&bin_output, sizeof(TxOutputBinType));
|
||||||
if (idx1 < outputs_count - 1) {
|
if (idx1 < outputs_count - 1) {
|
||||||
idx1++;
|
idx1++;
|
||||||
send_req_3_output();
|
send_req_3_output();
|
||||||
} else {
|
} else {
|
||||||
|
sha256_Final(&hashers[0], hash_outputs);
|
||||||
|
sha256_Raw(hash_sequence, 32, hash_outputs);
|
||||||
sha256_Final(&tc, hash_check);
|
sha256_Final(&tc, hash_check);
|
||||||
// check fees
|
// check fees
|
||||||
if (spending > to_spend) {
|
if (spending > to_spend) {
|
||||||
@ -532,6 +553,7 @@ void signing_txack(TransactionType *tx)
|
|||||||
}
|
}
|
||||||
tx->inputs[0].script_sig.size = compile_script_multisig(&(tx->inputs[0].multisig), tx->inputs[0].script_sig.bytes);
|
tx->inputs[0].script_sig.size = compile_script_multisig(&(tx->inputs[0].multisig), tx->inputs[0].script_sig.bytes);
|
||||||
} else { // SPENDADDRESS
|
} else { // SPENDADDRESS
|
||||||
|
uint8_t hash[20];
|
||||||
ecdsa_get_pubkeyhash(node.public_key, hash);
|
ecdsa_get_pubkeyhash(node.public_key, hash);
|
||||||
tx->inputs[0].script_sig.size = compile_script_sig(coin->address_type, hash, tx->inputs[0].script_sig.bytes);
|
tx->inputs[0].script_sig.size = compile_script_sig(coin->address_type, hash, tx->inputs[0].script_sig.bytes);
|
||||||
}
|
}
|
||||||
@ -580,6 +602,7 @@ void signing_txack(TransactionType *tx)
|
|||||||
idx2++;
|
idx2++;
|
||||||
send_req_4_output();
|
send_req_4_output();
|
||||||
} else {
|
} else {
|
||||||
|
uint8_t hash[32];
|
||||||
sha256_Final(&tc, hash);
|
sha256_Final(&tc, hash);
|
||||||
if (memcmp(hash, hash_check, 32) != 0) {
|
if (memcmp(hash, hash_check, 32) != 0) {
|
||||||
fsm_sendFailure(FailureType_Failure_Other, "Transaction has changed during signing");
|
fsm_sendFailure(FailureType_Failure_Other, "Transaction has changed during signing");
|
||||||
|
@ -286,6 +286,31 @@ uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uin
|
|||||||
|
|
||||||
// tx methods
|
// tx methods
|
||||||
|
|
||||||
|
uint32_t tx_prevout_hash(SHA256_CTX *ctx, const TxInputType *input)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
sha256_Update(ctx, &(input->prev_hash.bytes[31 - i]), 1);
|
||||||
|
}
|
||||||
|
sha256_Update(ctx, (const uint8_t *)&input->prev_index, 4);
|
||||||
|
return 36;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tx_sequence_hash(SHA256_CTX *ctx, const TxInputType *input)
|
||||||
|
{
|
||||||
|
sha256_Update(ctx, (const uint8_t *)&input->sequence, 4);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tx_output_hash(SHA256_CTX *ctx, const TxOutputBinType *output)
|
||||||
|
{
|
||||||
|
uint32_t r = 0;
|
||||||
|
sha256_Update(ctx, (const uint8_t *)&output->amount, 8); r += 8;
|
||||||
|
r += ser_length_hash(ctx, output->script_pubkey.size);
|
||||||
|
sha256_Update(ctx, output->script_pubkey.bytes, output->script_pubkey.size); r+= output->script_pubkey.size;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out)
|
uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out)
|
||||||
{
|
{
|
||||||
memcpy(out, &(tx->version), 4);
|
memcpy(out, &(tx->version), 4);
|
||||||
@ -326,7 +351,6 @@ uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, uint8_t *out
|
|||||||
|
|
||||||
uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input)
|
uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
if (tx->have_inputs >= tx->inputs_len) {
|
if (tx->have_inputs >= tx->inputs_len) {
|
||||||
// already got all inputs
|
// already got all inputs
|
||||||
return 0;
|
return 0;
|
||||||
@ -335,14 +359,10 @@ uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input)
|
|||||||
if (tx->have_inputs == 0) {
|
if (tx->have_inputs == 0) {
|
||||||
r += tx_serialize_header_hash(tx);
|
r += tx_serialize_header_hash(tx);
|
||||||
}
|
}
|
||||||
for (i = 0; i < 32; i++) {
|
r += tx_prevout_hash(&(tx->ctx), input);
|
||||||
sha256_Update(&(tx->ctx), &(input->prev_hash.bytes[31 - i]), 1);
|
|
||||||
}
|
|
||||||
r += 32;
|
|
||||||
sha256_Update(&(tx->ctx), (const uint8_t *)&input->prev_index, 4); r += 4;
|
|
||||||
r += ser_length_hash(&(tx->ctx), input->script_sig.size);
|
r += ser_length_hash(&(tx->ctx), input->script_sig.size);
|
||||||
sha256_Update(&(tx->ctx), input->script_sig.bytes, input->script_sig.size); r += input->script_sig.size;
|
sha256_Update(&(tx->ctx), input->script_sig.bytes, input->script_sig.size); r += input->script_sig.size;
|
||||||
sha256_Update(&(tx->ctx), (const uint8_t *)&input->sequence, 4); r += 4;
|
r += tx_sequence_hash(&(tx->ctx), input);
|
||||||
|
|
||||||
tx->have_inputs++;
|
tx->have_inputs++;
|
||||||
tx->size += r;
|
tx->size += r;
|
||||||
@ -423,9 +443,7 @@ uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output)
|
|||||||
if (tx->have_outputs == 0) {
|
if (tx->have_outputs == 0) {
|
||||||
r += tx_serialize_middle_hash(tx);
|
r += tx_serialize_middle_hash(tx);
|
||||||
}
|
}
|
||||||
sha256_Update(&(tx->ctx), (const uint8_t *)&output->amount, 8); r += 8;
|
r += tx_output_hash(&(tx->ctx), output);
|
||||||
r += ser_length_hash(&(tx->ctx), output->script_pubkey.size);
|
|
||||||
sha256_Update(&(tx->ctx), output->script_pubkey.bytes, output->script_pubkey.size); r+= output->script_pubkey.size;
|
|
||||||
tx->have_outputs++;
|
tx->have_outputs++;
|
||||||
if (tx->have_outputs == tx->outputs_len) {
|
if (tx->have_outputs == tx->outputs_len) {
|
||||||
r += tx_serialize_footer_hash(tx);
|
r += tx_serialize_footer_hash(tx);
|
||||||
|
@ -51,6 +51,11 @@ uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig,
|
|||||||
uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len, const uint8_t *pubkey, uint32_t pubkey_len, uint8_t *out);
|
uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len, const uint8_t *pubkey, uint32_t pubkey_len, uint8_t *out);
|
||||||
uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
|
uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
|
||||||
int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm);
|
int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm);
|
||||||
|
|
||||||
|
uint32_t tx_prevout_hash(SHA256_CTX *ctx, const TxInputType *input);
|
||||||
|
uint32_t tx_sequence_hash(SHA256_CTX *ctx, const TxInputType *input);
|
||||||
|
uint32_t tx_output_hash(SHA256_CTX *ctx, const TxOutputBinType *output);
|
||||||
|
|
||||||
uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, uint8_t *out);
|
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_output(TxStruct *tx, const TxOutputBinType *output, uint8_t *out);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user