signing: Use Hasher instead of SHA256_CTX

This commit is contained in:
Saleem Rashid 2017-12-09 14:38:37 +00:00 committed by Pavol Rusnak
parent dd7b21a6ca
commit 54b0869535
8 changed files with 78 additions and 78 deletions

View File

@ -29,6 +29,7 @@ def get_fields(coin):
'%d' % coin['forkid'] if coin['forkid'] else '0',
'"%s"' % coin['bech32_prefix'] if coin.get('bech32_prefix') is not None else 'NULL',
'0x%08x' % (0x80000000 + coin['bip44']),
'HASHER_SHA2',
]

View File

@ -24,6 +24,7 @@
#include <stdbool.h>
#include "coins_count.h"
#include "hasher.h"
typedef struct _CoinInfo {
const char *coin_name;
@ -43,6 +44,7 @@ typedef struct _CoinInfo {
uint32_t forkid;
const char *bech32_prefix;
uint32_t coin_type;
HasherType hasher_type;
} CoinInfo;
extern const CoinInfo coins[COINS_COUNT];

View File

@ -54,21 +54,21 @@ uint32_t ser_length(uint32_t len, uint8_t *out)
return 5;
}
uint32_t ser_length_hash(SHA256_CTX *ctx, uint32_t len)
uint32_t ser_length_hash(Hasher *hasher, uint32_t len)
{
if (len < 253) {
sha256_Update(ctx, (const uint8_t *)&len, 1);
hasher_Update(hasher, (const uint8_t *)&len, 1);
return 1;
}
if (len < 0x10000) {
uint8_t d = 253;
sha256_Update(ctx, &d, 1);
sha256_Update(ctx, (const uint8_t *)&len, 2);
hasher_Update(hasher, &d, 1);
hasher_Update(hasher, (const uint8_t *)&len, 2);
return 3;
}
uint8_t d = 254;
sha256_Update(ctx, &d, 1);
sha256_Update(ctx, (const uint8_t *)&len, 4);
hasher_Update(hasher, &d, 1);
hasher_Update(hasher, (const uint8_t *)&len, 4);
return 5;
}

View File

@ -28,13 +28,14 @@
#include <sha2.h>
#include <pb.h>
#include "coins.h"
#include "hasher.h"
#include "types.pb.h"
#define ser_length_size(len) ((len) < 253 ? 1 : (len) < 0x10000 ? 3 : 5)
uint32_t ser_length(uint32_t len, uint8_t *out);
uint32_t ser_length_hash(SHA256_CTX *ctx, uint32_t len);
uint32_t ser_length_hash(Hasher *hasher, uint32_t len);
int sshMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uint8_t *signature);

View File

@ -53,7 +53,7 @@ static TxRequest resp;
static TxInputType input;
static TxOutputBinType bin_output;
static TxStruct to, tp, ti;
static SHA256_CTX hashers[3];
static Hasher hashers[3];
static uint8_t CONFIDENTIAL privkey[32];
static uint8_t pubkey[33], sig[64];
static uint8_t hash_prevouts[32], hash_sequence[32],hash_outputs[32];
@ -323,13 +323,11 @@ void phase1_request_next_input(void)
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);
sha256_Final(&hashers[2], hash_check);
hasher_Double(&hashers[0], hash_prevouts);
hasher_Double(&hashers[1], hash_sequence);
hasher_Final(&hashers[2], hash_check);
// init hashOutputs
sha256_Init(&hashers[0]);
hasher_Reset(&hashers[0]);
idx1 = 0;
send_req_3_output();
}
@ -467,9 +465,9 @@ void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinInf
tx_init(&to, inputs_count, outputs_count, version, lock_time, 0);
// segwit hashes for hashPrevouts and hashSequence
sha256_Init(&hashers[0]);
sha256_Init(&hashers[1]);
sha256_Init(&hashers[2]);
hasher_Init(&hashers[0], coin->hasher_type);
hasher_Init(&hashers[1], coin->hasher_type);
hasher_Init(&hashers[2], coin->hasher_type);
layoutProgressSwipe(_("Signing transaction"), 0);
@ -507,7 +505,7 @@ static bool signing_check_input(TxInputType *txinput) {
tx_sequence_hash(&hashers[1], txinput);
// hash prevout and script type to check it later (relevant for fee computation)
tx_prevout_hash(&hashers[2], txinput);
sha256_Update(&hashers[2], &txinput->script_type, sizeof(&txinput->script_type));
hasher_Update(&hashers[2], &txinput->script_type, sizeof(&txinput->script_type));
return true;
}
@ -638,8 +636,7 @@ static void phase1_request_next_output(void) {
idx1++;
send_req_3_output();
} else {
sha256_Final(&hashers[0], hash_outputs);
sha256_Raw(hash_outputs, 32, hash_outputs);
hasher_Double(&hashers[0], hash_outputs);
if (!signing_check_fee()) {
return;
}
@ -653,19 +650,18 @@ 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();
sha256_Init(&hashers[0]);
sha256_Update(&hashers[0], (const uint8_t *)&version, 4);
sha256_Update(&hashers[0], hash_prevouts, 32);
sha256_Update(&hashers[0], hash_sequence, 32);
hasher_Reset(&hashers[0]);
hasher_Update(&hashers[0], (const uint8_t *)&version, 4);
hasher_Update(&hashers[0], hash_prevouts, 32);
hasher_Update(&hashers[0], hash_sequence, 32);
tx_prevout_hash(&hashers[0], txinput);
tx_script_hash(&hashers[0], txinput->script_sig.size, txinput->script_sig.bytes);
sha256_Update(&hashers[0], (const uint8_t*) &txinput->amount, 8);
hasher_Update(&hashers[0], (const uint8_t*) &txinput->amount, 8);
tx_sequence_hash(&hashers[0], txinput);
sha256_Update(&hashers[0], hash_outputs, 32);
sha256_Update(&hashers[0], (const uint8_t*) &lock_time, 4);
sha256_Update(&hashers[0], (const uint8_t*) &hash_type, 4);
sha256_Final(&hashers[0], hash);
sha256_Raw(hash, 32, hash);
hasher_Update(&hashers[0], hash_outputs, 32);
hasher_Update(&hashers[0], (const uint8_t*) &lock_time, 4);
hasher_Update(&hashers[0], (const uint8_t*) &hash_type, 4);
hasher_Double(&hashers[0], hash);
}
static bool signing_sign_hash(TxInputType *txinput, const uint8_t* private_key, const uint8_t *public_key, const uint8_t *hash) {
@ -705,8 +701,7 @@ static bool signing_sign_hash(TxInputType *txinput, const uint8_t* private_key,
static bool signing_sign_input(void) {
uint8_t hash[32];
sha256_Final(&hashers[0], hash);
sha256_Raw(hash, 32, hash);
hasher_Double(&hashers[0], hash);
if (memcmp(hash, hash_outputs, 32) != 0) {
fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing"));
signing_abort();
@ -714,7 +709,7 @@ static bool signing_sign_input(void) {
}
uint32_t hash_type = signing_hash_type();
sha256_Update(&ti.ctx, (const uint8_t *)&hash_type, 4);
hasher_Update(&ti.hasher, (const uint8_t *)&hash_type, 4);
tx_hash_final(&ti, hash, false);
resp.has_serialized = true;
if (!signing_sign_hash(&input, privkey, pubkey, hash))
@ -963,11 +958,11 @@ void signing_txack(TransactionType *tx)
progress = 500 + ((signatures * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION);
if (idx2 == 0) {
tx_init(&ti, inputs_count, outputs_count, version, lock_time, 0);
sha256_Init(&hashers[0]);
hasher_Reset(&hashers[0]);
}
// check prevouts and script type
tx_prevout_hash(&hashers[0], tx->inputs);
sha256_Update(&hashers[0], &tx->inputs[0].script_type, sizeof(&tx->inputs[0].script_type));
hasher_Update(&hashers[0], &tx->inputs[0].script_type, sizeof(&tx->inputs[0].script_type));
if (idx2 == idx1) {
if (!compile_input_script_sig(&tx->inputs[0])) {
fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile input"));
@ -995,13 +990,13 @@ void signing_txack(TransactionType *tx)
send_req_4_input();
} else {
uint8_t hash[32];
sha256_Final(&hashers[0], hash);
hasher_Final(&hashers[0], hash);
if (memcmp(hash, hash_check, 32) != 0) {
fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing"));
signing_abort();
return;
}
sha256_Init(&hashers[0]);
hasher_Reset(&hashers[0]);
idx2 = 0;
send_req_4_output();
}
@ -1096,7 +1091,7 @@ void signing_txack(TransactionType *tx)
tx->inputs[0].script_sig.bytes[1] = 0x00; // witness 0 script
tx->inputs[0].script_sig.bytes[2] = 0x20; // push 32 bytes (digest)
// compute digest of multisig script
if (!compile_script_multisig_hash(&tx->inputs[0].multisig, tx->inputs[0].script_sig.bytes + 3)) {
if (!compile_script_multisig_hash(&tx->inputs[0].multisig, coin->hasher_type, tx->inputs[0].script_sig.bytes + 3)) {
fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile input"));
signing_abort();
return;

View File

@ -24,6 +24,7 @@
#include <stdbool.h>
#include "bip32.h"
#include "coins.h"
#include "hasher.h"
#include "types.pb.h"
void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinInfo *_coin, const HDNode *_root, uint32_t _version, uint32_t _lock_time);

View File

@ -97,7 +97,7 @@ bool compute_address(const CoinInfo *coin,
if (cryptoMultisigPubkeyIndex(multisig, node->public_key) < 0) {
return 0;
}
if (compile_script_multisig_hash(multisig, digest) == 0) {
if (compile_script_multisig_hash(multisig, coin->hasher_type, digest) == 0) {
return 0;
}
if (script_type == InputScriptType_SPENDWITNESS) {
@ -119,7 +119,7 @@ bool compute_address(const CoinInfo *coin,
raw[0] = 0; // push version
raw[1] = 32; // push 32 bytes
memcpy(raw+2, digest, 32); // push hash
sha256_Raw(raw, 34, digest);
hasher_Raw(coin->hasher_type, raw, 34, digest);
prelen = address_prefix_bytes_len(coin->address_type_p2sh);
address_write_prefix_bytes(coin->address_type_p2sh, raw);
ripemd160(digest, 32, raw + prelen);
@ -305,7 +305,7 @@ uint32_t compile_script_multisig(const MultisigRedeemScriptType *multisig, uint8
return r;
}
uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, uint8_t *hash)
uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, HasherType hasher_type, uint8_t *hash)
{
if (!multisig->has_m) return 0;
const uint32_t m = multisig->m;
@ -313,22 +313,22 @@ uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig,
if (m < 1 || m > 15) return 0;
if (n < 1 || n > 15) return 0;
SHA256_CTX ctx;
sha256_Init(&ctx);
Hasher hasher;
hasher_Init(&hasher, hasher_type);
uint8_t d[2];
d[0] = 0x50 + m; sha256_Update(&ctx, d, 1);
d[0] = 0x50 + m; hasher_Update(&hasher, d, 1);
for (uint32_t i = 0; i < n; i++) {
d[0] = 33; sha256_Update(&ctx, d, 1); // OP_PUSH 33
d[0] = 33; hasher_Update(&hasher, d, 1); // OP_PUSH 33
const uint8_t *pubkey = cryptoHDNodePathToPubkey(&(multisig->pubkeys[i]));
if (!pubkey) return 0;
sha256_Update(&ctx, pubkey, 33);
hasher_Update(&hasher, pubkey, 33);
}
d[0] = 0x50 + n;
d[1] = 0xAE;
sha256_Update(&ctx, d, 2);
hasher_Update(&hasher, d, 2);
sha256_Final(&ctx, hash);
hasher_Final(&hasher, hash);
return 1;
}
@ -367,33 +367,33 @@ uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uin
// tx methods
uint32_t tx_prevout_hash(SHA256_CTX *ctx, const TxInputType *input)
uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input)
{
for (int i = 0; i < 32; i++) {
sha256_Update(ctx, &(input->prev_hash.bytes[31 - i]), 1);
hasher_Update(hasher, &(input->prev_hash.bytes[31 - i]), 1);
}
sha256_Update(ctx, (const uint8_t *)&input->prev_index, 4);
hasher_Update(hasher, (const uint8_t *)&input->prev_index, 4);
return 36;
}
uint32_t tx_script_hash(SHA256_CTX *ctx, 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(ctx, size);
sha256_Update(ctx, data, size);
int r = ser_length_hash(hasher, size);
hasher_Update(hasher, data, size);
return r + size;
}
uint32_t tx_sequence_hash(SHA256_CTX *ctx, const TxInputType *input)
uint32_t tx_sequence_hash(Hasher *hasher, const TxInputType *input)
{
sha256_Update(ctx, (const uint8_t *)&input->sequence, 4);
hasher_Update(hasher, (const uint8_t *)&input->sequence, 4);
return 4;
}
uint32_t tx_output_hash(SHA256_CTX *ctx, const TxOutputBinType *output)
uint32_t tx_output_hash(Hasher *hasher, const TxOutputBinType *output)
{
uint32_t r = 0;
sha256_Update(ctx, (const uint8_t *)&output->amount, 8); r += 8;
r += tx_script_hash(ctx, output->script_pubkey.size, output->script_pubkey.bytes);
hasher_Update(hasher, (const uint8_t *)&output->amount, 8); r += 8;
r += tx_script_hash(hasher, output->script_pubkey.size, output->script_pubkey.bytes);
return r;
}
@ -418,12 +418,12 @@ uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out)
uint32_t tx_serialize_header_hash(TxStruct *tx)
{
int r = 4;
sha256_Update(&(tx->ctx), (const uint8_t *)&(tx->version), 4);
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->version), 4);
if (tx->is_segwit) {
sha256_Update(&(tx->ctx), segwit_header, 2);
hasher_Update(&(tx->hasher), segwit_header, 2);
r += 2;
}
return r + ser_length_hash(&(tx->ctx), tx->inputs_len);
return r + ser_length_hash(&(tx->hasher), tx->inputs_len);
}
uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, uint8_t *out)
@ -460,9 +460,9 @@ uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input)
if (tx->have_inputs == 0) {
r += tx_serialize_header_hash(tx);
}
r += tx_prevout_hash(&(tx->ctx), input);
r += tx_script_hash(&(tx->ctx), input->script_sig.size, input->script_sig.bytes);
r += tx_sequence_hash(&(tx->ctx), input);
r += tx_prevout_hash(&(tx->hasher), input);
r += tx_script_hash(&(tx->hasher), input->script_sig.size, input->script_sig.bytes);
r += tx_sequence_hash(&(tx->hasher), input);
tx->have_inputs++;
tx->size += r;
@ -477,7 +477,7 @@ uint32_t tx_serialize_middle(TxStruct *tx, uint8_t *out)
uint32_t tx_serialize_middle_hash(TxStruct *tx)
{
return ser_length_hash(&(tx->ctx), tx->outputs_len);
return ser_length_hash(&(tx->hasher), tx->outputs_len);
}
uint32_t tx_serialize_footer(TxStruct *tx, uint8_t *out)
@ -488,7 +488,7 @@ uint32_t tx_serialize_footer(TxStruct *tx, uint8_t *out)
uint32_t tx_serialize_footer_hash(TxStruct *tx)
{
sha256_Update(&(tx->ctx), (const uint8_t *)&(tx->lock_time), 4);
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->lock_time), 4);
return 4;
}
@ -531,7 +531,7 @@ uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output)
if (tx->have_outputs == 0) {
r += tx_serialize_middle_hash(tx);
}
r += tx_output_hash(&(tx->ctx), output);
r += tx_output_hash(&(tx->hasher), output);
tx->have_outputs++;
if (tx->have_outputs == tx->outputs_len
&& !tx->is_segwit) {
@ -555,7 +555,7 @@ uint32_t tx_serialize_extra_data_hash(TxStruct *tx, const uint8_t *data, uint32_
// we are receiving too much data
return 0;
}
sha256_Update(&(tx->ctx), data, datalen);
hasher_Update(&(tx->hasher), data, datalen);
tx->extra_data_received += datalen;
tx->size += datalen;
return datalen;
@ -573,13 +573,12 @@ void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t v
tx->extra_data_received = 0;
tx->size = 0;
tx->is_segwit = false;
sha256_Init(&(tx->ctx));
hasher_Init(&(tx->hasher), HASHER_SHA2);
}
void tx_hash_final(TxStruct *t, uint8_t *hash, bool reverse)
{
sha256_Final(&(t->ctx), hash);
sha256_Raw(hash, 32, hash);
hasher_Double(&(t->hasher), hash);
if (!reverse) return;
for (uint8_t i = 0; i < 16; i++) {
uint8_t k = hash[31 - i];

View File

@ -25,6 +25,7 @@
#include "sha2.h"
#include "bip32.h"
#include "coins.h"
#include "hasher.h"
#include "types.pb.h"
typedef struct {
@ -43,21 +44,21 @@ typedef struct {
uint32_t size;
SHA256_CTX ctx;
Hasher hasher;
} TxStruct;
bool compute_address(const CoinInfo *coin, InputScriptType script_type, const HDNode *node, bool has_multisig, const MultisigRedeemScriptType *multisig, char address[MAX_ADDR_SIZE]);
uint32_t compile_script_sig(uint32_t address_type, const uint8_t *pubkeyhash, uint8_t *out);
uint32_t compile_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, uint8_t *hash);
uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, HasherType hasher_type, uint8_t *hash);
uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len, const uint8_t *pubkey, uint32_t pubkey_len, uint8_t sighash, uint8_t *out);
uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t sighash, uint8_t *out);
int compile_output(const CoinInfo *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_script_hash(SHA256_CTX *ctx, uint32_t size, const uint8_t *data);
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_prevout_hash(Hasher *hasher, const TxInputType *input);
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_output_hash(Hasher *hasher, const TxOutputBinType *output);
uint32_t tx_serialize_script(uint32_t size, const uint8_t *data, uint8_t *out);
uint32_t tx_serialize_footer(TxStruct *tx, uint8_t *out);