diff --git a/include/secp256k1_chilldkg.h b/include/secp256k1_chilldkg.h index 7764ce30..bb0c6bed 100644 --- a/include/secp256k1_chilldkg.h +++ b/include/secp256k1_chilldkg.h @@ -27,10 +27,286 @@ extern "C" { * key, and the public shares of all participants) is designed to be used * directly with the FROST signing module (see include/secp256k1_frost.h). * + * A DKG session involves n participants (identified by uint32 identifiers + * 0..n-1) and an untrusted coordinator. The number of participants n must + * not exceed SECP256K1_CHILLDKG_MAX_PARTICIPANTS. The message flow is: + * 1. Every participant runs secp256k1_chilldkg_participant_step1 and sends + * the resulting pmsg1 to the coordinator. + * 2. The coordinator aggregates the pmsg1s into a single cmsg1 broadcast + * to all participants (coordinator API is not available yet). + * 3. Every participant runs secp256k1_chilldkg_participant_step2 and sends + * the resulting signature (pmsg2) to the coordinator. + * 4. The coordinator collects the n signatures into a certificate (cmsg2) + * broadcast to all participants. + * 5. Every participant runs secp256k1_chilldkg_participant_finalize to + * obtain the DKG output and the recovery data. + * * It is recommended to read the documentation in this include file carefully. * Further notes on API usage can be found in src/modules/chilldkg/chilldkg.md. */ +/** The maximum number of participants n in a ChillDKG session. The state + * objects of this module are fixed-size and do not use dynamic allocation, + * so a compile-time cap is required. This matches the FROST module's + * SECP256K1_FROST_MAX_PARTICIPANTS. */ +#define SECP256K1_CHILLDKG_MAX_PARTICIPANTS 128 + +/** Fault report of the ChillDKG protocol functions, mapping the exception + * taxonomy of the reference implementation. + * + * For SECP256K1_CHILLDKG_FAULTY_PARTICIPANT and + * SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, the fault_index + * output of the failing function is set to the identifier of the (suspected) + * faulty participant. For the other fault codes, fault_index is set to + * UINT32_MAX, except where documented otherwise. */ +typedef enum { + /** No fault; the step succeeded. */ + SECP256K1_CHILLDKG_OK = 0, + /** The coordinator is faulty. */ + SECP256K1_CHILLDKG_FAULTY_COORDINATOR = 1, + /** The participant with the given fault_index is faulty. */ + SECP256K1_CHILLDKG_FAULTY_PARTICIPANT = 2, + /** The participant with the given fault_index or the coordinator is + * faulty. */ + SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR = 3, + /** Some unknown participant or the coordinator is faulty; the + * investigation procedure of the protocol is necessary to determine a + * suspected participant. */ + SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR = 4, + /** The caller provided invalid input (e.g., an invalid host secret key or + * invalid session parameters). */ + SECP256K1_CHILLDKG_INVALID_INPUT = 5 +} secp256k1_chilldkg_fault; + +/** Opaque data structures + * + * The exact representation of data inside the opaque data structures is + * implementation defined and not guaranteed to be portable between different + * platforms or versions. The data structures can be safely copied/moved. + */ + +/** Opaque data structure that holds a participant's session state after + * secp256k1_chilldkg_participant_step1. + * + * The state does not contain secret key material (the secret shares it + * relates to are encrypted in pmsg1), but it must not be reused: it must be + * passed only to a single secp256k1_chilldkg_participant_step2 call. + * + * Guaranteed to be 4306 bytes in size. + */ +typedef struct secp256k1_chilldkg_participant_state1 { + unsigned char data[4 + 12 + 33 + 33 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS]; +} secp256k1_chilldkg_participant_state1; + +/** Opaque data structure that holds a participant's session state after + * secp256k1_chilldkg_participant_step2. + * + * This structure contains the participant's secret share; it MUST be kept + * secret and MUST NOT be copied. It must not be reused: it must be passed + * only to a single secp256k1_chilldkg_participant_finalize call. + * + * Guaranteed to be 21073 bytes in size. + */ +typedef struct secp256k1_chilldkg_participant_state2 { + unsigned char data[12 + 4 + 131 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 32 + 33 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS]; +} secp256k1_chilldkg_participant_state2; + +/** Compute the participant's host public key from the host secret key. + * + * The host public key is the long-term cryptographic identity of the + * participant. This function interprets hostseckey32 as a big-endian integer + * and computes the corresponding "plain" public key in compressed + * serialization (33 bytes, starting with 0x02 or 0x03), equivalent to + * IndividualPubkey as defined in BIP 327. + * + * Returns: 1 on success, 0 if the host secret key is invalid (zero or not + * less than the group order). On failure, hostpubkey33 is set to + * zero. + * Args: ctx: pointer to a context object + * Out: hostpubkey33: pointer to a 33-byte array to store the host public key + * In: hostseckey32: pointer to the 32-byte host secret key + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_hostpubkey_gen( + const secp256k1_context *ctx, + unsigned char *hostpubkey33, + const unsigned char *hostseckey32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Return a hash of the session parameters for out-of-band comparison. + * + * If all participants have obtained an identical parameters hash (as can be + * verified out of band), then they all agree on all host public keys and the + * threshold t. + * + * Returns: 1 on success, 0 if the session parameters are invalid (not + * 1 <= t <= n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS, an invalid + * host public key, or a duplicate host public key). On failure, + * hash32 is set to zero. + * Args: ctx: pointer to a context object + * Out: hash32: pointer to a 32-byte array to store the parameters + * hash + * In: hostpubkeys33: pointer to an array of n_participants host public + * keys (33 bytes each, compressed serialization) + * n_participants: total number of participants n + * threshold: threshold t + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_params_hash( + const secp256k1_context *ctx, + unsigned char *hash32, + const unsigned char *hostpubkeys33, + size_t n_participants, + uint32_t threshold +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Length of a participant's first message (pmsg1): 33*t + 32*n + 97 bytes. + * Returns 0 if the parameters are out of range. */ +SECP256K1_API size_t secp256k1_chilldkg_participant_msg1_len( + size_t n_participants, + uint32_t threshold +); + +/** Length of the coordinator's first message (cmsg1): 162*n + 33*(t-1) bytes. + * Returns 0 if the parameters are out of range. */ +SECP256K1_API size_t secp256k1_chilldkg_coordinator_msg1_len( + size_t n_participants, + uint32_t threshold +); + +/** Length of a participant's second message (pmsg2): 64 bytes. */ +SECP256K1_API size_t secp256k1_chilldkg_participant_msg2_len(void); + +/** Length of the coordinator's second message (cmsg2, the certificate): + * 64*n bytes. Returns 0 if the parameters are out of range. */ +SECP256K1_API size_t secp256k1_chilldkg_coordinator_msg2_len( + size_t n_participants +); + +/** Length of the recovery data output by + * secp256k1_chilldkg_participant_finalize: 4 + 33*t + 162*n bytes. + * Returns 0 if the parameters are out of range. */ +SECP256K1_API size_t secp256k1_chilldkg_recovery_data_len( + size_t n_participants, + uint32_t threshold +); + +/** Perform a participant's first step of a ChillDKG session. + * + * Returns: 1 on success, 0 on invalid input (invalid host secret key, host + * secret key not matching any host public key, invalid session + * parameters, or all-zero randomness). On failure, pmsg1 and the + * state are set to zero. + * Args: ctx: pointer to a context object + * Out: state1: pointer to a state1 object to be passed to + * secp256k1_chilldkg_participant_step2 (must not be + * reused) + * pmsg1: pointer to a 33*t + 32*n + 97 byte array (see + * secp256k1_chilldkg_participant_msg1_len) to store + * the message to be sent to the coordinator + * In: hostseckey32: pointer to the 32-byte host secret key + * hostpubkeys33: pointer to an array of n host public keys (33 bytes + * each); all participants must agree on the order + * n_participants: total number of participants n + * threshold: threshold t + * random32: pointer to 32 bytes of FRESH randomness + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_participant_step1( + const secp256k1_context *ctx, + secp256k1_chilldkg_participant_state1 *state1, + unsigned char *pmsg1, + const unsigned char *hostseckey32, + const unsigned char *hostpubkeys33, + size_t n_participants, + uint32_t threshold, + const unsigned char *random32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(8); + +/** Perform a participant's second step of a ChillDKG session. + * + * Verifies the coordinator's first message, computes the DKG output, and + * produces the CertEq signature over the session transcript. + * + * **Warning:** After sending the produced signature to the coordinator, the + * caller **must not** erase the hostseckey, even if the coordinator reply + * needed for secp256k1_chilldkg_participant_finalize is not received (some + * other participant may deem the session successful and use the resulting + * threshold public key). + * + * Returns: SECP256K1_CHILLDKG_OK on success, otherwise a fault code: + * SECP256K1_CHILLDKG_INVALID_INPUT if the host secret key is + * invalid or does not match the one used in step 1; + * SECP256K1_CHILLDKG_FAULTY_COORDINATOR, + * SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, or + * SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR on + * protocol faults. On failure, sig64 and the state are set to zero. + * Args: ctx: pointer to a context object + * Out: state2: pointer to a state2 object to be passed to + * secp256k1_chilldkg_participant_finalize (must not be + * reused) + * sig64: pointer to a 64-byte array to store the CertEq + * signature (pmsg2) to be sent to the coordinator + * fault_index: pointer to a uint32 that receives the identifier of + * the (suspected) faulty participant where applicable, + * and UINT32_MAX otherwise + * In: state1: pointer to the state1 object output by + * secp256k1_chilldkg_participant_step1 + * hostseckey32: pointer to the 32-byte host secret key (must be the + * same as in step 1) + * cmsg1: pointer to the coordinator's first message + * (162*n + 33*(t-1) bytes, see + * secp256k1_chilldkg_coordinator_msg1_len) + * aux_rand32: pointer to 32 bytes of auxiliary randomness for the + * CertEq signature (see BIP 340) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_step2( + const secp256k1_context *ctx, + secp256k1_chilldkg_participant_state2 *state2, + unsigned char *sig64, + uint32_t *fault_index, + const secp256k1_chilldkg_participant_state1 *state1, + const unsigned char *hostseckey32, + const unsigned char *cmsg1, + const unsigned char *aux_rand32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8); + +/** Perform a participant's final step of a ChillDKG session. + * + * Re-verifies all n CertEq signatures of the certificate and outputs the + * DKG output and the recovery data. If this function returns + * SECP256K1_CHILLDKG_OK, this participant deems the DKG session successful. + * + * Returns: SECP256K1_CHILLDKG_OK on success, + * SECP256K1_CHILLDKG_FAULTY_COORDINATOR if the certificate contains + * an invalid signature. As diagnostic information (deviating from + * the reference implementation, which does not report it), + * fault_index receives the index of the first invalid signature in + * the latter case. On failure, all outputs are set to zero. + * Args: ctx: pointer to a context object + * Out: secshare32: pointer to a 32-byte array to store the (tweaked) + * secret share + * thresh_pk33: pointer to a 33-byte array to store the threshold + * public key (compressed serialization) + * pubshares33: pointer to an array of n 33-byte elements to store + * the public shares of all participants + * recovery: pointer to a 4 + 33*t + 162*n byte array (see + * secp256k1_chilldkg_recovery_data_len) to store the + * recovery data + * fault_index: pointer to a uint32 (see above) + * In: state2: pointer to the state2 object output by + * secp256k1_chilldkg_participant_step2 + * cmsg2: pointer to the coordinator's second message (the + * certificate, 64*n bytes) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_finalize( + const secp256k1_context *ctx, + unsigned char *secshare32, + unsigned char *thresh_pk33, + unsigned char *pubshares33, + unsigned char *recovery, + uint32_t *fault_index, + const secp256k1_chilldkg_participant_state2 *state2, + const unsigned char *cmsg2 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8); + #ifdef __cplusplus } #endif diff --git a/src/modules/chilldkg/Makefile.am.include b/src/modules/chilldkg/Makefile.am.include index 66683950..49f75151 100644 --- a/src/modules/chilldkg/Makefile.am.include +++ b/src/modules/chilldkg/Makefile.am.include @@ -8,4 +8,6 @@ noinst_HEADERS += src/modules/chilldkg/simplpedpop.h noinst_HEADERS += src/modules/chilldkg/simplpedpop_impl.h noinst_HEADERS += src/modules/chilldkg/encpedpop.h noinst_HEADERS += src/modules/chilldkg/encpedpop_impl.h +noinst_HEADERS += src/modules/chilldkg/certeq.h +noinst_HEADERS += src/modules/chilldkg/certeq_impl.h noinst_HEADERS += src/modules/chilldkg/tests_impl.h diff --git a/src/modules/chilldkg/certeq.h b/src/modules/chilldkg/certeq.h new file mode 100644 index 00000000..565c43d7 --- /dev/null +++ b/src/modules/chilldkg/certeq.h @@ -0,0 +1,36 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_CHILLDKG_CERTEQ_H +#define SECP256K1_MODULE_CHILLDKG_CERTEQ_H + +#include "../../../include/secp256k1.h" + +#include "util.h" + +/* This file contains the internal CertEq equality-check sub-protocol of the + * ChillDKG module, mirroring the certeq_* functions of + * chilldkg_ref/chilldkg.py of the bip-frost-dkg reference implementation. + * + * The CertEq message of participant i is + * pad33("BIP DKG/certeq message") || u32be(i) || eq_input + * signed with plain BIP 340 (tag prefix "BIP0340") under the participant's + * host key. */ + +/* Produce the CertEq signature of the given participant over eq_input + * (certeq_participant_step). Returns 1 on success and 0 if hostseckey32 is + * invalid. On failure, sig64 is set to zero. */ +static int secp256k1_chilldkg_certeq_participant_step(const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *hostseckey32, uint32_t participant_id, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *aux_rand32); + +/* Verify all n CertEq signatures of a certificate (64 bytes per participant) + * against the host public keys (certeq_verify). The signature of participant + * i is verified against the x-only encoding of hostpubkeys33[i]; the message + * commits to the full 33-byte key via eq_input, so dropping the sign byte is + * okay (see the reference). Returns 1 if all signatures are valid and 0 + * otherwise; in the latter case *fault_index receives the index of the first + * invalid signature. */ +static int secp256k1_chilldkg_certeq_verify(const secp256k1_context *ctx, const unsigned char *hostpubkeys33, size_t n, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *cert, uint32_t *fault_index); + +#endif diff --git a/src/modules/chilldkg/certeq_impl.h b/src/modules/chilldkg/certeq_impl.h new file mode 100644 index 00000000..1a3487a7 --- /dev/null +++ b/src/modules/chilldkg/certeq_impl.h @@ -0,0 +1,58 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_CHILLDKG_CERTEQ_IMPL_H +#define SECP256K1_MODULE_CHILLDKG_CERTEQ_IMPL_H + +#include + +#include "../../../include/secp256k1.h" + +#include "util.h" +#include "certeq.h" +#include "../../util.h" + +/* The maximum length of an eq_input (and thus of the variable-length part of + * a CertEq message): 4 + 33*t + 33*n + 33*n + 32*n with t, n <= + * SECP256K1_CHILLDKG_MAX_PARTICIPANTS. */ +#define SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN (4 + 131 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS) + +/* certeq_message: pad33("BIP DKG/certeq message") || u32be(participant_id) || + * x. msg must hold 37 + x_len bytes. */ +static void secp256k1_chilldkg_certeq_message(unsigned char *msg, const unsigned char *x, size_t x_len, uint32_t participant_id) { + secp256k1_chilldkg_pad33(msg, "BIP DKG/certeq message"); + secp256k1_write_be32(msg + 33, participant_id); + memcpy(msg + 37, x, x_len); +} + +static int secp256k1_chilldkg_certeq_participant_step(const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *hostseckey32, uint32_t participant_id, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *aux_rand32) { + unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN]; + int ret; + + VERIFY_CHECK(eq_input_len <= SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN); + secp256k1_chilldkg_certeq_message(msg, eq_input, eq_input_len, participant_id); + ret = secp256k1_chilldkg_schnorrsig_sign(ctx, sig64, msg, 37 + eq_input_len, hostseckey32, aux_rand32, "BIP0340"); + secp256k1_memclear_explicit(msg, sizeof(msg)); + return ret; +} + +static int secp256k1_chilldkg_certeq_verify(const secp256k1_context *ctx, const unsigned char *hostpubkeys33, size_t n, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *cert, uint32_t *fault_index) { + unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN]; + size_t i; + + VERIFY_CHECK(eq_input_len <= SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN); + for (i = 0; i < n; i++) { + secp256k1_chilldkg_certeq_message(msg, eq_input, eq_input_len, (uint32_t)i); + /* Dropping the sign byte from hostpubkeys33[i] is okay because the + * message commits to the full host public key. */ + if (!secp256k1_chilldkg_schnorrsig_verify(ctx, cert + 64 * i, msg, 37 + eq_input_len, hostpubkeys33 + 33 * i + 1, "BIP0340")) { + *fault_index = (uint32_t)i; + return 0; + } + } + return 1; +} + +#endif diff --git a/src/modules/chilldkg/encpedpop.h b/src/modules/chilldkg/encpedpop.h index 271beb93..37f8aaf7 100644 --- a/src/modules/chilldkg/encpedpop.h +++ b/src/modules/chilldkg/encpedpop.h @@ -61,7 +61,7 @@ static int secp256k1_chilldkg_encpedpop_encrypt_multi(const secp256k1_context *c * pubnonce (receiver-side ordering in the pad hash). deckey32 is our host * secret key and enckey33 our host public key. * - * Returns SECP256K1_CHILLDKG_SUCCESS on success, + * Returns SECP256K1_CHILLDKG_OK on success, * SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR (with *fault_index) if * some sender's pubnonce is invalid, and SECP256K1_CHILLDKG_INVALID_INPUT if * deckey32 is invalid. On failure, all pads are cleared. */ @@ -101,7 +101,7 @@ static int secp256k1_chilldkg_encpedpop_participant_step1(const secp256k1_contex * output and the EncPedPop eq_input (4 + 33*t + 33*n + 33*n bytes). * * cmsg must be exactly 97*n + 33*(t-1) + 33*n bytes. Returns - * SECP256K1_CHILLDKG_SUCCESS on success; otherwise a fault code (with + * SECP256K1_CHILLDKG_OK on success; otherwise a fault code (with * *fault_index set when applicable): FAULTY_COORDINATOR if cmsg is malformed * or the pubnonce echo is wrong, FAULTY_PARTICIPANT_OR_COORDINATOR(i) if * sender i's pubnonce is invalid or their pop/commitment is bad, and @@ -117,7 +117,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(c * the n summed encrypted secshares. (In pure EncPedPop the coordinator would * send enc_secshares[i] to participant i only; ChillDKG broadcasts them.) * - * Returns SECP256K1_CHILLDKG_SUCCESS on success and + * Returns SECP256K1_CHILLDKG_OK on success and * SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with *fault_index) if a participant * message is malformed (invalid commitment, or an encrypted share that * overflows the group order). */ diff --git a/src/modules/chilldkg/encpedpop_impl.h b/src/modules/chilldkg/encpedpop_impl.h index 4c243ccf..d9bd6bb3 100644 --- a/src/modules/chilldkg/encpedpop_impl.h +++ b/src/modules/chilldkg/encpedpop_impl.h @@ -125,7 +125,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_decaps_multi(const } } secp256k1_scalar_clear(&deckey); - return SECP256K1_CHILLDKG_SUCCESS; + return SECP256K1_CHILLDKG_OK; } static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_decrypt_sum(const secp256k1_context *ctx, secp256k1_scalar *out, uint32_t *fault_index, const unsigned char *deckey32, const unsigned char *enckey33, const unsigned char *pubnonces33, const unsigned char *enc_context, size_t enc_context_len, uint32_t participant_id, const secp256k1_scalar *sum_ciphertexts, size_t n) { @@ -135,7 +135,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_decrypt_sum(const s VERIFY_CHECK(n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS); fault = secp256k1_chilldkg_encpedpop_decaps_multi(ctx, pads, fault_index, deckey32, enckey33, pubnonces33, enc_context, enc_context_len, participant_id, n); - if (fault == SECP256K1_CHILLDKG_SUCCESS) { + if (fault == SECP256K1_CHILLDKG_OK) { secp256k1_scalar_set_int(out, 0); for (i = 0; i < n; i++) { secp256k1_scalar_add(out, out, &pads[i]); @@ -277,7 +277,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(c /* secshare = enc_secshare - sum of the pads (decrypt_sum). */ secp256k1_chilldkg_encpedpop_serialize_enc_context(enc_context, t, &state->enckeys33[0][0], n); fault = secp256k1_chilldkg_encpedpop_decaps_multi(ctx, pads, fault_index, deckey32, state->enckeys33[participant_id], pubnonces, enc_context, 4 + 33 * (size_t)n, participant_id, n); - if (fault != SECP256K1_CHILLDKG_SUCCESS) { + if (fault != SECP256K1_CHILLDKG_OK) { for (i = 0; i < n; i++) { secp256k1_scalar_clear(&pads[i]); } @@ -297,14 +297,14 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(c for (i = 0; i < n; i++) { secp256k1_scalar_clear(&pads[i]); } - if (fault != SECP256K1_CHILLDKG_SUCCESS) { + if (fault != SECP256K1_CHILLDKG_OK) { return fault; } /* eq_input += enckeys || pubnonces */ memcpy(eq_input + 4 + 33 * t, &state->enckeys33[0][0], 33 * (size_t)n); memcpy(eq_input + 4 + 33 * t + 33 * (size_t)n, pubnonces, 33 * (size_t)n); - return SECP256K1_CHILLDKG_SUCCESS; + return SECP256K1_CHILLDKG_OK; } static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_coordinator_step(const secp256k1_context *ctx, unsigned char *cmsg, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, secp256k1_scalar *enc_secshares, uint32_t *fault_index, const unsigned char *const *pmsgs, uint32_t t, const unsigned char *enckeys33, size_t n) { @@ -365,14 +365,14 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_coordinator_step(co secp256k1_scalar_clear(&share); fault = secp256k1_chilldkg_simplpedpop_coordinator_step(ctx, cmsg, dkg_output, eq_input, fault_index, pmsgs, t, (uint32_t)n); - if (fault != SECP256K1_CHILLDKG_SUCCESS) { + if (fault != SECP256K1_CHILLDKG_OK) { return fault; } /* eq_input += enckeys || pubnonces */ memcpy(eq_input + 4 + 33 * t, enckeys33, 33 * n); memcpy(eq_input + 4 + 33 * t + 33 * n, cmsg + simpl_cmsg_len, 33 * n); - return SECP256K1_CHILLDKG_SUCCESS; + return SECP256K1_CHILLDKG_OK; } #endif diff --git a/src/modules/chilldkg/main_impl.h b/src/modules/chilldkg/main_impl.h index 013c5acf..e88a31d7 100644 --- a/src/modules/chilldkg/main_impl.h +++ b/src/modules/chilldkg/main_impl.h @@ -6,11 +6,440 @@ #ifndef SECP256K1_MODULE_CHILLDKG_MAIN_H #define SECP256K1_MODULE_CHILLDKG_MAIN_H +#include + #include "../../../include/secp256k1_chilldkg.h" #include "util_impl.h" #include "vss_impl.h" #include "simplpedpop_impl.h" #include "encpedpop_impl.h" +#include "certeq_impl.h" + +/* ARG_CHECK returns 0, which would read as SECP256K1_CHILLDKG_OK in the + * enum-returning public functions of this module. Use this variant there. */ +#define SECP256K1_CHILLDKG_ARG_CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + secp256k1_callback_call(&ctx->illegal_callback, #cond); \ + return SECP256K1_CHILLDKG_INVALID_INPUT; \ + } \ +} while(0) + +/* Validate the session parameters (params_validate in chilldkg_ref): it must + * hold that 1 <= t <= n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS (the reference + * allows n up to 2^32 - 1), all host public keys must be valid compressed + * public keys (the infinity encoding is not a valid public key), and there + * must be no duplicates. */ +static int secp256k1_chilldkg_params_validate(const unsigned char *hostpubkeys33, size_t n, uint32_t t) { + size_t i, j; + + if (t < 1 || n < 1 || t > n || n > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) { + return 0; + } + for (i = 0; i < n; i++) { + secp256k1_ge hostpubkey; + if (!secp256k1_chilldkg_point_load(&hostpubkey, hostpubkeys33 + 33 * i) + || secp256k1_ge_is_infinity(&hostpubkey)) { + /* InvalidHostPubkeyError(i) in the reference. */ + return 0; + } + } + for (i = 0; i < n; i++) { + for (j = i + 1; j < n; j++) { + if (secp256k1_memcmp_var(hostpubkeys33 + 33 * i, hostpubkeys33 + 33 * j, 33) == 0) { + /* DuplicateHostPubkeyError in the reference. */ + return 0; + } + } + } + return 1; +} + +static const unsigned char secp256k1_chilldkg_participant_state1_magic[4] = { 0x3f, 0x2c, 0x9e, 0x51 }; +static const unsigned char secp256k1_chilldkg_participant_state2_magic[4] = { 0x7a, 0xd1, 0x44, 0x0b }; + +/* A state1 object consists of + * - 4 byte magic set during initialization to allow detecting an + * uninitialized object + * - 4 byte threshold t, 4 byte participant count n, 4 byte participant_id + * (big-endian) + * - 33 byte commitment to the secret (compressed encoding with infinity) + * - 33 byte pubnonce + * - 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS byte host public keys (only the + * first n entries are meaningful) + * The state contains no secret key material. */ +static void secp256k1_chilldkg_participant_state1_save(secp256k1_chilldkg_participant_state1 *state, const secp256k1_chilldkg_encpedpop_participant_state *state_i) { + unsigned char *ptr = state->data; + + memcpy(ptr, secp256k1_chilldkg_participant_state1_magic, 4); + ptr += 4; + secp256k1_write_be32(ptr, state_i->simpl_state.t); + ptr += 4; + secp256k1_write_be32(ptr, state_i->simpl_state.n); + ptr += 4; + secp256k1_write_be32(ptr, state_i->simpl_state.participant_id); + ptr += 4; + secp256k1_chilldkg_point_save(ptr, &state_i->simpl_state.com_to_secret); + ptr += 33; + memcpy(ptr, state_i->pubnonce33, 33); + ptr += 33; + memcpy(ptr, &state_i->enckeys33[0][0], 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS); + VERIFY_CHECK(ptr + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS == state->data + sizeof(state->data)); +} + +static int secp256k1_chilldkg_participant_state1_load(const secp256k1_context *ctx, secp256k1_chilldkg_encpedpop_participant_state *state_i, const secp256k1_chilldkg_participant_state1 *state) { + const unsigned char *ptr = state->data; + + ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_chilldkg_participant_state1_magic, 4) == 0); + ptr += 4; + state_i->simpl_state.t = secp256k1_read_be32(ptr); + ptr += 4; + state_i->simpl_state.n = secp256k1_read_be32(ptr); + ptr += 4; + state_i->simpl_state.participant_id = secp256k1_read_be32(ptr); + ptr += 4; + /* The remaining contents were written by state1_save. */ + VERIFY_CHECK(state_i->simpl_state.t >= 1 + && state_i->simpl_state.t <= state_i->simpl_state.n + && state_i->simpl_state.n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS + && state_i->simpl_state.participant_id < state_i->simpl_state.n); + /* This load always succeeds; call it unconditionally (it must not sit + * inside VERIFY_CHECK, which is compiled out in noverify builds). */ + if (!secp256k1_chilldkg_point_load(&state_i->simpl_state.com_to_secret, ptr)) { + VERIFY_CHECK(0); + secp256k1_ge_set_infinity(&state_i->simpl_state.com_to_secret); + } + ptr += 33; + memcpy(state_i->pubnonce33, ptr, 33); + ptr += 33; + memcpy(&state_i->enckeys33[0][0], ptr, 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS); + return 1; +} + +typedef struct { + uint32_t t; + uint32_t n; + /* Only the first 4 + 33*t + 98*n bytes are meaningful. */ + unsigned char eq_input[SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN]; + secp256k1_chilldkg_simplpedpop_dkg_output dkg_output; +} secp256k1_chilldkg_participant_state2_internal; + +/* A state2 object consists of + * - 4 byte magic + * - 4 byte threshold t, 4 byte participant count n (big-endian) + * - eq_input (fixed-capacity buffer) + * - 32 byte (tweaked) secret share + * - 33 byte threshold public key + * - 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS byte public shares (only the first + * n entries are meaningful) + * The state contains the secret share and must be kept secret. */ +static void secp256k1_chilldkg_participant_state2_save(secp256k1_chilldkg_participant_state2 *state, const secp256k1_chilldkg_participant_state2_internal *state_i) { + unsigned char *ptr = state->data; + + memcpy(ptr, secp256k1_chilldkg_participant_state2_magic, 4); + ptr += 4; + secp256k1_write_be32(ptr, state_i->t); + ptr += 4; + secp256k1_write_be32(ptr, state_i->n); + ptr += 4; + memcpy(ptr, state_i->eq_input, sizeof(state_i->eq_input)); + ptr += sizeof(state_i->eq_input); + memcpy(ptr, state_i->dkg_output.secshare32, 32); + ptr += 32; + memcpy(ptr, state_i->dkg_output.thresh_pk33, 33); + ptr += 33; + memcpy(ptr, &state_i->dkg_output.pubshares33[0][0], 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS); + VERIFY_CHECK(ptr + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS == state->data + sizeof(state->data)); +} + +static int secp256k1_chilldkg_participant_state2_load(const secp256k1_context *ctx, secp256k1_chilldkg_participant_state2_internal *state_i, const secp256k1_chilldkg_participant_state2 *state) { + const unsigned char *ptr = state->data; + + ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_chilldkg_participant_state2_magic, 4) == 0); + ptr += 4; + state_i->t = secp256k1_read_be32(ptr); + ptr += 4; + state_i->n = secp256k1_read_be32(ptr); + ptr += 4; + /* The remaining contents were written by state2_save. */ + VERIFY_CHECK(state_i->t >= 1 + && state_i->t <= state_i->n + && state_i->n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS); + memcpy(state_i->eq_input, ptr, sizeof(state_i->eq_input)); + ptr += sizeof(state_i->eq_input); + memcpy(state_i->dkg_output.secshare32, ptr, 32); + ptr += 32; + memcpy(state_i->dkg_output.thresh_pk33, ptr, 33); + ptr += 33; + memcpy(&state_i->dkg_output.pubshares33[0][0], ptr, 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS); + return 1; +} + +int secp256k1_chilldkg_hostpubkey_gen(const secp256k1_context *ctx, unsigned char *hostpubkey33, const unsigned char *hostseckey32) { + secp256k1_scalar seckey; + secp256k1_gej pubkeyj; + secp256k1_ge pubkey; + int overflow; + int ret; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(hostpubkey33 != NULL); + ARG_CHECK(hostseckey32 != NULL); + + memset(hostpubkey33, 0, 33); + secp256k1_scalar_set_b32(&seckey, hostseckey32, &overflow); + ret = !overflow & !secp256k1_scalar_is_zero(&seckey); + /* Branching on the validity of the host secret key is fine: whether the + * caller's key is in range 1..n-1 is not secret. */ + secp256k1_declassify(ctx, &ret, sizeof(ret)); + if (ret) { + /* pubkey_gen_plain in the reference (IndividualPubkey of BIP 327). */ + secp256k1_ecmult_gen_gej(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey); + secp256k1_ge_set_gej(&pubkey, &pubkeyj); + secp256k1_chilldkg_point_save(hostpubkey33, &pubkey); + secp256k1_gej_clear(&pubkeyj); + } + secp256k1_scalar_clear(&seckey); + return ret; +} + +int secp256k1_chilldkg_params_hash(const secp256k1_context *ctx, unsigned char *hash32, const unsigned char *hostpubkeys33, size_t n_participants, uint32_t threshold) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(hash32 != NULL); + ARG_CHECK(hostpubkeys33 != NULL); + + memset(hash32, 0, 32); + if (!secp256k1_chilldkg_params_validate(hostpubkeys33, n_participants, threshold)) { + return 0; + } + secp256k1_chilldkg_params_hash_internal(secp256k1_get_hash_context(ctx), hash32, hostpubkeys33, n_participants, threshold); + return 1; +} + +size_t secp256k1_chilldkg_participant_msg1_len(size_t n_participants, uint32_t threshold) { + if (threshold < 1 || n_participants < 1 || threshold > n_participants || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) { + return 0; + } + return 33 * (size_t)threshold + 32 * n_participants + 97; +} + +size_t secp256k1_chilldkg_coordinator_msg1_len(size_t n_participants, uint32_t threshold) { + if (threshold < 1 || n_participants < 1 || threshold > n_participants || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) { + return 0; + } + return 162 * n_participants + 33 * (size_t)(threshold - 1); +} + +size_t secp256k1_chilldkg_participant_msg2_len(void) { + return 64; +} + +size_t secp256k1_chilldkg_coordinator_msg2_len(size_t n_participants) { + if (n_participants < 1 || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) { + return 0; + } + return 64 * n_participants; +} + +size_t secp256k1_chilldkg_recovery_data_len(size_t n_participants, uint32_t threshold) { + if (threshold < 1 || n_participants < 1 || threshold > n_participants || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) { + return 0; + } + return 4 + 33 * (size_t)threshold + 162 * n_participants; +} + +int secp256k1_chilldkg_participant_step1(const secp256k1_context *ctx, secp256k1_chilldkg_participant_state1 *state1, unsigned char *pmsg1, const unsigned char *hostseckey32, const unsigned char *hostpubkeys33, size_t n_participants, uint32_t threshold, const unsigned char *random32) { + secp256k1_chilldkg_encpedpop_participant_state enc_state; + unsigned char hostpubkey33[33]; + uint32_t participant_id = 0; + size_t pmsg1_len; + size_t i; + int found = 0; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(state1 != NULL); + ARG_CHECK(pmsg1 != NULL); + ARG_CHECK(hostseckey32 != NULL); + ARG_CHECK(hostpubkeys33 != NULL); + ARG_CHECK(random32 != NULL); + + memset(state1->data, 0, sizeof(state1->data)); + pmsg1_len = secp256k1_chilldkg_participant_msg1_len(n_participants, threshold); + + /* params_validate, then hostpubkey_gen (HostSeckeyError if invalid). */ + if (secp256k1_chilldkg_params_validate(hostpubkeys33, n_participants, threshold) + && secp256k1_chilldkg_hostpubkey_gen(ctx, hostpubkey33, hostseckey32)) { + /* hostpubkeys.index(hostpubkey); the params validation rules out + * duplicates, so there is at most one match. */ + for (i = 0; i < n_participants; i++) { + if (secp256k1_memcmp_var(hostpubkeys33 + 33 * i, hostpubkey33, 33) == 0) { + participant_id = (uint32_t)i; + found = 1; + break; + } + } + /* HostSeckeyError if there is no match; RandomnessError if the + * randomness is all zeroes (guards against a malfunctioning random + * number generator). */ + if (found && !secp256k1_is_zero_array(random32, 32)) { + /* In EncPedPop, both the seed and the deckey are the host secret + * key, and the enckeys are the host public keys (see + * chilldkg_ref/chilldkg.py participant_step1). */ + ret = secp256k1_chilldkg_encpedpop_participant_step1(ctx, &enc_state, pmsg1, hostseckey32, hostseckey32, hostpubkeys33, threshold, participant_id, random32, n_participants); + } + } + + if (ret) { + secp256k1_chilldkg_participant_state1_save(state1, &enc_state); + } else { + memset(state1->data, 0, sizeof(state1->data)); + if (pmsg1_len > 0) { + memset(pmsg1, 0, pmsg1_len); + } + } + return ret; +} + +secp256k1_chilldkg_fault secp256k1_chilldkg_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_participant_state2 *state2, unsigned char *sig64, uint32_t *fault_index, const secp256k1_chilldkg_participant_state1 *state1, const unsigned char *hostseckey32, const unsigned char *cmsg1, const unsigned char *aux_rand32) { + secp256k1_chilldkg_encpedpop_participant_state enc_state; + secp256k1_chilldkg_participant_state2_internal state2i; + unsigned char hostpubkey33[33]; + secp256k1_scalar enc_secshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS]; + secp256k1_chilldkg_fault fault = SECP256K1_CHILLDKG_INVALID_INPUT; + size_t n, t, enc_cmsg_len, eq_input_len; + uint32_t participant_id; + size_t i; + int overflow; + + VERIFY_CHECK(ctx != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + SECP256K1_CHILLDKG_ARG_CHECK(state2 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(sig64 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(state1 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(hostseckey32 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(cmsg1 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(aux_rand32 != NULL); + + memset(&state2i, 0, sizeof(state2i)); + memset(state2->data, 0, sizeof(state2->data)); + memset(sig64, 0, 64); + *fault_index = UINT32_MAX; + + if (!secp256k1_chilldkg_participant_state1_load(ctx, &enc_state, state1)) { + return SECP256K1_CHILLDKG_INVALID_INPUT; + } + t = enc_state.simpl_state.t; + n = enc_state.simpl_state.n; + participant_id = enc_state.simpl_state.participant_id; + + /* HostSeckeyError if the host secret key is invalid or does not match the + * one used in participant_step1. */ + if (!secp256k1_chilldkg_hostpubkey_gen(ctx, hostpubkey33, hostseckey32) + || secp256k1_memcmp_var(hostpubkey33, enc_state.enckeys33[participant_id], 33) != 0) { + return SECP256K1_CHILLDKG_INVALID_INPUT; + } + + /* CoordinatorMsg1.from_bytes: cmsg1 = enc_cmsg || enc_secshares, where + * enc_cmsg has 97*n + 33*(t-1) + 33*n bytes. The encrypted shares are + * parsed checked; an overflow blames the coordinator (MsgParseError -> + * FaultyCoordinatorError in the reference). */ + enc_cmsg_len = 97 * n + 33 * (t - 1) + 33 * n; + for (i = 0; i < n; i++) { + secp256k1_scalar_set_b32(&enc_secshares[i], cmsg1 + enc_cmsg_len + 32 * i, &overflow); + if (overflow) { + fault = SECP256K1_CHILLDKG_FAULTY_COORDINATOR; + goto cleanup; + } + } + + eq_input_len = 4 + 33 * t + 66 * n; + fault = secp256k1_chilldkg_encpedpop_participant_step2(ctx, &state2i.dkg_output, state2i.eq_input, fault_index, &enc_state, hostseckey32, cmsg1, enc_cmsg_len, &enc_secshares[participant_id]); + if (fault != SECP256K1_CHILLDKG_OK) { + goto cleanup; + } + + /* Include the enc_secshares in eq_input to ensure that participants agree + * on all shares, which in turn ensures that they have the right recovery + * data. */ + for (i = 0; i < n; i++) { + secp256k1_scalar_get_b32(state2i.eq_input + eq_input_len + 32 * i, &enc_secshares[i]); + } + eq_input_len += 32 * n; + state2i.t = (uint32_t)t; + state2i.n = (uint32_t)n; + + /* pmsg2 = certeq_participant_step(hostseckey, participant_id, eq_input, aux_rand) */ + if (!secp256k1_chilldkg_certeq_participant_step(ctx, sig64, hostseckey32, participant_id, state2i.eq_input, eq_input_len, aux_rand32)) { + /* Unreachable: the host secret key was validated above. */ + fault = SECP256K1_CHILLDKG_INVALID_INPUT; + memset(sig64, 0, 64); + goto cleanup; + } + secp256k1_chilldkg_participant_state2_save(state2, &state2i); + +cleanup: + for (i = 0; i < n; i++) { + secp256k1_scalar_clear(&enc_secshares[i]); + } + /* state2i contains the secret share. */ + secp256k1_memclear_explicit(&state2i, sizeof(state2i)); + return fault; +} + +secp256k1_chilldkg_fault secp256k1_chilldkg_participant_finalize(const secp256k1_context *ctx, unsigned char *secshare32, unsigned char *thresh_pk33, unsigned char *pubshares33, unsigned char *recovery, uint32_t *fault_index, const secp256k1_chilldkg_participant_state2 *state2, const unsigned char *cmsg2) { + secp256k1_chilldkg_participant_state2_internal state2i; + size_t n, t, eq_input_len; + + VERIFY_CHECK(ctx != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + SECP256K1_CHILLDKG_ARG_CHECK(secshare32 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(thresh_pk33 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(pubshares33 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(recovery != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(state2 != NULL); + SECP256K1_CHILLDKG_ARG_CHECK(cmsg2 != NULL); + + memset(secshare32, 0, 32); + memset(thresh_pk33, 0, 33); + *fault_index = UINT32_MAX; + + /* On a state load failure (uninitialized state), only secshare32 and + * thresh_pk33 are zeroed: the sizes of pubshares33 and recovery depend on + * the state contents. */ + if (!secp256k1_chilldkg_participant_state2_load(ctx, &state2i, state2)) { + return SECP256K1_CHILLDKG_INVALID_INPUT; + } + t = state2i.t; + n = state2i.n; + eq_input_len = 4 + 33 * t + 98 * n; + + memset(pubshares33, 0, 33 * n); + memset(recovery, 0, 4 + 33 * t + 162 * n); + + /* certeq_verify: the host public keys are part of eq_input (at offset + * 4 + 33*t). An invalid signature in the certificate blames the + * coordinator; fault_index receives the index of the first invalid + * signature as diagnostic information. */ + if (!secp256k1_chilldkg_certeq_verify(ctx, state2i.eq_input + 4 + 33 * t, n, state2i.eq_input, eq_input_len, cmsg2, fault_index)) { + secp256k1_memclear_explicit(&state2i, sizeof(state2i)); + return SECP256K1_CHILLDKG_FAULTY_COORDINATOR; + } + + memcpy(secshare32, state2i.dkg_output.secshare32, 32); + memcpy(thresh_pk33, state2i.dkg_output.thresh_pk33, 33); + memcpy(pubshares33, &state2i.dkg_output.pubshares33[0][0], 33 * n); + /* recovery data = eq_input || cert */ + memcpy(recovery, state2i.eq_input, eq_input_len); + memcpy(recovery + eq_input_len, cmsg2, 64 * n); + + /* state2i contains the secret share. */ + secp256k1_memclear_explicit(&state2i, sizeof(state2i)); + return SECP256K1_CHILLDKG_OK; +} #endif diff --git a/src/modules/chilldkg/simplpedpop.h b/src/modules/chilldkg/simplpedpop.h index 6afad71d..13aac08d 100644 --- a/src/modules/chilldkg/simplpedpop.h +++ b/src/modules/chilldkg/simplpedpop.h @@ -86,7 +86,7 @@ static void secp256k1_chilldkg_simplpedpop_participant_step2_prepare_secshare(se * verification). Outputs the DKG output and the SimplPedPop contribution to * eq_input (4 + 33*t bytes). * - * cmsg must be exactly 97*n + 33*(t-1) bytes. Returns SECP256K1_CHILLDKG_SUCCESS + * cmsg must be exactly 97*n + 33*(t-1) bytes. Returns SECP256K1_CHILLDKG_OK * on success; otherwise a fault code (with *fault_index set when applicable): * - FAULTY_COORDINATOR if cmsg is malformed or the echo of our own * commitment to the secret is wrong; @@ -109,7 +109,7 @@ static void secp256k1_chilldkg_simplpedpop_assemble_sum_coms(secp256k1_ge *sum_c * eq_input (4 + 33*t bytes). The pops are NOT verified here (participants * verify them in step 2). * - * Outputs cmsg (97*n + 33*(t-1) bytes). Returns SECP256K1_CHILLDKG_SUCCESS on + * Outputs cmsg (97*n + 33*(t-1) bytes). Returns SECP256K1_CHILLDKG_OK on * success and SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with *fault_index) if a * participant message is malformed. */ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_coordinator_step(const secp256k1_context *ctx, unsigned char *cmsg, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, const unsigned char *const *pmsgs, uint32_t t, uint32_t n); diff --git a/src/modules/chilldkg/simplpedpop_impl.h b/src/modules/chilldkg/simplpedpop_impl.h index 2e9936c0..b627914e 100644 --- a/src/modules/chilldkg/simplpedpop_impl.h +++ b/src/modules/chilldkg/simplpedpop_impl.h @@ -241,7 +241,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2 secp256k1_scalar_clear(&tweak); secp256k1_scalar_clear(&secshare_tweaked); - return SECP256K1_CHILLDKG_SUCCESS; + return SECP256K1_CHILLDKG_OK; } static void secp256k1_chilldkg_simplpedpop_assemble_sum_coms(secp256k1_ge *sum_coms, const secp256k1_ge *coms_to_secrets, const secp256k1_ge *sum_coms_to_nonconst_terms, size_t n, size_t t) { @@ -350,7 +350,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_coordinator_step( } secp256k1_scalar_clear(&tweak); - return SECP256K1_CHILLDKG_SUCCESS; + return SECP256K1_CHILLDKG_OK; } #endif diff --git a/src/modules/chilldkg/tests_impl.h b/src/modules/chilldkg/tests_impl.h index e908c9eb..e2af3351 100644 --- a/src/modules/chilldkg/tests_impl.h +++ b/src/modules/chilldkg/tests_impl.h @@ -201,6 +201,54 @@ static const unsigned char vec_enc_pubshares[3][33] = { /* encpedpop n = 3, t = 2 */ /* all python-side sanity checks passed */ +static const unsigned char vec3_hostseckeys[3][32] = { + { 0x63, 0xf1, 0xca, 0xd7, 0x7b, 0xa9, 0x64, 0x63, 0x48, 0x03, 0xa3, 0x11, 0x03, 0x0f, 0x5c, 0x74, 0x30, 0x5b, 0x9c, 0x06, 0x24, 0x13, 0xc3, 0xbe, 0xc0, 0xe1, 0xbc, 0xf4, 0x39, 0xb3, 0x35, 0xcf }, + { 0xba, 0x8b, 0x85, 0xb8, 0xd3, 0x0d, 0xcf, 0x07, 0x87, 0xc6, 0x5b, 0x7c, 0x6a, 0x46, 0x08, 0xef, 0xc7, 0x25, 0x35, 0x52, 0x8d, 0xc5, 0x4f, 0xf1, 0xa7, 0x13, 0x52, 0x32, 0x6b, 0x51, 0x71, 0xb1 }, + { 0x73, 0xed, 0x74, 0x96, 0x68, 0x50, 0xa1, 0x21, 0x61, 0x59, 0xd6, 0xe1, 0xf8, 0x07, 0xcc, 0xfb, 0xfa, 0x89, 0x3d, 0xc8, 0xa9, 0x07, 0xfe, 0xfd, 0xe2, 0x34, 0x01, 0xd0, 0xd2, 0xe9, 0xa3, 0xa8 }, +}; +static const unsigned char vec3_hostpubkeys[3][33] = { + { 0x02, 0x2d, 0x9b, 0xc8, 0xa8, 0x44, 0x57, 0xc7, 0x51, 0x00, 0x1f, 0x71, 0x4a, 0xd9, 0xac, 0x72, 0x82, 0x8a, 0x01, 0xe5, 0x31, 0xbe, 0x63, 0xe7, 0xfc, 0x3c, 0x4d, 0x37, 0x0c, 0x2f, 0xec, 0xd8, 0x43 }, + { 0x03, 0x34, 0xbe, 0xe4, 0x54, 0x9f, 0x86, 0x95, 0xd8, 0x96, 0xa3, 0xf0, 0x60, 0x40, 0xe0, 0x26, 0x3c, 0x41, 0x90, 0x54, 0xf3, 0xb8, 0xc7, 0x83, 0xa7, 0x7a, 0x77, 0x02, 0x82, 0x86, 0x14, 0x97, 0x3a }, + { 0x02, 0x85, 0xe6, 0xb7, 0xa7, 0xfb, 0x26, 0x5f, 0x38, 0xb9, 0xad, 0xc3, 0x9e, 0x51, 0xd4, 0xac, 0x2d, 0xfb, 0x0f, 0x31, 0xa6, 0xf1, 0x8e, 0x7f, 0xf8, 0xae, 0x2f, 0x3c, 0xa7, 0xbc, 0xaa, 0x7d, 0xcf }, +}; +static const unsigned char vec3_params_hash[32] = { 0x40, 0x6a, 0x61, 0xe7, 0xd3, 0x91, 0x7e, 0xc0, 0x8d, 0x10, 0x51, 0x38, 0x62, 0xab, 0xbb, 0x40, 0x42, 0x14, 0x39, 0x7c, 0x81, 0x5b, 0x32, 0x60, 0x87, 0xb8, 0x0b, 0x90, 0x31, 0xee, 0xf6, 0xbb }; +static const unsigned char vec3_randoms[3][32] = { + { 0x47, 0x1f, 0x0e, 0xfc, 0x32, 0x6d, 0xaa, 0x68, 0xbb, 0x76, 0x70, 0x31, 0x88, 0x3a, 0xff, 0x5a, 0xcd, 0xc8, 0xca, 0xad, 0x58, 0x5b, 0x0f, 0x5d, 0x13, 0x52, 0xf7, 0x54, 0x70, 0x6c, 0x23, 0xcc }, + { 0xb6, 0x2d, 0x69, 0xb3, 0x7f, 0x3b, 0x20, 0xbd, 0x57, 0x7a, 0xf0, 0x05, 0x7d, 0xd5, 0x11, 0x52, 0xe2, 0xea, 0x90, 0x1c, 0xe1, 0x0f, 0xe9, 0x6c, 0x25, 0x68, 0x55, 0x1d, 0xda, 0xfc, 0xa1, 0x9d }, + { 0xda, 0x99, 0x81, 0x45, 0xd2, 0x74, 0x0f, 0x62, 0xbe, 0x66, 0x57, 0x5b, 0x5f, 0xc1, 0xfd, 0x8d, 0xf4, 0x42, 0x53, 0x72, 0xbb, 0x59, 0x5a, 0x5b, 0xe5, 0x55, 0x17, 0xb9, 0xfe, 0xac, 0x3e, 0x21 }, +}; +static const unsigned char vec3_aux_rands[3][32] = { + { 0x43, 0xbb, 0x36, 0xca, 0xf9, 0x05, 0x46, 0x37, 0xdf, 0x41, 0x06, 0x33, 0x10, 0x0c, 0x83, 0x4c, 0x96, 0x5f, 0x6b, 0x88, 0xe9, 0x4c, 0x54, 0x7a, 0x88, 0x0d, 0xce, 0x85, 0x7a, 0xd9, 0x58, 0x66 }, + { 0x01, 0x96, 0xeb, 0x2f, 0x75, 0x84, 0x78, 0x28, 0x2d, 0x0a, 0x8f, 0x73, 0x55, 0x90, 0x22, 0x8c, 0x2d, 0x26, 0xef, 0xfe, 0x9e, 0xad, 0xf8, 0x4b, 0xf2, 0xfe, 0x5d, 0xa0, 0x94, 0x3e, 0x64, 0x03 }, + { 0x4a, 0xee, 0x4b, 0xc4, 0x92, 0x1b, 0xf2, 0x6e, 0xf1, 0xe2, 0x25, 0x75, 0x1b, 0x4f, 0x5f, 0x3d, 0x5f, 0x9a, 0x16, 0x08, 0x04, 0x45, 0x18, 0x5c, 0x98, 0xb5, 0xbf, 0xb1, 0x70, 0xa7, 0x0a, 0x0d }, +}; +static const unsigned char vec3_pmsgs1[3][259] = { + { 0x03, 0x13, 0xa8, 0x3d, 0xe5, 0x5f, 0xc3, 0xef, 0x04, 0xe3, 0xd5, 0x0b, 0xe3, 0xe5, 0xae, 0x6f, 0x7d, 0xc8, 0x17, 0x5c, 0x03, 0x61, 0xa2, 0x87, 0xe3, 0x05, 0xac, 0x24, 0xb7, 0xdb, 0x90, 0x5b, 0xa0, 0x02, 0x8e, 0x23, 0x9d, 0x76, 0x52, 0xf4, 0xe2, 0x7b, 0x8f, 0xf7, 0x3b, 0xce, 0xe1, 0xd5, 0xb4, 0xea, 0xf3, 0xc4, 0x1b, 0xef, 0x9d, 0xfc, 0xae, 0x10, 0x53, 0x51, 0xc3, 0x5d, 0xce, 0x73, 0x15, 0xaf, 0x5a, 0x61, 0xbc, 0x3f, 0x93, 0x88, 0x46, 0xad, 0x6e, 0x75, 0x60, 0x32, 0xaf, 0x07, 0x13, 0x50, 0xa5, 0x7f, 0x4d, 0xe5, 0xcc, 0x19, 0x2c, 0xb8, 0x94, 0xc9, 0x05, 0x7e, 0xd1, 0x98, 0x92, 0x80, 0xf4, 0xba, 0x10, 0x30, 0xe5, 0x6a, 0x11, 0xe9, 0xfa, 0xf6, 0x6c, 0xe9, 0x15, 0xcc, 0x29, 0x19, 0xb6, 0x5c, 0x91, 0x3c, 0xbf, 0xcf, 0xf1, 0x92, 0x88, 0xf6, 0xd5, 0x6f, 0x0a, 0x19, 0xb9, 0x06, 0x03, 0x14, 0x18, 0x10, 0xaf, 0x9a, 0x1b, 0x7c, 0x34, 0x27, 0x0a, 0x83, 0xaa, 0x52, 0x62, 0xc2, 0xbe, 0x22, 0x4a, 0x4c, 0x6b, 0xde, 0x0d, 0xc4, 0xdf, 0xda, 0xd1, 0xc2, 0x7f, 0x09, 0x3b, 0x9b, 0x38, 0xea, 0x7b, 0xb3, 0xd7, 0x0c, 0xfc, 0x81, 0x31, 0xe7, 0x7c, 0x63, 0x93, 0xad, 0x2a, 0x28, 0xd7, 0x8b, 0x5a, 0xda, 0x3b, 0xc4, 0x18, 0x5a, 0xcb, 0x64, 0x49, 0x5a, 0x4d, 0xfe, 0xde, 0xd9, 0x82, 0xd7, 0xcc, 0x01, 0x2a, 0x67, 0x40, 0x5b, 0x09, 0xe8, 0x61, 0xbd, 0xa2, 0x72, 0xb8, 0x23, 0x1f, 0xa6, 0xaa, 0xe5, 0xee, 0xdd, 0x01, 0x35, 0xa4, 0x13, 0x5d, 0x08, 0xa5, 0xc5, 0x5c, 0xd9, 0xd4, 0xe1, 0x0e, 0x48, 0x6f, 0x44, 0x6c, 0x29, 0x72, 0xe2, 0x25, 0x06, 0x25, 0x37, 0x0e, 0x28, 0x3f, 0x69, 0x26, 0xc2, 0xc1, 0x79, 0x50, 0xad, 0x0a, 0x0b, 0x20, 0xc1, 0xce, 0x41, 0xe1, 0xff, 0x66 }, + { 0x03, 0x98, 0xf0, 0x88, 0x65, 0x27, 0x59, 0x6b, 0x2c, 0x49, 0xf6, 0xa3, 0xf6, 0x58, 0x46, 0x52, 0x76, 0xdf, 0x6c, 0xd5, 0xc6, 0x68, 0xe2, 0xdf, 0x88, 0x6b, 0xe6, 0x15, 0x81, 0x60, 0x5e, 0x10, 0xa7, 0x02, 0x8c, 0x88, 0x50, 0xb8, 0x9e, 0xe9, 0xb1, 0xe9, 0x89, 0x8a, 0xb2, 0x61, 0x91, 0xb4, 0xf4, 0xc2, 0x9e, 0x9b, 0x7b, 0x0f, 0x71, 0x27, 0x05, 0xe3, 0xd9, 0x54, 0xb0, 0xaf, 0xa1, 0x40, 0x3c, 0x6c, 0xc5, 0xe6, 0x8a, 0xcd, 0xb0, 0xaf, 0x07, 0x62, 0xb1, 0x3f, 0x24, 0xeb, 0x34, 0xd0, 0x39, 0x72, 0xd5, 0x34, 0xcc, 0x72, 0x02, 0x0c, 0x10, 0x19, 0x44, 0x00, 0xd0, 0x21, 0x3f, 0x0d, 0x7f, 0x1e, 0x0d, 0x08, 0xaa, 0xd3, 0xec, 0x21, 0xff, 0x9b, 0xc7, 0xcb, 0x04, 0x97, 0x79, 0x27, 0xd7, 0xc6, 0xe6, 0xbb, 0x4f, 0x0d, 0x88, 0x7a, 0x70, 0x4a, 0x7d, 0xbd, 0x65, 0x8f, 0xa3, 0xc3, 0xc9, 0x2d, 0x03, 0x77, 0xb8, 0xeb, 0x7f, 0x3c, 0xf3, 0x08, 0x9a, 0xeb, 0x55, 0x77, 0xeb, 0xb3, 0x7a, 0xf4, 0x84, 0x25, 0x91, 0xcf, 0x6c, 0x97, 0x42, 0xa4, 0x8e, 0xc6, 0x56, 0xdb, 0xb8, 0xf2, 0x50, 0xf7, 0x09, 0xaf, 0xa6, 0x65, 0x5c, 0xee, 0xee, 0x61, 0x74, 0x28, 0x40, 0xb7, 0xf1, 0xaf, 0x76, 0x0d, 0xf2, 0xf6, 0xcc, 0x6d, 0x4e, 0xe0, 0x5a, 0x9a, 0xd1, 0xfc, 0x7b, 0x5d, 0x86, 0x5c, 0x42, 0xc0, 0x52, 0xd5, 0xb6, 0x97, 0xb0, 0x91, 0xdb, 0xf8, 0xde, 0x6d, 0x2d, 0x81, 0xab, 0xff, 0xb5, 0xf0, 0xcb, 0x75, 0xbd, 0x86, 0xe3, 0x86, 0x04, 0x15, 0x68, 0x05, 0x5e, 0xe2, 0xb4, 0x8f, 0x7c, 0xfc, 0x3d, 0x91, 0x54, 0x76, 0x91, 0x11, 0x18, 0x25, 0x84, 0xf4, 0xf9, 0xdf, 0xad, 0x29, 0xc6, 0x2b, 0x57, 0xc1, 0xf1, 0xe4, 0xa5, 0x40, 0xc0, 0x7f, 0xcb, 0x18, 0x65, 0x07, 0x5c, 0xb2, 0x14, 0x6c, 0x2b }, + { 0x02, 0xc0, 0xa6, 0xde, 0xcb, 0x4a, 0xd7, 0x34, 0xe9, 0xec, 0x43, 0xbd, 0x50, 0xf3, 0xa6, 0xd6, 0xe8, 0xad, 0xa8, 0x38, 0xe8, 0x44, 0x40, 0x0b, 0xfe, 0x14, 0x7e, 0x46, 0xc8, 0xa1, 0x61, 0x5a, 0x2e, 0x03, 0xc8, 0x14, 0xb5, 0xe1, 0x99, 0xff, 0x42, 0x88, 0x52, 0x78, 0x52, 0x96, 0xc4, 0x57, 0x06, 0x65, 0xde, 0x04, 0x58, 0x15, 0x99, 0xc3, 0xb0, 0xcd, 0x24, 0x7e, 0x67, 0x0c, 0x15, 0x51, 0x01, 0xc2, 0x7b, 0x09, 0xdd, 0x3d, 0x86, 0x90, 0xba, 0x4c, 0x1d, 0x65, 0x33, 0x07, 0x50, 0x7a, 0x2c, 0xb3, 0x06, 0x9e, 0xab, 0xbd, 0xe2, 0xb6, 0xe2, 0x4f, 0x0d, 0x79, 0xb4, 0x0a, 0xb4, 0x90, 0xae, 0x89, 0x48, 0xcc, 0x90, 0x5a, 0x4d, 0xc5, 0xc2, 0xe0, 0x59, 0xda, 0x08, 0x33, 0x1b, 0x82, 0x40, 0x51, 0xfa, 0x0b, 0x07, 0x93, 0xe3, 0x6d, 0x96, 0xaf, 0xeb, 0xf6, 0xfc, 0xef, 0x85, 0x1b, 0x21, 0x94, 0x03, 0xfc, 0x22, 0xdc, 0xf0, 0xed, 0xd5, 0x9e, 0xdf, 0x52, 0xab, 0x06, 0xeb, 0xce, 0xba, 0x18, 0x33, 0x7d, 0x00, 0xec, 0x2e, 0xf5, 0x57, 0xcd, 0x23, 0x70, 0xe4, 0x82, 0x07, 0x2b, 0x51, 0x6d, 0x37, 0x6b, 0xc6, 0x34, 0x69, 0xb1, 0x4e, 0x16, 0xc0, 0x90, 0xdf, 0x4a, 0xc9, 0x3b, 0x3d, 0xbc, 0xee, 0xee, 0x29, 0x96, 0x3e, 0xa4, 0x87, 0x2b, 0x9a, 0xb2, 0x59, 0x4f, 0x81, 0x45, 0xaf, 0xfc, 0x3a, 0xfe, 0x8b, 0xfb, 0x90, 0x3d, 0x9b, 0x91, 0xde, 0x14, 0x0f, 0xee, 0xfb, 0x7a, 0x30, 0x67, 0x6d, 0x0d, 0x0f, 0x0e, 0xe7, 0xd9, 0x1b, 0xb8, 0x99, 0xcf, 0xe6, 0xf9, 0x2c, 0x74, 0x1f, 0xb5, 0xb8, 0x20, 0xab, 0x89, 0x01, 0x21, 0x83, 0xf7, 0x65, 0x7e, 0x27, 0x60, 0xf6, 0xa6, 0x73, 0xfa, 0xef, 0x33, 0x72, 0x77, 0xd3, 0xdc, 0x12, 0xc2, 0xe3, 0x87, 0xa9, 0xd4, 0x57, 0x80, 0x89, 0xab, 0xa2 }, +}; +static const unsigned char vec3_cmsg1[519] = { 0x03, 0x13, 0xa8, 0x3d, 0xe5, 0x5f, 0xc3, 0xef, 0x04, 0xe3, 0xd5, 0x0b, 0xe3, 0xe5, 0xae, 0x6f, 0x7d, 0xc8, 0x17, 0x5c, 0x03, 0x61, 0xa2, 0x87, 0xe3, 0x05, 0xac, 0x24, 0xb7, 0xdb, 0x90, 0x5b, 0xa0, 0x03, 0x98, 0xf0, 0x88, 0x65, 0x27, 0x59, 0x6b, 0x2c, 0x49, 0xf6, 0xa3, 0xf6, 0x58, 0x46, 0x52, 0x76, 0xdf, 0x6c, 0xd5, 0xc6, 0x68, 0xe2, 0xdf, 0x88, 0x6b, 0xe6, 0x15, 0x81, 0x60, 0x5e, 0x10, 0xa7, 0x02, 0xc0, 0xa6, 0xde, 0xcb, 0x4a, 0xd7, 0x34, 0xe9, 0xec, 0x43, 0xbd, 0x50, 0xf3, 0xa6, 0xd6, 0xe8, 0xad, 0xa8, 0x38, 0xe8, 0x44, 0x40, 0x0b, 0xfe, 0x14, 0x7e, 0x46, 0xc8, 0xa1, 0x61, 0x5a, 0x2e, 0x03, 0xe5, 0x85, 0xdb, 0x07, 0xe5, 0x5b, 0xe4, 0x78, 0x39, 0x99, 0xeb, 0xae, 0x7a, 0x14, 0xe0, 0x02, 0x32, 0x42, 0x98, 0x8f, 0x93, 0x8d, 0x44, 0x71, 0x9b, 0x3a, 0x52, 0xae, 0x63, 0xed, 0x0b, 0x6d, 0x5a, 0x61, 0xbc, 0x3f, 0x93, 0x88, 0x46, 0xad, 0x6e, 0x75, 0x60, 0x32, 0xaf, 0x07, 0x13, 0x50, 0xa5, 0x7f, 0x4d, 0xe5, 0xcc, 0x19, 0x2c, 0xb8, 0x94, 0xc9, 0x05, 0x7e, 0xd1, 0x98, 0x92, 0x80, 0xf4, 0xba, 0x10, 0x30, 0xe5, 0x6a, 0x11, 0xe9, 0xfa, 0xf6, 0x6c, 0xe9, 0x15, 0xcc, 0x29, 0x19, 0xb6, 0x5c, 0x91, 0x3c, 0xbf, 0xcf, 0xf1, 0x92, 0x88, 0xf6, 0xd5, 0x6f, 0x0a, 0x19, 0xb9, 0x06, 0xc5, 0xe6, 0x8a, 0xcd, 0xb0, 0xaf, 0x07, 0x62, 0xb1, 0x3f, 0x24, 0xeb, 0x34, 0xd0, 0x39, 0x72, 0xd5, 0x34, 0xcc, 0x72, 0x02, 0x0c, 0x10, 0x19, 0x44, 0x00, 0xd0, 0x21, 0x3f, 0x0d, 0x7f, 0x1e, 0x0d, 0x08, 0xaa, 0xd3, 0xec, 0x21, 0xff, 0x9b, 0xc7, 0xcb, 0x04, 0x97, 0x79, 0x27, 0xd7, 0xc6, 0xe6, 0xbb, 0x4f, 0x0d, 0x88, 0x7a, 0x70, 0x4a, 0x7d, 0xbd, 0x65, 0x8f, 0xa3, 0xc3, 0xc9, 0x2d, 0x7b, 0x09, 0xdd, 0x3d, 0x86, 0x90, 0xba, 0x4c, 0x1d, 0x65, 0x33, 0x07, 0x50, 0x7a, 0x2c, 0xb3, 0x06, 0x9e, 0xab, 0xbd, 0xe2, 0xb6, 0xe2, 0x4f, 0x0d, 0x79, 0xb4, 0x0a, 0xb4, 0x90, 0xae, 0x89, 0x48, 0xcc, 0x90, 0x5a, 0x4d, 0xc5, 0xc2, 0xe0, 0x59, 0xda, 0x08, 0x33, 0x1b, 0x82, 0x40, 0x51, 0xfa, 0x0b, 0x07, 0x93, 0xe3, 0x6d, 0x96, 0xaf, 0xeb, 0xf6, 0xfc, 0xef, 0x85, 0x1b, 0x21, 0x94, 0x03, 0x14, 0x18, 0x10, 0xaf, 0x9a, 0x1b, 0x7c, 0x34, 0x27, 0x0a, 0x83, 0xaa, 0x52, 0x62, 0xc2, 0xbe, 0x22, 0x4a, 0x4c, 0x6b, 0xde, 0x0d, 0xc4, 0xdf, 0xda, 0xd1, 0xc2, 0x7f, 0x09, 0x3b, 0x9b, 0x38, 0x03, 0x77, 0xb8, 0xeb, 0x7f, 0x3c, 0xf3, 0x08, 0x9a, 0xeb, 0x55, 0x77, 0xeb, 0xb3, 0x7a, 0xf4, 0x84, 0x25, 0x91, 0xcf, 0x6c, 0x97, 0x42, 0xa4, 0x8e, 0xc6, 0x56, 0xdb, 0xb8, 0xf2, 0x50, 0xf7, 0x09, 0x03, 0xfc, 0x22, 0xdc, 0xf0, 0xed, 0xd5, 0x9e, 0xdf, 0x52, 0xab, 0x06, 0xeb, 0xce, 0xba, 0x18, 0x33, 0x7d, 0x00, 0xec, 0x2e, 0xf5, 0x57, 0xcd, 0x23, 0x70, 0xe4, 0x82, 0x07, 0x2b, 0x51, 0x6d, 0x37, 0x05, 0xe8, 0x4d, 0x9d, 0xad, 0x38, 0xf9, 0x66, 0xa0, 0x9c, 0x66, 0x4e, 0x97, 0xdd, 0xf3, 0xbb, 0xfa, 0xf3, 0x23, 0xfb, 0xea, 0x68, 0xe0, 0xc0, 0x93, 0x79, 0x4a, 0x3c, 0x00, 0x65, 0x13, 0x8c, 0xac, 0x0e, 0x94, 0x6b, 0x36, 0xb7, 0xe5, 0xc6, 0x69, 0x9f, 0x2e, 0x49, 0xec, 0x9e, 0x7b, 0x5a, 0xb4, 0x19, 0xc1, 0xec, 0xdd, 0x8f, 0xc3, 0x2e, 0x68, 0xfe, 0x27, 0x6d, 0x28, 0x8d, 0x09, 0x47, 0x93, 0x0e, 0x48, 0x01, 0x77, 0x08, 0x46, 0x5d, 0x55, 0x46, 0x46, 0xc9, 0x07, 0x48, 0x4e, 0x87, 0xa3, 0xdc, 0x42, 0x53, 0xe6, 0xdb, 0x4f, 0x7c, 0xeb, 0x5d, 0x3e, 0xf5, 0xa4, 0x49, 0xd5, 0xf2 }; +static const unsigned char vec3_pmsgs2[3][64] = { + { 0x09, 0x1e, 0xab, 0x60, 0x71, 0x94, 0x54, 0x81, 0xfb, 0x97, 0xd0, 0x1c, 0x93, 0xdc, 0x2d, 0xd2, 0xcb, 0xea, 0xbc, 0xa1, 0xb0, 0x9a, 0xd6, 0x65, 0x85, 0xa4, 0x25, 0x84, 0xf2, 0x8d, 0xeb, 0xb3, 0x2c, 0x20, 0x4e, 0xc5, 0xe0, 0x5d, 0xaf, 0xd5, 0xc9, 0xf2, 0x65, 0xce, 0x1a, 0x2b, 0xa4, 0x50, 0x1b, 0x4a, 0x1b, 0x9a, 0x0e, 0x97, 0xc7, 0xf4, 0xb3, 0x4f, 0x86, 0x23, 0x31, 0x85, 0x54, 0xe5 }, + { 0x4f, 0x38, 0xc9, 0x07, 0xc0, 0x20, 0x29, 0xb9, 0x8d, 0x8b, 0x65, 0xa1, 0xc1, 0xbb, 0x24, 0x89, 0x64, 0x38, 0xc0, 0x71, 0xef, 0xd6, 0xa4, 0x90, 0x96, 0x4e, 0x9d, 0x83, 0x23, 0x8a, 0x98, 0xf0, 0xd3, 0x06, 0xf3, 0xc9, 0x4c, 0xa1, 0x50, 0x07, 0x57, 0x89, 0xc6, 0xfc, 0xe8, 0xb8, 0x02, 0xf2, 0x36, 0xfd, 0xcd, 0xf5, 0x8e, 0x5a, 0x1c, 0x65, 0x21, 0x4d, 0xa2, 0x7f, 0xed, 0x3e, 0xa6, 0xed }, + { 0x8b, 0x92, 0x3f, 0xae, 0x45, 0x7c, 0xb0, 0x5c, 0x36, 0x9f, 0x7d, 0x9d, 0x84, 0x28, 0xa2, 0x2c, 0x63, 0x0a, 0x62, 0xeb, 0x6b, 0x51, 0x89, 0x11, 0x54, 0x6a, 0x96, 0xf7, 0x45, 0x88, 0xc1, 0x4a, 0xbd, 0x63, 0xa7, 0xfa, 0x16, 0x9e, 0x17, 0xd9, 0xc5, 0x97, 0x4b, 0x0b, 0xe6, 0xc5, 0x92, 0xfe, 0x48, 0x6b, 0xec, 0xfc, 0xfd, 0xea, 0x76, 0xa3, 0xfa, 0x92, 0xa7, 0x2f, 0xba, 0x1e, 0x7b, 0xef }, +}; +static const unsigned char vec3_cmsg2[192] = { 0x09, 0x1e, 0xab, 0x60, 0x71, 0x94, 0x54, 0x81, 0xfb, 0x97, 0xd0, 0x1c, 0x93, 0xdc, 0x2d, 0xd2, 0xcb, 0xea, 0xbc, 0xa1, 0xb0, 0x9a, 0xd6, 0x65, 0x85, 0xa4, 0x25, 0x84, 0xf2, 0x8d, 0xeb, 0xb3, 0x2c, 0x20, 0x4e, 0xc5, 0xe0, 0x5d, 0xaf, 0xd5, 0xc9, 0xf2, 0x65, 0xce, 0x1a, 0x2b, 0xa4, 0x50, 0x1b, 0x4a, 0x1b, 0x9a, 0x0e, 0x97, 0xc7, 0xf4, 0xb3, 0x4f, 0x86, 0x23, 0x31, 0x85, 0x54, 0xe5, 0x4f, 0x38, 0xc9, 0x07, 0xc0, 0x20, 0x29, 0xb9, 0x8d, 0x8b, 0x65, 0xa1, 0xc1, 0xbb, 0x24, 0x89, 0x64, 0x38, 0xc0, 0x71, 0xef, 0xd6, 0xa4, 0x90, 0x96, 0x4e, 0x9d, 0x83, 0x23, 0x8a, 0x98, 0xf0, 0xd3, 0x06, 0xf3, 0xc9, 0x4c, 0xa1, 0x50, 0x07, 0x57, 0x89, 0xc6, 0xfc, 0xe8, 0xb8, 0x02, 0xf2, 0x36, 0xfd, 0xcd, 0xf5, 0x8e, 0x5a, 0x1c, 0x65, 0x21, 0x4d, 0xa2, 0x7f, 0xed, 0x3e, 0xa6, 0xed, 0x8b, 0x92, 0x3f, 0xae, 0x45, 0x7c, 0xb0, 0x5c, 0x36, 0x9f, 0x7d, 0x9d, 0x84, 0x28, 0xa2, 0x2c, 0x63, 0x0a, 0x62, 0xeb, 0x6b, 0x51, 0x89, 0x11, 0x54, 0x6a, 0x96, 0xf7, 0x45, 0x88, 0xc1, 0x4a, 0xbd, 0x63, 0xa7, 0xfa, 0x16, 0x9e, 0x17, 0xd9, 0xc5, 0x97, 0x4b, 0x0b, 0xe6, 0xc5, 0x92, 0xfe, 0x48, 0x6b, 0xec, 0xfc, 0xfd, 0xea, 0x76, 0xa3, 0xfa, 0x92, 0xa7, 0x2f, 0xba, 0x1e, 0x7b, 0xef }; +static const unsigned char vec3_secshares[3][32] = { + { 0x38, 0xf8, 0x44, 0xd4, 0x6d, 0xf1, 0xf9, 0x51, 0x56, 0x40, 0x60, 0x09, 0xb7, 0x04, 0x11, 0xcf, 0x88, 0x02, 0x4c, 0xa6, 0xd6, 0x4a, 0x37, 0x06, 0x9f, 0x44, 0x97, 0x10, 0x7d, 0x3d, 0x47, 0x33 }, + { 0x01, 0x1d, 0x1f, 0x86, 0x77, 0xaf, 0x70, 0x71, 0xcf, 0x89, 0xf6, 0x3f, 0x94, 0xad, 0xf7, 0x7c, 0xfa, 0xe7, 0xca, 0xb3, 0x28, 0xd4, 0x4d, 0x5e, 0x24, 0x29, 0x5e, 0x06, 0x77, 0xda, 0x3b, 0xfe }, + { 0xc9, 0x41, 0xfa, 0x38, 0x81, 0x6c, 0xe7, 0x92, 0x48, 0xd3, 0x8c, 0x75, 0x72, 0x57, 0xdd, 0x29, 0x28, 0x7c, 0x25, 0xa6, 0x2a, 0xa7, 0x03, 0xf1, 0x68, 0xe0, 0x83, 0x89, 0x42, 0xad, 0x72, 0x0a }, +}; +static const unsigned char vec3_thresh_pk[33] = { 0x03, 0x07, 0xf3, 0xc6, 0x29, 0x69, 0xf9, 0xee, 0xaf, 0xb9, 0xf3, 0xd6, 0x25, 0xcb, 0xa6, 0xe8, 0x09, 0x00, 0x17, 0x04, 0xc0, 0x92, 0xd7, 0xca, 0xac, 0x49, 0x6f, 0xd3, 0xed, 0x07, 0x35, 0x23, 0x2c }; +static const unsigned char vec3_pubshares[3][33] = { + { 0x02, 0x2a, 0x8d, 0x1c, 0x2a, 0x1c, 0x95, 0x97, 0x89, 0xdf, 0xa2, 0xb5, 0xc4, 0xc2, 0x97, 0xdb, 0xc9, 0x09, 0x6b, 0xb7, 0xd7, 0x20, 0x1f, 0xe6, 0x67, 0x38, 0x13, 0xae, 0xff, 0x9f, 0xbc, 0x58, 0xba }, + { 0x03, 0x1a, 0x40, 0x20, 0x79, 0x6b, 0x0c, 0x5f, 0x0e, 0x4a, 0x67, 0xd2, 0x74, 0x8f, 0xd2, 0xea, 0x93, 0x65, 0x2c, 0xae, 0x41, 0x0f, 0xf0, 0x2d, 0x45, 0x79, 0x8a, 0x44, 0xb4, 0x50, 0x8f, 0xd5, 0x4d }, + { 0x02, 0xea, 0xad, 0x03, 0x65, 0xfe, 0x7e, 0xa9, 0xea, 0xd9, 0x30, 0x44, 0xb9, 0x68, 0xf6, 0xe7, 0x18, 0x51, 0xe5, 0xac, 0xd3, 0x80, 0x92, 0x11, 0xd8, 0x4d, 0xe2, 0xd7, 0x3a, 0xf6, 0xf9, 0x4a, 0xee }, +}; +static const unsigned char vec3_recovery[556] = { 0x00, 0x00, 0x00, 0x02, 0x03, 0xdd, 0xe3, 0x46, 0x0b, 0x06, 0x56, 0x58, 0xf6, 0x85, 0x78, 0x85, 0xee, 0x42, 0xa8, 0xfa, 0x9c, 0x53, 0xd6, 0x3d, 0x75, 0x02, 0x16, 0x65, 0x03, 0xf1, 0xb6, 0x6a, 0x56, 0xb9, 0x76, 0xa2, 0x70, 0x03, 0xe5, 0x85, 0xdb, 0x07, 0xe5, 0x5b, 0xe4, 0x78, 0x39, 0x99, 0xeb, 0xae, 0x7a, 0x14, 0xe0, 0x02, 0x32, 0x42, 0x98, 0x8f, 0x93, 0x8d, 0x44, 0x71, 0x9b, 0x3a, 0x52, 0xae, 0x63, 0xed, 0x0b, 0x6d, 0x02, 0x2d, 0x9b, 0xc8, 0xa8, 0x44, 0x57, 0xc7, 0x51, 0x00, 0x1f, 0x71, 0x4a, 0xd9, 0xac, 0x72, 0x82, 0x8a, 0x01, 0xe5, 0x31, 0xbe, 0x63, 0xe7, 0xfc, 0x3c, 0x4d, 0x37, 0x0c, 0x2f, 0xec, 0xd8, 0x43, 0x03, 0x34, 0xbe, 0xe4, 0x54, 0x9f, 0x86, 0x95, 0xd8, 0x96, 0xa3, 0xf0, 0x60, 0x40, 0xe0, 0x26, 0x3c, 0x41, 0x90, 0x54, 0xf3, 0xb8, 0xc7, 0x83, 0xa7, 0x7a, 0x77, 0x02, 0x82, 0x86, 0x14, 0x97, 0x3a, 0x02, 0x85, 0xe6, 0xb7, 0xa7, 0xfb, 0x26, 0x5f, 0x38, 0xb9, 0xad, 0xc3, 0x9e, 0x51, 0xd4, 0xac, 0x2d, 0xfb, 0x0f, 0x31, 0xa6, 0xf1, 0x8e, 0x7f, 0xf8, 0xae, 0x2f, 0x3c, 0xa7, 0xbc, 0xaa, 0x7d, 0xcf, 0x03, 0x14, 0x18, 0x10, 0xaf, 0x9a, 0x1b, 0x7c, 0x34, 0x27, 0x0a, 0x83, 0xaa, 0x52, 0x62, 0xc2, 0xbe, 0x22, 0x4a, 0x4c, 0x6b, 0xde, 0x0d, 0xc4, 0xdf, 0xda, 0xd1, 0xc2, 0x7f, 0x09, 0x3b, 0x9b, 0x38, 0x03, 0x77, 0xb8, 0xeb, 0x7f, 0x3c, 0xf3, 0x08, 0x9a, 0xeb, 0x55, 0x77, 0xeb, 0xb3, 0x7a, 0xf4, 0x84, 0x25, 0x91, 0xcf, 0x6c, 0x97, 0x42, 0xa4, 0x8e, 0xc6, 0x56, 0xdb, 0xb8, 0xf2, 0x50, 0xf7, 0x09, 0x03, 0xfc, 0x22, 0xdc, 0xf0, 0xed, 0xd5, 0x9e, 0xdf, 0x52, 0xab, 0x06, 0xeb, 0xce, 0xba, 0x18, 0x33, 0x7d, 0x00, 0xec, 0x2e, 0xf5, 0x57, 0xcd, 0x23, 0x70, 0xe4, 0x82, 0x07, 0x2b, 0x51, 0x6d, 0x37, 0x05, 0xe8, 0x4d, 0x9d, 0xad, 0x38, 0xf9, 0x66, 0xa0, 0x9c, 0x66, 0x4e, 0x97, 0xdd, 0xf3, 0xbb, 0xfa, 0xf3, 0x23, 0xfb, 0xea, 0x68, 0xe0, 0xc0, 0x93, 0x79, 0x4a, 0x3c, 0x00, 0x65, 0x13, 0x8c, 0xac, 0x0e, 0x94, 0x6b, 0x36, 0xb7, 0xe5, 0xc6, 0x69, 0x9f, 0x2e, 0x49, 0xec, 0x9e, 0x7b, 0x5a, 0xb4, 0x19, 0xc1, 0xec, 0xdd, 0x8f, 0xc3, 0x2e, 0x68, 0xfe, 0x27, 0x6d, 0x28, 0x8d, 0x09, 0x47, 0x93, 0x0e, 0x48, 0x01, 0x77, 0x08, 0x46, 0x5d, 0x55, 0x46, 0x46, 0xc9, 0x07, 0x48, 0x4e, 0x87, 0xa3, 0xdc, 0x42, 0x53, 0xe6, 0xdb, 0x4f, 0x7c, 0xeb, 0x5d, 0x3e, 0xf5, 0xa4, 0x49, 0xd5, 0xf2, 0x09, 0x1e, 0xab, 0x60, 0x71, 0x94, 0x54, 0x81, 0xfb, 0x97, 0xd0, 0x1c, 0x93, 0xdc, 0x2d, 0xd2, 0xcb, 0xea, 0xbc, 0xa1, 0xb0, 0x9a, 0xd6, 0x65, 0x85, 0xa4, 0x25, 0x84, 0xf2, 0x8d, 0xeb, 0xb3, 0x2c, 0x20, 0x4e, 0xc5, 0xe0, 0x5d, 0xaf, 0xd5, 0xc9, 0xf2, 0x65, 0xce, 0x1a, 0x2b, 0xa4, 0x50, 0x1b, 0x4a, 0x1b, 0x9a, 0x0e, 0x97, 0xc7, 0xf4, 0xb3, 0x4f, 0x86, 0x23, 0x31, 0x85, 0x54, 0xe5, 0x4f, 0x38, 0xc9, 0x07, 0xc0, 0x20, 0x29, 0xb9, 0x8d, 0x8b, 0x65, 0xa1, 0xc1, 0xbb, 0x24, 0x89, 0x64, 0x38, 0xc0, 0x71, 0xef, 0xd6, 0xa4, 0x90, 0x96, 0x4e, 0x9d, 0x83, 0x23, 0x8a, 0x98, 0xf0, 0xd3, 0x06, 0xf3, 0xc9, 0x4c, 0xa1, 0x50, 0x07, 0x57, 0x89, 0xc6, 0xfc, 0xe8, 0xb8, 0x02, 0xf2, 0x36, 0xfd, 0xcd, 0xf5, 0x8e, 0x5a, 0x1c, 0x65, 0x21, 0x4d, 0xa2, 0x7f, 0xed, 0x3e, 0xa6, 0xed, 0x8b, 0x92, 0x3f, 0xae, 0x45, 0x7c, 0xb0, 0x5c, 0x36, 0x9f, 0x7d, 0x9d, 0x84, 0x28, 0xa2, 0x2c, 0x63, 0x0a, 0x62, 0xeb, 0x6b, 0x51, 0x89, 0x11, 0x54, 0x6a, 0x96, 0xf7, 0x45, 0x88, 0xc1, 0x4a, 0xbd, 0x63, 0xa7, 0xfa, 0x16, 0x9e, 0x17, 0xd9, 0xc5, 0x97, 0x4b, 0x0b, 0xe6, 0xc5, 0x92, 0xfe, 0x48, 0x6b, 0xec, 0xfc, 0xfd, 0xea, 0x76, 0xa3, 0xfa, 0x92, 0xa7, 0x2f, 0xba, 0x1e, 0x7b, 0xef }; +/* chilldkg session n = 3, t = 2 */ +/* all python-side sanity checks passed */ + /* The group order n and (2^256 - 1) mod n, for scalar parsing edge cases. */ static const unsigned char vec_scalar_order_n[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -265,11 +313,11 @@ static void chilldkg_params_hash_test(void) { unsigned char out[32]; /* TH("BIP DKG/params_hash", u32be(2) || hostpubkeys) */ - secp256k1_chilldkg_params_hash(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 2); + secp256k1_chilldkg_params_hash_internal(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 2); CHECK(secp256k1_memcmp_var(out, vec_params_hash, 32) == 0); /* t is part of the hash input. */ - secp256k1_chilldkg_params_hash(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 3); + secp256k1_chilldkg_params_hash_internal(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 3); CHECK(secp256k1_memcmp_var(out, vec_params_hash, 32) != 0); } @@ -638,7 +686,7 @@ static void chilldkg_simplpedpop_test(void) { /* coordinator_step: cmsg, eq_input and the DKG output are byte-exact. */ fault = secp256k1_chilldkg_simplpedpop_coordinator_step(CTX, cmsg, &coord_dkg, eq_input, &fault_index, pmsg_ptrs, t, n); - CHECK(fault == SECP256K1_CHILLDKG_SUCCESS); + CHECK(fault == SECP256K1_CHILLDKG_OK); CHECK(secp256k1_memcmp_var(cmsg, vec_simpl_cmsg, cmsg_len) == 0); CHECK(secp256k1_memcmp_var(eq_input, vec_simpl_eq_input, eq_len) == 0); CHECK(secp256k1_memcmp_var(coord_dkg.thresh_pk33, vec_simpl_thresh_pk, 33) == 0); @@ -659,7 +707,7 @@ static void chilldkg_simplpedpop_test(void) { secp256k1_scalar_get_b32(buf32, &secshare); CHECK(secp256k1_memcmp_var(buf32, vec_simpl_untweaked_secshares[i], 32) == 0); fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[i], eq_input_p, &fault_index, &states[i], cmsg, cmsg_len, &secshare); - CHECK(fault == SECP256K1_CHILLDKG_SUCCESS); + CHECK(fault == SECP256K1_CHILLDKG_OK); CHECK(secp256k1_memcmp_var(eq_input_p, vec_simpl_eq_input, eq_len) == 0); CHECK(secp256k1_memcmp_var(dkg_outputs[i].secshare32, vec_simpl_secshares[i], 32) == 0); CHECK(secp256k1_memcmp_var(dkg_outputs[i].thresh_pk33, vec_simpl_thresh_pk, 33) == 0); @@ -819,7 +867,7 @@ static void chilldkg_encpedpop_test(void) { CHECK(secp256k1_chilldkg_encpedpop_encaps_multi(CTX, pads_send, &scalar_tmp, vec_enc_pubnonces[0], vec_enc_hostseckeys[0], &vec_enc_hostpubkeys[0][0], enc_context, sizeof(enc_context), 0, n) == 1); for (i = 0; i < n; i++) { fault = secp256k1_chilldkg_encpedpop_decaps_multi(CTX, pads_recv, &fault_index, vec_enc_hostseckeys[i], vec_enc_hostpubkeys[i], &vec_enc_pubnonces[0][0], enc_context, sizeof(enc_context), i, n); - CHECK(fault == SECP256K1_CHILLDKG_SUCCESS); + CHECK(fault == SECP256K1_CHILLDKG_OK); CHECK(secp256k1_scalar_eq(&pads_send[i], &pads_recv[0])); } /* decaps_multi rejects an invalid own host secret key. */ @@ -849,7 +897,7 @@ static void chilldkg_encpedpop_test(void) { } for (j = 0; j < n; j++) { fault = secp256k1_chilldkg_encpedpop_decrypt_sum(CTX, &scalar_tmp, &fault_index, vec_enc_hostseckeys[j], vec_enc_hostpubkeys[j], &vec_enc_pubnonces[0][0], enc_context, sizeof(enc_context), j, &enc_secshares[j], n); - CHECK(fault == SECP256K1_CHILLDKG_SUCCESS); + CHECK(fault == SECP256K1_CHILLDKG_OK); secp256k1_scalar_set_int(&scalar_tmp2, 0); for (i = 0; i < n; i++) { secp256k1_scalar p; @@ -862,7 +910,7 @@ static void chilldkg_encpedpop_test(void) { /* coordinator_step: cmsg, eq_input, summed encrypted shares and the DKG * output are byte-exact. */ fault = secp256k1_chilldkg_encpedpop_coordinator_step(CTX, cmsg, &coord_dkg, eq_input, enc_secshares, &fault_index, pmsg_ptrs, t, &vec_enc_hostpubkeys[0][0], n); - CHECK(fault == SECP256K1_CHILLDKG_SUCCESS); + CHECK(fault == SECP256K1_CHILLDKG_OK); CHECK(secp256k1_memcmp_var(cmsg, vec_enc_cmsg, cmsg_len) == 0); CHECK(secp256k1_memcmp_var(eq_input, vec_enc_eq_input, eq_len) == 0); for (i = 0; i < n; i++) { @@ -878,7 +926,7 @@ static void chilldkg_encpedpop_test(void) { for (i = 0; i < n; i++) { unsigned char eq_input_p[268]; fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input_p, &fault_index, &states[i], vec_enc_hostseckeys[i], cmsg, cmsg_len, &enc_secshares[i]); - CHECK(fault == SECP256K1_CHILLDKG_SUCCESS); + CHECK(fault == SECP256K1_CHILLDKG_OK); CHECK(secp256k1_memcmp_var(eq_input_p, vec_enc_eq_input, eq_len) == 0); CHECK(secp256k1_memcmp_var(dkg_output.secshare32, vec_enc_out_secshares[i], 32) == 0); CHECK(secp256k1_memcmp_var(dkg_output.thresh_pk33, vec_enc_thresh_pk, 33) == 0); @@ -958,6 +1006,262 @@ static void chilldkg_encpedpop_test(void) { } } +static void chilldkg_participant_api_test(void) { + const size_t n = 3; + const uint32_t t = 2; + const size_t pmsg1_len = 33 * 2 + 32 * 3 + 97; /* 259 */ + const size_t cmsg1_len = 162 * 3 + 33 * 1; /* 519 */ + const size_t enc_cmsg_len = 97 * 3 + 33 * 1 + 33 * 3; /* 423 */ + const size_t recovery_len = 4 + 33 * 2 + 162 * 3; /* 556 */ + secp256k1_chilldkg_participant_state1 state1[3]; + secp256k1_chilldkg_participant_state2 state2[3]; + secp256k1_chilldkg_simplpedpop_dkg_output coord_dkg; + secp256k1_scalar enc_secshares[3]; + unsigned char pmsg1[3][259]; + unsigned char sig64[3][64]; + unsigned char cmsg1[519]; + unsigned char cmsg1_bad[519]; + unsigned char cmsg2[192]; + unsigned char cmsg2_bad[192]; + unsigned char hostpubkeys33[3 * 33]; + unsigned char pubshares33[3 * 33]; + unsigned char recovery[556]; + unsigned char eq_input[268]; + unsigned char buf33[33]; + unsigned char buf32[32]; + unsigned char secshare32[32]; + unsigned char zero32[32] = { 0 }; + const unsigned char *pmsg1_ptrs[3]; + secp256k1_chilldkg_fault fault; + uint32_t fault_index = 0; + size_t i, j; + + for (i = 0; i < n; i++) { + pmsg1_ptrs[i] = pmsg1[i]; + memcpy(hostpubkeys33 + 33 * i, vec3_hostpubkeys[i], 33); + } + + /* Message length helpers. */ + CHECK(secp256k1_chilldkg_participant_msg1_len(n, t) == pmsg1_len); + CHECK(secp256k1_chilldkg_coordinator_msg1_len(n, t) == cmsg1_len); + CHECK(secp256k1_chilldkg_participant_msg2_len() == 64); + CHECK(secp256k1_chilldkg_coordinator_msg2_len(n) == sizeof(cmsg2)); + CHECK(secp256k1_chilldkg_recovery_data_len(n, t) == recovery_len); + CHECK(secp256k1_chilldkg_participant_msg1_len(0, 1) == 0); + CHECK(secp256k1_chilldkg_participant_msg1_len(n, 0) == 0); + CHECK(secp256k1_chilldkg_participant_msg1_len(n, (uint32_t)(n + 1)) == 0); + CHECK(secp256k1_chilldkg_participant_msg1_len(SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 1, 1) == 0); + CHECK(secp256k1_chilldkg_coordinator_msg1_len(n, 0) == 0); + CHECK(secp256k1_chilldkg_coordinator_msg2_len(0) == 0); + CHECK(secp256k1_chilldkg_recovery_data_len(n, (uint32_t)(n + 1)) == 0); + + /* hostpubkey_gen: byte-exact against the reference; invalid host secret + * keys are rejected and zero the output. */ + for (i = 0; i < n; i++) { + CHECK(secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, vec3_hostseckeys[i]) == 1); + CHECK(secp256k1_memcmp_var(buf33, vec3_hostpubkeys[i], 33) == 0); + } + CHECK(secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, zero32) == 0); + CHECK(secp256k1_is_zero_array(buf33, 33)); + CHECK(secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, vec_scalar_order_n) == 0); + CHECK(secp256k1_is_zero_array(buf33, 33)); + + /* params_hash: byte-exact against the reference; invalid parameters + * (duplicate or invalid host public keys, t or n out of range) are + * rejected and zero the output. */ + CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, n, t) == 1); + CHECK(secp256k1_memcmp_var(buf32, vec3_params_hash, 32) == 0); + { + unsigned char bad_hostpubkeys[3 * 33]; + memcpy(bad_hostpubkeys, hostpubkeys33, sizeof(bad_hostpubkeys)); + memcpy(bad_hostpubkeys + 33, hostpubkeys33, 33); /* duplicate */ + CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, bad_hostpubkeys, n, t) == 0); + CHECK(secp256k1_is_zero_array(buf32, 32)); + memcpy(bad_hostpubkeys, hostpubkeys33, sizeof(bad_hostpubkeys)); + memset(bad_hostpubkeys + 33, 0xff, 33); /* invalid public key */ + CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, bad_hostpubkeys, n, t) == 0); + memcpy(bad_hostpubkeys, hostpubkeys33, sizeof(bad_hostpubkeys)); + memset(bad_hostpubkeys + 33, 0, 33); /* infinity is not a valid public key */ + CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, bad_hostpubkeys, n, t) == 0); + } + CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, n, 0) == 0); + CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, n, (uint32_t)(n + 1)) == 0); + CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 1, t) == 0); + + /* participant_step1: byte-exact messages against the reference. */ + for (i = 0; i < n; i++) { + CHECK(secp256k1_chilldkg_participant_step1(CTX, &state1[i], pmsg1[i], vec3_hostseckeys[i], hostpubkeys33, n, t, vec3_randoms[i]) == 1); + CHECK(secp256k1_memcmp_var(pmsg1[i], vec3_pmsgs1[i], pmsg1_len) == 0); + } + + /* participant_step1 rejects invalid input and zeroes its outputs. */ + { + secp256k1_chilldkg_participant_state1 tmp_state1; + unsigned char tmp_pmsg1[259]; + unsigned char other_seckey[32]; + memset(other_seckey, 0, 32); + other_seckey[31] = 1; /* valid key, but not in hostpubkeys33 */ + + /* All-zero randomness (RandomnessError in the reference). */ + CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, vec3_hostseckeys[0], hostpubkeys33, n, t, zero32) == 0); + CHECK(secp256k1_is_zero_array(tmp_state1.data, sizeof(tmp_state1.data))); + CHECK(secp256k1_is_zero_array(tmp_pmsg1, sizeof(tmp_pmsg1))); + /* Host secret key not in the session (HostSeckeyError). */ + CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, other_seckey, hostpubkeys33, n, t, vec3_randoms[0]) == 0); + /* Invalid host secret key. */ + CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, zero32, hostpubkeys33, n, t, vec3_randoms[0]) == 0); + /* Invalid session parameters. */ + CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, vec3_hostseckeys[0], hostpubkeys33, n, 0, vec3_randoms[0]) == 0); + CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, vec3_hostseckeys[0], hostpubkeys33, n, (uint32_t)(n + 1), vec3_randoms[0]) == 0); + } + + /* Simulate the coordinator with the internal EncPedPop coordinator step: + * cmsg1 = enc_cmsg || enc_secshares. The result is byte-exact against the + * reference coordinator_step1. */ + fault = secp256k1_chilldkg_encpedpop_coordinator_step(CTX, cmsg1, &coord_dkg, eq_input, enc_secshares, &fault_index, pmsg1_ptrs, t, hostpubkeys33, n); + CHECK(fault == SECP256K1_CHILLDKG_OK); + for (i = 0; i < n; i++) { + secp256k1_scalar_get_b32(cmsg1 + enc_cmsg_len + 32 * i, &enc_secshares[i]); + } + CHECK(secp256k1_memcmp_var(cmsg1, vec3_cmsg1, cmsg1_len) == 0); + + /* participant_step2: byte-exact CertEq signatures against the reference. */ + for (i = 0; i < n; i++) { + fault = secp256k1_chilldkg_participant_step2(CTX, &state2[i], sig64[i], &fault_index, &state1[i], vec3_hostseckeys[i], cmsg1, vec3_aux_rands[i]); + CHECK(fault == SECP256K1_CHILLDKG_OK); + CHECK(secp256k1_memcmp_var(sig64[i], vec3_pmsgs2[i], 64) == 0); + } + + /* The certificate is the concatenation of the pmsg2 signatures. */ + for (i = 0; i < n; i++) { + memcpy(cmsg2 + 64 * i, sig64[i], 64); + } + CHECK(secp256k1_memcmp_var(cmsg2, vec3_cmsg2, sizeof(cmsg2)) == 0); + + /* participant_finalize: byte-exact outputs against the reference. */ + for (i = 0; i < n; i++) { + fault = secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &state2[i], cmsg2); + CHECK(fault == SECP256K1_CHILLDKG_OK); + CHECK(secp256k1_memcmp_var(secshare32, vec3_secshares[i], 32) == 0); + CHECK(secp256k1_memcmp_var(buf33, vec3_thresh_pk, 33) == 0); + for (j = 0; j < n; j++) { + CHECK(secp256k1_memcmp_var(pubshares33 + 33 * j, vec3_pubshares[j], 33) == 0); + } + CHECK(secp256k1_memcmp_var(recovery, vec3_recovery, recovery_len) == 0); + } + + /* participant_step2 with a host secret key that does not match the one + * used in step 1 is an input error (HostSeckeyError in the reference). */ + { + unsigned char tmp_sig64[64]; + fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &state1[0], vec3_hostseckeys[1], cmsg1, vec3_aux_rands[0]); + CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT); + CHECK(secp256k1_is_zero_array(tmp_sig64, 64)); + } + + /* participant_step2 blames faults correctly. */ + { + secp256k1_chilldkg_participant_state1 fresh_state1; + unsigned char tmp_sig64[64]; + + /* A tampered encrypted secshare: the decrypted share does not match + * the pubshare; the fault cannot be attributed without the + * investigation procedure. */ + CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1); + memcpy(cmsg1_bad, cmsg1, cmsg1_len); + cmsg1_bad[enc_cmsg_len + 31] ^= 1; + fault_index = 0; + fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]); + CHECK(fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR); + CHECK(fault_index == UINT32_MAX); + + /* An invalid pubnonce of participant 1 blames that participant or the + * coordinator. */ + CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1); + memcpy(cmsg1_bad, cmsg1, cmsg1_len); + memset(cmsg1_bad + 324 + 33, 0xff, 33); + fault_index = 0; + fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]); + CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR); + CHECK(fault_index == 1); + + /* An encrypted secshare that overflows the group order blames the + * coordinator. */ + CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1); + memcpy(cmsg1_bad, cmsg1, cmsg1_len); + memset(cmsg1_bad + enc_cmsg_len, 0xff, 32); + fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]); + CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR); + } + + /* participant_finalize: an invalid signature in the certificate blames + * the coordinator and zeroes the outputs. */ + { + secp256k1_chilldkg_participant_state1 fresh_state1; + secp256k1_chilldkg_participant_state2 fresh_state2; + unsigned char tmp_sig64[64]; + CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1); + fault = secp256k1_chilldkg_participant_step2(CTX, &fresh_state2, tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]); + CHECK(fault == SECP256K1_CHILLDKG_OK); + + memcpy(cmsg2_bad, cmsg2, sizeof(cmsg2)); + cmsg2_bad[64 + 10] ^= 1; /* corrupt the signature of participant 1 */ + fault_index = 0; + fault = secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &fresh_state2, cmsg2_bad); + CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR); + CHECK(fault_index == 1); + CHECK(secp256k1_is_zero_array(secshare32, 32)); + CHECK(secp256k1_is_zero_array(buf33, 33)); + CHECK(secp256k1_is_zero_array(pubshares33, 33 * n)); + CHECK(secp256k1_is_zero_array(recovery, recovery_len)); + } + + /* API misuse. */ + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_hostpubkey_gen(CTX, NULL, vec3_hostseckeys[0])); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, NULL)); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_params_hash(CTX, NULL, hostpubkeys33, n, t)); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_params_hash(CTX, buf32, NULL, n, t)); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, NULL, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0])); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], NULL, vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0])); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], pmsg1[0], NULL, hostpubkeys33, n, t, vec3_randoms[0])); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], pmsg1[0], vec3_hostseckeys[0], NULL, n, t, vec3_randoms[0])); + CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, NULL)); + /* API misuse of the enum-returning functions: the illegal-argument + * callback fires exactly once and the function returns INVALID_INPUT. */ + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, NULL, sig64[0], &fault_index, &state1[0], vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], NULL, &fault_index, &state1[0], vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], NULL, &state1[0], vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, NULL, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, &state1[0], NULL, cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, &state1[0], vec3_hostseckeys[0], NULL, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, &state1[0], vec3_hostseckeys[0], cmsg1, NULL) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, NULL, buf33, pubshares33, recovery, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, NULL, pubshares33, recovery, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, NULL, recovery, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, NULL, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, NULL, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, NULL, cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &state2[0], NULL) == SECP256K1_CHILLDKG_INVALID_INPUT)); + + /* States with a bad magic (uninitialized or corrupted) are rejected. */ + { + secp256k1_chilldkg_participant_state1 bad_state1; + secp256k1_chilldkg_participant_state2 bad_state2; + unsigned char tmp_sig64[64]; + memset(&bad_state1, 0, sizeof(bad_state1)); + memset(&bad_state2, 0, sizeof(bad_state2)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &bad_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &bad_state2, cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT)); + CHECK(secp256k1_chilldkg_participant_step1(CTX, &bad_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1); + bad_state1.data[0] ^= 1; + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &bad_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT)); + } + + for (i = 0; i < n; i++) { + secp256k1_scalar_clear(&enc_secshares[i]); + } +} + static const struct tf_test_entry tests_chilldkg[] = { CASE1(chilldkg_tagged_hashes_test), CASE1(chilldkg_params_hash_test), @@ -968,6 +1272,7 @@ static const struct tf_test_entry tests_chilldkg[] = { CASE1(chilldkg_vss_test), CASE1(chilldkg_simplpedpop_test), CASE1(chilldkg_encpedpop_test), + CASE1(chilldkg_participant_api_test), }; #endif diff --git a/src/modules/chilldkg/util.h b/src/modules/chilldkg/util.h index 219078d4..9f6b5091 100644 --- a/src/modules/chilldkg/util.h +++ b/src/modules/chilldkg/util.h @@ -7,36 +7,16 @@ #define SECP256K1_MODULE_CHILLDKG_UTIL_H #include "../../../include/secp256k1.h" +#include "../../../include/secp256k1_chilldkg.h" #include "../../group.h" #include "../../hash.h" #include "../../scalar.h" -/* Maximum number of participants (and thus the maximum threshold) supported by - * this module. The state objects of the module are fixed-size and do not use - * dynamic allocation, so a compile-time cap is required. This matches the - * frost module's convention; the public header will expose the same constant - * in a later phase. */ -#define SECP256K1_CHILLDKG_MAX_PARTICIPANTS 128 - -/* Return codes of the internal SimplPedPop/EncPedPop functions, mirroring the - * exception taxonomy of chilldkg_ref/util.py. The public API will expose its - * own enum in a later phase. - * - * For SECP256K1_CHILLDKG_FAULTY_PARTICIPANT and - * SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, the fault_index output - * of the failing function receives the index of the (suspected) faulty - * participant. For SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR - * the faulty party cannot be identified without the investigation procedure - * (a later phase); fault_index is set to UINT32_MAX. */ -typedef enum { - SECP256K1_CHILLDKG_SUCCESS = 0, - SECP256K1_CHILLDKG_FAULTY_COORDINATOR, - SECP256K1_CHILLDKG_FAULTY_PARTICIPANT, - SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, - SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR, - SECP256K1_CHILLDKG_INVALID_INPUT -} secp256k1_chilldkg_fault; +/* The public header defines SECP256K1_CHILLDKG_MAX_PARTICIPANTS and the fault + * enum secp256k1_chilldkg_fault (SECP256K1_CHILLDKG_OK, ...), which the + * internal SimplPedPop/EncPedPop functions use directly as their return + * codes. */ /* This file contains the internal primitives of the ChillDKG module that * mirror chilldkg_ref/util.py, secp256k1lab/bip340.py and secp256k1lab/ecdh.py @@ -120,6 +100,6 @@ static void secp256k1_chilldkg_encpedpop_self_pad(const secp256k1_hash_ctx *hash /* Compute the session parameters hash (chilldkg.py `params_hash`): * out32 = TH("BIP DKG/params_hash", u32be(t) || hostpubkeys[0] || ... || hostpubkeys[n-1]) * where hostpubkeys33 is an array of n 33-byte compressed host public keys. */ -static void secp256k1_chilldkg_params_hash(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t); +static void secp256k1_chilldkg_params_hash_internal(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t); #endif diff --git a/src/modules/chilldkg/util_impl.h b/src/modules/chilldkg/util_impl.h index 3b6cb29d..70267a92 100644 --- a/src/modules/chilldkg/util_impl.h +++ b/src/modules/chilldkg/util_impl.h @@ -371,7 +371,7 @@ static void secp256k1_chilldkg_encpedpop_self_pad(const secp256k1_hash_ctx *hash secp256k1_memclear_explicit(hash32, sizeof(hash32)); } -static void secp256k1_chilldkg_params_hash(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t) { +static void secp256k1_chilldkg_params_hash_internal(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t) { unsigned char buf[4]; secp256k1_sha256 sha;