use std::time::Duration;
use tacet::{helpers::InputPair, timing_test_checked, AttackerModel, Outcome, TimingOracle};
fn main() {
println!("tacet simple example\n");
let secret = [0u8; 32];
let inputs = InputPair::new(
|| [0u8; 32], || {
let mut arr = [0u8; 32];
for item in &mut arr {
*item = rand::random();
}
arr
},
);
let outcome = TimingOracle::for_attacker(AttackerModel::AdjacentNetwork)
.time_budget(Duration::from_secs(30))
.test(inputs, |data| {
compare_bytes(&secret, data);
});
match &outcome {
Outcome::Pass {
leak_probability,
quality,
diagnostics,
..
} => {
println!("Result: PASS");
println!("Leak probability: {:.1}%", leak_probability * 100.0);
println!("Quality: {:?}", quality);
println!("Timer resolution: {:.1}ns", diagnostics.timer_resolution_ns);
}
Outcome::Fail {
leak_probability,
exploitability,
effect,
..
} => {
println!("Result: FAIL");
println!("Leak probability: {:.1}%", leak_probability * 100.0);
println!("Exploitability: {:?}", exploitability);
println!(
"Max effect: {:.1}ns (95% CI: {:.1}–{:.1}ns)",
effect.max_effect_ns, effect.credible_interval_ns.0, effect.credible_interval_ns.1
);
}
Outcome::Inconclusive {
reason,
leak_probability,
..
} => {
println!("Result: INCONCLUSIVE");
println!("Leak probability: {:.1}%", leak_probability * 100.0);
println!("Reason: {:?}", reason);
}
Outcome::Unmeasurable { recommendation, .. } => {
println!("Could not measure: {}", recommendation);
return;
}
Outcome::Research(research) => {
println!("Result: RESEARCH MODE");
println!("Max effect: {:.1}ns", research.max_effect_ns);
println!("Status: {:?}", research.status);
return;
}
}
let outcome = timing_test_checked! {
oracle: TimingOracle::for_attacker(AttackerModel::AdjacentNetwork)
.time_budget(Duration::from_secs(10)),
baseline: || [0u8; 32],
sample: || {
let mut arr = [0u8; 32];
for item in &mut arr {
*item = rand::random();
}
arr
},
measure: |data| {
compare_bytes(&secret, data);
},
};
if let Outcome::Pass {
leak_probability, ..
}
| Outcome::Fail {
leak_probability, ..
} = outcome
{
println!("\nWith custom config:");
println!("Leak probability: {:.1}%", leak_probability * 100.0);
}
}
fn compare_bytes(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
for i in 0..a.len() {
if a[i] != b[i] {
return false; }
}
true
}