extern crate std;
use core::cell::Cell;
use rand_chacha::ChaCha8Rng;
use rand_core::{Rng, SeedableRng};
use std::vec::Vec;
use crate::{
keygen::{ClientKeyShare, ClientKeygen0, ServerKeyShare, ServerKeygen0},
setup::SetupData,
sign::{ClientSign, ServerSign0},
testutil::{TestClock, fx, keygen, params},
};
fn mutate(rng: &mut ChaCha8Rng, src: &[u8]) -> Vec<u8> {
let mut v = src.to_vec();
match rng.next_u32() % 6 {
0 => {
for _ in 0..=rng.next_u32() % 4 {
if !v.is_empty() {
let i = rng.next_u32() as usize % v.len();
v[i] ^= 1 << (rng.next_u32() % 8);
}
}
}
1 => v.truncate(rng.next_u32() as usize % (v.len() + 1)),
2 => {
let extra = 1 + rng.next_u32() as usize % 16;
let mut tail = std::vec![0u8; extra];
rng.fill_bytes(&mut tail);
v.extend(tail);
}
3 => {
if !v.is_empty() {
let i = rng.next_u32() as usize % v.len();
let n = (1 + rng.next_u32() as usize % 40).min(v.len() - i);
let b = if rng.next_u32() & 1 == 0 { 0 } else { 0xFF };
v[i..i + n].fill(b);
}
}
4 => {
rng.fill_bytes(&mut v);
}
_ => {
if v.len() > 4 {
let i = rng.next_u32() as usize % (v.len() - 2);
let n = 1 + rng.next_u32() as usize % (v.len() - i).min(64);
let chunk = v[i..i + n].to_vec();
v.splice(i..i, chunk);
}
}
}
v
}
const ROUNDS: usize = 150;
#[test]
fn mangled_keygen_and_setup_never_panic_or_verify() {
let p = params();
let mut rng = ChaCha8Rng::seed_from_u64(900);
let clock = TestClock(Cell::new(1_000));
let (s1, m1) = ServerKeygen0::start(&mut rng, &p, &fx().data, b"c").unwrap();
let (c1, m2) = ClientKeygen0::on_msg1(&mut rng, &clock, &fx().setup, b"c", &m1).unwrap();
let (_, m3) = s1.on_msg2(&mut rng, &m2).unwrap();
let _ = c1;
for _ in 0..ROUNDS {
let bad1 = mutate(&mut rng, &m1);
if bad1 != m1 {
let (s1, m1) = ServerKeygen0::start(&mut rng, &p, &fx().data, b"c").unwrap();
let bad1 = mutate(&mut rng, &m1);
if bad1 != m1 {
let done = ClientKeygen0::on_msg1(&mut rng, &clock, &fx().setup, b"c", &bad1)
.and_then(|(c1, m2)| {
let (_, m3) = s1.on_msg2(&mut rng, &m2)?;
c1.on_msg3(&clock, &m3)
});
assert!(done.is_err());
}
}
let bad2 = mutate(&mut rng, &m2);
if bad2 != m2 {
let (s1, _) = ServerKeygen0::start(&mut rng, &p, &fx().data, b"c").unwrap();
assert!(s1.on_msg2(&mut rng, &bad2).is_err());
}
let bad3 = mutate(&mut rng, &m3);
if bad3 != m3 {
let (s1, m1) = ServerKeygen0::start(&mut rng, &p, &fx().data, b"c").unwrap();
let (c1, _) = ClientKeygen0::on_msg1(&mut rng, &clock, &fx().setup, b"c", &m1).unwrap();
let _ = s1;
assert!(c1.on_msg3(&clock, &bad3).is_err());
}
}
let bytes = fx().data.to_bytes().unwrap();
for _ in 0..40 {
let bad = mutate(&mut rng, &bytes);
if bad == bytes {
continue;
}
if let Ok(d) = SetupData::from_bytes_with(&bad, &p, &fx().fac) {
assert!(d.verify_with(&p, &fx().fac).is_err());
}
}
}
#[test]
fn mangled_signing_and_secrets_never_panic_or_verify() {
let p = params();
let mut rng = ChaCha8Rng::seed_from_u64(901);
let (c, s) = keygen(60);
let d = [5u8; 32];
let (st, m1) = ServerSign0::start(&mut rng, &fx().server_view, &s, b"c", &d, None).unwrap();
let m2 = ClientSign::respond(&mut rng, &fx().setup, &c, b"c", &d, &m1, None).unwrap();
let _ = st;
for _ in 0..ROUNDS {
let bad1 = mutate(&mut rng, &m1);
if bad1 != m1 {
assert!(ClientSign::respond(&mut rng, &fx().setup, &c, b"c", &d, &bad1, None).is_err());
}
let bad2 = mutate(&mut rng, &m2);
if bad2 != m2 {
let (st, m1b) =
ServerSign0::start(&mut rng, &fx().server_view, &s, b"c", &d, None).unwrap();
let _ = m1b;
assert!(
st.finish(&fx().server_view, fx().sk.paillier_sk(), &bad2)
.is_err()
);
}
}
let cs = c.export_secret();
let ss = s.export_secret();
for _ in 0..60 {
let bad = mutate(&mut rng, &cs);
if bad.as_slice() != cs.as_slice() {
if let Ok(x) = ClientKeyShare::import_secret(&bad, &p) {
assert_ne!(x.export_secret().as_slice(), cs.as_slice());
}
}
let bad = mutate(&mut rng, &ss);
if bad.as_slice() != ss.as_slice() {
if let Ok(x) = ServerKeyShare::import_secret(&bad, &p) {
assert_ne!(x.export_secret().as_slice(), ss.as_slice());
}
}
}
}