palisade_config/
timing.rs1use std::sync::atomic::{AtomicU8, Ordering};
4use std::time::{Duration, Instant};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8#[repr(u8)]
9pub enum TimingProfile {
10 Balanced = 0,
12 Hardened = 1,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub(crate) enum TimingOperation {
19 ConfigLoad,
20 ConfigValidateStandard,
21 ConfigValidateStrict,
22 ConfigHostname,
23 ConfigDiff,
24 PolicyLoad,
25 PolicyValidate,
26 PolicyDiff,
27 PolicySuspiciousCheckLegacy,
28 RuntimeConfigBuild,
29 RuntimePolicyBuild,
30 RootTagNew,
31 RootTagGenerate,
32 RootTagDeriveHost,
33 RootTagDeriveArtifact,
34 RootTagHashCompare,
35 PolicySuspiciousCheck,
36 PolicyCustomConditionCheck,
37}
38
39static TIMING_PROFILE: AtomicU8 = AtomicU8::new(TimingProfile::Balanced as u8);
40
41pub fn set_timing_profile(profile: TimingProfile) {
43 TIMING_PROFILE.store(profile as u8, Ordering::Relaxed);
44}
45
46#[must_use]
48pub fn get_timing_profile() -> TimingProfile {
49 match TIMING_PROFILE.load(Ordering::Relaxed) {
50 1 => TimingProfile::Hardened,
51 _ => TimingProfile::Balanced,
52 }
53}
54
55#[inline]
56const fn timing_floor(profile: TimingProfile, op: TimingOperation) -> Duration {
57 match profile {
58 TimingProfile::Balanced => match op {
59 TimingOperation::ConfigLoad => Duration::from_micros(30),
60 TimingOperation::ConfigValidateStandard => Duration::from_micros(12),
61 TimingOperation::ConfigValidateStrict => Duration::from_micros(16),
62 TimingOperation::ConfigHostname => Duration::from_micros(2),
63 TimingOperation::ConfigDiff => Duration::from_micros(8),
64 TimingOperation::PolicyLoad => Duration::from_micros(30),
65 TimingOperation::PolicyValidate => Duration::from_micros(12),
66 TimingOperation::PolicyDiff => Duration::from_micros(8),
67 TimingOperation::PolicySuspiciousCheckLegacy => Duration::from_micros(8),
68 TimingOperation::RuntimeConfigBuild => Duration::from_micros(10),
69 TimingOperation::RuntimePolicyBuild => Duration::from_micros(10),
70 TimingOperation::RootTagNew => Duration::from_micros(18),
71 TimingOperation::RootTagGenerate => Duration::from_micros(18),
72 TimingOperation::RootTagDeriveHost => Duration::from_micros(8),
73 TimingOperation::RootTagDeriveArtifact => Duration::from_micros(12),
74 TimingOperation::RootTagHashCompare => Duration::from_micros(1),
75 TimingOperation::PolicySuspiciousCheck => Duration::from_micros(8),
76 TimingOperation::PolicyCustomConditionCheck => Duration::from_micros(4),
77 },
78 TimingProfile::Hardened => match op {
79 TimingOperation::ConfigLoad => Duration::from_micros(45),
80 TimingOperation::ConfigValidateStandard => Duration::from_micros(18),
81 TimingOperation::ConfigValidateStrict => Duration::from_micros(24),
82 TimingOperation::ConfigHostname => Duration::from_micros(4),
83 TimingOperation::ConfigDiff => Duration::from_micros(12),
84 TimingOperation::PolicyLoad => Duration::from_micros(45),
85 TimingOperation::PolicyValidate => Duration::from_micros(18),
86 TimingOperation::PolicyDiff => Duration::from_micros(12),
87 TimingOperation::PolicySuspiciousCheckLegacy => Duration::from_micros(12),
88 TimingOperation::RuntimeConfigBuild => Duration::from_micros(16),
89 TimingOperation::RuntimePolicyBuild => Duration::from_micros(16),
90 TimingOperation::RootTagNew => Duration::from_micros(28),
91 TimingOperation::RootTagGenerate => Duration::from_micros(28),
92 TimingOperation::RootTagDeriveHost => Duration::from_micros(12),
93 TimingOperation::RootTagDeriveArtifact => Duration::from_micros(18),
94 TimingOperation::RootTagHashCompare => Duration::from_micros(2),
95 TimingOperation::PolicySuspiciousCheck => Duration::from_micros(12),
96 TimingOperation::PolicyCustomConditionCheck => Duration::from_micros(6),
97 },
98 }
99}
100
101#[inline]
102pub(crate) fn enforce_operation_min_timing(started: Instant, op: TimingOperation) {
103 let target = started + timing_floor(get_timing_profile(), op);
104 while Instant::now() < target {
105 std::hint::spin_loop();
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn profile_roundtrip() {
115 set_timing_profile(TimingProfile::Balanced);
116 assert_eq!(get_timing_profile(), TimingProfile::Balanced);
117 set_timing_profile(TimingProfile::Hardened);
118 assert_eq!(get_timing_profile(), TimingProfile::Hardened);
119 }
120}