diff --git a/cggmp24-keygen/src/lib.rs b/cggmp24-keygen/src/lib.rs index c834ccf..4c20b70 100644 --- a/cggmp24-keygen/src/lib.rs +++ b/cggmp24-keygen/src/lib.rs @@ -363,6 +363,14 @@ enum Bug { ZeroShare, #[displaydoc("shared public key is zero - probability of that is negligible")] ZeroPk, + #[displaydoc("too few parties: n must be at least 2")] + TooFewParties, + #[displaydoc("threshold too small: t must be at least 2")] + ThresholdTooSmall, + #[displaydoc("threshold too large: t must not exceed n")] + ThresholdTooLarge, + #[displaydoc("party index out of range: i must be less than n")] + PartyIndexOutOfRange, } /// Distributed key generation protocol diff --git a/cggmp24-keygen/src/threshold.rs b/cggmp24-keygen/src/threshold.rs index 7f67af2..d63ac78 100644 --- a/cggmp24-keygen/src/threshold.rs +++ b/cggmp24-keygen/src/threshold.rs @@ -150,6 +150,19 @@ where R: RngCore + CryptoRng, M: Mpc>, { + if n < 2 { + return Err(Bug::TooFewParties.into()); + } + if t < 2 { + return Err(Bug::ThresholdTooSmall.into()); + } + if t > n { + return Err(Bug::ThresholdTooLarge.into()); + } + if i >= n { + return Err(Bug::PartyIndexOutOfRange.into()); + } + tracer.protocol_begins(); tracer.stage("Setup networking"); diff --git a/tests/tests/it/keygen.rs b/tests/tests/it/keygen.rs index e9a008a..e61eef4 100644 --- a/tests/tests/it/keygen.rs +++ b/tests/tests/it/keygen.rs @@ -138,6 +138,72 @@ where validate_keygen_output::(&mut rng, &key_shares); } +cggmp24_tests::test_suite! { + test: threshold_keygen_rejects_invalid_params, + generics: all_curves, + suites: { + t_greater_than_n: (5, 3), + t_too_small: (1, 3), + n_too_small: (2, 1), + } +} +fn threshold_keygen_rejects_invalid_params(t: u16, n: u16) +where + E: Curve + cggmp24_tests::CurveParams, +{ + let mut rng = DevRng::new(); + + let eid: [u8; 32] = rng.gen(); + let eid = ExecutionId::new(&eid); + + let sim_n = n.max(1); + let results = round_based::sim::run(sim_n, |i, party| { + let party = cggmp24_tests::buffer_outgoing(party); + let mut party_rng = rng.fork(); + + async move { + cggmp24::keygen::(eid, i, n) + .set_security_level::() + .set_digest::() + .set_threshold(t) + .start(&mut party_rng, party) + .await + } + }) + .unwrap() + .into_vec(); + + for result in &results { + assert!(result.is_err(), "expected error for t={t}, n={n}, got Ok"); + } +} + +#[test] +fn threshold_keygen_rejects_i_out_of_range() { + let mut rng = DevRng::new(); + + let eid: [u8; 32] = rng.gen(); + let eid = ExecutionId::new(&eid); + + let (t, n) = (2, 3); + let bad_i = n; + let result = round_based::sim::run(1, |_sim_i, party| { + let party = cggmp24_tests::buffer_outgoing(party); + let mut party_rng = rng.fork(); + + async move { + cggmp24::keygen::(eid, bad_i, n) + .set_threshold(t) + .start(&mut party_rng, party) + .await + } + }) + .unwrap() + .into_vec(); + + assert!(result[0].is_err(), "expected error for i >= n, got Ok"); +} + fn validate_keygen_output>( rng: &mut impl rand::RngCore, key_shares: &[cggmp24::IncompleteKeyShare],