use crate::source::{EntropySource, Platform, Requirement, SourceCategory, SourceInfo};
static SITVA_INFO: SourceInfo = SourceInfo {
name: "sitva",
description: "Scheduler-induced timing variance amplification via NEON FMLA companion thread",
physics: "Spawns a companion thread running continuous NEON FMLA (FP multiply-accumulate) \
bursts. The macOS scheduler responds by increasing preemption frequency and \
migrating threads across P/E cores, which creates a bimodal AES timing \
distribution: fast (post-preemption L1-refill burst, 0–17 ticks) vs slow \
(steady-state P-core, 41–59 ticks). AES CV triples: 66% baseline → 189% \
under load. The stochastic preemption boundary encodes OS scheduler quantum \
timing, P/E-core migration decisions, thermal state, and DVFS history. \
Novel primitive: no prior entropy library deliberately uses a companion \
computation thread as a variance amplifier (discovered 2026-02-24).",
category: SourceCategory::Microarch,
platform: Platform::MacOS,
requirements: &[Requirement::AppleSilicon],
entropy_rate_estimate: 2.0, composite: false,
is_fast: false,
};
pub struct SITVASource;
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
mod imp {
use super::*;
use crate::sources::helpers::extract_timing_entropy_debiased;
use crate::sources::helpers::mach_time;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
fn companion_body(stop: Arc<AtomicBool>) {
unsafe {
core::arch::asm!(
"fmov v0.4s, #1.0",
"fmov v1.4s, #1.5",
"fmov v2.4s, #2.0",
"fmov v3.4s, #2.5",
"fmov v4.4s, #0.5",
"fmov v5.4s, #1.25",
"fmov v6.4s, #0.75",
"fmov v7.4s, #1.75",
out("v0") _, out("v1") _, out("v2") _, out("v3") _,
out("v4") _, out("v5") _, out("v6") _, out("v7") _,
options(nostack),
);
}
while !stop.load(Ordering::Relaxed) {
unsafe {
core::arch::asm!(
"fmla v0.4s, v1.4s, v2.4s",
"fmla v1.4s, v2.4s, v3.4s",
"fmla v2.4s, v3.4s, v4.4s",
"fmla v3.4s, v4.4s, v5.4s",
"fmla v4.4s, v5.4s, v6.4s",
"fmla v5.4s, v6.4s, v7.4s",
"fmla v6.4s, v7.4s, v0.4s",
"fmla v7.4s, v0.4s, v1.4s",
"fmla v0.4s, v1.4s, v2.4s",
"fmla v1.4s, v2.4s, v3.4s",
"fmla v2.4s, v3.4s, v4.4s",
"fmla v3.4s, v4.4s, v5.4s",
"fmla v4.4s, v5.4s, v6.4s",
"fmla v5.4s, v6.4s, v7.4s",
"fmla v6.4s, v7.4s, v0.4s",
"fmla v7.4s, v0.4s, v1.4s",
"fmla v0.4s, v1.4s, v2.4s",
"fmla v1.4s, v2.4s, v3.4s",
"fmla v2.4s, v3.4s, v4.4s",
"fmla v3.4s, v4.4s, v5.4s",
"fmla v4.4s, v5.4s, v6.4s",
"fmla v5.4s, v6.4s, v7.4s",
"fmla v6.4s, v7.4s, v0.4s",
"fmla v7.4s, v0.4s, v1.4s",
"fmla v0.4s, v1.4s, v2.4s",
"fmla v1.4s, v2.4s, v3.4s",
"fmla v2.4s, v3.4s, v4.4s",
"fmla v3.4s, v4.4s, v5.4s",
"fmla v4.4s, v5.4s, v6.4s",
"fmla v5.4s, v6.4s, v7.4s",
"fmla v6.4s, v7.4s, v0.4s",
"fmla v7.4s, v0.4s, v1.4s",
out("v0") _, out("v1") _, out("v2") _, out("v3") _,
out("v4") _, out("v5") _, out("v6") _, out("v7") _,
options(nostack),
);
}
std::thread::yield_now();
}
}
#[inline]
fn time_aes_under_load() -> u64 {
let t0 = mach_time();
unsafe {
core::arch::asm!(
"fmov v8.4s, #1.5",
"fmov v9.4s, #2.5",
"aese v9.16b, v8.16b",
"aesmc v9.16b, v9.16b",
"aese v9.16b, v8.16b",
"aesmc v9.16b, v9.16b",
out("v8") _, out("v9") _,
options(nostack),
);
}
mach_time().wrapping_sub(t0)
}
impl EntropySource for SITVASource {
fn info(&self) -> &SourceInfo {
&SITVA_INFO
}
fn is_available(&self) -> bool {
true }
fn collect(&self, n_samples: usize) -> Vec<u8> {
let stop = Arc::new(AtomicBool::new(false));
let stop_clone = Arc::clone(&stop);
let handle = std::thread::spawn(move || companion_body(stop_clone));
std::thread::sleep(std::time::Duration::from_millis(50));
let raw_count = n_samples * 4 + 128;
let mut timings = Vec::with_capacity(raw_count);
for _ in 0..raw_count {
timings.push(time_aes_under_load());
}
stop.store(true, Ordering::Relaxed);
let _ = handle.join();
extract_timing_entropy_debiased(&timings, n_samples)
}
}
}
#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
impl EntropySource for SITVASource {
fn info(&self) -> &SourceInfo {
&SITVA_INFO
}
fn is_available(&self) -> bool {
false
}
fn collect(&self, _: usize) -> Vec<u8> {
Vec::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn info() {
let src = SITVASource;
assert_eq!(src.info().name, "sitva");
assert!(matches!(src.info().category, SourceCategory::Microarch));
assert_eq!(src.info().platform, Platform::MacOS);
assert!(!src.info().composite);
assert!(src.info().entropy_rate_estimate > 1.0 && src.info().entropy_rate_estimate <= 8.0);
}
#[test]
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
fn available_on_apple_silicon() {
assert!(SITVASource.is_available());
}
#[test]
#[ignore] fn amplified_variance_exceeds_baseline() {
let baseline_cv = {
let mut t = Vec::new();
for _ in 0..500 {
let t0 = crate::sources::helpers::mach_time();
unsafe {
core::arch::asm!(
"fmov v8.4s, #1.5", "fmov v9.4s, #2.5",
"aese v9.16b, v8.16b", "aesmc v9.16b, v9.16b",
out("v8") _, out("v9") _, options(nostack)
);
}
t.push(crate::sources::helpers::mach_time() - t0);
}
let mean: f64 = t.iter().map(|&x| x as f64).sum::<f64>() / 500.0;
let var: f64 = t.iter().map(|&x| (x as f64 - mean).powi(2)).sum::<f64>() / 500.0;
100.0 * var.sqrt() / mean
};
let src = SITVASource;
let data = src.collect(64);
assert!(!data.is_empty());
let unique: std::collections::HashSet<u8> = data.iter().copied().collect();
assert!(
unique.len() > 16,
"expected high-entropy SITVA output (got {} unique bytes, baseline CV={:.1}%)",
unique.len(),
baseline_cv
);
}
}