From f4425a3ac158f6f15024ea684314ca96abbcdd8d Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 16 Mar 2023 16:10:43 +0100 Subject: [PATCH] feat(legacy): implement CoSi verification --- legacy/firmware/crypto.c | 44 ++++++++++++++++++++++++++++++++++++++++ legacy/firmware/crypto.h | 5 +++++ 2 files changed, 49 insertions(+) diff --git a/legacy/firmware/crypto.c b/legacy/firmware/crypto.c index 90e7b6a42..5d1f4ae90 100644 --- a/legacy/firmware/crypto.c +++ b/legacy/firmware/crypto.c @@ -856,3 +856,47 @@ void slip21_derive_path(Slip21Node *inout, const uint8_t *label, } const uint8_t *slip21_key(const Slip21Node *node) { return &node->data[32]; } + +bool cryptoCosiVerify(const ed25519_signature signature, const uint8_t *message, + const size_t message_len, const int threshold, + const ed25519_public_key *pubkeys, + const int pubkeys_count, const uint8_t sigmask) + +{ + if (sigmask == 0 || threshold < 1 || pubkeys_count < 1 || pubkeys_count > 8) { + // invalid parameters: + // - sigmask must specify at least one signer + // - at least one signature must be required + // - at least one pubkey must be provided + // - at most 8 pubkeys are supported (bit size of sigmask) + return false; + } + if (sigmask >= (1 << pubkeys_count)) { + // sigmask indicates more signers than provided pubkeys + return false; + } + + ed25519_public_key selected_keys[8] = {0}; + int N = 0; + for (int i = 0; i < pubkeys_count; i++) { + if (sigmask & (1 << i)) { + memcpy(selected_keys[N], pubkeys[i], sizeof(ed25519_public_key)); + N++; + } + } + + if (N < threshold) { + // not enough signatures + return false; + } + + ed25519_public_key pk_combined = {0}; + int res = ed25519_cosi_combine_publickeys(pk_combined, selected_keys, N); + if (res != 0) { + // error combining public keys + return false; + } + + res = ed25519_sign_open(message, message_len, pk_combined, signature); + return res == 0; +} diff --git a/legacy/firmware/crypto.h b/legacy/firmware/crypto.h index 9098730c6..8df938fc2 100644 --- a/legacy/firmware/crypto.h +++ b/legacy/firmware/crypto.h @@ -93,6 +93,11 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, int cryptoIdentityFingerprint(const IdentityType *identity, uint8_t *hash); +bool cryptoCosiVerify(const ed25519_signature signature, const uint8_t *message, + const size_t message_len, const int threshold, + const ed25519_public_key *pubkeys, + const int pubkeys_count, const uint8_t sigmask); + bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, uint32_t address_n_count, const uint32_t *address_n, bool has_multisig, PathSchema unlock, bool full_check);