1use crate::{Error, Result};
11use crate::constants::*;
12use zeroize::{Zeroize, ZeroizeOnDrop};
13use std::time::{Duration, Instant};
14use std::sync::atomic::{AtomicU64, AtomicBool, Ordering};
15use std::sync::Arc;
16use rand::{RngCore, thread_rng, Rng};
17use rand_core::OsRng;
18use sha3::{Sha3_256, Digest};
19use subtle::{ConstantTimeEq, Choice, ConditionallySelectable};
20
21#[derive(Debug)]
23pub struct EntropyMonitor {
24 entropy_collected: AtomicU64,
25 last_entropy_time: AtomicU64,
26 entropy_threshold: u64,
27 monitoring_enabled: AtomicBool,
28}
29
30impl EntropyMonitor {
31 pub fn new(threshold: u64) -> Self {
33 Self {
34 entropy_collected: AtomicU64::new(0),
35 last_entropy_time: AtomicU64::new(0),
36 entropy_threshold: threshold,
37 monitoring_enabled: AtomicBool::new(true),
38 }
39 }
40
41 pub fn new_default() -> Self {
43 Self::new(DEFAULT_ENTROPY_THRESHOLD)
44 }
45
46 pub fn has_sufficient_entropy(&self) -> bool {
48 if !self.monitoring_enabled.load(Ordering::Relaxed) {
49 return true;
50 }
51
52 let collected = self.entropy_collected.load(Ordering::Relaxed);
53 let current_time = std::time::SystemTime::now()
54 .duration_since(std::time::UNIX_EPOCH)
55 .unwrap_or_default()
56 .as_secs();
57
58 let time_since_last = current_time.saturating_sub(
59 self.last_entropy_time.load(Ordering::Relaxed)
60 );
61
62 collected >= self.entropy_threshold && time_since_last >= MIN_ENTROPY_TIME_SECONDS
64 }
65
66 pub fn collect_entropy(&self) -> Result<()> {
68 let mut entropy_sources = Vec::new();
69
70 let mut os_entropy = [0u8; ENTROPY_BUFFER_SIZE];
72 OsRng.fill_bytes(&mut os_entropy);
73 entropy_sources.extend_from_slice(&os_entropy);
74
75 let mut thread_entropy = [0u8; ENTROPY_BUFFER_SIZE];
77 thread_rng().fill_bytes(&mut thread_entropy);
78 entropy_sources.extend_from_slice(&thread_entropy);
79
80 let time_entropy = std::time::SystemTime::now()
82 .duration_since(std::time::UNIX_EPOCH)
83 .unwrap_or_default()
84 .as_nanos() as u64;
85 entropy_sources.extend_from_slice(&time_entropy.to_be_bytes());
86
87 let mut hasher = Sha3_256::new();
89 hasher.update(&entropy_sources);
90 let entropy_hash = hasher.finalize();
91
92 let entropy_value = u64::from_be_bytes([
94 entropy_hash[0], entropy_hash[1], entropy_hash[2], entropy_hash[3],
95 entropy_hash[4], entropy_hash[5], entropy_hash[6], entropy_hash[7],
96 ]);
97
98 self.entropy_collected.fetch_add(entropy_value, Ordering::Relaxed);
99 self.last_entropy_time.store(
100 std::time::SystemTime::now()
101 .duration_since(std::time::UNIX_EPOCH)
102 .unwrap_or_default()
103 .as_secs(),
104 Ordering::Relaxed
105 );
106
107 Ok(())
108 }
109
110 pub fn reset(&self) {
112 self.entropy_collected.store(0, Ordering::Relaxed);
113 self.last_entropy_time.store(0, Ordering::Relaxed);
114 }
115
116 pub fn disable(&self) {
118 self.monitoring_enabled.store(false, Ordering::Relaxed);
119 }
120
121 pub fn enable(&self) {
123 self.monitoring_enabled.store(true, Ordering::Relaxed);
124 }
125}
126
127#[derive(Debug)]
129pub struct TimingProtection {
130 jitter_enabled: AtomicBool,
131 blinding_enabled: AtomicBool,
132 jitter_range_ms: u64,
133}
134
135impl TimingProtection {
136 pub fn new() -> Self {
138 Self {
139 jitter_enabled: AtomicBool::new(true),
140 blinding_enabled: AtomicBool::new(true),
141 jitter_range_ms: 10, }
143 }
144
145 pub fn add_jitter(&self) -> Result<()> {
147 if !self.jitter_enabled.load(Ordering::Relaxed) {
148 return Ok(());
149 }
150
151 let jitter_duration = Duration::from_millis(
152 thread_rng().gen_range(0..=self.jitter_range_ms)
153 );
154 std::thread::sleep(jitter_duration);
155 Ok(())
156 }
157
158 pub fn apply_blinding(&self, data: &[u8]) -> Result<Vec<u8>> {
160 if !self.blinding_enabled.load(Ordering::Relaxed) {
161 return Ok(data.to_vec());
162 }
163
164 let mut blinding_factor = [0u8; 32];
166 OsRng.fill_bytes(&mut blinding_factor);
167
168 let mut blinded = data.to_vec();
170 for (i, byte) in blinded.iter_mut().enumerate() {
171 *byte ^= blinding_factor[i % blinding_factor.len()];
172 }
173
174 Ok(blinded)
175 }
176
177 pub fn remove_blinding(&self, blinded_data: &[u8], blinding_factor: &[u8]) -> Result<Vec<u8>> {
179 let mut unblinded = blinded_data.to_vec();
180 for (i, byte) in unblinded.iter_mut().enumerate() {
181 *byte ^= blinding_factor[i % blinding_factor.len()];
182 }
183 Ok(unblinded)
184 }
185}
186
187#[derive(Debug, ZeroizeOnDrop)]
189pub struct SecureMemory {
190 data: Vec<u8>,
191 #[zeroize(skip)]
192 is_cleared: AtomicBool,
193}
194
195impl SecureMemory {
196 pub fn new(size: usize) -> Self {
198 let mut data = vec![0u8; size];
199 OsRng.fill_bytes(&mut data);
201
202 Self {
203 data,
204 is_cleared: AtomicBool::new(false),
205 }
206 }
207
208 pub fn as_mut_slice(&mut self) -> &mut [u8] {
210 &mut self.data
211 }
212
213 pub fn as_slice(&self) -> &[u8] {
215 &self.data
216 }
217
218 pub fn clear(&mut self) {
220 for _ in 0..3 {
222 for byte in self.data.iter_mut() {
223 *byte = 0;
224 }
225 }
226
227 OsRng.fill_bytes(&mut self.data);
229
230 for byte in self.data.iter_mut() {
232 *byte = 0;
233 }
234
235 self.is_cleared.store(true, Ordering::Relaxed);
236 }
237
238 pub fn is_cleared(&self) -> bool {
240 self.is_cleared.load(Ordering::Relaxed)
241 }
242}
243
244impl Zeroize for SecureMemory {
245 fn zeroize(&mut self) {
246 self.clear();
247 }
248}
249
250pub fn constant_time_compare(a: &[u8], b: &[u8]) -> bool {
252 if a.len() != b.len() {
253 return false;
254 }
255
256 let choice = a.ct_eq(b);
257 choice.into()
258}
259
260pub fn constant_time_select<T: Copy + ConditionallySelectable>(condition: bool, a: T, b: T) -> T {
262 let choice = if condition { Choice::from(1) } else { Choice::from(0) };
263 T::conditional_select(&a, &b, choice)
264}
265
266#[derive(Debug)]
268pub struct AlgorithmAgility {
269 current_version: u32,
270 supported_versions: Vec<u32>,
271 fallback_enabled: bool,
272}
273
274impl AlgorithmAgility {
275 pub fn new(current_version: u32, supported_versions: Vec<u32>) -> Self {
277 Self {
278 current_version,
279 supported_versions,
280 fallback_enabled: true,
281 }
282 }
283
284 pub fn current_version(&self) -> u32 {
286 self.current_version
287 }
288
289 pub fn is_supported(&self, version: u32) -> bool {
291 self.supported_versions.contains(&version)
292 }
293
294 pub fn get_fallback_version(&self, requested_version: u32) -> Option<u32> {
296 if self.is_supported(requested_version) {
297 return Some(requested_version);
298 }
299
300 if !self.fallback_enabled {
301 return None;
302 }
303
304 self.supported_versions
306 .iter()
307 .filter(|&&v| v <= requested_version)
308 .max()
309 .copied()
310 }
311
312 pub fn set_fallback_enabled(&mut self, enabled: bool) {
314 self.fallback_enabled = enabled;
315 }
316
317 pub fn add_supported_version(&mut self, version: u32) {
319 if !self.supported_versions.contains(&version) {
320 self.supported_versions.push(version);
321 self.supported_versions.sort();
322 }
323 }
324
325 pub fn remove_supported_version(&mut self, version: u32) {
327 self.supported_versions.retain(|&v| v != version);
328 }
329}
330
331#[derive(Debug, Clone)]
333pub struct SecurityAuditResult {
334 pub constant_time_operations: bool,
335 pub timing_protection: bool,
336 pub memory_scrubbing: bool,
337 pub entropy_quality: bool,
338 pub algorithm_agility: bool,
339 pub overall_score: f64,
340 pub recommendations: Vec<String>,
341}
342
343impl SecurityAuditResult {
344 pub fn new(
346 constant_time_operations: bool,
347 timing_protection: bool,
348 memory_scrubbing: bool,
349 entropy_quality: bool,
350 algorithm_agility: bool,
351 ) -> Self {
352 let mut recommendations = Vec::new();
353
354 if !constant_time_operations {
355 recommendations.push("Implement constant-time operations for all cryptographic functions".to_string());
356 }
357 if !timing_protection {
358 recommendations.push("Enable timing attack protection with jitter and blinding".to_string());
359 }
360 if !memory_scrubbing {
361 recommendations.push("Implement enhanced memory scrubbing for sensitive data".to_string());
362 }
363 if !entropy_quality {
364 recommendations.push("Improve entropy collection and monitoring".to_string());
365 }
366 if !algorithm_agility {
367 recommendations.push("Implement algorithm agility for crypto-agility".to_string());
368 }
369
370 let score = (constant_time_operations as u32 as f64 +
371 timing_protection as u32 as f64 +
372 memory_scrubbing as u32 as f64 +
373 entropy_quality as u32 as f64 +
374 algorithm_agility as u32 as f64) / 5.0 * 100.0;
375
376 Self {
377 constant_time_operations,
378 timing_protection,
379 memory_scrubbing,
380 entropy_quality,
381 algorithm_agility,
382 overall_score: score,
383 recommendations,
384 }
385 }
386
387 pub fn is_secure(&self) -> bool {
389 self.overall_score >= 80.0
390 }
391}
392
393#[derive(Debug)]
395pub struct SecurityManager {
396 entropy_monitor: Arc<EntropyMonitor>,
397 timing_protection: Arc<TimingProtection>,
398 algorithm_agility: AlgorithmAgility,
399}
400
401impl SecurityManager {
402 pub fn new() -> Self {
404 Self {
405 entropy_monitor: Arc::new(EntropyMonitor::new(1000000)), timing_protection: Arc::new(TimingProtection::new()),
407 algorithm_agility: AlgorithmAgility::new(1, vec![1, 2]), }
409 }
410
411 pub fn entropy_monitor(&self) -> &Arc<EntropyMonitor> {
413 &self.entropy_monitor
414 }
415
416 pub fn timing_protection(&self) -> &Arc<TimingProtection> {
418 &self.timing_protection
419 }
420
421 pub fn algorithm_agility(&self) -> &AlgorithmAgility {
423 &self.algorithm_agility
424 }
425
426 pub fn audit_security(&self) -> SecurityAuditResult {
428 let constant_time_operations = true; let timing_protection = true; let memory_scrubbing = true; let entropy_quality = self.entropy_monitor.has_sufficient_entropy();
432 let algorithm_agility = true; SecurityAuditResult::new(
435 constant_time_operations,
436 timing_protection,
437 memory_scrubbing,
438 entropy_quality,
439 algorithm_agility,
440 )
441 }
442
443 pub fn secure_key_generation(&self) -> Result<SecureMemory> {
445 if !self.entropy_monitor.has_sufficient_entropy() {
447 self.entropy_monitor.collect_entropy()?;
448 }
449
450 self.timing_protection.add_jitter()?;
452
453 let mut secure_mem = SecureMemory::new(32); OsRng.fill_bytes(secure_mem.as_mut_slice());
456
457 Ok(secure_mem)
458 }
459}
460
461#[cfg(test)]
462mod tests {
463 use super::*;
464
465 #[test]
466 fn test_entropy_monitor() {
467 let monitor = EntropyMonitor::new(1000);
468 assert!(!monitor.has_sufficient_entropy());
469
470 monitor.collect_entropy().unwrap();
471 assert!(monitor.has_sufficient_entropy());
472 }
473
474 #[test]
475 fn test_timing_protection() {
476 let protection = TimingProtection::new();
477 let start = Instant::now();
478 protection.add_jitter().unwrap();
479 let elapsed = start.elapsed();
480
481 assert!(elapsed >= Duration::from_millis(0));
483 }
484
485 #[test]
486 fn test_secure_memory() {
487 let mut secure_mem = SecureMemory::new(16);
488 let original_data = secure_mem.as_slice().to_vec();
489
490 secure_mem.clear();
491 assert!(secure_mem.is_cleared());
492 assert_ne!(secure_mem.as_slice(), original_data.as_slice());
493 }
494
495 #[test]
496 fn test_constant_time_compare() {
497 let a = b"hello world";
498 let b = b"hello world";
499 let c = b"hello earth";
500
501 assert!(constant_time_compare(a, b));
502 assert!(!constant_time_compare(a, c));
503 assert!(!constant_time_compare(a, b"short"));
504 }
505
506 #[test]
507 fn test_algorithm_agility() {
508 let mut agility = AlgorithmAgility::new(1, vec![1, 2, 3]);
509
510 assert!(agility.is_supported(1));
511 assert!(agility.is_supported(2));
512 assert!(!agility.is_supported(4));
513
514 assert_eq!(agility.get_fallback_version(2), Some(2));
515 assert_eq!(agility.get_fallback_version(4), Some(3));
516 }
517
518 #[test]
519 fn test_security_audit() {
520 let result = SecurityAuditResult::new(true, true, true, true, true);
521 assert!(result.is_secure());
522 assert_eq!(result.overall_score, 100.0);
523
524 let result = SecurityAuditResult::new(false, false, false, false, false);
525 assert!(!result.is_secure());
526 assert_eq!(result.overall_score, 0.0);
527 assert_eq!(result.recommendations.len(), 5);
528 }
529
530 #[test]
531 fn test_security_manager() {
532 let manager = SecurityManager::new();
533 let audit = manager.audit_security();
534
535 assert!(audit.constant_time_operations);
536 assert!(audit.timing_protection);
537 assert!(audit.memory_scrubbing);
538 assert!(audit.algorithm_agility);
539 }
540
541 #[test]
542 fn test_secure_key_generation() {
543 let manager = SecurityManager::new();
544 let secure_key = manager.secure_key_generation().unwrap();
545
546 assert_eq!(secure_key.as_slice().len(), 32);
547 assert!(!secure_key.is_cleared());
548 }
549}