1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 04:18:10 +00:00

feat(legacy): Implement the BIP-341 common signature message computation.

This commit is contained in:
Andrew Kozlik 2021-11-10 12:43:03 +01:00 committed by Andrew Kozlik
parent 1f4573905f
commit 34e8284331
3 changed files with 89 additions and 22 deletions

View File

@ -115,11 +115,18 @@ typedef struct {
uint32_t branch_id; uint32_t branch_id;
#endif #endif
Hasher hasher_prevouts; Hasher hasher_prevouts;
Hasher hasher_sequence; Hasher hasher_amounts;
Hasher hasher_scriptpubkeys;
Hasher hasher_sequences;
Hasher hasher_outputs; Hasher hasher_outputs;
uint8_t hash_prevouts[32]; uint8_t hash_prevouts[32];
uint8_t hash_sequence[32]; uint8_t hash_amounts[32];
uint8_t hash_scriptpubkeys[32];
uint8_t hash_sequences[32];
uint8_t hash_outputs[32]; uint8_t hash_outputs[32];
uint8_t hash_prevouts143[32];
uint8_t hash_outputs143[32];
uint8_t hash_sequence143[32];
} TxInfo; } TxInfo;
static TxInfo info; static TxInfo info;
@ -193,13 +200,13 @@ Phase1 - process inputs
foreach I (idx1): foreach I (idx1):
Request I STAGE_REQUEST_1_INPUT Request I STAGE_REQUEST_1_INPUT
Add I to segwit hash_prevouts, hash_sequence Add I to segwit sub-hashes
Add I to Decred decred_hash_prefix Add I to Decred decred_hash_prefix
Add I to TransactionChecksum (prevout and type) Add I to TransactionChecksum (prevout and type)
if (I has orig_hash) if (I has orig_hash)
Request input I2 orig_hash, orig_index STAGE_REQUEST_1_ORIG_INPUT Request input I2 orig_hash, orig_index STAGE_REQUEST_1_ORIG_INPUT
Check I matches I2 Check I matches I2
Add I2 to orig_hash_prevouts, orig_hash_sequence Add I2 to original segwit sub-hashes
if (Decred) if (Decred)
Return I Return I
@ -820,17 +827,19 @@ static bool tx_info_init(TxInfo *tx_info, uint32_t inputs_count,
// ZIP-243 // ZIP-243
hasher_InitParam(&tx_info->hasher_prevouts, HASHER_BLAKE2B_PERSONAL, hasher_InitParam(&tx_info->hasher_prevouts, HASHER_BLAKE2B_PERSONAL,
"ZcashPrevoutHash", 16); "ZcashPrevoutHash", 16);
hasher_InitParam(&tx_info->hasher_sequence, HASHER_BLAKE2B_PERSONAL, hasher_InitParam(&tx_info->hasher_sequences, HASHER_BLAKE2B_PERSONAL,
"ZcashSequencHash", 16); "ZcashSequencHash", 16);
hasher_InitParam(&tx_info->hasher_outputs, HASHER_BLAKE2B_PERSONAL, hasher_InitParam(&tx_info->hasher_outputs, HASHER_BLAKE2B_PERSONAL,
"ZcashOutputsHash", 16); "ZcashOutputsHash", 16);
} else } else
#endif #endif
{ {
// BIP-143 // BIP-143/BIP-341
hasher_Init(&tx_info->hasher_prevouts, coin->curve->hasher_sign); hasher_Init(&tx_info->hasher_prevouts, HASHER_SHA2);
hasher_Init(&tx_info->hasher_sequence, coin->curve->hasher_sign); hasher_Init(&tx_info->hasher_amounts, HASHER_SHA2);
hasher_Init(&tx_info->hasher_outputs, coin->curve->hasher_sign); hasher_Init(&tx_info->hasher_scriptpubkeys, HASHER_SHA2);
hasher_Init(&tx_info->hasher_sequences, HASHER_SHA2);
hasher_Init(&tx_info->hasher_outputs, HASHER_SHA2);
} }
return true; return true;
@ -901,7 +910,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin,
} }
#endif #endif
hasher_Init(&hasher_check, coin->curve->hasher_sign); hasher_Init(&hasher_check, HASHER_SHA2);
layoutProgressSwipe(_("Signing transaction"), 0); layoutProgressSwipe(_("Signing transaction"), 0);
@ -1123,28 +1132,49 @@ static bool tx_info_add_input(TxInfo *tx_info, const TxInputType *txinput) {
tx_info->min_sequence = txinput->sequence; tx_info->min_sequence = txinput->sequence;
} }
// Add input to BIP-143 hashPrevouts and hashSequence. // Add input to BIP-143 and BIP-341 running sub-hashes.
tx_prevout_hash(&tx_info->hasher_prevouts, txinput); tx_prevout_hash(&tx_info->hasher_prevouts, txinput);
tx_sequence_hash(&tx_info->hasher_sequence, txinput); tx_amount_hash(&tx_info->hasher_amounts, txinput);
tx_script_hash(&tx_info->hasher_scriptpubkeys, txinput->script_pubkey.size,
txinput->script_pubkey.bytes);
tx_sequence_hash(&tx_info->hasher_sequences, txinput);
return true; return true;
} }
static bool tx_info_add_output(TxInfo *tx_info, static bool tx_info_add_output(TxInfo *tx_info,
const TxOutputBinType *tx_bin_output) { const TxOutputBinType *tx_bin_output) {
// Add output to BIP-143 hashOutputs. // Add output to BIP-143/BIP-341 hashOutputs.
tx_output_hash(&tx_info->hasher_outputs, tx_bin_output, coin->decred); tx_output_hash(&tx_info->hasher_outputs, tx_bin_output, coin->decred);
return true; return true;
} }
static void tx_info_finish(TxInfo *tx_info) { static void tx_info_finish(TxInfo *tx_info) {
hasher_Final(&tx_info->hasher_prevouts, tx_info->hash_prevouts); hasher_Final(&tx_info->hasher_prevouts, tx_info->hash_prevouts);
hasher_Final(&tx_info->hasher_sequence, tx_info->hash_sequence); hasher_Final(&tx_info->hasher_amounts, tx_info->hash_amounts);
hasher_Final(&tx_info->hasher_scriptpubkeys, tx_info->hash_scriptpubkeys);
hasher_Final(&tx_info->hasher_sequences, tx_info->hash_sequences);
hasher_Final(&tx_info->hasher_outputs, tx_info->hash_outputs); hasher_Final(&tx_info->hasher_outputs, tx_info->hash_outputs);
if (coin->curve->hasher_sign == HASHER_SHA2D) {
hasher_Raw(HASHER_SHA2, tx_info->hash_prevouts,
sizeof(tx_info->hash_prevouts), tx_info->hash_prevouts143);
hasher_Raw(HASHER_SHA2, tx_info->hash_sequences,
sizeof(tx_info->hash_sequences), tx_info->hash_sequence143);
hasher_Raw(HASHER_SHA2, tx_info->hash_outputs,
sizeof(tx_info->hash_outputs), tx_info->hash_outputs143);
} else {
memcpy(tx_info->hash_prevouts143, tx_info->hash_prevouts,
sizeof(tx_info->hash_prevouts));
memcpy(tx_info->hash_sequence143, tx_info->hash_sequences,
sizeof(tx_info->hash_sequences));
memcpy(tx_info->hash_outputs143, tx_info->hash_outputs,
sizeof(tx_info->hash_outputs));
}
} }
static bool signing_check_input(const TxInputType *txinput) { static bool signing_check_input(const TxInputType *txinput) {
// Add input to BIP143 computation. // Add input to BIP-143/BIP-341 computation.
if (!tx_info_add_input(&info, txinput)) { if (!tx_info_add_input(&info, txinput)) {
return false; return false;
} }
@ -1301,7 +1331,7 @@ static bool signing_check_output(TxOutputType *txoutput) {
tx_serialize_output_hash(&ti, &bin_output); tx_serialize_output_hash(&ti, &bin_output);
} }
#endif #endif
// Add output to BIP143 computation. // Add output to BIP-143/BIP-341 computation.
return tx_info_add_output(&info, &bin_output); return tx_info_add_output(&info, &bin_output);
} }
@ -1361,7 +1391,7 @@ static bool signing_check_orig_input(TxInputType *orig_input) {
return false; return false;
} }
// Add input to original BIP143 computation. // Add input to original BIP-143/BIP-341 computation.
if (!tx_info_add_input(&orig_info, orig_input)) { if (!tx_info_add_input(&orig_info, orig_input)) {
return false; return false;
} }
@ -1429,7 +1459,7 @@ static bool signing_check_orig_output(TxOutputType *orig_output) {
return false; return false;
} }
// Add output to original BIP143 computation. // Add output to original BIP-143/BIP-341 computation.
if (!tx_info_add_output(&orig_info, &orig_bin_output)) { if (!tx_info_add_output(&orig_info, &orig_bin_output)) {
return false; return false;
} }
@ -1653,9 +1683,9 @@ static void signing_hash_bip143(const TxInfo *tx_info,
// nVersion // nVersion
hasher_Update(&hasher_preimage, (const uint8_t *)&tx_info->version, 4); hasher_Update(&hasher_preimage, (const uint8_t *)&tx_info->version, 4);
// hashPrevouts // hashPrevouts
hasher_Update(&hasher_preimage, tx_info->hash_prevouts, 32); hasher_Update(&hasher_preimage, tx_info->hash_prevouts143, 32);
// hashSequence // hashSequence
hasher_Update(&hasher_preimage, tx_info->hash_sequence, 32); hasher_Update(&hasher_preimage, tx_info->hash_sequence143, 32);
// outpoint // outpoint
tx_prevout_hash(&hasher_preimage, txinput); tx_prevout_hash(&hasher_preimage, txinput);
// scriptCode // scriptCode
@ -1666,7 +1696,7 @@ static void signing_hash_bip143(const TxInfo *tx_info,
// nSequence // nSequence
tx_sequence_hash(&hasher_preimage, txinput); tx_sequence_hash(&hasher_preimage, txinput);
// hashOutputs // hashOutputs
hasher_Update(&hasher_preimage, tx_info->hash_outputs, 32); hasher_Update(&hasher_preimage, tx_info->hash_outputs143, 32);
// nLockTime // nLockTime
hasher_Update(&hasher_preimage, (const uint8_t *)&tx_info->lock_time, 4); hasher_Update(&hasher_preimage, (const uint8_t *)&tx_info->lock_time, 4);
// nHashType // nHashType
@ -1675,6 +1705,37 @@ static void signing_hash_bip143(const TxInfo *tx_info,
hasher_Final(&hasher_preimage, hash); hasher_Final(&hasher_preimage, hash);
} }
static void signing_hash_bip341(const TxInfo *tx_info, uint32_t i,
uint8_t sighash_type, uint8_t *hash) {
const uint8_t zero = 0;
Hasher sigmsg_hasher = {0};
hasher_Init(&sigmsg_hasher, HASHER_SHA2_TAPSIGHASH);
// sighash epoch 0
hasher_Update(&sigmsg_hasher, &zero, 1);
// nHashType
hasher_Update(&sigmsg_hasher, &sighash_type, 1);
// nVersion
hasher_Update(&sigmsg_hasher, (const uint8_t *)&tx_info->version, 4);
// nLockTime
hasher_Update(&sigmsg_hasher, (const uint8_t *)&tx_info->lock_time, 4);
// sha_prevouts
hasher_Update(&sigmsg_hasher, tx_info->hash_prevouts, 32);
// sha_amounts
hasher_Update(&sigmsg_hasher, tx_info->hash_amounts, 32);
// sha_scriptpubkeys
hasher_Update(&sigmsg_hasher, tx_info->hash_scriptpubkeys, 32);
// sha_sequences
hasher_Update(&sigmsg_hasher, tx_info->hash_sequences, 32);
// sha_outputs
hasher_Update(&sigmsg_hasher, tx_info->hash_outputs, 32);
// spend_type 0 (no tapscript message extension, no annex)
hasher_Update(&sigmsg_hasher, &zero, 1);
// input_index
hasher_Update(&sigmsg_hasher, (const uint8_t *)&i, 4);
hasher_Final(&sigmsg_hasher, hash);
}
#if !BITCOIN_ONLY #if !BITCOIN_ONLY
static void signing_hash_zip243(const TxInfo *tx_info, static void signing_hash_zip243(const TxInfo *tx_info,
const TxInputType *txinput, uint8_t *hash) { const TxInputType *txinput, uint8_t *hash) {
@ -1695,7 +1756,7 @@ static void signing_hash_zip243(const TxInfo *tx_info,
// 3. hashPrevouts // 3. hashPrevouts
hasher_Update(&hasher_preimage, tx_info->hash_prevouts, 32); hasher_Update(&hasher_preimage, tx_info->hash_prevouts, 32);
// 4. hashSequence // 4. hashSequence
hasher_Update(&hasher_preimage, tx_info->hash_sequence, 32); hasher_Update(&hasher_preimage, tx_info->hash_sequences, 32);
// 5. hashOutputs // 5. hashOutputs
hasher_Update(&hasher_preimage, tx_info->hash_outputs, 32); hasher_Update(&hasher_preimage, tx_info->hash_outputs, 32);
// 6. hashJoinSplits // 6. hashJoinSplits

View File

@ -489,6 +489,11 @@ uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input) {
return 36; return 36;
} }
uint32_t tx_amount_hash(Hasher *hasher, const TxInputType *input) {
hasher_Update(hasher, (const uint8_t *)&input->amount, 8);
return 8;
}
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) {
int r = ser_length_hash(hasher, size); int r = ser_length_hash(hasher, size);
hasher_Update(hasher, data, size); hasher_Update(hasher, data, size);

View File

@ -78,6 +78,7 @@ int compile_output(const CoinInfo *coin, AmountUnit amount_unit,
void tx_input_check_hash(Hasher *hasher, const TxInputType *input); void 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_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);
uint32_t tx_sequence_hash(Hasher *hasher, const TxInputType *input); uint32_t tx_sequence_hash(Hasher *hasher, const TxInputType *input);
uint32_t tx_output_hash(Hasher *hasher, const TxOutputBinType *output, uint32_t tx_output_hash(Hasher *hasher, const TxOutputBinType *output,