Skip to main content

lib_q_aead/security/
mod.rs

1//! Security enhancements for lib-q-aead
2//!
3//! This module provides comprehensive security features including:
4//! - Constant-time operations
5//! - Side-channel attack protection
6//! - Secure memory handling
7//! - Input validation and sanitization
8//! - Constant-time operation wrapper (fixed wall-clock duration)
9//! - Fault injection resistance
10
11pub mod constant_time;
12pub mod memory;
13pub mod nonce;
14pub mod side_channel;
15pub mod stack_buffer;
16pub mod timing;
17pub mod validation;
18
19// Re-export commonly used security functions
20// Note: Individual modules are available for specific use cases
21
22/// Security configuration for AEAD operations
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct SecurityConfig {
25    /// Enable constant-time operations
26    pub constant_time: bool,
27    /// Enable side-channel protection
28    pub side_channel_protection: bool,
29    /// Enable secure memory handling
30    pub secure_memory: bool,
31    /// Enable comprehensive input validation
32    pub strict_validation: bool,
33    /// Enable constant-time operation wrapper (fixed wall-clock duration)
34    pub timing_protection: bool,
35    /// Enable fault injection protection
36    pub fault_injection_protection: bool,
37}
38
39impl Default for SecurityConfig {
40    fn default() -> Self {
41        Self {
42            constant_time: true,
43            side_channel_protection: true,
44            secure_memory: true,
45            strict_validation: true,
46            timing_protection: true,
47            fault_injection_protection: true,
48        }
49    }
50}
51
52impl SecurityConfig {
53    /// Create a strict security configuration (maximum security)
54    pub fn strict() -> Self {
55        Self {
56            constant_time: true,
57            side_channel_protection: true,
58            secure_memory: true,
59            strict_validation: true,
60            timing_protection: true,
61            fault_injection_protection: true,
62        }
63    }
64
65    /// Create a permissive security configuration (performance optimized)
66    pub fn permissive() -> Self {
67        Self {
68            constant_time: false,
69            side_channel_protection: false,
70            secure_memory: false,
71            strict_validation: false,
72            timing_protection: false,
73            fault_injection_protection: false,
74        }
75    }
76
77    /// Create a balanced security configuration
78    pub fn balanced() -> Self {
79        Self {
80            constant_time: true,
81            side_channel_protection: true,
82            secure_memory: true,
83            strict_validation: true,
84            timing_protection: false,
85            fault_injection_protection: false,
86        }
87    }
88}
89
90/// Global security configuration
91static mut SECURITY_CONFIG: SecurityConfig = SecurityConfig {
92    constant_time: true,
93    side_channel_protection: true,
94    secure_memory: true,
95    strict_validation: true,
96    timing_protection: true,
97    fault_injection_protection: true,
98};
99
100/// Get the current security configuration
101pub fn get_security_config() -> SecurityConfig {
102    unsafe { SECURITY_CONFIG }
103}
104
105/// Set the security configuration
106pub fn set_security_config(config: SecurityConfig) {
107    unsafe {
108        SECURITY_CONFIG = config;
109    }
110}
111
112/// Security context for cryptographic operations
113pub struct SecurityContext {
114    config: SecurityConfig,
115    operation_id: u64,
116    start_time: u64,
117}
118
119impl SecurityContext {
120    /// Create a new security context
121    pub fn new() -> Self {
122        Self {
123            config: get_security_config(),
124            operation_id: Self::generate_operation_id(),
125            start_time: Self::get_timestamp(),
126        }
127    }
128
129    /// Create a security context with custom configuration
130    pub fn with_config(config: SecurityConfig) -> Self {
131        Self {
132            config,
133            operation_id: Self::generate_operation_id(),
134            start_time: Self::get_timestamp(),
135        }
136    }
137
138    /// Get the operation ID
139    pub fn operation_id(&self) -> u64 {
140        self.operation_id
141    }
142
143    /// Get the elapsed time since context creation
144    pub fn elapsed_time(&self) -> u64 {
145        Self::get_timestamp() - self.start_time
146    }
147
148    /// Check if constant-time operations are enabled
149    pub fn constant_time_enabled(&self) -> bool {
150        self.config.constant_time
151    }
152
153    /// Check if side-channel protection is enabled
154    pub fn side_channel_protection_enabled(&self) -> bool {
155        self.config.side_channel_protection
156    }
157
158    /// Check if secure memory handling is enabled
159    pub fn secure_memory_enabled(&self) -> bool {
160        self.config.secure_memory
161    }
162
163    /// Check if strict validation is enabled
164    pub fn strict_validation_enabled(&self) -> bool {
165        self.config.strict_validation
166    }
167
168    /// Check if timing protection is enabled
169    pub fn timing_protection_enabled(&self) -> bool {
170        self.config.timing_protection
171    }
172
173    /// Check if fault injection protection is enabled
174    pub fn fault_injection_protection_enabled(&self) -> bool {
175        self.config.fault_injection_protection
176    }
177
178    /// Generate a unique operation ID
179    fn generate_operation_id() -> u64 {
180        // Use a simple counter for now - in production, this should use
181        // cryptographically secure random number generation
182        static mut COUNTER: u64 = 0;
183        unsafe {
184            COUNTER += 1;
185            COUNTER
186        }
187    }
188
189    /// Get current timestamp with high-resolution timing
190    fn get_timestamp() -> u64 {
191        #[cfg(all(feature = "std", not(target_arch = "wasm32")))]
192        {
193            use std::time::{
194                SystemTime,
195                UNIX_EPOCH,
196            };
197            SystemTime::now()
198                .duration_since(UNIX_EPOCH)
199                .unwrap_or_default()
200                .as_nanos() as u64
201        }
202        // wasm32-unknown-unknown has no working `SystemTime`; no_std targets
203        // have no clock at all. Both fall back to a monotonic counter that
204        // still gives consistent relative measurements.
205        #[cfg(any(not(feature = "std"), target_arch = "wasm32"))]
206        {
207            use core::sync::atomic::{
208                AtomicU64,
209                Ordering,
210            };
211            static COUNTER: AtomicU64 = AtomicU64::new(0);
212            COUNTER.fetch_add(1, Ordering::SeqCst)
213        }
214    }
215}
216
217impl Default for SecurityContext {
218    fn default() -> Self {
219        Self::new()
220    }
221}
222
223#[cfg(test)]
224mod tests {
225    use super::*;
226
227    #[test]
228    fn test_security_config_defaults() {
229        let config = SecurityConfig::default();
230        assert!(config.constant_time);
231        assert!(config.side_channel_protection);
232        assert!(config.secure_memory);
233        assert!(config.strict_validation);
234        assert!(config.timing_protection);
235        assert!(config.fault_injection_protection);
236    }
237
238    #[test]
239    fn test_security_config_strict() {
240        let config = SecurityConfig::strict();
241        assert!(config.constant_time);
242        assert!(config.side_channel_protection);
243        assert!(config.secure_memory);
244        assert!(config.strict_validation);
245        assert!(config.timing_protection);
246        assert!(config.fault_injection_protection);
247    }
248
249    #[test]
250    fn test_security_config_permissive() {
251        let config = SecurityConfig::permissive();
252        assert!(!config.constant_time);
253        assert!(!config.side_channel_protection);
254        assert!(!config.secure_memory);
255        assert!(!config.strict_validation);
256        assert!(!config.timing_protection);
257        assert!(!config.fault_injection_protection);
258    }
259
260    #[test]
261    fn test_security_config_balanced() {
262        let config = SecurityConfig::balanced();
263        assert!(config.constant_time);
264        assert!(config.side_channel_protection);
265        assert!(config.secure_memory);
266        assert!(config.strict_validation);
267        assert!(!config.timing_protection);
268        assert!(!config.fault_injection_protection);
269    }
270
271    #[test]
272    fn test_security_context_creation() {
273        let ctx = SecurityContext::new();
274        assert!(ctx.operation_id() > 0);
275        // Note: elapsed_time() returns u64, so it's always >= 0
276        // We just verify it's a valid timestamp
277        let _elapsed = ctx.elapsed_time();
278        assert!(ctx.constant_time_enabled());
279    }
280
281    #[test]
282    fn test_security_context_with_config() {
283        let config = SecurityConfig::permissive();
284        let ctx = SecurityContext::with_config(config);
285        assert!(!ctx.constant_time_enabled());
286        assert!(!ctx.side_channel_protection_enabled());
287        assert!(!ctx.secure_memory_enabled());
288        assert!(!ctx.strict_validation_enabled());
289        assert!(!ctx.timing_protection_enabled());
290        assert!(!ctx.fault_injection_protection_enabled());
291    }
292
293    #[test]
294    fn test_global_security_config() {
295        let original_config = get_security_config();
296
297        let new_config = SecurityConfig::permissive();
298        set_security_config(new_config);
299
300        let retrieved_config = get_security_config();
301        assert_eq!(retrieved_config, new_config);
302
303        // Restore original config
304        set_security_config(original_config);
305    }
306}