1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-30 19:38:15 +00:00

feat(legacy): support sortedmulti

This commit is contained in:
Ondřej Vejpustek 2024-11-22 18:08:29 +01:00
parent f3c85e7ec7
commit 2322c6774d
5 changed files with 34 additions and 32 deletions

View File

@ -18,6 +18,7 @@
*/
#include "crypto.h"
#include <stdlib.h>
#include <string.h>
#include "address.h"
#include "aes/aes.h"
@ -368,6 +369,11 @@ uint32_t cryptoMultisigPubkeyCount(const MultisigRedeemScriptType *multisig) {
: multisig->pubkeys_count;
}
static int comparePubkeysLexicographically(const void *first,
const void *second) {
return memcmp(first, second, 33);
}
uint32_t cryptoMultisigPubkeys(const CoinInfo *coin,
const MultisigRedeemScriptType *multisig,
uint8_t *pubkeys) {
@ -384,6 +390,11 @@ uint32_t cryptoMultisigPubkeys(const CoinInfo *coin,
memcpy(pubkeys + i * 33, pubnode->public_key, 33);
}
if (multisig->has_pubkeys_order &&
multisig->pubkeys_order == MultisigPubkeysOrder_LEXICOGRAPHIC) {
qsort(pubkeys, n, 33, comparePubkeysLexicographically);
}
return n;
}
@ -399,9 +410,14 @@ int cryptoMultisigPubkeyIndex(const CoinInfo *coin,
return -1;
}
static int comparePubnodesLexicographically(const void *first,
const void *second) {
return memcmp(first, second, sizeof(HDNodeType));
}
int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,
uint8_t *hash) {
static const HDNodeType *pubnodes[15], *swap;
static const HDNodeType *pubnodes[15];
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
if (n < 1 || n > 15) {
return 0;
@ -422,21 +438,20 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,
if (pubnodes[i]->public_key.size != 33) return 0;
if (pubnodes[i]->chain_code.size != 32) return 0;
}
// minsort according to pubkey
for (uint32_t i = 0; i < n - 1; i++) {
for (uint32_t j = n - 1; j > i; j--) {
if (memcmp(pubnodes[i]->public_key.bytes, pubnodes[j]->public_key.bytes,
33) > 0) {
swap = pubnodes[i];
pubnodes[i] = pubnodes[j];
pubnodes[j] = swap;
}
}
if (multisig->has_pubkeys_order &&
multisig->pubkeys_order == MultisigPubkeysOrder_LEXICOGRAPHIC) {
// If the order of pubkeys is lexicographic, we don't want the fingerprint
// to depend on the order of the pubnodes, so we sort the pubnodes before
// hashing.
qsort(pubnodes, n, sizeof(HDNodeType *), comparePubnodesLexicographically);
}
// hash sorted nodes
SHA256_CTX ctx = {0};
sha256_Init(&ctx);
sha256_Update(&ctx, (const uint8_t *)&(multisig->m), sizeof(uint32_t));
sha256_Update(&ctx, (const uint8_t *)&(multisig->pubkeys_order),
sizeof(uint32_t));
for (uint32_t i = 0; i < n; i++) {
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->depth),
sizeof(uint32_t));

View File

@ -296,10 +296,15 @@ void fsm_msgGetAddress(const GetAddress *msg) {
}
if (msg->has_show_display && msg->show_display) {
char desc[20] = {0};
char desc[29] = {0};
int multisig_index = 0;
if (msg->has_multisig) {
strlcpy(desc, "Multisig __ of __:", sizeof(desc));
if (msg->multisig.has_pubkeys_order &&
msg->multisig.pubkeys_order == MultisigPubkeysOrder_LEXICOGRAPHIC) {
strlcpy(desc, "Multisig __ of __ (sorted):", sizeof(desc));
} else {
strlcpy(desc, "Multisig __ of __:", sizeof(desc));
}
const uint32_t m = msg->multisig.m;
const uint32_t n = cryptoMultisigPubkeyCount(&(msg->multisig));
desc[9] = (m < 10) ? ' ' : ('0' + (m / 10));

View File

@ -364,11 +364,6 @@ uint32_t compile_script_sig(uint32_t address_type, const uint8_t *pubkeyhash,
uint32_t compile_script_multisig(const CoinInfo *coin,
const MultisigRedeemScriptType *multisig,
uint8_t *out) {
if (multisig->pubkeys_order != MultisigPubkeysOrder_PRESERVED) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Sortedmulti is not supported"));
return 0;
}
const uint32_t m = multisig->m;
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
if (m < 1 || m > 15) return 0;
@ -402,12 +397,6 @@ uint32_t compile_script_multisig(const CoinInfo *coin,
uint32_t compile_script_multisig_hash(const CoinInfo *coin,
const MultisigRedeemScriptType *multisig,
uint8_t *hash) {
if (multisig->pubkeys_order != MultisigPubkeysOrder_PRESERVED) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Sortedmulti is not supported"));
return 0;
}
const uint32_t m = multisig->m;
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
if (m < 1 || m > 15) return 0;
@ -457,11 +446,6 @@ 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) {
if (multisig->pubkeys_order != MultisigPubkeysOrder_PRESERVED) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Sortedmulti is not supported"));
return 0;
}
uint32_t r = 0;
#if !BITCOIN_ONLY
if (!coin->decred) {

View File

@ -197,7 +197,6 @@ def test_altcoin_address_mac(client: Client):
@pytest.mark.multisig
@pytest.mark.models(skip="legacy", reason="Sortedmulti is not supported")
def test_multisig_pubkeys_order(client: Client):
xpub_internal = btc.get_public_node(client, parse_path("m/45h/0")).xpub
xpub_external = btc.get_public_node(client, parse_path("m/44h/1")).xpub

View File

@ -162,7 +162,6 @@ def test_2_of_3(client: Client, chunkify: bool):
@pytest.mark.multisig
@pytest.mark.models(skip="legacy", reason="Sortedmulti is not supported")
def test_pubkeys_order(client: Client):
node_internal = btc.get_public_node(
client, parse_path("m/45h/0"), coin_name="Bitcoin"