1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-17 21:22:10 +00:00

refactor(legacy): Extract segwit signing code.

This commit is contained in:
Andrew Kozlik 2022-12-19 12:45:36 +01:00 committed by matejcik
parent 1ecb0f0c1c
commit 9732f6524a
3 changed files with 119 additions and 57 deletions

View File

@ -179,20 +179,6 @@ static uint8_t orig_hash[32]; // TXID of the original transaction.
transaction disables replace-by-fee opt-in. */
#define MAX_BIP125_RBF_SEQUENCE 0xFFFFFFFD
enum {
// Signature hash type with the same semantics as SIGHASH_ALL, but instead of
// having to include the byte in the signature, it is implied.
SIGHASH_ALL_TAPROOT = 0,
// Default signature hash type in Bitcoin which signs all inputs and all
// outputs of the transaction.
SIGHASH_ALL = 1,
// Signature hash flag used in some Bitcoin-like altcoins for replay
// protection.
SIGHASH_FORKID = 0x40,
};
enum {
DECRED_SERIALIZE_FULL = 0,
DECRED_SERIALIZE_NO_WITNESS = 1,
@ -2542,26 +2528,14 @@ static bool signing_sign_ecdsa(TxInputType *txinput, const uint8_t *private_key,
resp.serialized.signature_index = idx1;
resp.serialized.has_signature = true;
int ret = 0;
#ifdef USE_SECP256K1_ZKP_ECDSA
if (coin->curve->params == &secp256k1) {
ret = zkp_ecdsa_sign_digest(coin->curve->params, private_key, hash, sig,
NULL, NULL);
} else
#endif
{
ret = ecdsa_sign_digest(coin->curve->params, private_key, hash, sig, NULL,
NULL);
}
if (ret != 0) {
if (!tx_sign_ecdsa(coin->curve->params, private_key, hash,
resp.serialized.signature.bytes,
&resp.serialized.signature.size)) {
fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed"));
signing_abort();
return false;
}
resp.serialized.signature.size =
ecdsa_sig_to_der(sig, resp.serialized.signature.bytes);
uint8_t sighash = signing_hash_type(txinput) & 0xff;
if (txinput->has_multisig) {
// fill in the signature
@ -2599,22 +2573,15 @@ static bool signing_sign_bip340(const uint8_t *private_key,
resp.serialized.has_signature_index = true;
resp.serialized.signature_index = idx1;
resp.serialized.has_signature = true;
resp.serialized.signature.size = 64;
uint8_t output_private_key[32] = {0};
bool ret = (zkp_bip340_tweak_private_key(private_key, NULL,
output_private_key) == 0);
ret = ret &&
(zkp_bip340_sign_digest(output_private_key, hash,
resp.serialized.signature.bytes, NULL) == 0);
memzero(output_private_key, sizeof(output_private_key));
if (!ret) {
if (!tx_sign_bip340(private_key, hash, resp.serialized.signature.bytes,
&resp.serialized.signature.size)) {
fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed"));
signing_abort();
return false;
}
return ret;
return true;
}
static bool signing_sign_legacy_input(void) {
@ -2658,13 +2625,9 @@ static bool signing_sign_segwit_input(TxInputType *txinput) {
if (serialize) {
resp.has_serialized = true;
resp.serialized.has_serialized_tx = true;
uint32_t r = 0;
// write witness (number of stack items followed by signature)
r += ser_length(1, resp.serialized.serialized_tx.bytes + r);
r += tx_serialize_script(resp.serialized.signature.size,
resp.serialized.signature.bytes,
resp.serialized.serialized_tx.bytes + r);
resp.serialized.serialized_tx.size = r;
resp.serialized.serialized_tx.size = serialize_p2tr_witness(
resp.serialized.signature.bytes, resp.serialized.signature.size, 0,
resp.serialized.serialized_tx.bytes);
}
} else if (txinput->script_type == InputScriptType_SPENDP2SHWITNESS ||
txinput->script_type == InputScriptType_SPENDWITNESS) {
@ -2720,16 +2683,9 @@ static bool signing_sign_segwit_input(TxInputType *txinput) {
resp.serialized.serialized_tx.bytes[0] = nwitnesses;
resp.serialized.serialized_tx.size = r;
} else { // single signature
uint32_t r = 0;
r += ser_length(2, resp.serialized.serialized_tx.bytes + r);
resp.serialized.signature.bytes[resp.serialized.signature.size] =
sighash;
r += tx_serialize_script(resp.serialized.signature.size + 1,
resp.serialized.signature.bytes,
resp.serialized.serialized_tx.bytes + r);
r += tx_serialize_script(33, node.public_key,
resp.serialized.serialized_tx.bytes + r);
resp.serialized.serialized_tx.size = r;
resp.serialized.serialized_tx.size = serialize_p2wpkh_witness(
resp.serialized.signature.bytes, resp.serialized.signature.size,
node.public_key, 33, sighash, resp.serialized.serialized_tx.bytes);
}
}
} else {

View File

@ -30,9 +30,13 @@
#include "messages.pb.h"
#include "protect.h"
#include "ripemd160.h"
#include "secp256k1.h"
#include "segwit_addr.h"
#include "util.h"
#include "zkp_bip340.h"
#ifdef USE_SECP256K1_ZKP_ECDSA
#include "zkp_ecdsa.h"
#endif
#if !BITCOIN_ONLY
#include "cash_addr.h"
@ -555,6 +559,82 @@ uint32_t serialize_script_multisig(const CoinInfo *coin,
return r;
}
uint32_t serialize_p2wpkh_witness(const uint8_t *signature,
uint32_t signature_len,
const uint8_t *public_key,
uint32_t public_key_len, uint8_t sighash,
uint8_t *out) {
uint32_t r = 0;
// 2 stack items
r += ser_length(2, out + r);
// length-prefixed signature with sighash type
r += ser_length(signature_len + 1, out + r);
memcpy(out + r, signature, signature_len);
r += signature_len;
out[r] = sighash;
r += 1;
// length-prefixed public key
r += tx_serialize_script(public_key_len, public_key, out + r);
return r;
}
uint32_t serialize_p2tr_witness(const uint8_t *signature,
uint32_t signature_len, uint8_t sighash,
uint8_t *out) {
uint32_t r = 0;
// 1 stack item
r += ser_length(1, out + r);
// length-prefixed signature with optional sighash type
uint32_t sighash_len = sighash ? 1 : 0;
r += ser_length(signature_len + sighash_len, out + r);
memcpy(out + r, signature, signature_len);
r += signature_len;
if (sighash) {
out[r] = sighash;
r += 1;
}
return r;
}
bool tx_sign_ecdsa(const ecdsa_curve *curve, const uint8_t *private_key,
const uint8_t *hash, uint8_t *out, pb_size_t *size) {
int ret = 0;
uint8_t signature[64] = {0};
#ifdef USE_SECP256K1_ZKP_ECDSA
if (curve == &secp256k1) {
ret =
zkp_ecdsa_sign_digest(curve, private_key, hash, signature, NULL, NULL);
} else
#endif
{
ret = ecdsa_sign_digest(curve, private_key, hash, signature, NULL, NULL);
}
if (ret != 0) {
return false;
}
*size = ecdsa_sig_to_der(signature, out);
return true;
}
bool tx_sign_bip340(const uint8_t *private_key, const uint8_t *hash,
uint8_t *out, pb_size_t *size) {
static CONFIDENTIAL uint8_t output_private_key[32] = {0};
bool ret = (zkp_bip340_tweak_private_key(private_key, NULL,
output_private_key) == 0);
ret =
ret && (zkp_bip340_sign_digest(output_private_key, hash, out, NULL) == 0);
*size = ret ? 64 : 0;
memzero(output_private_key, sizeof(output_private_key));
return ret;
}
// tx methods
bool tx_input_check_hash(Hasher *hasher, const TxInputType *input) {
hasher_Update(hasher, (const uint8_t *)&input->address_n_count,

View File

@ -30,6 +30,20 @@
#define TX_OVERWINTERED 0x80000000
enum {
// Signature hash type with the same semantics as SIGHASH_ALL, but instead of
// having to include the byte in the signature, it is implied.
SIGHASH_ALL_TAPROOT = 0,
// Default signature hash type in Bitcoin which signs all inputs and all
// outputs of the transaction.
SIGHASH_ALL = 1,
// Signature hash flag used in some Bitcoin-like altcoins for replay
// protection.
SIGHASH_FORKID = 0x40,
};
typedef struct {
uint32_t inputs_len;
uint32_t outputs_len;
@ -73,6 +87,18 @@ uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len,
uint32_t serialize_script_multisig(const CoinInfo *coin,
const MultisigRedeemScriptType *multisig,
uint8_t sighash, uint8_t *out);
uint32_t serialize_p2wpkh_witness(const uint8_t *signature,
uint32_t signature_len,
const uint8_t *public_key,
uint32_t public_key_len, uint8_t sighash,
uint8_t *out);
uint32_t serialize_p2tr_witness(const uint8_t *signature,
uint32_t signature_len, uint8_t sighash,
uint8_t *out);
bool tx_sign_ecdsa(const ecdsa_curve *curve, const uint8_t *private_key,
const uint8_t *hash, uint8_t *out, pb_size_t *size);
bool tx_sign_bip340(const uint8_t *private_key, const uint8_t *hash,
uint8_t *out, pb_size_t *size);
int compile_output(const CoinInfo *coin, AmountUnit amount_unit,
const HDNode *root, TxOutputType *in, TxOutputBinType *out,
bool needs_confirm);