chilldkg: Phase 5 - recovery, recovery acks, investigation
Complete the ChillDKG protocol surface with the recovery and blame-
attribution procedures (bip-frost-dkg v0.3.0-dev, reference commit
a91896883f85b159415ecf298d5e844879af112d).
Recovery:
- secp256k1_chilldkg_participant_recover / _coordinator_recover: parse
the self-delimiting recovery layout u32be(t) || sum_coms(33t) ||
hostpubkeys(33n) || pubnonces(33n) || enc_secshares(32n, checked) ||
cert(64n), deriving n = (len-4-33t)/162 exactly as the reference's
deserialize_recovery_data; re-verify the certificate, recompute the
TapTweak and the receiver's ECDH/self pads from (hostseckey,
pubnonces, enc_context), recompute the tweaked secshare, and
sanity-check secshare*G == pubshares[own]. Also return hostpubkeys,
n and t so callers can re-derive session params. RecoveryDataError /
HostSeckeyError / params failures map to INVALID_INPUT (no index,
as in the reference); an invalid pubnonce during decrypt passes
through as FAULTY_PARTICIPANT_OR_COORDINATOR(i), matching the
reference leaking that exception from recover().
Recovery acks:
- secp256k1_chilldkg_recovery_ack_sign / _acks_verify: BIP-340
(standard BIP0340 tags) over pad33("BIP DKG/recovery acknowledgment")
|| u32be(i) || recovery_data. Verification failure maps to
FAULTY_PARTICIPANT(i) (InvalidRecoveryAckError subclasses
FaultyParticipantError in the reference).
Investigation:
- secp256k1_chilldkg_coordinator_investigate: builds one 65n-byte
per-participant message (per-dealer encrypted partial secshares
(32n) + partial pubshares (33n)) per call; the reference returns all
n at once -- equivalent, the caller iterates.
- secp256k1_chilldkg_participant_investigate: the reference's
three-step blame attribution -- sum-of-pubshares check ->
FAULTY_COORDINATOR; sum-of-secshares check -> FAULTY_COORDINATOR
(covers the reference's SecshareSumError translation); per-dealer
decrypted share vs commitment -> FAULTY_PARTICIPANT_OR_COORDINATOR(i)
(or FAULTY_COORDINATOR for the own index); all-consistent ->
INVALID_INPUT (the reference's uncaught RuntimeError).
- Investigation data is transported via a new opaque, secret-bearing
secp256k1_chilldkg_participant_inv_data object (4205 bytes,
magic-validated save/load, secret-cleared) filled by
participant_step2 on the UNKNOWN_FAULT paths. This amends the
Phase 3 participant_step2 signature with a nullable inv_data
out-param -- required because recomputing inside
participant_investigate would duplicate step2's decrypt/verify
logic.
- New length helper secp256k1_chilldkg_investigation_msg_len (65n).
tests_impl.h: chilldkg_recovery_test (recover roundtrips byte-exact
vs the session outputs and reference vectors, tampered/truncated/
over-long recovery data, unknown/invalid hostseckey, ack sign
byte-exact + verify with wrong-index and tampered-ack blame,
params/recovery mismatch rejects, misuse) and
chilldkg_investigate_test (two end-to-end public-API scenarios
generated from the reference: dealer corrupting a participant's
encrypted share, and coordinator tampering with an enc_secshare;
cmsg1/cinv/inv_data byte-exact, blame codes and indices matching the
reference's exception type and index; malformed cinv ->
FAULTY_COORDINATOR; malformed pmsg1 -> FAULTY_PARTICIPANT(j); misuse).
The all-consistent investigate path is not constructible without
discrete logs and matches the reference's unreachable RuntimeError.
Verified: make check 3/3 (incl. noverify); CMake ctest 369/369;
make distdir clean.
This commit is contained in:
@@ -112,6 +112,21 @@ 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;
|
||||
|
||||
/** Opaque data structure that holds the investigation data output by
|
||||
* secp256k1_chilldkg_participant_step2 when it returns
|
||||
* SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR, to be passed
|
||||
* to secp256k1_chilldkg_participant_investigate together with the
|
||||
* coordinator's investigation message.
|
||||
*
|
||||
* This structure contains secret data (the untweaked secret share and the
|
||||
* decryption pads); it MUST be kept secret.
|
||||
*
|
||||
* Guaranteed to be 4205 bytes in size.
|
||||
*/
|
||||
typedef struct secp256k1_chilldkg_participant_inv_data {
|
||||
unsigned char data[12 + 32 + 33 + 32 + 32 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
} secp256k1_chilldkg_participant_inv_data;
|
||||
|
||||
/** Opaque data structure that holds the coordinator's session state after
|
||||
* secp256k1_chilldkg_coordinator_step1, to be passed to
|
||||
* secp256k1_chilldkg_coordinator_finalize (it must not be reused).
|
||||
@@ -261,6 +276,12 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_participant_st
|
||||
* fault_index: pointer to a uint32 that receives the identifier of
|
||||
* the (suspected) faulty participant where applicable,
|
||||
* and UINT32_MAX otherwise
|
||||
* inv_data: pointer to a participant_inv_data object that
|
||||
* receives the investigation data if (and only if) the
|
||||
* return value is
|
||||
* SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR,
|
||||
* or NULL if the caller does not intend to run
|
||||
* secp256k1_chilldkg_participant_investigate
|
||||
* 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
|
||||
@@ -276,11 +297,12 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_ch
|
||||
secp256k1_chilldkg_participant_state2 *state2,
|
||||
unsigned char *sig64,
|
||||
uint32_t *fault_index,
|
||||
secp256k1_chilldkg_participant_inv_data *inv_data,
|
||||
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);
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8) SECP256K1_ARG_NONNULL(9);
|
||||
|
||||
/** Perform a participant's final step of a ChillDKG session.
|
||||
*
|
||||
@@ -400,6 +422,252 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_ch
|
||||
const unsigned char *const *pmsgs2
|
||||
) 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);
|
||||
|
||||
/** Length of a coordinator investigation message (cinv): 65*n bytes (n
|
||||
* encrypted partial secret shares of 32 bytes each, followed by n partial
|
||||
* public shares of 33 bytes each). Returns 0 if n is out of range. */
|
||||
SECP256K1_API size_t secp256k1_chilldkg_investigation_msg_len(
|
||||
size_t n_participants
|
||||
);
|
||||
|
||||
/** Recover the DKG output of a participant from recovery data.
|
||||
*
|
||||
* This function serves two purposes: recovering from a failure of
|
||||
* secp256k1_chilldkg_participant_finalize after obtaining the recovery data
|
||||
* from another participant or the coordinator, and reproducing the DKG
|
||||
* outputs on a new device (e.g., after data loss).
|
||||
*
|
||||
* The recovery data (see secp256k1_chilldkg_recovery_data_len) is
|
||||
* self-delimiting: the number of participants n and the threshold t are
|
||||
* derived from its length and contents.
|
||||
*
|
||||
* Returns: SECP256K1_CHILLDKG_OK on success,
|
||||
* SECP256K1_CHILLDKG_INVALID_INPUT if the recovery data is invalid
|
||||
* (this includes an invalid certificate) or if the host secret key
|
||||
* is invalid or does not match any host public key in the recovery
|
||||
* data (RecoveryDataError and HostSeckeyError in the reference
|
||||
* implementation), or
|
||||
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR (with
|
||||
* fault_index set) if a pubnonce in the recovery data is invalid.
|
||||
* On failure, secshare32 and thresh_pk33 are set to zero and
|
||||
* *n_participants_out and *threshold_out are set to 0; pubshares33
|
||||
* and hostpubkeys33_out are set to zero whenever n could be
|
||||
* determined.
|
||||
* 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 capable of holding
|
||||
* 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
|
||||
* to store the public shares (33 bytes each; the
|
||||
* first n entries are filled)
|
||||
* hostpubkeys33_out: pointer to an array capable of holding
|
||||
* 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
|
||||
* to store the host public keys of the recovered
|
||||
* session (the first n entries are filled)
|
||||
* n_participants_out: pointer to a size_t to store the number of
|
||||
* participants n of the recovered session
|
||||
* threshold_out: pointer to a uint32 to store the threshold t
|
||||
* of the recovered session
|
||||
* fault_index: pointer to a uint32 that receives the identifier
|
||||
* of the suspected participant where applicable,
|
||||
* and UINT32_MAX otherwise
|
||||
* In: hostseckey32: pointer to the 32-byte host secret key
|
||||
* recovery: pointer to the recovery data
|
||||
* recovery_len: length of the recovery data
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_recover(
|
||||
const secp256k1_context *ctx,
|
||||
unsigned char *secshare32,
|
||||
unsigned char *thresh_pk33,
|
||||
unsigned char *pubshares33,
|
||||
unsigned char *hostpubkeys33_out,
|
||||
size_t *n_participants_out,
|
||||
uint32_t *threshold_out,
|
||||
uint32_t *fault_index,
|
||||
const unsigned char *hostseckey32,
|
||||
const unsigned char *recovery,
|
||||
size_t recovery_len
|
||||
) 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) SECP256K1_ARG_NONNULL(9) SECP256K1_ARG_NONNULL(10);
|
||||
|
||||
/** Recover the DKG output of the coordinator from recovery data.
|
||||
*
|
||||
* Like secp256k1_chilldkg_participant_recover, but for the coordinator, who
|
||||
* has no secret share.
|
||||
*
|
||||
* Returns: SECP256K1_CHILLDKG_OK on success,
|
||||
* SECP256K1_CHILLDKG_INVALID_INPUT if the recovery data is invalid.
|
||||
* On failure, thresh_pk33 is set to zero and *n_participants_out
|
||||
* and *threshold_out are set to 0; pubshares33 and
|
||||
* hostpubkeys33_out are set to zero whenever n could be determined.
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: thresh_pk33: pointer to a 33-byte array to store the
|
||||
* threshold public key (compressed serialization)
|
||||
* pubshares33: pointer to an array capable of holding
|
||||
* 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
|
||||
* to store the public shares (the first n
|
||||
* entries are filled)
|
||||
* hostpubkeys33_out: pointer to an array capable of holding
|
||||
* 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
|
||||
* to store the host public keys of the recovered
|
||||
* session (the first n entries are filled)
|
||||
* n_participants_out: pointer to a size_t to store n
|
||||
* threshold_out: pointer to a uint32 to store t
|
||||
* In: recovery: pointer to the recovery data
|
||||
* recovery_len: length of the recovery data
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_recover(
|
||||
const secp256k1_context *ctx,
|
||||
unsigned char *thresh_pk33,
|
||||
unsigned char *pubshares33,
|
||||
unsigned char *hostpubkeys33_out,
|
||||
size_t *n_participants_out,
|
||||
uint32_t *threshold_out,
|
||||
const unsigned char *recovery,
|
||||
size_t recovery_len
|
||||
) 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);
|
||||
|
||||
/** Sign recovery data to create a recovery acknowledgment.
|
||||
*
|
||||
* The acknowledgment signature (64 bytes) is a BIP 340 signature over
|
||||
* pad33("BIP DKG/recovery acknowledgment") || u32be(participant_id) ||
|
||||
* recovery_data under the participant's host key. Acks can be collected in
|
||||
* an optional acknowledgment round to confirm that all participants have
|
||||
* received the recovery data.
|
||||
*
|
||||
* 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 recovery data that is invalid or does not match
|
||||
* the session parameters). On failure, sig64 is set to zero.
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: sig64: pointer to a 64-byte array to store the
|
||||
* acknowledgment signature
|
||||
* In: hostseckey32: pointer to the 32-byte host secret key
|
||||
* hostpubkeys33: pointer to an array of n host public keys (33 bytes
|
||||
* each)
|
||||
* n_participants: total number of participants n
|
||||
* threshold: threshold t
|
||||
* recovery: pointer to the recovery data
|
||||
* recovery_len: length of the recovery data
|
||||
* aux_rand32: pointer to 32 bytes of auxiliary randomness (see
|
||||
* BIP 340)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_recovery_ack_sign(
|
||||
const secp256k1_context *ctx,
|
||||
unsigned char *sig64,
|
||||
const unsigned char *hostseckey32,
|
||||
const unsigned char *hostpubkeys33,
|
||||
size_t n_participants,
|
||||
uint32_t threshold,
|
||||
const unsigned char *recovery,
|
||||
size_t recovery_len,
|
||||
const unsigned char *aux_rand32
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(9);
|
||||
|
||||
/** Verify recovery acknowledgment signatures from all participants.
|
||||
*
|
||||
* Note that a failure of this function does NOT mean the DKG failed
|
||||
* (reaching this point implies the DKG itself was successful). It only means
|
||||
* it cannot be confirmed that all participants have a copy of the recovery
|
||||
* data.
|
||||
*
|
||||
* Returns: SECP256K1_CHILLDKG_OK if all n acknowledgment signatures are
|
||||
* valid, SECP256K1_CHILLDKG_INVALID_INPUT on invalid session
|
||||
* parameters or recovery data, or SECP256K1_CHILLDKG_FAULTY_PARTICIPANT
|
||||
* (with fault_index set to the signer) if an acknowledgment
|
||||
* signature is invalid (InvalidRecoveryAckError in the reference
|
||||
* implementation).
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: fault_index: pointer to a uint32 that receives the identifier of
|
||||
* the participant whose signature is invalid, where
|
||||
* applicable, and UINT32_MAX otherwise
|
||||
* In: hostpubkeys33: pointer to an array of n host public keys (33 bytes
|
||||
* each)
|
||||
* n_participants: total number of participants n
|
||||
* threshold: threshold t
|
||||
* recovery: pointer to the recovery data
|
||||
* recovery_len: length of the recovery data
|
||||
* ack_sigs64: array of n pointers to the acknowledgment
|
||||
* signatures (64 bytes each), in the same order as
|
||||
* hostpubkeys33
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_recovery_acks_verify(
|
||||
const secp256k1_context *ctx,
|
||||
uint32_t *fault_index,
|
||||
const unsigned char *hostpubkeys33,
|
||||
size_t n_participants,
|
||||
uint32_t threshold,
|
||||
const unsigned char *recovery,
|
||||
size_t recovery_len,
|
||||
const unsigned char *const *ack_sigs64
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(8);
|
||||
|
||||
/** Generate the investigation message for a single participant.
|
||||
*
|
||||
* The investigation message (65*n bytes, see
|
||||
* secp256k1_chilldkg_investigation_msg_len) allows the given participant to
|
||||
* investigate who is to blame for a failed ChillDKG session (see
|
||||
* secp256k1_chilldkg_participant_investigate). The message contains no
|
||||
* confidential information and can be safely broadcast. (Unlike the
|
||||
* reference implementation, which computes the investigation messages for
|
||||
* all participants at once, this function computes one message per call.)
|
||||
*
|
||||
* Returns: SECP256K1_CHILLDKG_OK on success,
|
||||
* SECP256K1_CHILLDKG_INVALID_INPUT on invalid session parameters or
|
||||
* participant_id >= n, or SECP256K1_CHILLDKG_FAULTY_PARTICIPANT
|
||||
* (with fault_index set to the sender) if a participant message is
|
||||
* malformed. On failure, cinv is set to zero.
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: cinv: pointer to a 65*n byte array to store the
|
||||
* investigation message for the given participant
|
||||
* fault_index: pointer to a uint32 (see above)
|
||||
* In: pmsgs1: array of n pointers to the participants' first
|
||||
* messages (33*t + 32*n + 97 bytes each)
|
||||
* hostpubkeys33: pointer to an array of n host public keys (33 bytes
|
||||
* each)
|
||||
* n_participants: total number of participants n
|
||||
* threshold: threshold t
|
||||
* participant_id: the participant the investigation message is for
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_investigate(
|
||||
const secp256k1_context *ctx,
|
||||
unsigned char *cinv,
|
||||
uint32_t *fault_index,
|
||||
const unsigned char *const *pmsgs1,
|
||||
const unsigned char *hostpubkeys33,
|
||||
size_t n_participants,
|
||||
uint32_t threshold,
|
||||
uint32_t participant_id
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
|
||||
|
||||
/** Investigate who is to blame for a failed ChillDKG session.
|
||||
*
|
||||
* This function can be called when secp256k1_chilldkg_participant_step2
|
||||
* returned SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR. It
|
||||
* narrows down the suspected faulty parties by analyzing the investigation
|
||||
* message provided by the coordinator.
|
||||
*
|
||||
* Returns: SECP256K1_CHILLDKG_FAULTY_COORDINATOR if the coordinator is
|
||||
* faulty, SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR
|
||||
* (with fault_index set to the suspected participant) if another
|
||||
* participant or the coordinator is faulty, or
|
||||
* SECP256K1_CHILLDKG_INVALID_INPUT if all inputs are consistent
|
||||
* (i.e., the function was called even though no fault occurred).
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: fault_index: pointer to a uint32 (see above)
|
||||
* In: inv_data: pointer to the participant_inv_data object output by
|
||||
* secp256k1_chilldkg_participant_step2
|
||||
* cinv: pointer to the coordinator's investigation message
|
||||
* for this participant (65*n bytes, see
|
||||
* secp256k1_chilldkg_investigation_msg_len)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_investigate(
|
||||
const secp256k1_context *ctx,
|
||||
uint32_t *fault_index,
|
||||
const secp256k1_chilldkg_participant_inv_data *inv_data,
|
||||
const unsigned char *cinv
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,16 @@ typedef struct {
|
||||
* public keys) or on negligible-probability derivation failures. */
|
||||
static int secp256k1_chilldkg_encpedpop_participant_step1(const secp256k1_context *ctx, secp256k1_chilldkg_encpedpop_participant_state *state, unsigned char *pmsg, const unsigned char *seed32, const unsigned char *deckey32, const unsigned char *enckeys33, uint32_t t, uint32_t participant_id, const unsigned char *random32, size_t n);
|
||||
|
||||
/* Investigation data captured when participant_step2 fails with
|
||||
* SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR
|
||||
* (encpedpop.py ParticipantInvestigationData). Contains secrets (the
|
||||
* untweaked secshare and the pads); clear after use. */
|
||||
typedef struct {
|
||||
secp256k1_chilldkg_simplpedpop_participant_inv_data simpl;
|
||||
secp256k1_scalar enc_secshare;
|
||||
secp256k1_scalar pads[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
} secp256k1_chilldkg_encpedpop_participant_inv_data;
|
||||
|
||||
/* Participant step 2 (encpedpop.py participant_step2): verify that the
|
||||
* coordinator echoed our pubnonce, decrypt our secshare from the summed
|
||||
* encrypted secshare, and run SimplPedPop participant_step2. Outputs the DKG
|
||||
@@ -106,8 +116,22 @@ static int secp256k1_chilldkg_encpedpop_participant_step1(const secp256k1_contex
|
||||
* 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
|
||||
* UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR if the decrypted secshare does
|
||||
* not match the pubshare. */
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, const secp256k1_chilldkg_encpedpop_participant_state *state, const unsigned char *deckey32, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *enc_secshare);
|
||||
* not match the pubshare; in the latter case, and only in that case, inv_data
|
||||
* (if not NULL) is filled for
|
||||
* secp256k1_chilldkg_encpedpop_participant_investigate. */
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, secp256k1_chilldkg_encpedpop_participant_inv_data *inv_data, const secp256k1_chilldkg_encpedpop_participant_state *state, const unsigned char *deckey32, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *enc_secshare);
|
||||
|
||||
/* Determine the faulty party after an
|
||||
* UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR fault of participant_step2
|
||||
* (encpedpop.py participant_investigate). cinv is the coordinator's
|
||||
* investigation message for this participant (65*n bytes: n encrypted partial
|
||||
* secshares || n partial pubshares). Returns FAULTY_COORDINATOR if the
|
||||
* investigation message is malformed or if the coordinator is to blame,
|
||||
* FAULTY_PARTICIPANT_OR_COORDINATOR(i) (with *fault_index = i) if participant
|
||||
* i is to blame, and SECP256K1_CHILLDKG_INVALID_INPUT if all inputs are
|
||||
* consistent (i.e., the function was called even though no fault occurred;
|
||||
* the reference raises a RuntimeError in this case). */
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_investigate(const secp256k1_context *ctx, uint32_t *fault_index, const secp256k1_chilldkg_encpedpop_participant_inv_data *inv_data, const unsigned char *cinv, size_t cinv_len);
|
||||
|
||||
/* Coordinator step (encpedpop.py coordinator_step): parse the n participant
|
||||
* messages (each 33*t + 64 + 33 + 32*n bytes), aggregate SimplPedPop, and sum
|
||||
|
||||
@@ -240,7 +240,7 @@ static int secp256k1_chilldkg_encpedpop_participant_step1(const secp256k1_contex
|
||||
return ret;
|
||||
}
|
||||
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, const secp256k1_chilldkg_encpedpop_participant_state *state, const unsigned char *deckey32, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *enc_secshare) {
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, secp256k1_chilldkg_encpedpop_participant_inv_data *inv_data, const secp256k1_chilldkg_encpedpop_participant_state *state, const unsigned char *deckey32, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *enc_secshare) {
|
||||
const uint32_t t = state->simpl_state.t;
|
||||
const uint32_t n = state->simpl_state.n;
|
||||
const uint32_t participant_id = state->simpl_state.participant_id;
|
||||
@@ -290,7 +290,17 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(c
|
||||
secp256k1_scalar_negate(&secshare, &padsum);
|
||||
secp256k1_scalar_add(&secshare, &secshare, enc_secshare);
|
||||
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(ctx, dkg_output, eq_input, fault_index, &state->simpl_state, cmsg, simpl_cmsg_len, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(ctx, dkg_output, eq_input, fault_index, inv_data != NULL ? &inv_data->simpl : NULL, &state->simpl_state, cmsg, simpl_cmsg_len, &secshare);
|
||||
|
||||
/* On an UNKNOWN fault, capture the encrypted secshare and the pads so
|
||||
* that the investigation procedure can decrypt the partial secshares
|
||||
* (inv_data->simpl was filled by the SimplPedPop participant_step2). */
|
||||
if (fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR && inv_data != NULL) {
|
||||
inv_data->enc_secshare = *enc_secshare;
|
||||
for (i = 0; i < n; i++) {
|
||||
inv_data->pads[i] = pads[i];
|
||||
}
|
||||
}
|
||||
|
||||
secp256k1_scalar_clear(&secshare);
|
||||
secp256k1_scalar_clear(&padsum);
|
||||
@@ -375,4 +385,59 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_coordinator_step(co
|
||||
return SECP256K1_CHILLDKG_OK;
|
||||
}
|
||||
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_investigate(const secp256k1_context *ctx, uint32_t *fault_index, const secp256k1_chilldkg_encpedpop_participant_inv_data *inv_data, const unsigned char *cinv, size_t cinv_len) {
|
||||
const uint32_t n = inv_data->simpl.n;
|
||||
secp256k1_ge partial_pubshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_scalar enc_partial_secshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_scalar partial_secshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_chilldkg_fault fault;
|
||||
uint32_t i;
|
||||
int overflow;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
ARG_CHECK(fault_index != NULL);
|
||||
ARG_CHECK(inv_data != NULL);
|
||||
ARG_CHECK(cinv != NULL);
|
||||
/* inv_data was written by participant_step2. */
|
||||
VERIFY_CHECK(n >= 1 && n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
||||
|
||||
/* CoordinatorInvestigationMsg.from_bytes: enc_partial_secshares (32*n) ||
|
||||
* partial_pubshares (33*n). Parse errors blame the coordinator
|
||||
* (MsgParseError -> FaultyCoordinatorError in the reference). */
|
||||
if (cinv_len != 65 * (size_t)n) {
|
||||
return SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar_set_b32(&enc_partial_secshares[i], cinv + 32 * i, &overflow);
|
||||
if (overflow) {
|
||||
fault = SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!secp256k1_chilldkg_point_load(&partial_pubshares[i], cinv + 32 * n + 33 * i)) {
|
||||
fault = SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrypt the partial secshares addressed to us. */
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar pad_neg;
|
||||
secp256k1_scalar_negate(&pad_neg, &inv_data->pads[i]);
|
||||
secp256k1_scalar_add(&partial_secshares[i], &enc_partial_secshares[i], &pad_neg);
|
||||
secp256k1_scalar_clear(&pad_neg);
|
||||
}
|
||||
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_investigate(ctx, fault_index, &inv_data->simpl, partial_pubshares, partial_secshares);
|
||||
|
||||
cleanup:
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar_clear(&enc_partial_secshares[i]);
|
||||
secp256k1_scalar_clear(&partial_secshares[i]);
|
||||
}
|
||||
return fault;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -58,6 +58,70 @@ static int secp256k1_chilldkg_params_validate(const unsigned char *hostpubkeys33
|
||||
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 };
|
||||
static const unsigned char secp256k1_chilldkg_coordinator_state_magic[4] = { 0x1b, 0x8e, 0x63, 0xa7 };
|
||||
static const unsigned char secp256k1_chilldkg_participant_inv_data_magic[4] = { 0x62, 0x4a, 0xc5, 0x90 };
|
||||
|
||||
/* An inv_data object consists of
|
||||
* - 4 byte magic
|
||||
* - 4 byte participant count n, 4 byte participant_id (big-endian)
|
||||
* - 32 byte untweaked secshare
|
||||
* - 33 byte untweaked pubshare (compressed encoding with infinity)
|
||||
* - 32 byte encrypted secshare
|
||||
* - 32*SECP256K1_CHILLDKG_MAX_PARTICIPANTS byte pads (only the first n
|
||||
* entries are meaningful)
|
||||
* The inv data contains secrets (the untweaked secshare and the pads). */
|
||||
static void secp256k1_chilldkg_participant_inv_data_save(secp256k1_chilldkg_participant_inv_data *inv_data, const secp256k1_chilldkg_encpedpop_participant_inv_data *inv_data_i) {
|
||||
unsigned char *ptr = inv_data->data;
|
||||
size_t i;
|
||||
|
||||
memcpy(ptr, secp256k1_chilldkg_participant_inv_data_magic, 4);
|
||||
ptr += 4;
|
||||
secp256k1_write_be32(ptr, inv_data_i->simpl.n);
|
||||
ptr += 4;
|
||||
secp256k1_write_be32(ptr, inv_data_i->simpl.participant_id);
|
||||
ptr += 4;
|
||||
secp256k1_scalar_get_b32(ptr, &inv_data_i->simpl.secshare);
|
||||
ptr += 32;
|
||||
secp256k1_chilldkg_point_save(ptr, &inv_data_i->simpl.pubshare);
|
||||
ptr += 33;
|
||||
secp256k1_scalar_get_b32(ptr, &inv_data_i->enc_secshare);
|
||||
ptr += 32;
|
||||
for (i = 0; i < SECP256K1_CHILLDKG_MAX_PARTICIPANTS; i++) {
|
||||
secp256k1_scalar_get_b32(ptr + 32 * i, &inv_data_i->pads[i]);
|
||||
}
|
||||
ptr += 32 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS;
|
||||
VERIFY_CHECK(ptr == inv_data->data + sizeof(inv_data->data));
|
||||
}
|
||||
|
||||
static int secp256k1_chilldkg_participant_inv_data_load(const secp256k1_context *ctx, secp256k1_chilldkg_encpedpop_participant_inv_data *inv_data_i, const secp256k1_chilldkg_participant_inv_data *inv_data) {
|
||||
const unsigned char *ptr = inv_data->data;
|
||||
size_t i;
|
||||
|
||||
ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_chilldkg_participant_inv_data_magic, 4) == 0);
|
||||
ptr += 4;
|
||||
inv_data_i->simpl.n = secp256k1_read_be32(ptr);
|
||||
ptr += 4;
|
||||
inv_data_i->simpl.participant_id = secp256k1_read_be32(ptr);
|
||||
ptr += 4;
|
||||
/* The remaining contents were written by inv_data_save. */
|
||||
VERIFY_CHECK(inv_data_i->simpl.n >= 1
|
||||
&& inv_data_i->simpl.n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS
|
||||
&& inv_data_i->simpl.participant_id < inv_data_i->simpl.n);
|
||||
secp256k1_scalar_set_b32(&inv_data_i->simpl.secshare, ptr, NULL);
|
||||
ptr += 32;
|
||||
/* 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(&inv_data_i->simpl.pubshare, ptr)) {
|
||||
VERIFY_CHECK(0);
|
||||
secp256k1_ge_set_infinity(&inv_data_i->simpl.pubshare);
|
||||
}
|
||||
ptr += 33;
|
||||
secp256k1_scalar_set_b32(&inv_data_i->enc_secshare, ptr, NULL);
|
||||
ptr += 32;
|
||||
for (i = 0; i < SECP256K1_CHILLDKG_MAX_PARTICIPANTS; i++) {
|
||||
secp256k1_scalar_set_b32(&inv_data_i->pads[i], ptr + 32 * i, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A state1 object consists of
|
||||
* - 4 byte magic set during initialization to allow detecting an
|
||||
@@ -304,8 +368,9 @@ int secp256k1_chilldkg_participant_step1(const secp256k1_context *ctx, secp256k1
|
||||
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_fault secp256k1_chilldkg_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_participant_state2 *state2, unsigned char *sig64, uint32_t *fault_index, secp256k1_chilldkg_participant_inv_data *inv_data, 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_encpedpop_participant_inv_data inv_data_i;
|
||||
secp256k1_chilldkg_participant_state2_internal state2i;
|
||||
unsigned char hostpubkey33[33];
|
||||
secp256k1_scalar enc_secshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
@@ -326,9 +391,13 @@ secp256k1_chilldkg_fault secp256k1_chilldkg_participant_step2(const secp256k1_co
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(aux_rand32 != NULL);
|
||||
|
||||
memset(&state2i, 0, sizeof(state2i));
|
||||
memset(&inv_data_i, 0, sizeof(inv_data_i));
|
||||
memset(state2->data, 0, sizeof(state2->data));
|
||||
memset(sig64, 0, 64);
|
||||
*fault_index = UINT32_MAX;
|
||||
if (inv_data != NULL) {
|
||||
memset(inv_data->data, 0, sizeof(inv_data->data));
|
||||
}
|
||||
|
||||
if (!secp256k1_chilldkg_participant_state1_load(ctx, &enc_state, state1)) {
|
||||
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||
@@ -358,8 +427,11 @@ secp256k1_chilldkg_fault secp256k1_chilldkg_participant_step2(const secp256k1_co
|
||||
}
|
||||
|
||||
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]);
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(ctx, &state2i.dkg_output, state2i.eq_input, fault_index, inv_data != NULL ? &inv_data_i : NULL, &enc_state, hostseckey32, cmsg1, enc_cmsg_len, &enc_secshares[participant_id]);
|
||||
if (fault != SECP256K1_CHILLDKG_OK) {
|
||||
if (fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR && inv_data != NULL) {
|
||||
secp256k1_chilldkg_participant_inv_data_save(inv_data, &inv_data_i);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -386,8 +458,9 @@ cleanup:
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar_clear(&enc_secshares[i]);
|
||||
}
|
||||
/* state2i contains the secret share. */
|
||||
/* state2i and inv_data_i contain the secret share / decryption pads. */
|
||||
secp256k1_memclear_explicit(&state2i, sizeof(state2i));
|
||||
secp256k1_memclear_explicit(&inv_data_i, sizeof(inv_data_i));
|
||||
return fault;
|
||||
}
|
||||
|
||||
@@ -614,4 +687,406 @@ secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_finalize(const secp256k1
|
||||
return SECP256K1_CHILLDKG_OK;
|
||||
}
|
||||
|
||||
size_t secp256k1_chilldkg_investigation_msg_len(size_t n_participants) {
|
||||
if (n_participants < 1 || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) {
|
||||
return 0;
|
||||
}
|
||||
return 65 * n_participants;
|
||||
}
|
||||
|
||||
/* Parse the self-delimiting recovery data (deserialize_recovery_data in
|
||||
* chilldkg_ref/chilldkg.py):
|
||||
* u32be(t) || sum_coms (33*t) || hostpubkeys (33*n) || pubnonces (33*n) ||
|
||||
* enc_secshares (32*n) || cert (64*n)
|
||||
* where n = (recovery_len - 4 - 33*t) / 162. sum_coms may contain the point
|
||||
* at infinity; the enc_secshares are parsed checked. The hostpubkeys33,
|
||||
* pubnonces33 and cert outputs point into the recovery buffer. Returns 1 on
|
||||
* success and 0 on invalid recovery data (RecoveryDataError in the
|
||||
* reference). */
|
||||
static int secp256k1_chilldkg_deserialize_recovery_data(uint32_t *t_out, size_t *n_out, secp256k1_ge *sum_coms, secp256k1_scalar *enc_secshares, const unsigned char **hostpubkeys33, const unsigned char **pubnonces33, const unsigned char **cert, const unsigned char *recovery, size_t recovery_len) {
|
||||
size_t t, n, rest_len, i;
|
||||
const unsigned char *ptr;
|
||||
int overflow;
|
||||
|
||||
if (recovery_len < 4) {
|
||||
return 0;
|
||||
}
|
||||
t = secp256k1_read_be32(recovery);
|
||||
rest_len = recovery_len - 4;
|
||||
if (rest_len < 33 * t || (rest_len - 33 * t) % 162 != 0) {
|
||||
return 0;
|
||||
}
|
||||
n = (rest_len - 33 * t) / 162;
|
||||
if (n > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) {
|
||||
return 0;
|
||||
}
|
||||
ptr = recovery + 4;
|
||||
for (i = 0; i < t; i++) {
|
||||
if (!secp256k1_chilldkg_point_load(&sum_coms[i], ptr + 33 * i)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ptr += 33 * t;
|
||||
*hostpubkeys33 = ptr;
|
||||
ptr += 33 * n;
|
||||
*pubnonces33 = ptr;
|
||||
ptr += 33 * n;
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar_set_b32(&enc_secshares[i], ptr + 32 * i, &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ptr += 32 * n;
|
||||
*cert = ptr;
|
||||
*t_out = (uint32_t)t;
|
||||
*n_out = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Shared implementation of participant_recover and coordinator_recover
|
||||
* (recover in chilldkg_ref/chilldkg.py). hostseckey32 is NULL for the
|
||||
* coordinator. secshare32 is NULL for the coordinator. */
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_recover(const secp256k1_context *ctx, unsigned char *secshare32, unsigned char *thresh_pk33, unsigned char *pubshares33, unsigned char *hostpubkeys33_out, size_t *n_participants_out, uint32_t *threshold_out, uint32_t *fault_index, const unsigned char *hostseckey32, const unsigned char *recovery, size_t recovery_len) {
|
||||
secp256k1_ge sum_coms[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_ge sum_coms_tweaked[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_ge pubtweak;
|
||||
secp256k1_ge pubshare;
|
||||
secp256k1_gej pubsharej;
|
||||
secp256k1_scalar enc_secshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_scalar tweak;
|
||||
secp256k1_scalar secshare;
|
||||
unsigned char enc_context[4 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
unsigned char hostpubkey33[33];
|
||||
const unsigned char *hostpubkeys33 = NULL;
|
||||
const unsigned char *pubnonces33 = NULL;
|
||||
const unsigned char *cert = NULL;
|
||||
secp256k1_chilldkg_fault fault = SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||
uint32_t participant_id = 0;
|
||||
uint32_t t = 0;
|
||||
size_t n = 0;
|
||||
size_t i;
|
||||
int found = 0;
|
||||
|
||||
if (secshare32 != NULL) {
|
||||
memset(secshare32, 0, 32);
|
||||
}
|
||||
memset(thresh_pk33, 0, 33);
|
||||
*n_participants_out = 0;
|
||||
*threshold_out = 0;
|
||||
if (fault_index != NULL) {
|
||||
*fault_index = UINT32_MAX;
|
||||
}
|
||||
|
||||
/* Deserialize; invalid recovery data is a RecoveryDataError in the
|
||||
* reference. */
|
||||
if (!secp256k1_chilldkg_deserialize_recovery_data(&t, &n, sum_coms, enc_secshares, &hostpubkeys33, &pubnonces33, &cert, recovery, recovery_len)) {
|
||||
goto cleanup;
|
||||
}
|
||||
/* params_validate; invalid session parameters in the recovery data are a
|
||||
* RecoveryDataError in the reference. */
|
||||
if (!secp256k1_chilldkg_params_validate(hostpubkeys33, n, t)) {
|
||||
goto cleanup;
|
||||
}
|
||||
memset(pubshares33, 0, 33 * n);
|
||||
memset(hostpubkeys33_out, 0, 33 * n);
|
||||
|
||||
/* Verify the certificate over eq_input (the recovery data without the
|
||||
* cert). An invalid certificate is a RecoveryDataError in the reference
|
||||
* (the index of the invalid signature is not reported there). */
|
||||
if (!secp256k1_chilldkg_certeq_verify(ctx, hostpubkeys33, n, recovery, recovery_len - 64 * n, cert, fault_index)) {
|
||||
if (fault_index != NULL) {
|
||||
*fault_index = UINT32_MAX;
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* HostSeckeyError if the host secret key is invalid or does not match any
|
||||
* host public key in the recovery data. */
|
||||
if (hostseckey32 != NULL) {
|
||||
if (!secp256k1_chilldkg_hostpubkey_gen(ctx, hostpubkey33, hostseckey32)) {
|
||||
goto cleanup;
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
if (secp256k1_memcmp_var(hostpubkeys33 + 33 * i, hostpubkey33, 33) == 0) {
|
||||
participant_id = (uint32_t)i;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Recompute the tweaked threshold public key and pubshares. A failure of
|
||||
* invalid_taproot_commit (infinity commitment to the secret, or tweak
|
||||
* hash overflow) is not caught by the reference (it would raise a
|
||||
* non-protocol error); report it as invalid recovery data. */
|
||||
if (!secp256k1_chilldkg_vss_invalid_taproot_commit(ctx, sum_coms_tweaked, &tweak, &pubtweak, sum_coms, t)) {
|
||||
goto cleanup;
|
||||
}
|
||||
secp256k1_chilldkg_point_save(thresh_pk33, &sum_coms_tweaked[0]);
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_chilldkg_vss_pubshare(&pubsharej, sum_coms_tweaked, t, (uint32_t)i);
|
||||
secp256k1_ge_set_gej_var(&pubshare, &pubsharej);
|
||||
secp256k1_chilldkg_point_save(pubshares33 + 33 * i, &pubshare);
|
||||
}
|
||||
memcpy(hostpubkeys33_out, hostpubkeys33, 33 * n);
|
||||
*n_participants_out = n;
|
||||
*threshold_out = t;
|
||||
|
||||
if (hostseckey32 != NULL) {
|
||||
/* Decrypt our secshare and apply the tweak. */
|
||||
secp256k1_chilldkg_encpedpop_serialize_enc_context(enc_context, t, hostpubkeys33, n);
|
||||
fault = secp256k1_chilldkg_encpedpop_decrypt_sum(ctx, &secshare, fault_index, hostseckey32, hostpubkeys33 + 33 * participant_id, pubnonces33, enc_context, 4 + 33 * n, participant_id, &enc_secshares[participant_id], n);
|
||||
if (fault != SECP256K1_CHILLDKG_OK) {
|
||||
memset(thresh_pk33, 0, 33);
|
||||
memset(pubshares33, 0, 33 * n);
|
||||
memset(hostpubkeys33_out, 0, 33 * n);
|
||||
*n_participants_out = 0;
|
||||
*threshold_out = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
secp256k1_scalar_add(&secshare, &secshare, &tweak);
|
||||
/* This is just a sanity check (assert in the reference): the cert is
|
||||
* valid, so an equivalent check was done during the actual session. */
|
||||
if (!secp256k1_chilldkg_point_load(&pubshare, pubshares33 + 33 * participant_id)) {
|
||||
VERIFY_CHECK(0);
|
||||
}
|
||||
if (!secp256k1_chilldkg_vss_verify_secshare(ctx, &secshare, &pubshare)) {
|
||||
VERIFY_CHECK(0);
|
||||
}
|
||||
secp256k1_scalar_get_b32(secshare32, &secshare);
|
||||
}
|
||||
fault = SECP256K1_CHILLDKG_OK;
|
||||
|
||||
cleanup:
|
||||
secp256k1_scalar_clear(&tweak);
|
||||
secp256k1_scalar_clear(&secshare);
|
||||
for (i = 0; i < SECP256K1_CHILLDKG_MAX_PARTICIPANTS; i++) {
|
||||
secp256k1_scalar_clear(&enc_secshares[i]);
|
||||
}
|
||||
return fault;
|
||||
}
|
||||
|
||||
secp256k1_chilldkg_fault secp256k1_chilldkg_participant_recover(const secp256k1_context *ctx, unsigned char *secshare32, unsigned char *thresh_pk33, unsigned char *pubshares33, unsigned char *hostpubkeys33_out, size_t *n_participants_out, uint32_t *threshold_out, uint32_t *fault_index, const unsigned char *hostseckey32, const unsigned char *recovery, size_t recovery_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(hostpubkeys33_out != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(n_participants_out != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(threshold_out != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(hostseckey32 != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(recovery != NULL);
|
||||
|
||||
return secp256k1_chilldkg_recover(ctx, secshare32, thresh_pk33, pubshares33, hostpubkeys33_out, n_participants_out, threshold_out, fault_index, hostseckey32, recovery, recovery_len);
|
||||
}
|
||||
|
||||
secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_recover(const secp256k1_context *ctx, unsigned char *thresh_pk33, unsigned char *pubshares33, unsigned char *hostpubkeys33_out, size_t *n_participants_out, uint32_t *threshold_out, const unsigned char *recovery, size_t recovery_len) {
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(thresh_pk33 != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(pubshares33 != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(hostpubkeys33_out != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(n_participants_out != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(threshold_out != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(recovery != NULL);
|
||||
|
||||
return secp256k1_chilldkg_recover(ctx, NULL, thresh_pk33, pubshares33, hostpubkeys33_out, n_participants_out, threshold_out, NULL, NULL, recovery, recovery_len);
|
||||
}
|
||||
|
||||
/* recovery_ack_message: pad33("BIP DKG/recovery acknowledgment") ||
|
||||
* u32be(participant_id) || recovery_data. msg must hold 37 + recovery_len
|
||||
* bytes. */
|
||||
static void secp256k1_chilldkg_recovery_ack_message(unsigned char *msg, const unsigned char *recovery, size_t recovery_len, uint32_t participant_id) {
|
||||
secp256k1_chilldkg_pad33(msg, "BIP DKG/recovery acknowledgment");
|
||||
secp256k1_write_be32(msg + 33, participant_id);
|
||||
memcpy(msg + 37, recovery, recovery_len);
|
||||
}
|
||||
|
||||
/* The maximum length of recovery data: 4 + 33*t + 162*n with t, n <=
|
||||
* SECP256K1_CHILLDKG_MAX_PARTICIPANTS. */
|
||||
#define SECP256K1_CHILLDKG_MAX_RECOVERY_LEN (4 + 195 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS)
|
||||
|
||||
/* Check that the recovery data parses and matches the given session
|
||||
* parameters (part of participant_recovery_ack_sign and
|
||||
* participant_recovery_acks_verify in the reference). Returns 1 on match, 0
|
||||
* otherwise. */
|
||||
static int secp256k1_chilldkg_recovery_matches_params(const unsigned char *recovery, size_t recovery_len, const unsigned char *hostpubkeys33, size_t n, uint32_t t) {
|
||||
secp256k1_ge sum_coms[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_scalar enc_secshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
const unsigned char *hostpubkeys33_rec = NULL;
|
||||
const unsigned char *pubnonces33 = NULL;
|
||||
const unsigned char *cert = NULL;
|
||||
uint32_t t_rec = 0;
|
||||
size_t n_rec = 0;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
ret = secp256k1_chilldkg_deserialize_recovery_data(&t_rec, &n_rec, sum_coms, enc_secshares, &hostpubkeys33_rec, &pubnonces33, &cert, recovery, recovery_len)
|
||||
&& t_rec == t
|
||||
&& n_rec == n
|
||||
&& secp256k1_memcmp_var(hostpubkeys33_rec, hostpubkeys33, 33 * n) == 0;
|
||||
for (i = 0; i < SECP256K1_CHILLDKG_MAX_PARTICIPANTS; i++) {
|
||||
secp256k1_scalar_clear(&enc_secshares[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_chilldkg_recovery_ack_sign(const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *hostseckey32, const unsigned char *hostpubkeys33, size_t n_participants, uint32_t threshold, const unsigned char *recovery, size_t recovery_len, const unsigned char *aux_rand32) {
|
||||
unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_RECOVERY_LEN];
|
||||
unsigned char hostpubkey33[33];
|
||||
uint32_t participant_id = 0;
|
||||
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(sig64 != NULL);
|
||||
ARG_CHECK(hostseckey32 != NULL);
|
||||
ARG_CHECK(hostpubkeys33 != NULL);
|
||||
ARG_CHECK(recovery != NULL);
|
||||
ARG_CHECK(aux_rand32 != NULL);
|
||||
|
||||
memset(sig64, 0, 64);
|
||||
if (recovery_len > SECP256K1_CHILLDKG_MAX_RECOVERY_LEN) {
|
||||
return 0;
|
||||
}
|
||||
if (secp256k1_chilldkg_params_validate(hostpubkeys33, n_participants, threshold)
|
||||
&& secp256k1_chilldkg_hostpubkey_gen(ctx, hostpubkey33, hostseckey32)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* RecoveryDataError if the recovery data is invalid or does not match
|
||||
* the provided session parameters. */
|
||||
if (found && secp256k1_chilldkg_recovery_matches_params(recovery, recovery_len, hostpubkeys33, n_participants, threshold)) {
|
||||
secp256k1_chilldkg_recovery_ack_message(msg, recovery, recovery_len, participant_id);
|
||||
ret = secp256k1_chilldkg_schnorrsig_sign(ctx, sig64, msg, 37 + recovery_len, hostseckey32, aux_rand32, "BIP0340");
|
||||
}
|
||||
}
|
||||
secp256k1_memclear_explicit(msg, sizeof(msg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
secp256k1_chilldkg_fault secp256k1_chilldkg_recovery_acks_verify(const secp256k1_context *ctx, uint32_t *fault_index, const unsigned char *hostpubkeys33, size_t n_participants, uint32_t threshold, const unsigned char *recovery, size_t recovery_len, const unsigned char *const *ack_sigs64) {
|
||||
unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_RECOVERY_LEN];
|
||||
size_t i;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(hostpubkeys33 != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(recovery != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(ack_sigs64 != NULL);
|
||||
|
||||
*fault_index = UINT32_MAX;
|
||||
if (recovery_len > SECP256K1_CHILLDKG_MAX_RECOVERY_LEN
|
||||
|| !secp256k1_chilldkg_params_validate(hostpubkeys33, n_participants, threshold)
|
||||
|| !secp256k1_chilldkg_recovery_matches_params(recovery, recovery_len, hostpubkeys33, n_participants, threshold)) {
|
||||
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_participants; i++) {
|
||||
secp256k1_chilldkg_recovery_ack_message(msg, recovery, recovery_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, ack_sigs64[i], msg, 37 + recovery_len, hostpubkeys33 + 33 * i + 1, "BIP0340")) {
|
||||
/* InvalidRecoveryAckError(i) in the reference (a
|
||||
* FaultyParticipantError). */
|
||||
*fault_index = (uint32_t)i;
|
||||
return SECP256K1_CHILLDKG_FAULTY_PARTICIPANT;
|
||||
}
|
||||
}
|
||||
return SECP256K1_CHILLDKG_OK;
|
||||
}
|
||||
|
||||
secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_investigate(const secp256k1_context *ctx, unsigned char *cinv, uint32_t *fault_index, const unsigned char *const *pmsgs1, const unsigned char *hostpubkeys33, size_t n_participants, uint32_t threshold, uint32_t participant_id) {
|
||||
secp256k1_ge com[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||
secp256k1_ge pubshare;
|
||||
secp256k1_gej pubsharej;
|
||||
secp256k1_scalar share;
|
||||
size_t cinv_len;
|
||||
size_t i;
|
||||
size_t j;
|
||||
int overflow;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(cinv != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(pmsgs1 != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(hostpubkeys33 != NULL);
|
||||
|
||||
*fault_index = UINT32_MAX;
|
||||
cinv_len = secp256k1_chilldkg_investigation_msg_len(n_participants);
|
||||
if (!secp256k1_chilldkg_params_validate(hostpubkeys33, n_participants, threshold)
|
||||
|| participant_id >= n_participants) {
|
||||
if (cinv_len > 0) {
|
||||
memset(cinv, 0, cinv_len);
|
||||
}
|
||||
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||
}
|
||||
memset(cinv, 0, cinv_len);
|
||||
|
||||
/* For the given participant, collect the encrypted partial secshare and
|
||||
* the partial pubshare of every dealer. Every participant message is
|
||||
* parsed fully (ParticipantMsg1.from_bytes in the reference); a malformed
|
||||
* message blames its sender. The pubnonces are not parsed (they are plain
|
||||
* byte strings in the reference). */
|
||||
for (j = 0; j < n_participants; j++) {
|
||||
const unsigned char *pmsg1 = pmsgs1[j];
|
||||
for (i = 0; i < threshold; i++) {
|
||||
if (!secp256k1_chilldkg_point_load(&com[i], pmsg1 + 33 * i)) {
|
||||
*fault_index = (uint32_t)j;
|
||||
return SECP256K1_CHILLDKG_FAULTY_PARTICIPANT;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n_participants; i++) {
|
||||
secp256k1_scalar_set_b32(&share, pmsg1 + 33 * threshold + 97 + 32 * i, &overflow);
|
||||
if (overflow) {
|
||||
secp256k1_scalar_clear(&share);
|
||||
*fault_index = (uint32_t)j;
|
||||
return SECP256K1_CHILLDKG_FAULTY_PARTICIPANT;
|
||||
}
|
||||
if (i == participant_id) {
|
||||
secp256k1_scalar_get_b32(cinv + 32 * j, &share);
|
||||
}
|
||||
}
|
||||
secp256k1_scalar_clear(&share);
|
||||
secp256k1_chilldkg_vss_pubshare(&pubsharej, com, threshold, participant_id);
|
||||
secp256k1_ge_set_gej_var(&pubshare, &pubsharej);
|
||||
secp256k1_chilldkg_point_save(cinv + 32 * n_participants + 33 * j, &pubshare);
|
||||
}
|
||||
return SECP256K1_CHILLDKG_OK;
|
||||
}
|
||||
|
||||
secp256k1_chilldkg_fault secp256k1_chilldkg_participant_investigate(const secp256k1_context *ctx, uint32_t *fault_index, const secp256k1_chilldkg_participant_inv_data *inv_data, const unsigned char *cinv) {
|
||||
secp256k1_chilldkg_encpedpop_participant_inv_data inv_data_i;
|
||||
secp256k1_chilldkg_fault fault;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(inv_data != NULL);
|
||||
SECP256K1_CHILLDKG_ARG_CHECK(cinv != NULL);
|
||||
|
||||
*fault_index = UINT32_MAX;
|
||||
if (!secp256k1_chilldkg_participant_inv_data_load(ctx, &inv_data_i, inv_data)) {
|
||||
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||
}
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_investigate(ctx, fault_index, &inv_data_i, cinv, 65 * (size_t)inv_data_i.simpl.n);
|
||||
/* inv_data_i contains the untweaked secshare and the pads. */
|
||||
secp256k1_memclear_explicit(&inv_data_i, sizeof(inv_data_i));
|
||||
return fault;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -78,6 +78,17 @@ static int secp256k1_chilldkg_simplpedpop_participant_step1(const secp256k1_cont
|
||||
* (simplpedpop.py participant_step2_prepare_secshare). */
|
||||
static void secp256k1_chilldkg_simplpedpop_participant_step2_prepare_secshare(secp256k1_scalar *out, const secp256k1_scalar *partial_secshares, size_t n);
|
||||
|
||||
/* Investigation data captured when participant_step2 fails with
|
||||
* SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR
|
||||
* (simplpedpop.py ParticipantInvestigationData). Contains secrets (the
|
||||
* untweaked secshare); clear after use. */
|
||||
typedef struct {
|
||||
uint32_t n;
|
||||
uint32_t participant_id;
|
||||
secp256k1_scalar secshare; /* untweaked */
|
||||
secp256k1_ge pubshare; /* untweaked */
|
||||
} secp256k1_chilldkg_simplpedpop_participant_inv_data;
|
||||
|
||||
/* Participant step 2 (simplpedpop.py participant_step2): verify the
|
||||
* coordinator message, i.e., check that our own commitment to the secret was
|
||||
* echoed correctly, verify the pops of all other participants against the
|
||||
@@ -93,9 +104,21 @@ static void secp256k1_chilldkg_simplpedpop_participant_step2_prepare_secshare(se
|
||||
* - FAULTY_PARTICIPANT_OR_COORDINATOR(i) if participant i sent the point at
|
||||
* infinity as commitment to their secret or an invalid pop;
|
||||
* - UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR if the tweaked secshare does
|
||||
* not match the tweaked pubshare (the investigation procedure of a later
|
||||
* phase can attribute the fault). */
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, const secp256k1_chilldkg_simplpedpop_participant_state *state, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *secshare);
|
||||
* not match the tweaked pubshare; in this case, and only in this case,
|
||||
* inv_data (if not NULL) is filled for
|
||||
* secp256k1_chilldkg_simplpedpop_participant_investigate. */
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, secp256k1_chilldkg_simplpedpop_participant_inv_data *inv_data, const secp256k1_chilldkg_simplpedpop_participant_state *state, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *secshare);
|
||||
|
||||
/* Determine the faulty party after an
|
||||
* UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR fault of participant_step2
|
||||
* (simplpedpop.py participant_investigate): check that the n partial
|
||||
* pubshares sum to the pubshare, that the n partial secshares sum to the
|
||||
* secshare, and that every partial secshare matches its partial pubshare.
|
||||
* Returns FAULTY_COORDINATOR, or FAULTY_PARTICIPANT_OR_COORDINATOR(i) with
|
||||
* *fault_index = i. If all inputs are consistent (i.e., the function was
|
||||
* called even though no fault occurred), returns SECP256K1_CHILLDKG_INVALID_INPUT
|
||||
* (the reference raises a RuntimeError in this case). */
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_investigate(const secp256k1_context *ctx, uint32_t *fault_index, const secp256k1_chilldkg_simplpedpop_participant_inv_data *inv_data, const secp256k1_ge *partial_pubshares, const secp256k1_scalar *partial_secshares);
|
||||
|
||||
/* Assemble the summed VSS commitment (simplpedpop.py assemble_sum_coms):
|
||||
* sum_coms[0] = sum of the n coms_to_secrets, sum_coms[j] =
|
||||
|
||||
@@ -117,7 +117,7 @@ static void secp256k1_chilldkg_simplpedpop_participant_step2_prepare_secshare(se
|
||||
}
|
||||
}
|
||||
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, const secp256k1_chilldkg_simplpedpop_participant_state *state, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *secshare) {
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, secp256k1_chilldkg_simplpedpop_participant_inv_data *inv_data, const secp256k1_chilldkg_simplpedpop_participant_state *state, const unsigned char *cmsg, size_t cmsg_len, const secp256k1_scalar *secshare) {
|
||||
const uint32_t t = state->t;
|
||||
const uint32_t n = state->n;
|
||||
const uint32_t participant_id = state->participant_id;
|
||||
@@ -197,8 +197,16 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2
|
||||
/* Unreachable in practice: sum_coms[0] can only be the point at
|
||||
* infinity if some pop is invalid (checked above), and a tweak hash
|
||||
* overflow has negligible probability. The reference raises a
|
||||
* non-protocol error here. */
|
||||
* non-protocol error here. Fill inv_data with the untweaked values so
|
||||
* that the investigation procedure can still run. */
|
||||
*fault_index = UINT32_MAX;
|
||||
if (inv_data != NULL) {
|
||||
inv_data->n = n;
|
||||
inv_data->participant_id = participant_id;
|
||||
inv_data->secshare = *secshare;
|
||||
secp256k1_chilldkg_vss_pubshare(&pubsharej, sum_coms, t, participant_id);
|
||||
secp256k1_ge_set_gej_var(&inv_data->pubshare, &pubsharej);
|
||||
}
|
||||
return SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR;
|
||||
}
|
||||
|
||||
@@ -209,9 +217,21 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2
|
||||
secp256k1_ge_set_gej_var(&pubshare, &pubsharej);
|
||||
secp256k1_scalar_add(&secshare_tweaked, secshare, &tweak);
|
||||
if (!secp256k1_chilldkg_vss_verify_secshare(ctx, &secshare_tweaked, &pubshare)) {
|
||||
/* "Received invalid secshare"; the investigation procedure (a later
|
||||
* phase) can determine the faulty party. */
|
||||
/* "Received invalid secshare"; capture the investigation data so
|
||||
* that the investigation procedure can determine the faulty party. */
|
||||
*fault_index = UINT32_MAX;
|
||||
if (inv_data != NULL) {
|
||||
secp256k1_ge pubtweak_neg;
|
||||
inv_data->n = n;
|
||||
inv_data->participant_id = participant_id;
|
||||
/* The investigation works on the untweaked values. */
|
||||
inv_data->secshare = *secshare;
|
||||
/* pubshare = pubshare_tweaked - pubtweak (gej_add_ge_var handles
|
||||
* a pubtweak at infinity, which occurs iff the tweak is zero). */
|
||||
secp256k1_ge_neg(&pubtweak_neg, &pubtweak);
|
||||
secp256k1_gej_add_ge_var(&pubsharej, &pubsharej, &pubtweak_neg, NULL);
|
||||
secp256k1_ge_set_gej_var(&inv_data->pubshare, &pubsharej);
|
||||
}
|
||||
secp256k1_scalar_clear(&tweak);
|
||||
secp256k1_scalar_clear(&secshare_tweaked);
|
||||
return SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR;
|
||||
@@ -353,4 +373,68 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_coordinator_step(
|
||||
return SECP256K1_CHILLDKG_OK;
|
||||
}
|
||||
|
||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_investigate(const secp256k1_context *ctx, uint32_t *fault_index, const secp256k1_chilldkg_simplpedpop_participant_inv_data *inv_data, const secp256k1_ge *partial_pubshares, const secp256k1_scalar *partial_secshares) {
|
||||
const uint32_t n = inv_data->n;
|
||||
const uint32_t participant_id = inv_data->participant_id;
|
||||
secp256k1_gej sumj;
|
||||
secp256k1_ge sum;
|
||||
secp256k1_scalar secshare_sum;
|
||||
unsigned char buf33[33];
|
||||
unsigned char buf33b[33];
|
||||
uint32_t i;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
|
||||
/* If the sum of the partial pubshares is not equal to the pubshare, the
|
||||
* coordinator is faulty. */
|
||||
secp256k1_gej_set_infinity(&sumj);
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_gej termj;
|
||||
secp256k1_gej_set_ge(&termj, &partial_pubshares[i]);
|
||||
secp256k1_gej_add_var(&sumj, &sumj, &termj, NULL);
|
||||
}
|
||||
secp256k1_ge_set_gej_var(&sum, &sumj);
|
||||
secp256k1_chilldkg_point_save(buf33, &sum);
|
||||
secp256k1_chilldkg_point_save(buf33b, &inv_data->pubshare);
|
||||
if (secp256k1_memcmp_var(buf33, buf33b, 33) != 0) {
|
||||
return SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||
}
|
||||
|
||||
/* If the sum of the partial secshares is not equal to the secshare, the
|
||||
* coordinator is faulty (since the encryption is additively homomorphic,
|
||||
* this means that the sum of the *encrypted* partial secshares in the
|
||||
* investigation message was not equal to the encrypted secshare; the
|
||||
* reference signals this case with SecshareSumError, which the EncPedPop
|
||||
* layer translates to FaultyCoordinatorError). */
|
||||
secp256k1_scalar_set_int(&secshare_sum, 0);
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar_add(&secshare_sum, &secshare_sum, &partial_secshares[i]);
|
||||
}
|
||||
if (!secp256k1_scalar_eq(&secshare_sum, &inv_data->secshare)) {
|
||||
secp256k1_scalar_clear(&secshare_sum);
|
||||
return SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||
}
|
||||
secp256k1_scalar_clear(&secshare_sum);
|
||||
|
||||
/* If some partial secshare does not match its partial pubshare, the
|
||||
* corresponding participant or the coordinator is faulty; for our own
|
||||
* index, only the coordinator can be at fault ("Coordinator fiddled with
|
||||
* the share from me to myself"). */
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!secp256k1_chilldkg_vss_verify_secshare(ctx, &partial_secshares[i], &partial_pubshares[i])) {
|
||||
if (i != participant_id) {
|
||||
*fault_index = i;
|
||||
return SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR;
|
||||
}
|
||||
return SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||
}
|
||||
}
|
||||
|
||||
/* We now know that the secshare matches the pubshare. This means that
|
||||
* this function was called even though no fault occurred (the reference
|
||||
* raises a RuntimeError in this case). */
|
||||
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -249,6 +249,77 @@ static const unsigned char vec3_recovery[556] = { 0x00, 0x00, 0x00, 0x02, 0x03,
|
||||
/* chilldkg session n = 3, t = 2 */
|
||||
/* all python-side sanity checks passed */
|
||||
|
||||
static const unsigned char vec5_hostseckeys[3][32] = {
|
||||
{ 0x12, 0x83, 0xa7, 0x64, 0x03, 0x38, 0xef, 0x46, 0x92, 0x13, 0x25, 0xa8, 0x3e, 0xae, 0x85, 0x94, 0x58, 0x52, 0x0a, 0x93, 0x5a, 0x17, 0x9d, 0xe9, 0x1c, 0xba, 0x39, 0xd8, 0xb6, 0xf9, 0x3d, 0xbf },
|
||||
{ 0xd2, 0xd5, 0x5c, 0xf8, 0x10, 0xd0, 0x93, 0xcc, 0xfb, 0xff, 0xdd, 0x89, 0x65, 0x13, 0x59, 0x79, 0xa7, 0x3f, 0x5f, 0x70, 0x06, 0x20, 0x3e, 0x0f, 0x1f, 0x57, 0x20, 0x90, 0x1a, 0x0d, 0x3e, 0xf2 },
|
||||
{ 0x70, 0x86, 0x80, 0x07, 0x06, 0x69, 0xf8, 0x6b, 0x8f, 0x14, 0x24, 0xb3, 0x93, 0xdd, 0x03, 0x03, 0xd6, 0x63, 0xa6, 0xa9, 0x1f, 0x85, 0x2d, 0x03, 0x34, 0xae, 0x64, 0xac, 0xdd, 0x17, 0x72, 0x34 },
|
||||
};
|
||||
static const unsigned char vec5_hostpubkeys[3][33] = {
|
||||
{ 0x03, 0x4f, 0x68, 0x91, 0xb1, 0xd2, 0x7f, 0x67, 0xd3, 0xbb, 0x8a, 0xd4, 0x80, 0x83, 0x1a, 0x3d, 0x80, 0x7f, 0x58, 0xed, 0x42, 0x21, 0x6c, 0x94, 0x9b, 0xd0, 0xc7, 0x8a, 0x51, 0x9c, 0xbe, 0x76, 0xe0 },
|
||||
{ 0x02, 0xfb, 0x7e, 0x20, 0xfb, 0xa2, 0x87, 0xee, 0x46, 0xb9, 0x53, 0x62, 0x32, 0xf6, 0x9c, 0x31, 0xa9, 0x0c, 0x66, 0xea, 0xf1, 0xfd, 0x67, 0x18, 0xdd, 0xdc, 0x1f, 0x10, 0xaa, 0x15, 0xf8, 0xa3, 0x4f },
|
||||
{ 0x03, 0x59, 0x5a, 0x19, 0x3f, 0xe6, 0xe8, 0xf1, 0xf4, 0x36, 0x00, 0x79, 0x4e, 0x19, 0x39, 0xaa, 0x29, 0x04, 0x1f, 0x3b, 0xc1, 0xd3, 0x29, 0x49, 0x1e, 0x88, 0x38, 0x32, 0x19, 0x74, 0x8c, 0x2f, 0xa5 },
|
||||
};
|
||||
static const unsigned char vec5_randoms[3][32] = {
|
||||
{ 0xa8, 0xfa, 0xcd, 0xc0, 0x2b, 0x1f, 0xcf, 0x2a, 0x0f, 0x0e, 0xd0, 0x22, 0xe5, 0x59, 0x53, 0xb2, 0xf6, 0xf7, 0x96, 0x9e, 0x49, 0x55, 0x96, 0xde, 0xa9, 0x2c, 0xd4, 0x3d, 0xed, 0x48, 0x3a, 0x24 },
|
||||
{ 0xe9, 0xfb, 0x8f, 0x6b, 0x5e, 0x9a, 0x21, 0xc2, 0x16, 0x58, 0xbd, 0x75, 0x7e, 0x66, 0xda, 0x5f, 0x5c, 0x8f, 0xe6, 0x6b, 0x39, 0xf3, 0xca, 0x82, 0xf0, 0xd9, 0xe7, 0x5e, 0x49, 0x00, 0xde, 0xbd },
|
||||
{ 0xed, 0xf0, 0x7d, 0x54, 0x83, 0x08, 0xea, 0xf8, 0x85, 0x83, 0x38, 0x0b, 0xb2, 0xf4, 0xf0, 0x5d, 0x42, 0x4a, 0x7d, 0x2f, 0x6d, 0xed, 0x43, 0x36, 0xd7, 0x7e, 0xc4, 0x63, 0x59, 0x72, 0x37, 0x5f },
|
||||
};
|
||||
static const unsigned char vec5_aux_rands[3][32] = {
|
||||
{ 0xb7, 0x35, 0xae, 0xe7, 0x29, 0x77, 0x3e, 0x4f, 0xdd, 0xc1, 0x89, 0x15, 0xb7, 0xb1, 0x93, 0x5f, 0x86, 0x7c, 0xe1, 0x08, 0xa0, 0x50, 0x64, 0x27, 0x9a, 0x8f, 0x8d, 0x0d, 0x0e, 0xc1, 0xe8, 0x2f },
|
||||
{ 0x3f, 0xf6, 0x7d, 0xab, 0x0f, 0x97, 0xf4, 0x79, 0x28, 0xf3, 0x63, 0x67, 0xb8, 0x6f, 0xde, 0x1c, 0x16, 0xe7, 0x13, 0xf9, 0x25, 0x0f, 0xb6, 0xd9, 0x19, 0x44, 0xbf, 0x53, 0xc7, 0xfd, 0x6f, 0xfb },
|
||||
{ 0x01, 0xda, 0x0f, 0xd4, 0xa7, 0xff, 0xc9, 0x7a, 0x15, 0x1e, 0x01, 0xfa, 0x07, 0x54, 0x53, 0xf0, 0x83, 0x5e, 0x25, 0x40, 0x63, 0x01, 0x5f, 0xcd, 0xac, 0xc7, 0x31, 0xb9, 0xdc, 0x6e, 0x24, 0x15 },
|
||||
};
|
||||
static const unsigned char vec5_ack_aux_rands[3][32] = {
|
||||
{ 0xd1, 0x29, 0xa1, 0x50, 0x10, 0xb1, 0xba, 0x89, 0x99, 0x00, 0x1b, 0x3c, 0xb8, 0x35, 0x8e, 0x2c, 0x48, 0xb7, 0x87, 0x83, 0xb8, 0xdf, 0x4d, 0x94, 0xb4, 0x3e, 0x88, 0xa8, 0x97, 0xb6, 0x3a, 0xd6 },
|
||||
{ 0xc5, 0x26, 0xf1, 0xa4, 0xa1, 0x3d, 0xf9, 0xea, 0x33, 0x1e, 0x05, 0x48, 0x81, 0x79, 0x25, 0xfb, 0x3a, 0x1b, 0x82, 0x56, 0xb5, 0x8f, 0x93, 0xab, 0x22, 0xbf, 0x45, 0x1c, 0x70, 0x4e, 0x28, 0x89 },
|
||||
{ 0x39, 0x1c, 0xc5, 0x83, 0x75, 0x88, 0x23, 0x92, 0x8e, 0xd7, 0x87, 0xb5, 0x81, 0x9c, 0x40, 0x1e, 0x91, 0xe5, 0xa1, 0xe7, 0x5d, 0x5d, 0x4d, 0x42, 0x2f, 0xd3, 0xf7, 0x0d, 0x11, 0x6b, 0x2a, 0xae },
|
||||
};
|
||||
static const unsigned char vec5_pmsgs1[3][259] = {
|
||||
{ 0x02, 0xa9, 0xf7, 0xa6, 0x54, 0x1e, 0x12, 0x22, 0x46, 0xfd, 0x57, 0xee, 0xdc, 0x6e, 0x3a, 0x6a, 0x12, 0x48, 0x05, 0x4f, 0x02, 0x2b, 0x7c, 0x01, 0xe2, 0xa4, 0x36, 0x4c, 0x09, 0x20, 0xda, 0x93, 0x4b, 0x03, 0xcd, 0xba, 0xe2, 0x7d, 0xcc, 0x62, 0x90, 0x56, 0x8d, 0x21, 0xb6, 0x35, 0xa7, 0xbb, 0xd2, 0x93, 0x28, 0x78, 0xd7, 0x34, 0x55, 0x74, 0xa0, 0x52, 0xd6, 0x9e, 0xa1, 0x43, 0xe9, 0x8b, 0xc2, 0x12, 0xf5, 0xb1, 0x94, 0x34, 0xb9, 0x81, 0x06, 0x4d, 0x17, 0xa1, 0x6a, 0x1d, 0x81, 0x58, 0x4c, 0xf0, 0x55, 0xdf, 0x32, 0x62, 0x08, 0xd8, 0x29, 0x1e, 0xf2, 0xa6, 0xa3, 0xdb, 0x52, 0x98, 0xb8, 0x0f, 0xe6, 0x49, 0x74, 0xe1, 0x9f, 0x90, 0x70, 0x66, 0x09, 0x6b, 0xa9, 0xd5, 0x05, 0xd6, 0xb2, 0x36, 0x7a, 0xf2, 0x9b, 0xbb, 0x0e, 0x66, 0xed, 0x22, 0xd5, 0xdf, 0x21, 0xba, 0x1e, 0x51, 0x77, 0x40, 0x03, 0x07, 0xd9, 0x3f, 0x10, 0xca, 0xd5, 0x95, 0x92, 0xf3, 0x83, 0xc1, 0xd0, 0x0e, 0xb3, 0xb2, 0xf0, 0xea, 0xcb, 0x67, 0x79, 0xd7, 0xc1, 0x70, 0x0a, 0x42, 0x74, 0x77, 0x4d, 0xfd, 0x00, 0xab, 0x72, 0xbc, 0x05, 0xad, 0x21, 0x38, 0x77, 0xd9, 0x5b, 0x57, 0xb5, 0xa2, 0x0d, 0x49, 0x36, 0x53, 0x58, 0xfe, 0x61, 0x5e, 0x3c, 0x35, 0xb2, 0x8a, 0x6e, 0x7b, 0xdc, 0xc2, 0x44, 0x4c, 0x36, 0xeb, 0x06, 0xeb, 0x3b, 0xea, 0xd3, 0x1e, 0xb1, 0x6b, 0xe9, 0x70, 0x40, 0xd8, 0xeb, 0x68, 0x18, 0x84, 0x62, 0x82, 0xde, 0x65, 0x73, 0x5f, 0x24, 0x71, 0x9f, 0xd2, 0x68, 0xaf, 0x79, 0xdb, 0x1a, 0xa9, 0x8f, 0xe1, 0xab, 0xf1, 0x0b, 0xbb, 0x29, 0xf0, 0xf7, 0x33, 0xc4, 0x8e, 0x6f, 0xa6, 0x16, 0x94, 0x58, 0x75, 0x2a, 0x39, 0x8d, 0xfa, 0x5c, 0x37, 0x8d, 0x66, 0xb2, 0xb4, 0xfd, 0xe6, 0x5b, 0x27, 0xec },
|
||||
{ 0x03, 0x1a, 0x5c, 0xb4, 0x0b, 0x67, 0xdb, 0xbc, 0xc4, 0x8b, 0x03, 0xcc, 0x2c, 0xc5, 0x54, 0x52, 0x0c, 0x01, 0x72, 0x57, 0x55, 0xd5, 0x2a, 0x0d, 0xec, 0x5d, 0xb1, 0xe0, 0xe1, 0xad, 0x00, 0x45, 0x59, 0x02, 0x9b, 0xac, 0x46, 0x00, 0xbb, 0xa5, 0xa5, 0x43, 0x08, 0x81, 0xc5, 0xac, 0x25, 0x1c, 0x8a, 0x01, 0xc7, 0x2d, 0x04, 0x69, 0x0e, 0x89, 0xeb, 0x6c, 0xb8, 0xe3, 0xdb, 0x4c, 0x60, 0x9d, 0x12, 0xf1, 0x1d, 0xf4, 0x21, 0xdd, 0xdf, 0x41, 0xc4, 0x1c, 0xae, 0x3a, 0x03, 0xd6, 0xd6, 0x7a, 0x25, 0x48, 0xcb, 0x36, 0x8b, 0xfa, 0x59, 0xb8, 0xfe, 0x6a, 0x2a, 0x39, 0x1b, 0x30, 0x60, 0xd0, 0x2e, 0x8b, 0x2d, 0xab, 0x0a, 0x99, 0x90, 0x31, 0xb9, 0x0f, 0x62, 0xa1, 0xb0, 0x1a, 0x3f, 0x3e, 0x43, 0xf6, 0xce, 0x94, 0x73, 0xcc, 0x88, 0xda, 0x76, 0x91, 0x66, 0x98, 0xa2, 0xd2, 0x4f, 0xdf, 0x81, 0xcb, 0x03, 0x7f, 0xc5, 0xc6, 0x73, 0xb0, 0xe6, 0xfb, 0x74, 0x98, 0xce, 0x1a, 0x86, 0xd7, 0xf7, 0xe8, 0x05, 0xf4, 0x65, 0xe6, 0x8b, 0xca, 0xe2, 0x95, 0x10, 0xdd, 0xdd, 0xec, 0xb6, 0x34, 0x2f, 0xae, 0x12, 0x10, 0x87, 0xc2, 0xea, 0x8c, 0x60, 0xeb, 0xc6, 0x3d, 0x40, 0x37, 0x38, 0xcf, 0x60, 0x3e, 0xfd, 0x7b, 0xc8, 0x31, 0x10, 0xfa, 0x29, 0x61, 0x5b, 0x93, 0x6e, 0x85, 0xa0, 0xd3, 0x5c, 0xe0, 0xa1, 0xa2, 0xf0, 0xff, 0xfb, 0x07, 0x2f, 0x48, 0xdb, 0x25, 0x84, 0x4d, 0xd0, 0x5c, 0xeb, 0xc0, 0xba, 0x8c, 0x51, 0x3d, 0x06, 0x69, 0x28, 0x42, 0xe6, 0x40, 0x4a, 0xfe, 0x20, 0x0d, 0x37, 0xc4, 0xe1, 0x46, 0x4f, 0x8e, 0x55, 0xc0, 0xd5, 0x13, 0x65, 0xf2, 0x99, 0xa2, 0x78, 0x3e, 0xd4, 0xc9, 0x47, 0x5d, 0x4d, 0x45, 0xbd, 0x5c, 0xd7, 0xe8, 0xd2, 0x82, 0xc2, 0x4a, 0xe5, 0xd1, 0x5d, 0xe9, 0x4b },
|
||||
{ 0x02, 0x54, 0xc4, 0xc5, 0x71, 0x04, 0x3b, 0x01, 0x22, 0xe0, 0x1a, 0x79, 0x37, 0x1e, 0x0f, 0xc2, 0x6b, 0x66, 0x4e, 0xbc, 0xbb, 0x4e, 0x18, 0xe5, 0x1a, 0xa9, 0x67, 0x21, 0x18, 0x23, 0x0b, 0x86, 0xef, 0x02, 0xd3, 0x52, 0xd3, 0x63, 0x83, 0x81, 0xad, 0x26, 0x0d, 0x5d, 0xc0, 0x99, 0xcf, 0x80, 0xd4, 0xd7, 0x5f, 0x33, 0x3e, 0x15, 0xe3, 0xff, 0xce, 0xf6, 0x01, 0xe8, 0x66, 0x20, 0xb3, 0x15, 0x84, 0x18, 0xa7, 0x13, 0x00, 0x3b, 0x39, 0x2d, 0x2d, 0x35, 0xa5, 0x7c, 0x5d, 0x3c, 0x96, 0x92, 0xb8, 0xd4, 0x43, 0x94, 0xca, 0xf7, 0x71, 0x60, 0x5c, 0x6f, 0x5b, 0x99, 0x33, 0xcb, 0x39, 0xf8, 0xae, 0xf5, 0xbc, 0x92, 0x09, 0x3f, 0x03, 0xd0, 0x5c, 0x4a, 0x16, 0xff, 0x0a, 0xc3, 0x0b, 0x34, 0x78, 0xe7, 0xea, 0xfb, 0x48, 0xbc, 0x38, 0xbb, 0x18, 0x20, 0xf0, 0x8f, 0x10, 0x63, 0x3f, 0x42, 0xf4, 0xbd, 0x02, 0x6d, 0xda, 0xf4, 0x4d, 0x4a, 0x66, 0xfc, 0xf7, 0x7b, 0xc2, 0x81, 0x44, 0xa9, 0x62, 0xb9, 0x5b, 0xc9, 0x09, 0x9d, 0x87, 0x1e, 0x4d, 0xbe, 0x5f, 0x0a, 0x94, 0x78, 0xa5, 0x24, 0xaf, 0xb7, 0x90, 0xc8, 0x1e, 0xcf, 0x74, 0xdc, 0xd5, 0xb4, 0x7d, 0x16, 0xf1, 0xad, 0x68, 0xbc, 0xdb, 0x0c, 0xd5, 0x6e, 0x07, 0x49, 0xbf, 0xcc, 0x15, 0x62, 0x12, 0xd1, 0xa1, 0x91, 0x71, 0x37, 0x39, 0x98, 0x1d, 0x59, 0xdc, 0x42, 0x24, 0x9d, 0x7d, 0x04, 0x7f, 0xa4, 0x12, 0xc2, 0x4d, 0x87, 0x0b, 0x62, 0x1e, 0x81, 0x48, 0x68, 0x27, 0xfd, 0xde, 0x94, 0x34, 0x2e, 0xf3, 0x17, 0x78, 0x37, 0x4c, 0x90, 0xff, 0x71, 0x7f, 0x6a, 0xf2, 0xad, 0x9d, 0x84, 0x6e, 0x5d, 0x39, 0x36, 0xec, 0x80, 0xf1, 0xba, 0xa4, 0x1d, 0x5b, 0x09, 0xc6, 0xd5, 0x50, 0xeb, 0x45, 0x7c, 0x21, 0x7e, 0x86, 0xff, 0xf8, 0x15, 0x6c },
|
||||
};
|
||||
static const unsigned char vec5_cmsg1[519] = { 0x02, 0xa9, 0xf7, 0xa6, 0x54, 0x1e, 0x12, 0x22, 0x46, 0xfd, 0x57, 0xee, 0xdc, 0x6e, 0x3a, 0x6a, 0x12, 0x48, 0x05, 0x4f, 0x02, 0x2b, 0x7c, 0x01, 0xe2, 0xa4, 0x36, 0x4c, 0x09, 0x20, 0xda, 0x93, 0x4b, 0x03, 0x1a, 0x5c, 0xb4, 0x0b, 0x67, 0xdb, 0xbc, 0xc4, 0x8b, 0x03, 0xcc, 0x2c, 0xc5, 0x54, 0x52, 0x0c, 0x01, 0x72, 0x57, 0x55, 0xd5, 0x2a, 0x0d, 0xec, 0x5d, 0xb1, 0xe0, 0xe1, 0xad, 0x00, 0x45, 0x59, 0x02, 0x54, 0xc4, 0xc5, 0x71, 0x04, 0x3b, 0x01, 0x22, 0xe0, 0x1a, 0x79, 0x37, 0x1e, 0x0f, 0xc2, 0x6b, 0x66, 0x4e, 0xbc, 0xbb, 0x4e, 0x18, 0xe5, 0x1a, 0xa9, 0x67, 0x21, 0x18, 0x23, 0x0b, 0x86, 0xef, 0x02, 0x67, 0x0c, 0x35, 0xb2, 0xae, 0x50, 0x90, 0xff, 0xe0, 0x32, 0x36, 0xee, 0x4f, 0x86, 0xf9, 0x31, 0xac, 0x79, 0x80, 0x64, 0xfb, 0x9d, 0x9c, 0xd1, 0x95, 0x4b, 0xf0, 0x5f, 0xc1, 0x38, 0x38, 0x69, 0xf5, 0xb1, 0x94, 0x34, 0xb9, 0x81, 0x06, 0x4d, 0x17, 0xa1, 0x6a, 0x1d, 0x81, 0x58, 0x4c, 0xf0, 0x55, 0xdf, 0x32, 0x62, 0x08, 0xd8, 0x29, 0x1e, 0xf2, 0xa6, 0xa3, 0xdb, 0x52, 0x98, 0xb8, 0x0f, 0xe6, 0x49, 0x74, 0xe1, 0x9f, 0x90, 0x70, 0x66, 0x09, 0x6b, 0xa9, 0xd5, 0x05, 0xd6, 0xb2, 0x36, 0x7a, 0xf2, 0x9b, 0xbb, 0x0e, 0x66, 0xed, 0x22, 0xd5, 0xdf, 0x21, 0xba, 0x1e, 0x51, 0x77, 0x40, 0x1d, 0xf4, 0x21, 0xdd, 0xdf, 0x41, 0xc4, 0x1c, 0xae, 0x3a, 0x03, 0xd6, 0xd6, 0x7a, 0x25, 0x48, 0xcb, 0x36, 0x8b, 0xfa, 0x59, 0xb8, 0xfe, 0x6a, 0x2a, 0x39, 0x1b, 0x30, 0x60, 0xd0, 0x2e, 0x8b, 0x2d, 0xab, 0x0a, 0x99, 0x90, 0x31, 0xb9, 0x0f, 0x62, 0xa1, 0xb0, 0x1a, 0x3f, 0x3e, 0x43, 0xf6, 0xce, 0x94, 0x73, 0xcc, 0x88, 0xda, 0x76, 0x91, 0x66, 0x98, 0xa2, 0xd2, 0x4f, 0xdf, 0x81, 0xcb, 0xa7, 0x13, 0x00, 0x3b, 0x39, 0x2d, 0x2d, 0x35, 0xa5, 0x7c, 0x5d, 0x3c, 0x96, 0x92, 0xb8, 0xd4, 0x43, 0x94, 0xca, 0xf7, 0x71, 0x60, 0x5c, 0x6f, 0x5b, 0x99, 0x33, 0xcb, 0x39, 0xf8, 0xae, 0xf5, 0xbc, 0x92, 0x09, 0x3f, 0x03, 0xd0, 0x5c, 0x4a, 0x16, 0xff, 0x0a, 0xc3, 0x0b, 0x34, 0x78, 0xe7, 0xea, 0xfb, 0x48, 0xbc, 0x38, 0xbb, 0x18, 0x20, 0xf0, 0x8f, 0x10, 0x63, 0x3f, 0x42, 0xf4, 0xbd, 0x03, 0x07, 0xd9, 0x3f, 0x10, 0xca, 0xd5, 0x95, 0x92, 0xf3, 0x83, 0xc1, 0xd0, 0x0e, 0xb3, 0xb2, 0xf0, 0xea, 0xcb, 0x67, 0x79, 0xd7, 0xc1, 0x70, 0x0a, 0x42, 0x74, 0x77, 0x4d, 0xfd, 0x00, 0xab, 0x72, 0x03, 0x7f, 0xc5, 0xc6, 0x73, 0xb0, 0xe6, 0xfb, 0x74, 0x98, 0xce, 0x1a, 0x86, 0xd7, 0xf7, 0xe8, 0x05, 0xf4, 0x65, 0xe6, 0x8b, 0xca, 0xe2, 0x95, 0x10, 0xdd, 0xdd, 0xec, 0xb6, 0x34, 0x2f, 0xae, 0x12, 0x02, 0x6d, 0xda, 0xf4, 0x4d, 0x4a, 0x66, 0xfc, 0xf7, 0x7b, 0xc2, 0x81, 0x44, 0xa9, 0x62, 0xb9, 0x5b, 0xc9, 0x09, 0x9d, 0x87, 0x1e, 0x4d, 0xbe, 0x5f, 0x0a, 0x94, 0x78, 0xa5, 0x24, 0xaf, 0xb7, 0x90, 0x94, 0xac, 0x3f, 0x80, 0xa1, 0xae, 0x79, 0x9e, 0xab, 0xe7, 0x86, 0xae, 0xd5, 0x71, 0x9f, 0x2d, 0x2d, 0x81, 0xfc, 0x26, 0x4c, 0xa8, 0xad, 0xa1, 0x21, 0x1a, 0x7a, 0xc9, 0x86, 0x97, 0x22, 0x83, 0xe8, 0x09, 0x2c, 0xf2, 0xc3, 0x5d, 0xb9, 0x44, 0x39, 0xd7, 0xe9, 0x09, 0x4c, 0x0f, 0xa7, 0x3c, 0xd5, 0xc9, 0x2d, 0xbb, 0x16, 0xe2, 0xa8, 0x7e, 0x81, 0xd4, 0x66, 0x85, 0x4f, 0x68, 0xbe, 0x2e, 0x99, 0x7a, 0xea, 0x54, 0x29, 0x9c, 0x88, 0xcb, 0x83, 0x97, 0x67, 0xd4, 0x65, 0xdd, 0x18, 0x45, 0x35, 0x23, 0xac, 0x2b, 0x7d, 0x3c, 0x6b, 0x69, 0xa5, 0xc4, 0x1f, 0xdd, 0xe7, 0x7a, 0xe5, 0x62 };
|
||||
static const unsigned char vec5_pmsgs2[3][64] = {
|
||||
{ 0x37, 0x24, 0xa1, 0x76, 0xf2, 0x82, 0xd3, 0x37, 0xac, 0x82, 0x26, 0xd2, 0xe7, 0x1c, 0x92, 0xff, 0x87, 0x65, 0x9c, 0x7f, 0x98, 0x17, 0x4e, 0x54, 0xd3, 0x43, 0x6f, 0x1a, 0x83, 0xda, 0xc4, 0x14, 0xbf, 0xbb, 0x69, 0x94, 0x7a, 0xc2, 0x3c, 0xd4, 0x42, 0x3a, 0x0d, 0xdd, 0x4a, 0x22, 0x0c, 0xbb, 0x17, 0x63, 0xfa, 0xbb, 0x3f, 0x54, 0xd0, 0xdc, 0xcc, 0x4d, 0x44, 0xb3, 0xa3, 0x23, 0x83, 0x3b },
|
||||
{ 0x5e, 0xbc, 0xe2, 0x1d, 0x9a, 0xbe, 0x87, 0x88, 0x67, 0x56, 0xbd, 0x19, 0x66, 0x0c, 0x3a, 0x3c, 0x02, 0x36, 0x82, 0x4a, 0xb9, 0xc3, 0x3e, 0x3b, 0x5c, 0xb4, 0xa8, 0x3b, 0x06, 0xa1, 0x20, 0xff, 0x11, 0x7f, 0x2b, 0xf8, 0x18, 0x3b, 0x79, 0xe2, 0x46, 0x61, 0x1b, 0xd2, 0x3b, 0x22, 0x7a, 0x8c, 0x7b, 0xbb, 0xcb, 0xe7, 0xbd, 0xf8, 0x2a, 0x05, 0xf2, 0x34, 0xfa, 0x66, 0x26, 0xd3, 0x02, 0x20 },
|
||||
{ 0x30, 0x42, 0x47, 0x3e, 0x0b, 0x02, 0x24, 0xf9, 0x9a, 0xc5, 0x1a, 0xe8, 0x12, 0xdb, 0x5f, 0x99, 0x70, 0x78, 0x96, 0x72, 0x41, 0x75, 0x99, 0x2e, 0xf1, 0xdf, 0x5d, 0xdf, 0xee, 0x41, 0xc5, 0x75, 0x99, 0xa6, 0xb4, 0x3f, 0xd3, 0x86, 0xdc, 0xb7, 0xc4, 0x01, 0x21, 0xe2, 0xe9, 0x59, 0x34, 0xa8, 0xe3, 0x1d, 0x79, 0xb7, 0xa9, 0xda, 0xd4, 0x46, 0xea, 0x9a, 0x72, 0x7f, 0xb6, 0xe9, 0x26, 0x17 },
|
||||
};
|
||||
static const unsigned char vec5_cmsg2[192] = { 0x37, 0x24, 0xa1, 0x76, 0xf2, 0x82, 0xd3, 0x37, 0xac, 0x82, 0x26, 0xd2, 0xe7, 0x1c, 0x92, 0xff, 0x87, 0x65, 0x9c, 0x7f, 0x98, 0x17, 0x4e, 0x54, 0xd3, 0x43, 0x6f, 0x1a, 0x83, 0xda, 0xc4, 0x14, 0xbf, 0xbb, 0x69, 0x94, 0x7a, 0xc2, 0x3c, 0xd4, 0x42, 0x3a, 0x0d, 0xdd, 0x4a, 0x22, 0x0c, 0xbb, 0x17, 0x63, 0xfa, 0xbb, 0x3f, 0x54, 0xd0, 0xdc, 0xcc, 0x4d, 0x44, 0xb3, 0xa3, 0x23, 0x83, 0x3b, 0x5e, 0xbc, 0xe2, 0x1d, 0x9a, 0xbe, 0x87, 0x88, 0x67, 0x56, 0xbd, 0x19, 0x66, 0x0c, 0x3a, 0x3c, 0x02, 0x36, 0x82, 0x4a, 0xb9, 0xc3, 0x3e, 0x3b, 0x5c, 0xb4, 0xa8, 0x3b, 0x06, 0xa1, 0x20, 0xff, 0x11, 0x7f, 0x2b, 0xf8, 0x18, 0x3b, 0x79, 0xe2, 0x46, 0x61, 0x1b, 0xd2, 0x3b, 0x22, 0x7a, 0x8c, 0x7b, 0xbb, 0xcb, 0xe7, 0xbd, 0xf8, 0x2a, 0x05, 0xf2, 0x34, 0xfa, 0x66, 0x26, 0xd3, 0x02, 0x20, 0x30, 0x42, 0x47, 0x3e, 0x0b, 0x02, 0x24, 0xf9, 0x9a, 0xc5, 0x1a, 0xe8, 0x12, 0xdb, 0x5f, 0x99, 0x70, 0x78, 0x96, 0x72, 0x41, 0x75, 0x99, 0x2e, 0xf1, 0xdf, 0x5d, 0xdf, 0xee, 0x41, 0xc5, 0x75, 0x99, 0xa6, 0xb4, 0x3f, 0xd3, 0x86, 0xdc, 0xb7, 0xc4, 0x01, 0x21, 0xe2, 0xe9, 0x59, 0x34, 0xa8, 0xe3, 0x1d, 0x79, 0xb7, 0xa9, 0xda, 0xd4, 0x46, 0xea, 0x9a, 0x72, 0x7f, 0xb6, 0xe9, 0x26, 0x17 };
|
||||
static const unsigned char vec5_secshares[3][32] = {
|
||||
{ 0x1a, 0xba, 0xaa, 0x2d, 0x25, 0xd0, 0x5b, 0x3f, 0x9b, 0xdc, 0x54, 0xc4, 0x51, 0xe9, 0x90, 0xec, 0xf0, 0x4b, 0x22, 0x49, 0xf1, 0xbc, 0x61, 0x5e, 0xa8, 0x7b, 0xf7, 0x31, 0x62, 0xcb, 0xf5, 0xce },
|
||||
{ 0x35, 0xe1, 0x3c, 0x52, 0xfa, 0x2f, 0x39, 0x4c, 0x6a, 0x9d, 0x9b, 0xcd, 0x1b, 0x96, 0xd2, 0x95, 0xff, 0xbb, 0x85, 0x95, 0x62, 0x56, 0x02, 0xdf, 0x1a, 0x44, 0xd6, 0x7f, 0xf7, 0x25, 0x4f, 0x1f },
|
||||
{ 0x51, 0x07, 0xce, 0x78, 0xce, 0x8e, 0x17, 0x59, 0x39, 0x5e, 0xe2, 0xd5, 0xe5, 0x44, 0x14, 0x3f, 0x0f, 0x2b, 0xe8, 0xe0, 0xd2, 0xef, 0xa4, 0x5f, 0x8c, 0x0d, 0xb5, 0xce, 0x8b, 0x7e, 0xa8, 0x70 },
|
||||
};
|
||||
static const unsigned char vec5_thresh_pk[33] = { 0x02, 0xd6, 0x31, 0x69, 0x44, 0xf7, 0x8c, 0x21, 0x4a, 0xac, 0x9f, 0x93, 0x32, 0x70, 0xe7, 0xa6, 0xad, 0xa9, 0x5e, 0xd0, 0xe0, 0x03, 0x6a, 0xab, 0x78, 0x16, 0x1b, 0xbb, 0xbe, 0x25, 0xa5, 0xee, 0xb5 };
|
||||
static const unsigned char vec5_pubshares[3][33] = {
|
||||
{ 0x02, 0x9d, 0x60, 0x50, 0x8f, 0x5e, 0xd6, 0x93, 0x19, 0x8f, 0x17, 0x6d, 0x2e, 0x19, 0x99, 0x3e, 0x3a, 0x17, 0x0f, 0xb9, 0x83, 0xc8, 0x95, 0x97, 0x94, 0xe9, 0x8b, 0x4e, 0x75, 0x95, 0xf7, 0x99, 0x5f },
|
||||
{ 0x03, 0x81, 0xff, 0x24, 0x16, 0x43, 0xe5, 0x5b, 0x70, 0xc0, 0xfc, 0x01, 0x65, 0xcc, 0x16, 0x80, 0x6e, 0x23, 0x76, 0xf2, 0x6b, 0xf4, 0xf2, 0xc2, 0x58, 0x72, 0x98, 0x69, 0xb2, 0x89, 0x46, 0x2a, 0x69 },
|
||||
{ 0x02, 0x6e, 0x74, 0xfa, 0x97, 0x9d, 0x46, 0xe9, 0xe4, 0x71, 0x23, 0x66, 0x8a, 0x55, 0x85, 0x09, 0x21, 0x67, 0x3b, 0x37, 0x41, 0x6e, 0xcf, 0x95, 0x34, 0x98, 0xca, 0x19, 0x0a, 0xe6, 0xce, 0xd3, 0xa1 },
|
||||
};
|
||||
static const unsigned char vec5_recovery[556] = { 0x00, 0x00, 0x00, 0x02, 0x03, 0x3b, 0x49, 0x45, 0x46, 0x83, 0x43, 0x3e, 0xc5, 0x06, 0x9a, 0x38, 0xaf, 0x81, 0x12, 0xc3, 0xe8, 0x77, 0x51, 0x2a, 0xfe, 0xf3, 0x58, 0xfa, 0x5b, 0xb7, 0x2a, 0xb7, 0x6e, 0x26, 0x7e, 0x8f, 0x8a, 0x02, 0x67, 0x0c, 0x35, 0xb2, 0xae, 0x50, 0x90, 0xff, 0xe0, 0x32, 0x36, 0xee, 0x4f, 0x86, 0xf9, 0x31, 0xac, 0x79, 0x80, 0x64, 0xfb, 0x9d, 0x9c, 0xd1, 0x95, 0x4b, 0xf0, 0x5f, 0xc1, 0x38, 0x38, 0x69, 0x03, 0x4f, 0x68, 0x91, 0xb1, 0xd2, 0x7f, 0x67, 0xd3, 0xbb, 0x8a, 0xd4, 0x80, 0x83, 0x1a, 0x3d, 0x80, 0x7f, 0x58, 0xed, 0x42, 0x21, 0x6c, 0x94, 0x9b, 0xd0, 0xc7, 0x8a, 0x51, 0x9c, 0xbe, 0x76, 0xe0, 0x02, 0xfb, 0x7e, 0x20, 0xfb, 0xa2, 0x87, 0xee, 0x46, 0xb9, 0x53, 0x62, 0x32, 0xf6, 0x9c, 0x31, 0xa9, 0x0c, 0x66, 0xea, 0xf1, 0xfd, 0x67, 0x18, 0xdd, 0xdc, 0x1f, 0x10, 0xaa, 0x15, 0xf8, 0xa3, 0x4f, 0x03, 0x59, 0x5a, 0x19, 0x3f, 0xe6, 0xe8, 0xf1, 0xf4, 0x36, 0x00, 0x79, 0x4e, 0x19, 0x39, 0xaa, 0x29, 0x04, 0x1f, 0x3b, 0xc1, 0xd3, 0x29, 0x49, 0x1e, 0x88, 0x38, 0x32, 0x19, 0x74, 0x8c, 0x2f, 0xa5, 0x03, 0x07, 0xd9, 0x3f, 0x10, 0xca, 0xd5, 0x95, 0x92, 0xf3, 0x83, 0xc1, 0xd0, 0x0e, 0xb3, 0xb2, 0xf0, 0xea, 0xcb, 0x67, 0x79, 0xd7, 0xc1, 0x70, 0x0a, 0x42, 0x74, 0x77, 0x4d, 0xfd, 0x00, 0xab, 0x72, 0x03, 0x7f, 0xc5, 0xc6, 0x73, 0xb0, 0xe6, 0xfb, 0x74, 0x98, 0xce, 0x1a, 0x86, 0xd7, 0xf7, 0xe8, 0x05, 0xf4, 0x65, 0xe6, 0x8b, 0xca, 0xe2, 0x95, 0x10, 0xdd, 0xdd, 0xec, 0xb6, 0x34, 0x2f, 0xae, 0x12, 0x02, 0x6d, 0xda, 0xf4, 0x4d, 0x4a, 0x66, 0xfc, 0xf7, 0x7b, 0xc2, 0x81, 0x44, 0xa9, 0x62, 0xb9, 0x5b, 0xc9, 0x09, 0x9d, 0x87, 0x1e, 0x4d, 0xbe, 0x5f, 0x0a, 0x94, 0x78, 0xa5, 0x24, 0xaf, 0xb7, 0x90, 0x94, 0xac, 0x3f, 0x80, 0xa1, 0xae, 0x79, 0x9e, 0xab, 0xe7, 0x86, 0xae, 0xd5, 0x71, 0x9f, 0x2d, 0x2d, 0x81, 0xfc, 0x26, 0x4c, 0xa8, 0xad, 0xa1, 0x21, 0x1a, 0x7a, 0xc9, 0x86, 0x97, 0x22, 0x83, 0xe8, 0x09, 0x2c, 0xf2, 0xc3, 0x5d, 0xb9, 0x44, 0x39, 0xd7, 0xe9, 0x09, 0x4c, 0x0f, 0xa7, 0x3c, 0xd5, 0xc9, 0x2d, 0xbb, 0x16, 0xe2, 0xa8, 0x7e, 0x81, 0xd4, 0x66, 0x85, 0x4f, 0x68, 0xbe, 0x2e, 0x99, 0x7a, 0xea, 0x54, 0x29, 0x9c, 0x88, 0xcb, 0x83, 0x97, 0x67, 0xd4, 0x65, 0xdd, 0x18, 0x45, 0x35, 0x23, 0xac, 0x2b, 0x7d, 0x3c, 0x6b, 0x69, 0xa5, 0xc4, 0x1f, 0xdd, 0xe7, 0x7a, 0xe5, 0x62, 0x37, 0x24, 0xa1, 0x76, 0xf2, 0x82, 0xd3, 0x37, 0xac, 0x82, 0x26, 0xd2, 0xe7, 0x1c, 0x92, 0xff, 0x87, 0x65, 0x9c, 0x7f, 0x98, 0x17, 0x4e, 0x54, 0xd3, 0x43, 0x6f, 0x1a, 0x83, 0xda, 0xc4, 0x14, 0xbf, 0xbb, 0x69, 0x94, 0x7a, 0xc2, 0x3c, 0xd4, 0x42, 0x3a, 0x0d, 0xdd, 0x4a, 0x22, 0x0c, 0xbb, 0x17, 0x63, 0xfa, 0xbb, 0x3f, 0x54, 0xd0, 0xdc, 0xcc, 0x4d, 0x44, 0xb3, 0xa3, 0x23, 0x83, 0x3b, 0x5e, 0xbc, 0xe2, 0x1d, 0x9a, 0xbe, 0x87, 0x88, 0x67, 0x56, 0xbd, 0x19, 0x66, 0x0c, 0x3a, 0x3c, 0x02, 0x36, 0x82, 0x4a, 0xb9, 0xc3, 0x3e, 0x3b, 0x5c, 0xb4, 0xa8, 0x3b, 0x06, 0xa1, 0x20, 0xff, 0x11, 0x7f, 0x2b, 0xf8, 0x18, 0x3b, 0x79, 0xe2, 0x46, 0x61, 0x1b, 0xd2, 0x3b, 0x22, 0x7a, 0x8c, 0x7b, 0xbb, 0xcb, 0xe7, 0xbd, 0xf8, 0x2a, 0x05, 0xf2, 0x34, 0xfa, 0x66, 0x26, 0xd3, 0x02, 0x20, 0x30, 0x42, 0x47, 0x3e, 0x0b, 0x02, 0x24, 0xf9, 0x9a, 0xc5, 0x1a, 0xe8, 0x12, 0xdb, 0x5f, 0x99, 0x70, 0x78, 0x96, 0x72, 0x41, 0x75, 0x99, 0x2e, 0xf1, 0xdf, 0x5d, 0xdf, 0xee, 0x41, 0xc5, 0x75, 0x99, 0xa6, 0xb4, 0x3f, 0xd3, 0x86, 0xdc, 0xb7, 0xc4, 0x01, 0x21, 0xe2, 0xe9, 0x59, 0x34, 0xa8, 0xe3, 0x1d, 0x79, 0xb7, 0xa9, 0xda, 0xd4, 0x46, 0xea, 0x9a, 0x72, 0x7f, 0xb6, 0xe9, 0x26, 0x17 };
|
||||
static const unsigned char vec5_ack_sigs[3][64] = {
|
||||
{ 0x11, 0xfc, 0x90, 0x7c, 0x69, 0x20, 0x13, 0x7a, 0x51, 0x09, 0xa2, 0x03, 0x75, 0x32, 0x7e, 0x7f, 0x7f, 0x20, 0xf2, 0x82, 0x60, 0xa8, 0xf3, 0x01, 0xcf, 0xbc, 0xfd, 0xbb, 0xa7, 0xea, 0x64, 0xa8, 0xbc, 0xf5, 0xc7, 0x05, 0xfc, 0xa4, 0x81, 0xa9, 0xbb, 0x4e, 0x0b, 0x49, 0x1a, 0x2a, 0x49, 0x0d, 0x9c, 0xc8, 0x6f, 0x6d, 0x23, 0xdc, 0x15, 0x2f, 0xdc, 0xe7, 0x99, 0xa7, 0x8a, 0xe1, 0x4d, 0x1a },
|
||||
{ 0x44, 0xff, 0xf6, 0x84, 0xf5, 0x8d, 0x9f, 0xc4, 0xad, 0x46, 0xc6, 0x49, 0x33, 0x42, 0x8e, 0x9e, 0xa7, 0xc1, 0x25, 0xc0, 0x28, 0x6d, 0xbd, 0x78, 0xfd, 0x61, 0x30, 0x85, 0x52, 0x8f, 0x40, 0x67, 0x9e, 0x97, 0x55, 0xcc, 0x21, 0x30, 0xf8, 0xa4, 0x3b, 0x11, 0x88, 0xd2, 0xe4, 0x0a, 0xa2, 0x41, 0x4f, 0x60, 0x41, 0x01, 0x7b, 0x4b, 0xc1, 0x88, 0x6c, 0x74, 0x1d, 0xee, 0x85, 0xa7, 0x99, 0xa0 },
|
||||
{ 0x00, 0x20, 0xeb, 0x92, 0x88, 0x9e, 0x59, 0x81, 0x9e, 0x0d, 0x7b, 0x3f, 0x6b, 0x91, 0x3e, 0xe0, 0x70, 0x33, 0x02, 0x8e, 0xf3, 0xd9, 0x57, 0x66, 0xe8, 0x48, 0xb6, 0xad, 0xe8, 0x2b, 0x22, 0x21, 0xf5, 0x51, 0xa7, 0x4a, 0x64, 0x8e, 0xa6, 0xc1, 0x4e, 0xa7, 0x07, 0x81, 0xb9, 0x16, 0xfb, 0xc9, 0xca, 0x27, 0xac, 0x70, 0xd7, 0xb6, 0x2d, 0x97, 0xaa, 0x95, 0xd5, 0x40, 0x4f, 0x04, 0x56, 0x69 },
|
||||
};
|
||||
static const unsigned char vec5_inv_pmsg1_bad[259] = { 0x03, 0x1a, 0x5c, 0xb4, 0x0b, 0x67, 0xdb, 0xbc, 0xc4, 0x8b, 0x03, 0xcc, 0x2c, 0xc5, 0x54, 0x52, 0x0c, 0x01, 0x72, 0x57, 0x55, 0xd5, 0x2a, 0x0d, 0xec, 0x5d, 0xb1, 0xe0, 0xe1, 0xad, 0x00, 0x45, 0x59, 0x02, 0x9b, 0xac, 0x46, 0x00, 0xbb, 0xa5, 0xa5, 0x43, 0x08, 0x81, 0xc5, 0xac, 0x25, 0x1c, 0x8a, 0x01, 0xc7, 0x2d, 0x04, 0x69, 0x0e, 0x89, 0xeb, 0x6c, 0xb8, 0xe3, 0xdb, 0x4c, 0x60, 0x9d, 0x12, 0xf1, 0x1d, 0xf4, 0x21, 0xdd, 0xdf, 0x41, 0xc4, 0x1c, 0xae, 0x3a, 0x03, 0xd6, 0xd6, 0x7a, 0x25, 0x48, 0xcb, 0x36, 0x8b, 0xfa, 0x59, 0xb8, 0xfe, 0x6a, 0x2a, 0x39, 0x1b, 0x30, 0x60, 0xd0, 0x2e, 0x8b, 0x2d, 0xab, 0x0a, 0x99, 0x90, 0x31, 0xb9, 0x0f, 0x62, 0xa1, 0xb0, 0x1a, 0x3f, 0x3e, 0x43, 0xf6, 0xce, 0x94, 0x73, 0xcc, 0x88, 0xda, 0x76, 0x91, 0x66, 0x98, 0xa2, 0xd2, 0x4f, 0xdf, 0x81, 0xcb, 0x03, 0x7f, 0xc5, 0xc6, 0x73, 0xb0, 0xe6, 0xfb, 0x74, 0x98, 0xce, 0x1a, 0x86, 0xd7, 0xf7, 0xe8, 0x05, 0xf4, 0x65, 0xe6, 0x8b, 0xca, 0xe2, 0x95, 0x10, 0xdd, 0xdd, 0xec, 0xb6, 0x34, 0x2f, 0xae, 0x12, 0x10, 0x87, 0xc2, 0xea, 0x8c, 0x60, 0xeb, 0xc6, 0x3d, 0x40, 0x37, 0x38, 0xcf, 0x60, 0x3e, 0xfd, 0x7b, 0xc8, 0x31, 0x10, 0xfa, 0x29, 0x61, 0x5b, 0x93, 0x6e, 0x85, 0xa0, 0xd3, 0x5c, 0xe0, 0xa1, 0xa2, 0xf0, 0xff, 0xfb, 0x07, 0x2f, 0x48, 0xdb, 0x25, 0x84, 0x4d, 0xd0, 0x5c, 0xeb, 0xc0, 0xba, 0x8c, 0x51, 0x3d, 0x06, 0x69, 0x28, 0x42, 0xe6, 0x40, 0x4a, 0xfe, 0x20, 0x0d, 0x37, 0xc4, 0xe1, 0x46, 0x4f, 0x8e, 0x55, 0xc0, 0xd5, 0x13, 0x65, 0xf2, 0x99, 0xa2, 0x78, 0x3e, 0xd4, 0xc9, 0x47, 0x5d, 0x4d, 0x45, 0xbd, 0x5c, 0xd7, 0xe8, 0xd2, 0x82, 0xc2, 0x4a, 0xe5, 0xd1, 0x5d, 0xe9, 0x4a };
|
||||
static const unsigned char vec5_inv_cmsg1[519] = { 0x02, 0xa9, 0xf7, 0xa6, 0x54, 0x1e, 0x12, 0x22, 0x46, 0xfd, 0x57, 0xee, 0xdc, 0x6e, 0x3a, 0x6a, 0x12, 0x48, 0x05, 0x4f, 0x02, 0x2b, 0x7c, 0x01, 0xe2, 0xa4, 0x36, 0x4c, 0x09, 0x20, 0xda, 0x93, 0x4b, 0x03, 0x1a, 0x5c, 0xb4, 0x0b, 0x67, 0xdb, 0xbc, 0xc4, 0x8b, 0x03, 0xcc, 0x2c, 0xc5, 0x54, 0x52, 0x0c, 0x01, 0x72, 0x57, 0x55, 0xd5, 0x2a, 0x0d, 0xec, 0x5d, 0xb1, 0xe0, 0xe1, 0xad, 0x00, 0x45, 0x59, 0x02, 0x54, 0xc4, 0xc5, 0x71, 0x04, 0x3b, 0x01, 0x22, 0xe0, 0x1a, 0x79, 0x37, 0x1e, 0x0f, 0xc2, 0x6b, 0x66, 0x4e, 0xbc, 0xbb, 0x4e, 0x18, 0xe5, 0x1a, 0xa9, 0x67, 0x21, 0x18, 0x23, 0x0b, 0x86, 0xef, 0x02, 0x67, 0x0c, 0x35, 0xb2, 0xae, 0x50, 0x90, 0xff, 0xe0, 0x32, 0x36, 0xee, 0x4f, 0x86, 0xf9, 0x31, 0xac, 0x79, 0x80, 0x64, 0xfb, 0x9d, 0x9c, 0xd1, 0x95, 0x4b, 0xf0, 0x5f, 0xc1, 0x38, 0x38, 0x69, 0xf5, 0xb1, 0x94, 0x34, 0xb9, 0x81, 0x06, 0x4d, 0x17, 0xa1, 0x6a, 0x1d, 0x81, 0x58, 0x4c, 0xf0, 0x55, 0xdf, 0x32, 0x62, 0x08, 0xd8, 0x29, 0x1e, 0xf2, 0xa6, 0xa3, 0xdb, 0x52, 0x98, 0xb8, 0x0f, 0xe6, 0x49, 0x74, 0xe1, 0x9f, 0x90, 0x70, 0x66, 0x09, 0x6b, 0xa9, 0xd5, 0x05, 0xd6, 0xb2, 0x36, 0x7a, 0xf2, 0x9b, 0xbb, 0x0e, 0x66, 0xed, 0x22, 0xd5, 0xdf, 0x21, 0xba, 0x1e, 0x51, 0x77, 0x40, 0x1d, 0xf4, 0x21, 0xdd, 0xdf, 0x41, 0xc4, 0x1c, 0xae, 0x3a, 0x03, 0xd6, 0xd6, 0x7a, 0x25, 0x48, 0xcb, 0x36, 0x8b, 0xfa, 0x59, 0xb8, 0xfe, 0x6a, 0x2a, 0x39, 0x1b, 0x30, 0x60, 0xd0, 0x2e, 0x8b, 0x2d, 0xab, 0x0a, 0x99, 0x90, 0x31, 0xb9, 0x0f, 0x62, 0xa1, 0xb0, 0x1a, 0x3f, 0x3e, 0x43, 0xf6, 0xce, 0x94, 0x73, 0xcc, 0x88, 0xda, 0x76, 0x91, 0x66, 0x98, 0xa2, 0xd2, 0x4f, 0xdf, 0x81, 0xcb, 0xa7, 0x13, 0x00, 0x3b, 0x39, 0x2d, 0x2d, 0x35, 0xa5, 0x7c, 0x5d, 0x3c, 0x96, 0x92, 0xb8, 0xd4, 0x43, 0x94, 0xca, 0xf7, 0x71, 0x60, 0x5c, 0x6f, 0x5b, 0x99, 0x33, 0xcb, 0x39, 0xf8, 0xae, 0xf5, 0xbc, 0x92, 0x09, 0x3f, 0x03, 0xd0, 0x5c, 0x4a, 0x16, 0xff, 0x0a, 0xc3, 0x0b, 0x34, 0x78, 0xe7, 0xea, 0xfb, 0x48, 0xbc, 0x38, 0xbb, 0x18, 0x20, 0xf0, 0x8f, 0x10, 0x63, 0x3f, 0x42, 0xf4, 0xbd, 0x03, 0x07, 0xd9, 0x3f, 0x10, 0xca, 0xd5, 0x95, 0x92, 0xf3, 0x83, 0xc1, 0xd0, 0x0e, 0xb3, 0xb2, 0xf0, 0xea, 0xcb, 0x67, 0x79, 0xd7, 0xc1, 0x70, 0x0a, 0x42, 0x74, 0x77, 0x4d, 0xfd, 0x00, 0xab, 0x72, 0x03, 0x7f, 0xc5, 0xc6, 0x73, 0xb0, 0xe6, 0xfb, 0x74, 0x98, 0xce, 0x1a, 0x86, 0xd7, 0xf7, 0xe8, 0x05, 0xf4, 0x65, 0xe6, 0x8b, 0xca, 0xe2, 0x95, 0x10, 0xdd, 0xdd, 0xec, 0xb6, 0x34, 0x2f, 0xae, 0x12, 0x02, 0x6d, 0xda, 0xf4, 0x4d, 0x4a, 0x66, 0xfc, 0xf7, 0x7b, 0xc2, 0x81, 0x44, 0xa9, 0x62, 0xb9, 0x5b, 0xc9, 0x09, 0x9d, 0x87, 0x1e, 0x4d, 0xbe, 0x5f, 0x0a, 0x94, 0x78, 0xa5, 0x24, 0xaf, 0xb7, 0x90, 0x94, 0xac, 0x3f, 0x80, 0xa1, 0xae, 0x79, 0x9e, 0xab, 0xe7, 0x86, 0xae, 0xd5, 0x71, 0x9f, 0x2d, 0x2d, 0x81, 0xfc, 0x26, 0x4c, 0xa8, 0xad, 0xa1, 0x21, 0x1a, 0x7a, 0xc9, 0x86, 0x97, 0x22, 0x83, 0xe8, 0x09, 0x2c, 0xf2, 0xc3, 0x5d, 0xb9, 0x44, 0x39, 0xd7, 0xe9, 0x09, 0x4c, 0x0f, 0xa7, 0x3c, 0xd5, 0xc9, 0x2d, 0xbb, 0x16, 0xe2, 0xa8, 0x7e, 0x81, 0xd4, 0x66, 0x85, 0x4f, 0x68, 0xbe, 0x2e, 0x99, 0x7a, 0xea, 0x54, 0x29, 0x9c, 0x88, 0xcb, 0x83, 0x97, 0x67, 0xd4, 0x65, 0xdd, 0x18, 0x45, 0x35, 0x23, 0xac, 0x2b, 0x7d, 0x3c, 0x6b, 0x69, 0xa5, 0xc4, 0x1f, 0xdd, 0xe7, 0x7a, 0xe5, 0x61 };
|
||||
static const unsigned char vec5_inv_cinv[195] = { 0xe1, 0xab, 0xf1, 0x0b, 0xbb, 0x29, 0xf0, 0xf7, 0x33, 0xc4, 0x8e, 0x6f, 0xa6, 0x16, 0x94, 0x58, 0x75, 0x2a, 0x39, 0x8d, 0xfa, 0x5c, 0x37, 0x8d, 0x66, 0xb2, 0xb4, 0xfd, 0xe6, 0x5b, 0x27, 0xec, 0x46, 0x4f, 0x8e, 0x55, 0xc0, 0xd5, 0x13, 0x65, 0xf2, 0x99, 0xa2, 0x78, 0x3e, 0xd4, 0xc9, 0x47, 0x5d, 0x4d, 0x45, 0xbd, 0x5c, 0xd7, 0xe8, 0xd2, 0x82, 0xc2, 0x4a, 0xe5, 0xd1, 0x5d, 0xe9, 0x4a, 0x71, 0x7f, 0x6a, 0xf2, 0xad, 0x9d, 0x84, 0x6e, 0x5d, 0x39, 0x36, 0xec, 0x80, 0xf1, 0xba, 0xa4, 0x1d, 0x5b, 0x09, 0xc6, 0xd5, 0x50, 0xeb, 0x45, 0x7c, 0x21, 0x7e, 0x86, 0xff, 0xf8, 0x15, 0x6c, 0x03, 0x46, 0x53, 0x9b, 0xa9, 0x64, 0xd2, 0x4c, 0x64, 0x4b, 0x70, 0x9e, 0xa7, 0x39, 0xc3, 0xc0, 0x2d, 0x6a, 0xa3, 0xce, 0xe8, 0xd2, 0xad, 0x1d, 0x86, 0xff, 0x27, 0x51, 0x8b, 0xf6, 0xd1, 0xa4, 0x42, 0x03, 0x03, 0x35, 0xc1, 0x1b, 0x53, 0x33, 0xf4, 0xb5, 0x2c, 0x35, 0xaf, 0xcb, 0x5c, 0xc7, 0x8d, 0x15, 0x30, 0xdf, 0x92, 0x04, 0xe1, 0x26, 0xe1, 0x5f, 0x4b, 0x33, 0xb0, 0x2a, 0x59, 0x67, 0xf4, 0x80, 0x03, 0x31, 0x29, 0xb0, 0x6b, 0xfb, 0xf6, 0x50, 0xe1, 0x70, 0xd4, 0x90, 0x59, 0xd5, 0xcd, 0x80, 0x10, 0x1b, 0x39, 0xd8, 0x45, 0x04, 0x4f, 0xc3, 0x55, 0xea, 0x24, 0x18, 0x6f, 0x94, 0xe1, 0x62, 0xb2 };
|
||||
static const unsigned char vec5_inv_secshare[32] = { 0x40, 0x03, 0x27, 0xf8, 0xd3, 0xb5, 0x90, 0x1a, 0xb1, 0x15, 0x1f, 0x57, 0x34, 0xee, 0x71, 0xea, 0x8c, 0xa6, 0x79, 0x0f, 0xc6, 0xd7, 0x6a, 0xe8, 0x19, 0xc8, 0xb2, 0x46, 0x17, 0x4f, 0xaf, 0xce };
|
||||
static const unsigned char vec5_inv_pubshare[33] = { 0x02, 0x08, 0xd9, 0x49, 0xec, 0x74, 0xe5, 0xc0, 0xd9, 0x65, 0x75, 0xb8, 0x17, 0xd9, 0x3b, 0x00, 0xf8, 0xc3, 0xf6, 0x03, 0xde, 0x20, 0x66, 0x00, 0xc9, 0x3c, 0x18, 0xb0, 0x25, 0x4d, 0xc4, 0x47, 0x2e };
|
||||
static const unsigned char vec5_inv_enc_secshare[32] = { 0x99, 0x7a, 0xea, 0x54, 0x29, 0x9c, 0x88, 0xcb, 0x83, 0x97, 0x67, 0xd4, 0x65, 0xdd, 0x18, 0x45, 0x35, 0x23, 0xac, 0x2b, 0x7d, 0x3c, 0x6b, 0x69, 0xa5, 0xc4, 0x1f, 0xdd, 0xe7, 0x7a, 0xe5, 0x61 };
|
||||
static const unsigned char vec5_inv_pads[3][32] = {
|
||||
{ 0xa5, 0x7a, 0xcd, 0xa1, 0x9b, 0x4a, 0x2b, 0x89, 0xf3, 0x10, 0x6d, 0xd2, 0x77, 0x09, 0x3b, 0x29, 0x42, 0x86, 0x77, 0x22, 0x3b, 0x58, 0x8a, 0xe8, 0xa6, 0xa0, 0x9a, 0xfc, 0x43, 0x14, 0x42, 0x36 },
|
||||
{ 0x01, 0x8d, 0x94, 0xfa, 0x65, 0x1c, 0x3f, 0xdb, 0x06, 0x08, 0x3a, 0xcf, 0x2f, 0xd5, 0x79, 0x36, 0x53, 0x99, 0x1a, 0x8d, 0x80, 0x2f, 0x6a, 0xfa, 0x7a, 0xb4, 0x3d, 0x9f, 0xd1, 0x45, 0x59, 0xa2 },
|
||||
{ 0xb2, 0x6f, 0x5f, 0xbf, 0x55, 0x80, 0x8d, 0x4b, 0xd9, 0x69, 0x9f, 0xdb, 0x8a, 0x0f, 0xf1, 0xf9, 0xcd, 0x0c, 0x7e, 0x52, 0xaa, 0x25, 0xaa, 0xda, 0x2a, 0x78, 0xf3, 0x88, 0x8c, 0x07, 0xda, 0xfc },
|
||||
};
|
||||
/* investigation: dealer 1 sent bad share to participant 2; blame = FaultyParticipantOrCoordinatorError(1) */
|
||||
static const unsigned char vec5_inv_cmsg1_coord_bad[519] = { 0x02, 0xa9, 0xf7, 0xa6, 0x54, 0x1e, 0x12, 0x22, 0x46, 0xfd, 0x57, 0xee, 0xdc, 0x6e, 0x3a, 0x6a, 0x12, 0x48, 0x05, 0x4f, 0x02, 0x2b, 0x7c, 0x01, 0xe2, 0xa4, 0x36, 0x4c, 0x09, 0x20, 0xda, 0x93, 0x4b, 0x03, 0x1a, 0x5c, 0xb4, 0x0b, 0x67, 0xdb, 0xbc, 0xc4, 0x8b, 0x03, 0xcc, 0x2c, 0xc5, 0x54, 0x52, 0x0c, 0x01, 0x72, 0x57, 0x55, 0xd5, 0x2a, 0x0d, 0xec, 0x5d, 0xb1, 0xe0, 0xe1, 0xad, 0x00, 0x45, 0x59, 0x02, 0x54, 0xc4, 0xc5, 0x71, 0x04, 0x3b, 0x01, 0x22, 0xe0, 0x1a, 0x79, 0x37, 0x1e, 0x0f, 0xc2, 0x6b, 0x66, 0x4e, 0xbc, 0xbb, 0x4e, 0x18, 0xe5, 0x1a, 0xa9, 0x67, 0x21, 0x18, 0x23, 0x0b, 0x86, 0xef, 0x02, 0x67, 0x0c, 0x35, 0xb2, 0xae, 0x50, 0x90, 0xff, 0xe0, 0x32, 0x36, 0xee, 0x4f, 0x86, 0xf9, 0x31, 0xac, 0x79, 0x80, 0x64, 0xfb, 0x9d, 0x9c, 0xd1, 0x95, 0x4b, 0xf0, 0x5f, 0xc1, 0x38, 0x38, 0x69, 0xf5, 0xb1, 0x94, 0x34, 0xb9, 0x81, 0x06, 0x4d, 0x17, 0xa1, 0x6a, 0x1d, 0x81, 0x58, 0x4c, 0xf0, 0x55, 0xdf, 0x32, 0x62, 0x08, 0xd8, 0x29, 0x1e, 0xf2, 0xa6, 0xa3, 0xdb, 0x52, 0x98, 0xb8, 0x0f, 0xe6, 0x49, 0x74, 0xe1, 0x9f, 0x90, 0x70, 0x66, 0x09, 0x6b, 0xa9, 0xd5, 0x05, 0xd6, 0xb2, 0x36, 0x7a, 0xf2, 0x9b, 0xbb, 0x0e, 0x66, 0xed, 0x22, 0xd5, 0xdf, 0x21, 0xba, 0x1e, 0x51, 0x77, 0x40, 0x1d, 0xf4, 0x21, 0xdd, 0xdf, 0x41, 0xc4, 0x1c, 0xae, 0x3a, 0x03, 0xd6, 0xd6, 0x7a, 0x25, 0x48, 0xcb, 0x36, 0x8b, 0xfa, 0x59, 0xb8, 0xfe, 0x6a, 0x2a, 0x39, 0x1b, 0x30, 0x60, 0xd0, 0x2e, 0x8b, 0x2d, 0xab, 0x0a, 0x99, 0x90, 0x31, 0xb9, 0x0f, 0x62, 0xa1, 0xb0, 0x1a, 0x3f, 0x3e, 0x43, 0xf6, 0xce, 0x94, 0x73, 0xcc, 0x88, 0xda, 0x76, 0x91, 0x66, 0x98, 0xa2, 0xd2, 0x4f, 0xdf, 0x81, 0xcb, 0xa7, 0x13, 0x00, 0x3b, 0x39, 0x2d, 0x2d, 0x35, 0xa5, 0x7c, 0x5d, 0x3c, 0x96, 0x92, 0xb8, 0xd4, 0x43, 0x94, 0xca, 0xf7, 0x71, 0x60, 0x5c, 0x6f, 0x5b, 0x99, 0x33, 0xcb, 0x39, 0xf8, 0xae, 0xf5, 0xbc, 0x92, 0x09, 0x3f, 0x03, 0xd0, 0x5c, 0x4a, 0x16, 0xff, 0x0a, 0xc3, 0x0b, 0x34, 0x78, 0xe7, 0xea, 0xfb, 0x48, 0xbc, 0x38, 0xbb, 0x18, 0x20, 0xf0, 0x8f, 0x10, 0x63, 0x3f, 0x42, 0xf4, 0xbd, 0x03, 0x07, 0xd9, 0x3f, 0x10, 0xca, 0xd5, 0x95, 0x92, 0xf3, 0x83, 0xc1, 0xd0, 0x0e, 0xb3, 0xb2, 0xf0, 0xea, 0xcb, 0x67, 0x79, 0xd7, 0xc1, 0x70, 0x0a, 0x42, 0x74, 0x77, 0x4d, 0xfd, 0x00, 0xab, 0x72, 0x03, 0x7f, 0xc5, 0xc6, 0x73, 0xb0, 0xe6, 0xfb, 0x74, 0x98, 0xce, 0x1a, 0x86, 0xd7, 0xf7, 0xe8, 0x05, 0xf4, 0x65, 0xe6, 0x8b, 0xca, 0xe2, 0x95, 0x10, 0xdd, 0xdd, 0xec, 0xb6, 0x34, 0x2f, 0xae, 0x12, 0x02, 0x6d, 0xda, 0xf4, 0x4d, 0x4a, 0x66, 0xfc, 0xf7, 0x7b, 0xc2, 0x81, 0x44, 0xa9, 0x62, 0xb9, 0x5b, 0xc9, 0x09, 0x9d, 0x87, 0x1e, 0x4d, 0xbe, 0x5f, 0x0a, 0x94, 0x78, 0xa5, 0x24, 0xaf, 0xb7, 0x90, 0x94, 0xac, 0x3f, 0x80, 0xa1, 0xae, 0x79, 0x9e, 0xab, 0xe7, 0x86, 0xae, 0xd5, 0x71, 0x9f, 0x2d, 0x2d, 0x81, 0xfc, 0x26, 0x4c, 0xa8, 0xad, 0xa1, 0x21, 0x1a, 0x7a, 0xc9, 0x86, 0x97, 0x22, 0x83, 0xe8, 0x09, 0x2c, 0xf2, 0xc3, 0x5d, 0xb9, 0x44, 0x39, 0xd7, 0xe9, 0x09, 0x4c, 0x0f, 0xa7, 0x3c, 0xd5, 0xc9, 0x2d, 0xbb, 0x16, 0xe2, 0xa8, 0x7e, 0x81, 0xd4, 0x66, 0x85, 0x4f, 0x68, 0xbe, 0x2e, 0x99, 0x7a, 0xea, 0x54, 0x29, 0x9c, 0x88, 0xcb, 0x83, 0x97, 0x67, 0xd4, 0x65, 0xdd, 0x18, 0x45, 0x35, 0x23, 0xac, 0x2b, 0x7d, 0x3c, 0x6b, 0x69, 0xa5, 0xc4, 0x1f, 0xdd, 0xe7, 0x7a, 0xe5, 0x63 };
|
||||
/* investigation: coordinator tampered with enc_secshare of 2; blame = FaultyCoordinatorError */
|
||||
/* 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,
|
||||
@@ -706,7 +777,7 @@ static void chilldkg_simplpedpop_test(void) {
|
||||
secp256k1_chilldkg_simplpedpop_participant_step2_prepare_secshare(&secshare, partials, n);
|
||||
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);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[i], eq_input_p, &fault_index, NULL, &states[i], cmsg, cmsg_len, &secshare);
|
||||
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);
|
||||
@@ -735,7 +806,7 @@ static void chilldkg_simplpedpop_test(void) {
|
||||
memcpy(cmsg_bad, cmsg_bad + 33, 33);
|
||||
memcpy(cmsg_bad + 33, swap, 33);
|
||||
}
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, NULL, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
|
||||
/* A tampered pop blames the corresponding participant (or the
|
||||
@@ -743,7 +814,7 @@ static void chilldkg_simplpedpop_test(void) {
|
||||
memcpy(cmsg_bad, cmsg, cmsg_len);
|
||||
cmsg_bad[33 * 3 + 33 * 1 + 64 * 1] ^= 1;
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, NULL, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == 1);
|
||||
|
||||
@@ -757,7 +828,7 @@ static void chilldkg_simplpedpop_test(void) {
|
||||
memcpy(cmsg_bad + 33 * 3 + 33 + 2 * 64, swap, 64);
|
||||
}
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, NULL, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == 1);
|
||||
|
||||
@@ -765,7 +836,7 @@ static void chilldkg_simplpedpop_test(void) {
|
||||
memcpy(cmsg_bad, cmsg, cmsg_len);
|
||||
memset(cmsg_bad + 33 * 2, 0, 33);
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, NULL, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == 2);
|
||||
|
||||
@@ -776,16 +847,16 @@ static void chilldkg_simplpedpop_test(void) {
|
||||
memcpy(cmsg_bad, cmsg, cmsg_len);
|
||||
cmsg_bad[33 * 3] ^= 1;
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, NULL, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == UINT32_MAX);
|
||||
|
||||
/* A malformed cmsg (wrong length, invalid point) blames the coordinator. */
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, &states[0], cmsg, cmsg_len - 1, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, NULL, &states[0], cmsg, cmsg_len - 1, &secshare);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
memcpy(cmsg_bad, cmsg, cmsg_len);
|
||||
cmsg_bad[0] = 0x04;
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[0], eq_input, &fault_index, NULL, &states[0], cmsg_bad, cmsg_len, &secshare);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
|
||||
/* The coordinator blames the sender of a malformed participant message. */
|
||||
@@ -925,7 +996,7 @@ static void chilldkg_encpedpop_test(void) {
|
||||
* byte-exact. */
|
||||
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]);
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input_p, &fault_index, NULL, &states[i], vec_enc_hostseckeys[i], cmsg, cmsg_len, &enc_secshares[i]);
|
||||
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);
|
||||
@@ -943,7 +1014,7 @@ static void chilldkg_encpedpop_test(void) {
|
||||
/* The coordinator echoes a wrong pubnonce for us. */
|
||||
memcpy(cmsg_bad, cmsg, cmsg_len);
|
||||
cmsg_bad[simpl_cmsg_len] ^= 1;
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, &states[0], vec_enc_hostseckeys[0], cmsg_bad, cmsg_len, &enc_secshares[0]);
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, NULL, &states[0], vec_enc_hostseckeys[0], cmsg_bad, cmsg_len, &enc_secshares[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
|
||||
/* An invalid pubnonce of sender 1 (bad encoding, or the infinity
|
||||
@@ -951,13 +1022,13 @@ static void chilldkg_encpedpop_test(void) {
|
||||
memcpy(cmsg_bad, cmsg, cmsg_len);
|
||||
memset(cmsg_bad + simpl_cmsg_len + 33, 0xff, 33);
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, &states[0], vec_enc_hostseckeys[0], cmsg_bad, cmsg_len, &enc_secshares[0]);
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, NULL, &states[0], vec_enc_hostseckeys[0], cmsg_bad, cmsg_len, &enc_secshares[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == 1);
|
||||
memcpy(cmsg_bad, cmsg, cmsg_len);
|
||||
memset(cmsg_bad + simpl_cmsg_len + 33, 0, 33);
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, &states[0], vec_enc_hostseckeys[0], cmsg_bad, cmsg_len, &enc_secshares[0]);
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, NULL, &states[0], vec_enc_hostseckeys[0], cmsg_bad, cmsg_len, &enc_secshares[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == 1);
|
||||
|
||||
@@ -966,12 +1037,12 @@ static void chilldkg_encpedpop_test(void) {
|
||||
secp256k1_scalar_set_int(&scalar_tmp2, 1);
|
||||
secp256k1_scalar_add(&scalar_tmp, &enc_secshares[0], &scalar_tmp2);
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, &states[0], vec_enc_hostseckeys[0], cmsg, cmsg_len, &scalar_tmp);
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, NULL, &states[0], vec_enc_hostseckeys[0], cmsg, cmsg_len, &scalar_tmp);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == UINT32_MAX);
|
||||
|
||||
/* A malformed cmsg (wrong length) blames the coordinator. */
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, &states[0], vec_enc_hostseckeys[0], cmsg, cmsg_len - 1, &enc_secshares[0]);
|
||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input, &fault_index, NULL, &states[0], vec_enc_hostseckeys[0], cmsg, cmsg_len - 1, &enc_secshares[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
|
||||
/* The coordinator blames the sender of a malformed participant message:
|
||||
@@ -1127,7 +1198,7 @@ static void chilldkg_participant_api_test(void) {
|
||||
|
||||
/* 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]);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[i], sig64[i], &fault_index, NULL, &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);
|
||||
}
|
||||
@@ -1154,7 +1225,7 @@ static void chilldkg_participant_api_test(void) {
|
||||
* 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]);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, NULL, &state1[0], vec3_hostseckeys[1], cmsg1, vec3_aux_rands[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
CHECK(secp256k1_is_zero_array(tmp_sig64, 64));
|
||||
}
|
||||
@@ -1171,7 +1242,7 @@ static void chilldkg_participant_api_test(void) {
|
||||
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]);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, NULL, &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);
|
||||
|
||||
@@ -1181,7 +1252,7 @@ static void chilldkg_participant_api_test(void) {
|
||||
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]);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, NULL, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == 1);
|
||||
|
||||
@@ -1190,7 +1261,7 @@ static void chilldkg_participant_api_test(void) {
|
||||
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]);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, NULL, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
}
|
||||
|
||||
@@ -1201,7 +1272,7 @@ static void chilldkg_participant_api_test(void) {
|
||||
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]);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &fresh_state2, tmp_sig64, &fault_index, NULL, &fresh_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
|
||||
memcpy(cmsg2_bad, cmsg2, sizeof(cmsg2));
|
||||
@@ -1228,13 +1299,13 @@ static void chilldkg_participant_api_test(void) {
|
||||
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_step2(CTX, NULL, sig64[0], &fault_index, 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], NULL, &fault_index, 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], NULL, 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, 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, NULL, &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, NULL, &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, NULL, &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));
|
||||
@@ -1250,11 +1321,11 @@ static void chilldkg_participant_api_test(void) {
|
||||
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_step2(CTX, &state2[0], tmp_sig64, &fault_index, NULL, &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));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, NULL, &bad_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -1301,7 +1372,7 @@ static void chilldkg_coordinator_api_test(void) {
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
CHECK(secp256k1_memcmp_var(cmsg1, vec3_cmsg1, cmsg1_len) == 0);
|
||||
for (i = 0; i < n; i++) {
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &p_state2[i], pmsg2[i], &fault_index, &p_state1[i], vec3_hostseckeys[i], cmsg1, vec3_aux_rands[i]);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &p_state2[i], pmsg2[i], &fault_index, NULL, &p_state1[i], vec3_hostseckeys[i], cmsg1, vec3_aux_rands[i]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
CHECK(secp256k1_memcmp_var(pmsg2[i], vec3_pmsgs2[i], 64) == 0);
|
||||
}
|
||||
@@ -1410,6 +1481,283 @@ static void chilldkg_coordinator_api_test(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void chilldkg_recovery_test(void) {
|
||||
const size_t n = 3;
|
||||
const uint32_t t = 2;
|
||||
const size_t recovery_len = 4 + 33 * 2 + 162 * 3; /* 556 */
|
||||
unsigned char hostpubkeys33[3 * 33];
|
||||
unsigned char pubshares33[3 * 33];
|
||||
unsigned char hostpubkeys_out[3 * 33];
|
||||
unsigned char recovery[556];
|
||||
unsigned char recovery_bad[556];
|
||||
unsigned char buf33[33];
|
||||
unsigned char secshare32[32];
|
||||
unsigned char ack_sigs[3][64];
|
||||
const unsigned char *ack_sig_ptrs[3];
|
||||
size_t n_out;
|
||||
uint32_t t_out, fault_index;
|
||||
secp256k1_chilldkg_fault fault;
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
memcpy(hostpubkeys33 + 33 * i, vec5_hostpubkeys[i], 33);
|
||||
ack_sig_ptrs[i] = ack_sigs[i];
|
||||
}
|
||||
|
||||
CHECK(secp256k1_chilldkg_investigation_msg_len(n) == 65 * n);
|
||||
CHECK(secp256k1_chilldkg_investigation_msg_len(0) == 0);
|
||||
CHECK(secp256k1_chilldkg_investigation_msg_len(SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 1) == 0);
|
||||
|
||||
/* Recovery data taken from the reference vectors directly (the session
|
||||
* itself is covered by the participant/coordinator API tests). */
|
||||
memcpy(recovery, vec5_recovery, recovery_len);
|
||||
|
||||
/* participant_recover: outputs match the session's DKG output. */
|
||||
for (i = 0; i < n; i++) {
|
||||
fault = secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, vec5_hostseckeys[i], recovery, recovery_len);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
CHECK(secp256k1_memcmp_var(secshare32, vec5_secshares[i], 32) == 0);
|
||||
CHECK(secp256k1_memcmp_var(buf33, vec5_thresh_pk, 33) == 0);
|
||||
for (j = 0; j < n; j++) {
|
||||
CHECK(secp256k1_memcmp_var(pubshares33 + 33 * j, vec5_pubshares[j], 33) == 0);
|
||||
CHECK(secp256k1_memcmp_var(hostpubkeys_out + 33 * j, vec5_hostpubkeys[j], 33) == 0);
|
||||
}
|
||||
CHECK(n_out == n && t_out == t);
|
||||
}
|
||||
|
||||
/* coordinator_recover: same outputs, no secret share. */
|
||||
fault = secp256k1_chilldkg_coordinator_recover(CTX, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, recovery, recovery_len);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
CHECK(secp256k1_memcmp_var(buf33, vec5_thresh_pk, 33) == 0);
|
||||
CHECK(n_out == n && t_out == t);
|
||||
for (j = 0; j < n; j++) {
|
||||
CHECK(secp256k1_memcmp_var(pubshares33 + 33 * j, vec5_pubshares[j], 33) == 0);
|
||||
}
|
||||
|
||||
/* Invalid recovery data is an input error (RecoveryDataError in the
|
||||
* reference) and zeroes the outputs. */
|
||||
memcpy(recovery_bad, recovery, recovery_len);
|
||||
recovery_bad[recovery_len - 1] ^= 1; /* corrupt the last cert signature */
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, vec5_hostseckeys[0], recovery_bad, recovery_len);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
CHECK(fault_index == UINT32_MAX);
|
||||
CHECK(secp256k1_is_zero_array(secshare32, 32));
|
||||
CHECK(secp256k1_is_zero_array(buf33, 33));
|
||||
CHECK(n_out == 0 && t_out == 0);
|
||||
/* Truncated and extended recovery data have inconsistent lengths. */
|
||||
fault = secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, vec5_hostseckeys[0], recovery, recovery_len - 1);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
fault = secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, vec5_hostseckeys[0], recovery, 3);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
fault = secp256k1_chilldkg_coordinator_recover(CTX, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, recovery, recovery_len + 1);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
/* A host secret key not in the session is an input error
|
||||
* (HostSeckeyError in the reference). */
|
||||
{
|
||||
unsigned char other_seckey[32] = { 0 };
|
||||
other_seckey[31] = 1; /* valid key, but not in the session */
|
||||
fault = secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, other_seckey, recovery, recovery_len);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
}
|
||||
{
|
||||
unsigned char zero32[32] = { 0 };
|
||||
fault = secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, zero32, recovery, recovery_len);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
}
|
||||
|
||||
/* Recovery acks: byte-exact signatures, and verification succeeds. */
|
||||
for (i = 0; i < n; i++) {
|
||||
CHECK(secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[i], vec5_hostseckeys[i], hostpubkeys33, n, t, recovery, recovery_len, vec5_ack_aux_rands[i]) == 1);
|
||||
CHECK(secp256k1_memcmp_var(ack_sigs[i], vec5_ack_sigs[i], 64) == 0);
|
||||
}
|
||||
fault = secp256k1_chilldkg_recovery_acks_verify(CTX, &fault_index, hostpubkeys33, n, t, recovery, recovery_len, ack_sig_ptrs);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
|
||||
/* An invalid ack blames its signer (InvalidRecoveryAckError is a
|
||||
* FaultyParticipantError in the reference). */
|
||||
{
|
||||
unsigned char ack_bad[64];
|
||||
const unsigned char *bad_ptrs[3];
|
||||
bad_ptrs[0] = ack_sigs[0];
|
||||
bad_ptrs[1] = ack_bad;
|
||||
bad_ptrs[2] = ack_sigs[2];
|
||||
memcpy(ack_bad, ack_sigs[1], 64);
|
||||
ack_bad[7] ^= 1;
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_recovery_acks_verify(CTX, &fault_index, hostpubkeys33, n, t, recovery, recovery_len, bad_ptrs);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT);
|
||||
CHECK(fault_index == 1);
|
||||
/* An ack for the wrong participant index fails verification. */
|
||||
bad_ptrs[1] = ack_sigs[2];
|
||||
bad_ptrs[2] = ack_sigs[1];
|
||||
fault = secp256k1_chilldkg_recovery_acks_verify(CTX, &fault_index, hostpubkeys33, n, t, recovery, recovery_len, bad_ptrs);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT);
|
||||
CHECK(fault_index == 1);
|
||||
}
|
||||
|
||||
/* Ack sign/verify with mismatched session parameters or recovery data
|
||||
* fails (RecoveryDataError in the reference). */
|
||||
CHECK(secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[0], vec5_hostseckeys[0], hostpubkeys33, n, 1, recovery, recovery_len, vec5_ack_aux_rands[0]) == 0);
|
||||
CHECK(secp256k1_is_zero_array(ack_sigs[0], 64));
|
||||
memcpy(recovery_bad, recovery, recovery_len);
|
||||
recovery_bad[4 + 33 * 2] ^= 1; /* corrupt a host public key in eq_input */
|
||||
CHECK(secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[0], vec5_hostseckeys[0], hostpubkeys33, n, t, recovery_bad, recovery_len, vec5_ack_aux_rands[0]) == 0);
|
||||
fault = secp256k1_chilldkg_recovery_acks_verify(CTX, &fault_index, hostpubkeys33, n, t, recovery_bad, recovery_len, ack_sig_ptrs);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
/* A host secret key not in the session cannot sign an ack. */
|
||||
{
|
||||
unsigned char other_seckey[32] = { 0 };
|
||||
other_seckey[31] = 1;
|
||||
CHECK(secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[0], other_seckey, hostpubkeys33, n, t, recovery, recovery_len, vec5_ack_aux_rands[0]) == 0);
|
||||
}
|
||||
|
||||
/* API misuse. */
|
||||
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_recovery_ack_sign(CTX, NULL, vec5_hostseckeys[0], hostpubkeys33, n, t, recovery, recovery_len, vec5_ack_aux_rands[0]));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[0], NULL, hostpubkeys33, n, t, recovery, recovery_len, vec5_ack_aux_rands[0]));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[0], vec5_hostseckeys[0], NULL, n, t, recovery, recovery_len, vec5_ack_aux_rands[0]));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[0], vec5_hostseckeys[0], hostpubkeys33, n, t, NULL, recovery_len, vec5_ack_aux_rands[0]));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_recovery_ack_sign(CTX, ack_sigs[0], vec5_hostseckeys[0], hostpubkeys33, n, t, recovery, recovery_len, NULL));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_recover(CTX, NULL, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, vec5_hostseckeys[0], recovery, recovery_len) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, NULL, recovery, recovery_len) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_recover(CTX, secshare32, buf33, pubshares33, hostpubkeys_out, &n_out, &t_out, &fault_index, vec5_hostseckeys[0], NULL, recovery_len) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_coordinator_recover(CTX, NULL, pubshares33, hostpubkeys_out, &n_out, &t_out, recovery, recovery_len) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_recovery_acks_verify(CTX, NULL, hostpubkeys33, n, t, recovery, recovery_len, ack_sig_ptrs) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_recovery_acks_verify(CTX, &fault_index, NULL, n, t, recovery, recovery_len, ack_sig_ptrs) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_recovery_acks_verify(CTX, &fault_index, hostpubkeys33, n, t, recovery, recovery_len, NULL) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
}
|
||||
|
||||
static void chilldkg_investigate_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 cinv_len = 65 * 3; /* 195 */
|
||||
const uint32_t dealer = 1;
|
||||
const uint32_t victim = 2;
|
||||
secp256k1_chilldkg_participant_state1 state1;
|
||||
secp256k1_chilldkg_participant_state2 state2;
|
||||
secp256k1_chilldkg_participant_inv_data inv_data;
|
||||
secp256k1_chilldkg_coordinator_state coord_state;
|
||||
unsigned char pmsg1[3][259];
|
||||
const unsigned char *pmsg1_ptrs[3];
|
||||
unsigned char cmsg1[519];
|
||||
unsigned char cinv[195];
|
||||
unsigned char cinv_bad[195];
|
||||
unsigned char hostpubkeys33[3 * 33];
|
||||
unsigned char sig64[64];
|
||||
secp256k1_chilldkg_fault fault;
|
||||
uint32_t fault_index = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
pmsg1_ptrs[i] = pmsg1[i];
|
||||
memcpy(hostpubkeys33 + 33 * i, vec5_hostpubkeys[i], 33);
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
CHECK(secp256k1_chilldkg_participant_step1(CTX, &state1, pmsg1[i], vec5_hostseckeys[i], hostpubkeys33, n, t, vec5_randoms[i]) == 1);
|
||||
CHECK(secp256k1_memcmp_var(pmsg1[i], vec5_pmsgs1[i], pmsg1_len) == 0);
|
||||
}
|
||||
|
||||
/* Scenario 1: dealer 1 sent a corrupted encrypted share to participant
|
||||
* 2. */
|
||||
memcpy(pmsg1[dealer], vec5_inv_pmsg1_bad, pmsg1_len);
|
||||
fault = secp256k1_chilldkg_coordinator_step1(CTX, &coord_state, cmsg1, &fault_index, pmsg1_ptrs, hostpubkeys33, n, t);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
CHECK(secp256k1_memcmp_var(cmsg1, vec5_inv_cmsg1, cmsg1_len) == 0);
|
||||
|
||||
/* The victim's step2 fails with UNKNOWN and fills the inv data. */
|
||||
CHECK(secp256k1_chilldkg_participant_step1(CTX, &state1, pmsg1[victim], vec5_hostseckeys[victim], hostpubkeys33, n, t, vec5_randoms[victim]) == 1);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &state2, sig64, &fault_index, &inv_data, &state1, vec5_hostseckeys[victim], cmsg1, vec5_aux_rands[victim]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == UINT32_MAX);
|
||||
CHECK(secp256k1_is_zero_array(sig64, 64));
|
||||
/* The inv data is byte-exact against the reference's
|
||||
* ParticipantInvestigationData (layout: magic || n || participant_id ||
|
||||
* secshare || pubshare || enc_secshare || pads). */
|
||||
CHECK(secp256k1_read_be32(&inv_data.data[4]) == n);
|
||||
CHECK(secp256k1_read_be32(&inv_data.data[8]) == victim);
|
||||
CHECK(secp256k1_memcmp_var(&inv_data.data[12], vec5_inv_secshare, 32) == 0);
|
||||
CHECK(secp256k1_memcmp_var(&inv_data.data[44], vec5_inv_pubshare, 33) == 0);
|
||||
CHECK(secp256k1_memcmp_var(&inv_data.data[77], vec5_inv_enc_secshare, 32) == 0);
|
||||
for (i = 0; i < n; i++) {
|
||||
CHECK(secp256k1_memcmp_var(&inv_data.data[109 + 32 * i], vec5_inv_pads[i], 32) == 0);
|
||||
}
|
||||
|
||||
/* The coordinator's investigation message is byte-exact. */
|
||||
fault = secp256k1_chilldkg_coordinator_investigate(CTX, cinv, &fault_index, pmsg1_ptrs, hostpubkeys33, n, t, victim);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
CHECK(secp256k1_memcmp_var(cinv, vec5_inv_cinv, cinv_len) == 0);
|
||||
|
||||
/* The investigation blames the dealer. */
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_participant_investigate(CTX, &fault_index, &inv_data, cinv);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
CHECK(fault_index == dealer);
|
||||
|
||||
/* A malformed investigation message (invalid point encoding, wrong
|
||||
* scalar) blames the coordinator. */
|
||||
memcpy(cinv_bad, cinv, cinv_len);
|
||||
cinv_bad[32 * n] = 0x07; /* invalid prefix of the first partial pubshare */
|
||||
fault = secp256k1_chilldkg_participant_investigate(CTX, &fault_index, &inv_data, cinv_bad);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
memcpy(cinv_bad, cinv, cinv_len);
|
||||
memset(cinv_bad, 0xff, 32); /* overflowing first encrypted partial share */
|
||||
fault = secp256k1_chilldkg_participant_investigate(CTX, &fault_index, &inv_data, cinv_bad);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
|
||||
/* Scenario 2: the coordinator tampered with the encrypted secshare of
|
||||
* participant 2 in cmsg1. */
|
||||
for (i = 0; i < n; i++) {
|
||||
memcpy(pmsg1[i], vec5_pmsgs1[i], pmsg1_len);
|
||||
}
|
||||
memcpy(cmsg1, vec5_inv_cmsg1_coord_bad, cmsg1_len);
|
||||
CHECK(secp256k1_chilldkg_participant_step1(CTX, &state1, pmsg1[victim], vec5_hostseckeys[victim], hostpubkeys33, n, t, vec5_randoms[victim]) == 1);
|
||||
fault = secp256k1_chilldkg_participant_step2(CTX, &state2, sig64, &fault_index, &inv_data, &state1, vec5_hostseckeys[victim], cmsg1, vec5_aux_rands[victim]);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||
fault = secp256k1_chilldkg_coordinator_investigate(CTX, cinv, &fault_index, pmsg1_ptrs, hostpubkeys33, n, t, victim);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_participant_investigate(CTX, &fault_index, &inv_data, cinv);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||
CHECK(fault_index == UINT32_MAX);
|
||||
|
||||
/* coordinator_investigate: a malformed pmsg1 blames its sender; an
|
||||
* out-of-range participant id is an input error. */
|
||||
{
|
||||
unsigned char pmsg1_bad[259];
|
||||
const unsigned char *bad_ptrs[3];
|
||||
bad_ptrs[0] = pmsg1[0];
|
||||
bad_ptrs[1] = pmsg1_bad;
|
||||
bad_ptrs[2] = pmsg1[2];
|
||||
memcpy(pmsg1_bad, pmsg1[1], pmsg1_len);
|
||||
memset(pmsg1_bad + 33 * 2 + 97, 0xff, 32); /* overflowing share for participant 0 */
|
||||
fault_index = 0;
|
||||
fault = secp256k1_chilldkg_coordinator_investigate(CTX, cinv, &fault_index, bad_ptrs, hostpubkeys33, n, t, victim);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT);
|
||||
CHECK(fault_index == 1);
|
||||
fault = secp256k1_chilldkg_coordinator_investigate(CTX, cinv, &fault_index, pmsg1_ptrs, hostpubkeys33, n, t, (uint32_t)n);
|
||||
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||
CHECK(secp256k1_is_zero_array(cinv, cinv_len));
|
||||
}
|
||||
|
||||
/* A zeroed (or corrupted) inv_data object is rejected. */
|
||||
{
|
||||
secp256k1_chilldkg_participant_inv_data bad_inv_data;
|
||||
memset(&bad_inv_data, 0, sizeof(bad_inv_data));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_investigate(CTX, &fault_index, &bad_inv_data, cinv) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
}
|
||||
|
||||
/* API misuse. */
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_coordinator_investigate(CTX, NULL, &fault_index, pmsg1_ptrs, hostpubkeys33, n, t, victim) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_coordinator_investigate(CTX, cinv, NULL, pmsg1_ptrs, hostpubkeys33, n, t, victim) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_coordinator_investigate(CTX, cinv, &fault_index, NULL, hostpubkeys33, n, t, victim) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_coordinator_investigate(CTX, cinv, &fault_index, pmsg1_ptrs, NULL, n, t, victim) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_investigate(CTX, NULL, &inv_data, cinv) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_investigate(CTX, &fault_index, NULL, cinv) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_investigate(CTX, &fault_index, &inv_data, NULL) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||
}
|
||||
|
||||
static const struct tf_test_entry tests_chilldkg[] = {
|
||||
CASE1(chilldkg_tagged_hashes_test),
|
||||
CASE1(chilldkg_params_hash_test),
|
||||
@@ -1422,6 +1770,8 @@ static const struct tf_test_entry tests_chilldkg[] = {
|
||||
CASE1(chilldkg_encpedpop_test),
|
||||
CASE1(chilldkg_participant_api_test),
|
||||
CASE1(chilldkg_coordinator_api_test),
|
||||
CASE1(chilldkg_recovery_test),
|
||||
CASE1(chilldkg_investigate_test),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user