mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 01:18:28 +00:00
signing: implemented simplified API for MultisigRedeemScriptType
If address_n is the same for all nodes in the multisig, provide it just once and supply nodes directly (not in the HDNodePathType structure)
This commit is contained in:
parent
f9ba64ea94
commit
19c7c8bc3b
@ -334,28 +334,55 @@ int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, size_t payload_le
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t *cryptoHDNodePathToPubkey(const CoinInfo *coin, const HDNodePathType *hdnodepath)
|
||||
const HDNode *cryptoMultisigPubkey(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, uint32_t index)
|
||||
{
|
||||
if (!hdnodepath->node.has_public_key || hdnodepath->node.public_key.size != 33) return 0;
|
||||
const HDNodeType *node_ptr;
|
||||
const uint32_t *address_n;
|
||||
uint32_t address_n_count;
|
||||
if (multisig->nodes_count) { // use multisig->nodes
|
||||
if (index >= multisig->nodes_count) {
|
||||
return 0;
|
||||
}
|
||||
node_ptr = &(multisig->nodes[index]);
|
||||
address_n = multisig->address_n;
|
||||
address_n_count = multisig->address_n_count;
|
||||
} else
|
||||
if (multisig->pubkeys_count) { // use multisig->pubkeys
|
||||
if (index >= multisig->pubkeys_count) {
|
||||
return 0;
|
||||
}
|
||||
node_ptr = &(multisig->pubkeys[index].node);
|
||||
address_n = multisig->pubkeys[index].address_n;
|
||||
address_n_count = multisig->pubkeys[index].address_n_count;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (node_ptr->chain_code.size != 32) return 0;
|
||||
if (!node_ptr->has_public_key || node_ptr->public_key.size != 33) return 0;
|
||||
static HDNode node;
|
||||
if (hdnode_from_xpub(hdnodepath->node.depth, hdnodepath->node.child_num, hdnodepath->node.chain_code.bytes, hdnodepath->node.public_key.bytes, coin->curve_name, &node) == 0) {
|
||||
if (!hdnode_from_xpub(node_ptr->depth, node_ptr->child_num, node_ptr->chain_code.bytes, node_ptr->public_key.bytes, coin->curve_name, &node)) {
|
||||
return 0;
|
||||
}
|
||||
layoutProgressUpdate(true);
|
||||
for (uint32_t i = 0; i < hdnodepath->address_n_count; i++) {
|
||||
if (hdnode_public_ckd(&node, hdnodepath->address_n[i]) == 0) {
|
||||
for (uint32_t i = 0; i < address_n_count; i++) {
|
||||
if (!hdnode_public_ckd(&node, address_n[i])) {
|
||||
return 0;
|
||||
}
|
||||
layoutProgressUpdate(true);
|
||||
}
|
||||
return node.public_key;
|
||||
return &node;
|
||||
}
|
||||
|
||||
uint32_t cryptoMultisigPubkeyCount(const MultisigRedeemScriptType *multisig)
|
||||
{
|
||||
return multisig->nodes_count ? multisig->nodes_count : multisig->pubkeys_count;
|
||||
}
|
||||
|
||||
int cryptoMultisigPubkeyIndex(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, const uint8_t *pubkey)
|
||||
{
|
||||
for (size_t i = 0; i < multisig->pubkeys_count; i++) {
|
||||
const uint8_t *node_pubkey = cryptoHDNodePathToPubkey(coin, &(multisig->pubkeys[i]));
|
||||
if (node_pubkey && memcmp(node_pubkey, pubkey, 33) == 0) {
|
||||
for (size_t i = 0; i < cryptoMultisigPubkeyCount(multisig); i++) {
|
||||
const HDNode *pubnode = cryptoMultisigPubkey(coin, multisig, i);
|
||||
if (pubnode && memcmp(pubnode->public_key, pubkey, 33) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -364,25 +391,35 @@ int cryptoMultisigPubkeyIndex(const CoinInfo *coin, const MultisigRedeemScriptTy
|
||||
|
||||
int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t *hash)
|
||||
{
|
||||
static const HDNodePathType *ptr[15], *swap;
|
||||
const uint32_t n = multisig->pubkeys_count;
|
||||
static const HDNodeType *pubnodes[15], *swap;
|
||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||
if (n < 1 || n > 15) {
|
||||
return 0;
|
||||
}
|
||||
// check sanity
|
||||
if (!multisig->has_m || multisig->m < 1 || multisig->m > 15) return 0;
|
||||
if (!multisig->has_m || multisig->m < 1 || multisig->m > 15) {
|
||||
return 0;
|
||||
}
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
ptr[i] = &(multisig->pubkeys[i]);
|
||||
if (!ptr[i]->node.has_public_key || ptr[i]->node.public_key.size != 33) return 0;
|
||||
if (ptr[i]->node.chain_code.size != 32) return 0;
|
||||
if (multisig->nodes_count) { // use multisig->nodes
|
||||
pubnodes[i] = &(multisig->nodes[i]);
|
||||
} else
|
||||
if (multisig->pubkeys_count) { // use multisig->pubkeys
|
||||
pubnodes[i] = &(multisig->pubkeys[i].node);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
if (!pubnodes[i]->has_public_key || 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(ptr[i]->node.public_key.bytes, ptr[j]->node.public_key.bytes, 33) > 0) {
|
||||
swap = ptr[i];
|
||||
ptr[i] = ptr[j];
|
||||
ptr[j] = swap;
|
||||
if (memcmp(pubnodes[i]->public_key.bytes, pubnodes[j]->public_key.bytes, 33) > 0) {
|
||||
swap = pubnodes[i];
|
||||
pubnodes[i] = pubnodes[j];
|
||||
pubnodes[j] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -391,11 +428,11 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t
|
||||
sha256_Init(&ctx);
|
||||
sha256_Update(&ctx, (const uint8_t *)&(multisig->m), sizeof(uint32_t));
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
sha256_Update(&ctx, (const uint8_t *)&(ptr[i]->node.depth), sizeof(uint32_t));
|
||||
sha256_Update(&ctx, (const uint8_t *)&(ptr[i]->node.fingerprint), sizeof(uint32_t));
|
||||
sha256_Update(&ctx, (const uint8_t *)&(ptr[i]->node.child_num), sizeof(uint32_t));
|
||||
sha256_Update(&ctx, ptr[i]->node.chain_code.bytes, 32);
|
||||
sha256_Update(&ctx, ptr[i]->node.public_key.bytes, 33);
|
||||
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->depth), sizeof(uint32_t));
|
||||
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->fingerprint), sizeof(uint32_t));
|
||||
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->child_num), sizeof(uint32_t));
|
||||
sha256_Update(&ctx, pubnodes[i]->chain_code.bytes, 32);
|
||||
sha256_Update(&ctx, pubnodes[i]->public_key.bytes, 33);
|
||||
}
|
||||
sha256_Update(&ctx, (const uint8_t *)&n, sizeof(uint32_t));
|
||||
sha256_Final(&ctx, hash);
|
||||
|
@ -52,7 +52,9 @@ int cryptoMessageEncrypt(curve_point *pubkey, const uint8_t *msg, size_t msg_siz
|
||||
int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, size_t payload_len, const uint8_t *hmac, size_t hmac_len, const uint8_t *privkey, uint8_t *msg, size_t *msg_len, bool *display_only, bool *signing, uint8_t *address_raw);
|
||||
*/
|
||||
|
||||
uint8_t *cryptoHDNodePathToPubkey(const CoinInfo *coin, const HDNodePathType *hdnodepath);
|
||||
const HDNode *cryptoMultisigPubkey(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, uint32_t index);
|
||||
|
||||
uint32_t cryptoMultisigPubkeyCount(const MultisigRedeemScriptType *multisig);
|
||||
|
||||
int cryptoMultisigPubkeyIndex(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, const uint8_t *pubkey);
|
||||
|
||||
|
@ -340,7 +340,7 @@ uint32_t compile_script_multisig(const CoinInfo *coin, const MultisigRedeemScrip
|
||||
{
|
||||
if (!multisig->has_m) return 0;
|
||||
const uint32_t m = multisig->m;
|
||||
const uint32_t n = multisig->pubkeys_count;
|
||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||
if (m < 1 || m > 15) return 0;
|
||||
if (n < 1 || n > 15) return 0;
|
||||
uint32_t r = 0;
|
||||
@ -348,9 +348,9 @@ uint32_t compile_script_multisig(const CoinInfo *coin, const MultisigRedeemScrip
|
||||
out[r] = 0x50 + m; r++;
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
out[r] = 33; r++; // OP_PUSH 33
|
||||
const uint8_t *pubkey = cryptoHDNodePathToPubkey(coin, &(multisig->pubkeys[i]));
|
||||
if (!pubkey) return 0;
|
||||
memcpy(out + r, pubkey, 33); r += 33;
|
||||
const HDNode *pubnode = cryptoMultisigPubkey(coin, multisig, i);
|
||||
if (!pubnode) return 0;
|
||||
memcpy(out + r, pubnode->public_key, 33); r += 33;
|
||||
}
|
||||
out[r] = 0x50 + n; r++;
|
||||
out[r] = 0xAE; r++; // OP_CHECKMULTISIG
|
||||
@ -364,7 +364,7 @@ uint32_t compile_script_multisig_hash(const CoinInfo *coin, const MultisigRedeem
|
||||
{
|
||||
if (!multisig->has_m) return 0;
|
||||
const uint32_t m = multisig->m;
|
||||
const uint32_t n = multisig->pubkeys_count;
|
||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||
if (m < 1 || m > 15) return 0;
|
||||
if (n < 1 || n > 15) return 0;
|
||||
|
||||
@ -375,9 +375,9 @@ uint32_t compile_script_multisig_hash(const CoinInfo *coin, const MultisigRedeem
|
||||
d[0] = 0x50 + m; hasher_Update(&hasher, d, 1);
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
d[0] = 33; hasher_Update(&hasher, d, 1); // OP_PUSH 33
|
||||
const uint8_t *pubkey = cryptoHDNodePathToPubkey(coin, &(multisig->pubkeys[i]));
|
||||
if (!pubkey) return 0;
|
||||
hasher_Update(&hasher, pubkey, 33);
|
||||
const HDNode *pubnode = cryptoMultisigPubkey(coin, multisig, i);
|
||||
if (!pubnode) return 0;
|
||||
hasher_Update(&hasher, pubnode->public_key, 33);
|
||||
}
|
||||
d[0] = 0x50 + n;
|
||||
d[1] = 0xAE;
|
||||
|
Loading…
Reference in New Issue
Block a user