mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-09 18:38:47 +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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
layoutProgressUpdate(true);
|
layoutProgressUpdate(true);
|
||||||
for (uint32_t i = 0; i < hdnodepath->address_n_count; i++) {
|
for (uint32_t i = 0; i < address_n_count; i++) {
|
||||||
if (hdnode_public_ckd(&node, hdnodepath->address_n[i]) == 0) {
|
if (!hdnode_public_ckd(&node, address_n[i])) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
layoutProgressUpdate(true);
|
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)
|
int cryptoMultisigPubkeyIndex(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, const uint8_t *pubkey)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < multisig->pubkeys_count; i++) {
|
for (size_t i = 0; i < cryptoMultisigPubkeyCount(multisig); i++) {
|
||||||
const uint8_t *node_pubkey = cryptoHDNodePathToPubkey(coin, &(multisig->pubkeys[i]));
|
const HDNode *pubnode = cryptoMultisigPubkey(coin, multisig, i);
|
||||||
if (node_pubkey && memcmp(node_pubkey, pubkey, 33) == 0) {
|
if (pubnode && memcmp(pubnode->public_key, pubkey, 33) == 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,25 +391,35 @@ int cryptoMultisigPubkeyIndex(const CoinInfo *coin, const MultisigRedeemScriptTy
|
|||||||
|
|
||||||
int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t *hash)
|
int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t *hash)
|
||||||
{
|
{
|
||||||
static const HDNodePathType *ptr[15], *swap;
|
static const HDNodeType *pubnodes[15], *swap;
|
||||||
const uint32_t n = multisig->pubkeys_count;
|
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||||
if (n < 1 || n > 15) {
|
if (n < 1 || n > 15) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// check sanity
|
if (!multisig->has_m || multisig->m < 1 || multisig->m > 15) {
|
||||||
if (!multisig->has_m || multisig->m < 1 || multisig->m > 15) return 0;
|
return 0;
|
||||||
|
}
|
||||||
for (uint32_t i = 0; i < n; i++) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
ptr[i] = &(multisig->pubkeys[i]);
|
if (multisig->nodes_count) { // use multisig->nodes
|
||||||
if (!ptr[i]->node.has_public_key || ptr[i]->node.public_key.size != 33) return 0;
|
pubnodes[i] = &(multisig->nodes[i]);
|
||||||
if (ptr[i]->node.chain_code.size != 32) return 0;
|
} 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
|
// minsort according to pubkey
|
||||||
for (uint32_t i = 0; i < n - 1; i++) {
|
for (uint32_t i = 0; i < n - 1; i++) {
|
||||||
for (uint32_t j = n - 1; j > i; j--) {
|
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) {
|
if (memcmp(pubnodes[i]->public_key.bytes, pubnodes[j]->public_key.bytes, 33) > 0) {
|
||||||
swap = ptr[i];
|
swap = pubnodes[i];
|
||||||
ptr[i] = ptr[j];
|
pubnodes[i] = pubnodes[j];
|
||||||
ptr[j] = swap;
|
pubnodes[j] = swap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,11 +428,11 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t
|
|||||||
sha256_Init(&ctx);
|
sha256_Init(&ctx);
|
||||||
sha256_Update(&ctx, (const uint8_t *)&(multisig->m), sizeof(uint32_t));
|
sha256_Update(&ctx, (const uint8_t *)&(multisig->m), sizeof(uint32_t));
|
||||||
for (uint32_t i = 0; i < n; i++) {
|
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 *)&(pubnodes[i]->depth), sizeof(uint32_t));
|
||||||
sha256_Update(&ctx, (const uint8_t *)&(ptr[i]->node.fingerprint), sizeof(uint32_t));
|
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->fingerprint), sizeof(uint32_t));
|
||||||
sha256_Update(&ctx, (const uint8_t *)&(ptr[i]->node.child_num), sizeof(uint32_t));
|
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->child_num), sizeof(uint32_t));
|
||||||
sha256_Update(&ctx, ptr[i]->node.chain_code.bytes, 32);
|
sha256_Update(&ctx, pubnodes[i]->chain_code.bytes, 32);
|
||||||
sha256_Update(&ctx, ptr[i]->node.public_key.bytes, 33);
|
sha256_Update(&ctx, pubnodes[i]->public_key.bytes, 33);
|
||||||
}
|
}
|
||||||
sha256_Update(&ctx, (const uint8_t *)&n, sizeof(uint32_t));
|
sha256_Update(&ctx, (const uint8_t *)&n, sizeof(uint32_t));
|
||||||
sha256_Final(&ctx, hash);
|
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);
|
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);
|
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;
|
if (!multisig->has_m) return 0;
|
||||||
const uint32_t m = multisig->m;
|
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 (m < 1 || m > 15) return 0;
|
||||||
if (n < 1 || n > 15) return 0;
|
if (n < 1 || n > 15) return 0;
|
||||||
uint32_t r = 0;
|
uint32_t r = 0;
|
||||||
@ -348,9 +348,9 @@ uint32_t compile_script_multisig(const CoinInfo *coin, const MultisigRedeemScrip
|
|||||||
out[r] = 0x50 + m; r++;
|
out[r] = 0x50 + m; r++;
|
||||||
for (uint32_t i = 0; i < n; i++) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
out[r] = 33; r++; // OP_PUSH 33
|
out[r] = 33; r++; // OP_PUSH 33
|
||||||
const uint8_t *pubkey = cryptoHDNodePathToPubkey(coin, &(multisig->pubkeys[i]));
|
const HDNode *pubnode = cryptoMultisigPubkey(coin, multisig, i);
|
||||||
if (!pubkey) return 0;
|
if (!pubnode) return 0;
|
||||||
memcpy(out + r, pubkey, 33); r += 33;
|
memcpy(out + r, pubnode->public_key, 33); r += 33;
|
||||||
}
|
}
|
||||||
out[r] = 0x50 + n; r++;
|
out[r] = 0x50 + n; r++;
|
||||||
out[r] = 0xAE; r++; // OP_CHECKMULTISIG
|
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;
|
if (!multisig->has_m) return 0;
|
||||||
const uint32_t m = multisig->m;
|
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 (m < 1 || m > 15) return 0;
|
||||||
if (n < 1 || n > 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);
|
d[0] = 0x50 + m; hasher_Update(&hasher, d, 1);
|
||||||
for (uint32_t i = 0; i < n; i++) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
d[0] = 33; hasher_Update(&hasher, d, 1); // OP_PUSH 33
|
d[0] = 33; hasher_Update(&hasher, d, 1); // OP_PUSH 33
|
||||||
const uint8_t *pubkey = cryptoHDNodePathToPubkey(coin, &(multisig->pubkeys[i]));
|
const HDNode *pubnode = cryptoMultisigPubkey(coin, multisig, i);
|
||||||
if (!pubkey) return 0;
|
if (!pubnode) return 0;
|
||||||
hasher_Update(&hasher, pubkey, 33);
|
hasher_Update(&hasher, pubnode->public_key, 33);
|
||||||
}
|
}
|
||||||
d[0] = 0x50 + n;
|
d[0] = 0x50 + n;
|
||||||
d[1] = 0xAE;
|
d[1] = 0xAE;
|
||||||
|
Loading…
Reference in New Issue
Block a user