1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-30 03:18:20 +00:00

implement GetAddress.multisig field

This commit is contained in:
Pavol Rusnak 2014-12-10 18:04:51 +01:00
parent 6561647d6b
commit 92cfcd1565
6 changed files with 68 additions and 10 deletions

View File

@ -251,3 +251,14 @@ int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, pb_size_t payload
*msg_len = o; *msg_len = o;
return 0; return 0;
} }
int cryptoMultisigPubkeyIndex(const MultisigRedeemScriptType *multisig, const uint8_t *pubkey, uint32_t pubkey_len)
{
int i;
for (i = 0; i < multisig->pubkeys_count; i++) {
if (multisig->pubkeys[i].size == pubkey_len && memcmp(multisig->pubkeys[i].bytes, pubkey, pubkey_len) == 0) {
return i;
}
}
return -1;
}

View File

@ -25,6 +25,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <secp256k1.h> #include <secp256k1.h>
#include <pb.h> #include <pb.h>
#include "types.pb.h"
uint32_t ser_length(uint32_t len, uint8_t *out); uint32_t ser_length(uint32_t len, uint8_t *out);
@ -38,4 +39,6 @@ int cryptoMessageEncrypt(curve_point *pubkey, const uint8_t *msg, pb_size_t msg_
int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, pb_size_t payload_len, const uint8_t *hmac, pb_size_t hmac_len, const uint8_t *privkey, uint8_t *msg, pb_size_t *msg_len, bool *display_only, bool *signing, uint8_t *address_raw); int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, pb_size_t payload_len, const uint8_t *hmac, pb_size_t hmac_len, const uint8_t *privkey, uint8_t *msg, pb_size_t *msg_len, bool *display_only, bool *signing, uint8_t *address_raw);
int cryptoMultisigPubkeyIndex(const MultisigRedeemScriptType *multisig, const uint8_t *pubkey, uint32_t pubkey_len);
#endif #endif

View File

@ -43,6 +43,7 @@
#include "crypto.h" #include "crypto.h"
#include "base58.h" #include "base58.h"
#include "bip39.h" #include "bip39.h"
#include "ripemd160.h"
// message methods // message methods
@ -487,7 +488,24 @@ void fsm_msgGetAddress(GetAddress *msg)
fsm_deriveKey(node, msg->address_n, msg->address_n_count); fsm_deriveKey(node, msg->address_n, msg->address_n_count);
ecdsa_get_address(node->public_key, coin->address_type, resp->address); if (msg->has_multisig) {
if (cryptoMultisigPubkeyIndex(&(msg->multisig), node->public_key, 33) < 0) {
fsm_sendFailure(FailureType_Failure_Other, "Pubkey not found in multisig script");
layoutHome();
return;
}
uint8_t buf[32];
if (compile_script_multisig_hash(&(msg->multisig), buf) == 0) {
fsm_sendFailure(FailureType_Failure_Other, "Invalid multisig script");
layoutHome();
return;
}
ripemd160(buf, 32, buf + 1);
buf[0] = 0x05; // multisig cointype
base58_encode_check(buf, 21, resp->address);
} else {
ecdsa_get_address(node->public_key, coin->address_type, resp->address);
}
if (msg->has_show_display && msg->show_display) { if (msg->has_show_display && msg->show_display) {
layoutAddress(resp->address); layoutAddress(resp->address);

View File

@ -24,6 +24,7 @@
#include "transaction.h" #include "transaction.h"
#include "ecdsa.h" #include "ecdsa.h"
#include "protect.h" #include "protect.h"
#include "crypto.h"
static uint32_t inputs_count; static uint32_t inputs_count;
static uint32_t outputs_count; static uint32_t outputs_count;
@ -378,14 +379,8 @@ void signing_txack(TransactionType *tx)
return; return;
} }
// fill in the signature // fill in the signature
int i, pubkey_idx = -1; int pubkey_idx = cryptoMultisigPubkeyIndex(&(input.multisig), pubkey, 33);
for (i = 0; i < input.multisig.pubkeys_count; i++) { if (pubkey_idx < 0) {
if (input.multisig.pubkeys[i].size == 33 && memcmp(input.multisig.pubkeys[i].bytes, pubkey, 33) == 0) {
pubkey_idx = i;
break;
}
}
if (pubkey_idx == -1) {
fsm_sendFailure(FailureType_Failure_Other, "Pubkey not found in multisig script"); fsm_sendFailure(FailureType_Failure_Other, "Pubkey not found in multisig script");
signing_abort(); signing_abort();
return; return;

View File

@ -149,8 +149,8 @@ uint32_t compile_script_multisig(const MultisigRedeemScriptType *multisig, uint8
out[r] = 0xAE; r++; // OP_CHECKMULTISIG out[r] = 0xAE; r++; // OP_CHECKMULTISIG
} else { } else {
r++; r++;
uint8_t dummy[8];
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
uint8_t dummy[8];
r += op_push(multisig->pubkeys[i].size, dummy); r += op_push(multisig->pubkeys[i].size, dummy);
r += multisig->pubkeys[i].size; r += multisig->pubkeys[i].size;
} }
@ -160,6 +160,36 @@ uint32_t compile_script_multisig(const MultisigRedeemScriptType *multisig, uint8
return r; return r;
} }
uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, uint8_t *hash)
{
if (!multisig->has_m) return 0;
uint32_t m = multisig->m;
uint32_t n = multisig->pubkeys_count;
if (m < 2 || m > 3) return 0;
if (n < 2 || n > 3) return 0;
SHA256_CTX ctx;
sha256_Init(&ctx);
uint8_t d, dummy[8];
d = 0x50 + m;
sha256_Update(&ctx, &d, 1);
uint32_t i, r;
for (i = 0; i < n; i++) {
r = op_push(multisig->pubkeys[i].size, dummy);
sha256_Update(&ctx, dummy, r);
sha256_Update(&ctx, multisig->pubkeys[i].bytes, multisig->pubkeys[i].size);
}
d = 0x50 + n;
sha256_Update(&ctx, &d, 1);
d = 0xAE;
sha256_Update(&ctx, &d, 1);
sha256_Final(hash, &ctx);
return 1;
}
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 r = 0; uint32_t r = 0;

View File

@ -43,6 +43,7 @@ typedef struct {
uint32_t compile_script_sig(uint8_t address_type, const uint8_t *pubkeyhash, uint8_t *out); uint32_t compile_script_sig(uint8_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(const MultisigRedeemScriptType *multisig, uint8_t *out);
uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, 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 *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);