1
0
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:
Pavol Rusnak 2019-02-04 01:26:26 +01:00
parent f9ba64ea94
commit 19c7c8bc3b
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
3 changed files with 73 additions and 34 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;