mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-02 19:01:04 +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 TxStruct to, tp, ti;
|
||||
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 uint32_t version = 1;
|
||||
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 *)&version, sizeof(version));
|
||||
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);
|
||||
|
||||
@ -326,6 +331,9 @@ void signing_txack(TransactionType *tx)
|
||||
} else { // InputScriptType_SPENDADDRESS
|
||||
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));
|
||||
memcpy(&input, tx->inputs, sizeof(TxInputType));
|
||||
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
|
||||
send_req_2_prev_extradata(tp.extra_data_received, MIN(1024, tp.extra_data_len - tp.extra_data_received));
|
||||
} else {
|
||||
/* Check next output */
|
||||
uint8_t hash[32];
|
||||
tx_hash_final(&tp, hash, true);
|
||||
if (memcmp(hash, input.prev_hash.bytes, 32) != 0) {
|
||||
fsm_sendFailure(FailureType_Failure_Other, "Encountered invalid prevhash");
|
||||
@ -409,6 +419,13 @@ void signing_txack(TransactionType *tx)
|
||||
idx1++;
|
||||
send_req_1_input();
|
||||
} 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;
|
||||
send_req_3_output();
|
||||
}
|
||||
@ -463,11 +480,15 @@ void signing_txack(TransactionType *tx)
|
||||
signing_abort();
|
||||
return;
|
||||
}
|
||||
// compute segwit hashOuts
|
||||
tx_output_hash(&hashers[0], &bin_output);
|
||||
sha256_Update(&tc, (const uint8_t *)&bin_output, sizeof(TxOutputBinType));
|
||||
if (idx1 < outputs_count - 1) {
|
||||
idx1++;
|
||||
send_req_3_output();
|
||||
} else {
|
||||
sha256_Final(&hashers[0], hash_outputs);
|
||||
sha256_Raw(hash_sequence, 32, hash_outputs);
|
||||
sha256_Final(&tc, hash_check);
|
||||
// check fees
|
||||
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);
|
||||
} else { // SPENDADDRESS
|
||||
uint8_t hash[20];
|
||||
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);
|
||||
}
|
||||
@ -580,6 +602,7 @@ void signing_txack(TransactionType *tx)
|
||||
idx2++;
|
||||
send_req_4_output();
|
||||
} else {
|
||||
uint8_t hash[32];
|
||||
sha256_Final(&tc, hash);
|
||||
if (memcmp(hash, hash_check, 32) != 0) {
|
||||
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
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
if (tx->have_inputs >= tx->inputs_len) {
|
||||
// already got all inputs
|
||||
return 0;
|
||||
@ -335,14 +359,10 @@ uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input)
|
||||
if (tx->have_inputs == 0) {
|
||||
r += tx_serialize_header_hash(tx);
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
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 += tx_prevout_hash(&(tx->ctx), input);
|
||||
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), (const uint8_t *)&input->sequence, 4); r += 4;
|
||||
r += tx_sequence_hash(&(tx->ctx), input);
|
||||
|
||||
tx->have_inputs++;
|
||||
tx->size += r;
|
||||
@ -423,9 +443,7 @@ uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output)
|
||||
if (tx->have_outputs == 0) {
|
||||
r += tx_serialize_middle_hash(tx);
|
||||
}
|
||||
sha256_Update(&(tx->ctx), (const uint8_t *)&output->amount, 8); r += 8;
|
||||
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;
|
||||
r += tx_output_hash(&(tx->ctx), output);
|
||||
tx->have_outputs++;
|
||||
if (tx->have_outputs == tx->outputs_len) {
|
||||
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_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
|
||||
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_output(TxStruct *tx, const TxOutputBinType *output, uint8_t *out);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user