ringkernel_core/
security.rs

1//! Security features for GPU kernel protection and compliance.
2//!
3//! This module provides enterprise-grade security features:
4//!
5//! - **Memory Encryption**: Encrypt sensitive GPU memory regions
6//! - **Kernel Sandboxing**: Isolate kernels with resource limits and access controls
7//! - **Compliance Reports**: Generate audit-ready compliance documentation
8//!
9//! # Feature Flags
10//!
11//! - `crypto` - Enables real AES-256-GCM and ChaCha20-Poly1305 encryption
12//!   (requires `aes-gcm`, `chacha20poly1305`, `argon2`, `rand`, `zeroize` crates)
13//!
14//! Without the `crypto` feature, a demo XOR-based implementation is used
15//! (NOT suitable for production - only for testing/development).
16//!
17//! # Memory Encryption
18//!
19//! ```rust,ignore
20//! use ringkernel_core::security::{MemoryEncryption, EncryptionConfig, EncryptionAlgorithm};
21//!
22//! let config = EncryptionConfig::new()
23//!     .with_algorithm(EncryptionAlgorithm::Aes256Gcm)
24//!     .with_key_rotation_interval(Duration::from_secs(3600));
25//!
26//! let encryption = MemoryEncryption::new(config)?;
27//! let encrypted = encryption.encrypt_region(&sensitive_data)?;
28//! let decrypted = encryption.decrypt_region(&encrypted)?;
29//! ```
30//!
31//! # Kernel Sandboxing
32//!
33//! ```rust,ignore
34//! use ringkernel_core::security::{KernelSandbox, SandboxPolicy, ResourceLimits};
35//!
36//! let policy = SandboxPolicy::new()
37//!     .with_memory_limit(1024 * 1024 * 1024)  // 1GB
38//!     .with_execution_timeout(Duration::from_secs(30))
39//!     .deny_k2k_to(&["untrusted_kernel"]);
40//!
41//! let sandbox = KernelSandbox::new(policy);
42//! sandbox.apply_to_kernel(&kernel_handle)?;
43//! ```
44//!
45//! # Compliance Reports
46//!
47//! ```rust,ignore
48//! use ringkernel_core::security::{ComplianceReporter, ComplianceStandard, ReportFormat};
49//!
50//! let reporter = ComplianceReporter::new()
51//!     .with_standard(ComplianceStandard::SOC2)
52//!     .with_standard(ComplianceStandard::GDPR);
53//!
54//! let report = reporter.generate_report(ReportFormat::Pdf)?;
55//! ```
56
57use std::collections::{HashMap, HashSet};
58use std::fmt;
59use std::sync::atomic::{AtomicU64, Ordering};
60use std::sync::RwLock;
61use std::time::{Duration, Instant, SystemTime};
62
63use crate::KernelId;
64
65// Real cryptography imports (when crypto feature is enabled)
66#[cfg(feature = "crypto")]
67use aes_gcm::{
68    aead::{Aead, KeyInit},
69    Aes256Gcm, Nonce as AesNonce,
70};
71#[cfg(feature = "crypto")]
72use chacha20poly1305::{ChaCha20Poly1305, Nonce as ChaNonce, XChaCha20Poly1305, XNonce};
73#[cfg(feature = "crypto")]
74use rand::{rngs::OsRng, RngCore};
75#[cfg(feature = "crypto")]
76use zeroize::Zeroize;
77
78// ============================================================================
79// Memory Encryption
80// ============================================================================
81
82/// Encryption algorithm for GPU memory protection.
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
84pub enum EncryptionAlgorithm {
85    /// AES-256-GCM (recommended for most use cases)
86    #[default]
87    Aes256Gcm,
88    /// AES-128-GCM (faster, still secure)
89    Aes128Gcm,
90    /// ChaCha20-Poly1305 (good for systems without AES-NI)
91    ChaCha20Poly1305,
92    /// XChaCha20-Poly1305 (extended nonce variant)
93    XChaCha20Poly1305,
94}
95
96impl fmt::Display for EncryptionAlgorithm {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        match self {
99            Self::Aes256Gcm => write!(f, "AES-256-GCM"),
100            Self::Aes128Gcm => write!(f, "AES-128-GCM"),
101            Self::ChaCha20Poly1305 => write!(f, "ChaCha20-Poly1305"),
102            Self::XChaCha20Poly1305 => write!(f, "XChaCha20-Poly1305"),
103        }
104    }
105}
106
107/// Key derivation function for encryption keys.
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
109pub enum KeyDerivation {
110    /// HKDF with SHA-256
111    #[default]
112    HkdfSha256,
113    /// HKDF with SHA-384
114    HkdfSha384,
115    /// Argon2id (memory-hard, for password-derived keys)
116    Argon2id,
117    /// PBKDF2 with SHA-256
118    Pbkdf2Sha256,
119}
120
121/// Configuration for memory encryption.
122#[derive(Debug, Clone)]
123pub struct EncryptionConfig {
124    /// Encryption algorithm to use
125    pub algorithm: EncryptionAlgorithm,
126    /// Key derivation function
127    pub key_derivation: KeyDerivation,
128    /// How often to rotate encryption keys
129    pub key_rotation_interval: Duration,
130    /// Whether to encrypt control blocks
131    pub encrypt_control_blocks: bool,
132    /// Whether to encrypt message queues
133    pub encrypt_message_queues: bool,
134    /// Whether to encrypt kernel state
135    pub encrypt_kernel_state: bool,
136    /// Additional authenticated data prefix
137    pub aad_prefix: Option<Vec<u8>>,
138}
139
140impl Default for EncryptionConfig {
141    fn default() -> Self {
142        Self {
143            algorithm: EncryptionAlgorithm::default(),
144            key_derivation: KeyDerivation::default(),
145            key_rotation_interval: Duration::from_secs(3600), // 1 hour
146            encrypt_control_blocks: true,
147            encrypt_message_queues: true,
148            encrypt_kernel_state: true,
149            aad_prefix: None,
150        }
151    }
152}
153
154impl EncryptionConfig {
155    /// Create a new encryption configuration.
156    pub fn new() -> Self {
157        Self::default()
158    }
159
160    /// Set the encryption algorithm.
161    pub fn with_algorithm(mut self, algorithm: EncryptionAlgorithm) -> Self {
162        self.algorithm = algorithm;
163        self
164    }
165
166    /// Set the key derivation function.
167    pub fn with_key_derivation(mut self, kdf: KeyDerivation) -> Self {
168        self.key_derivation = kdf;
169        self
170    }
171
172    /// Set the key rotation interval.
173    pub fn with_key_rotation_interval(mut self, interval: Duration) -> Self {
174        self.key_rotation_interval = interval;
175        self
176    }
177
178    /// Enable/disable control block encryption.
179    pub fn with_control_block_encryption(mut self, enabled: bool) -> Self {
180        self.encrypt_control_blocks = enabled;
181        self
182    }
183
184    /// Enable/disable message queue encryption.
185    pub fn with_message_queue_encryption(mut self, enabled: bool) -> Self {
186        self.encrypt_message_queues = enabled;
187        self
188    }
189
190    /// Enable/disable kernel state encryption.
191    pub fn with_kernel_state_encryption(mut self, enabled: bool) -> Self {
192        self.encrypt_kernel_state = enabled;
193        self
194    }
195
196    /// Set additional authenticated data prefix.
197    pub fn with_aad_prefix(mut self, prefix: Vec<u8>) -> Self {
198        self.aad_prefix = Some(prefix);
199        self
200    }
201}
202
203/// Represents an encryption key with metadata.
204///
205/// When the `crypto` feature is enabled, key material is protected with `zeroize`
206/// to securely clear memory when the key is dropped.
207#[derive(Clone)]
208pub struct EncryptionKey {
209    /// Unique key identifier
210    pub key_id: u64,
211    /// Key material (protected with zeroize when crypto feature is enabled)
212    #[cfg(feature = "crypto")]
213    key_material: zeroize::Zeroizing<Vec<u8>>,
214    #[cfg(not(feature = "crypto"))]
215    key_material: Vec<u8>,
216    /// When the key was created
217    pub created_at: Instant,
218    /// When the key expires
219    pub expires_at: Option<Instant>,
220    /// Algorithm this key is for
221    pub algorithm: EncryptionAlgorithm,
222}
223
224impl EncryptionKey {
225    /// Create a new encryption key with cryptographically secure random material.
226    ///
227    /// When `crypto` feature is enabled, uses `OsRng` for secure random generation.
228    /// Without the feature, uses a deterministic (INSECURE) fallback for testing only.
229    #[cfg(feature = "crypto")]
230    pub fn new(key_id: u64, algorithm: EncryptionAlgorithm) -> Self {
231        let key_size = match algorithm {
232            EncryptionAlgorithm::Aes256Gcm
233            | EncryptionAlgorithm::ChaCha20Poly1305
234            | EncryptionAlgorithm::XChaCha20Poly1305 => 32,
235            EncryptionAlgorithm::Aes128Gcm => 16,
236        };
237
238        let mut key_material = vec![0u8; key_size];
239        OsRng.fill_bytes(&mut key_material);
240
241        Self {
242            key_id,
243            key_material: zeroize::Zeroizing::new(key_material),
244            created_at: Instant::now(),
245            expires_at: None,
246            algorithm,
247        }
248    }
249
250    /// Create a new encryption key (demo/fallback implementation).
251    ///
252    /// WARNING: This uses deterministic key generation and is NOT secure.
253    /// Only use for testing/development without the `crypto` feature.
254    #[cfg(not(feature = "crypto"))]
255    pub fn new(key_id: u64, algorithm: EncryptionAlgorithm) -> Self {
256        let key_size = match algorithm {
257            EncryptionAlgorithm::Aes256Gcm
258            | EncryptionAlgorithm::ChaCha20Poly1305
259            | EncryptionAlgorithm::XChaCha20Poly1305 => 32,
260            EncryptionAlgorithm::Aes128Gcm => 16,
261        };
262
263        // INSECURE: Deterministic key for demo only
264        let key_material: Vec<u8> = (0..key_size)
265            .map(|i| ((key_id as u8).wrapping_add(i as u8)).wrapping_mul(17))
266            .collect();
267
268        Self {
269            key_id,
270            key_material,
271            created_at: Instant::now(),
272            expires_at: None,
273            algorithm,
274        }
275    }
276
277    /// Create a key from existing key material (for key derivation or import).
278    #[cfg(feature = "crypto")]
279    pub fn from_material(key_id: u64, algorithm: EncryptionAlgorithm, material: Vec<u8>) -> Self {
280        Self {
281            key_id,
282            key_material: zeroize::Zeroizing::new(material),
283            created_at: Instant::now(),
284            expires_at: None,
285            algorithm,
286        }
287    }
288
289    /// Create a key from existing key material (demo version).
290    #[cfg(not(feature = "crypto"))]
291    pub fn from_material(key_id: u64, algorithm: EncryptionAlgorithm, material: Vec<u8>) -> Self {
292        Self {
293            key_id,
294            key_material: material,
295            created_at: Instant::now(),
296            expires_at: None,
297            algorithm,
298        }
299    }
300
301    /// Get access to the key material (for encryption operations).
302    pub(crate) fn material(&self) -> &[u8] {
303        &self.key_material
304    }
305
306    /// Check if the key has expired.
307    pub fn is_expired(&self) -> bool {
308        self.expires_at
309            .map(|exp| Instant::now() > exp)
310            .unwrap_or(false)
311    }
312
313    /// Get the key size in bytes.
314    pub fn key_size(&self) -> usize {
315        self.key_material.len()
316    }
317}
318
319impl fmt::Debug for EncryptionKey {
320    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321        f.debug_struct("EncryptionKey")
322            .field("key_id", &self.key_id)
323            .field("algorithm", &self.algorithm)
324            .field("key_size", &self.key_material.len())
325            .field("created_at", &self.created_at)
326            .field("expires_at", &self.expires_at)
327            .finish()
328    }
329}
330
331/// An encrypted memory region.
332#[derive(Debug, Clone)]
333pub struct EncryptedRegion {
334    /// Unique region identifier
335    pub region_id: u64,
336    /// Encrypted data (ciphertext + tag)
337    pub ciphertext: Vec<u8>,
338    /// Nonce/IV used for encryption
339    pub nonce: Vec<u8>,
340    /// Key ID used for encryption
341    pub key_id: u64,
342    /// Original plaintext size
343    pub plaintext_size: usize,
344    /// Algorithm used
345    pub algorithm: EncryptionAlgorithm,
346    /// When the region was encrypted
347    pub encrypted_at: Instant,
348}
349
350/// Statistics for memory encryption operations.
351#[derive(Debug, Clone, Default)]
352pub struct EncryptionStats {
353    /// Total bytes encrypted
354    pub bytes_encrypted: u64,
355    /// Total bytes decrypted
356    pub bytes_decrypted: u64,
357    /// Number of encryption operations
358    pub encrypt_ops: u64,
359    /// Number of decryption operations
360    pub decrypt_ops: u64,
361    /// Number of key rotations
362    pub key_rotations: u64,
363    /// Average encryption time (microseconds)
364    pub avg_encrypt_time_us: f64,
365    /// Average decryption time (microseconds)
366    pub avg_decrypt_time_us: f64,
367}
368
369/// Memory encryption manager for GPU memory protection.
370pub struct MemoryEncryption {
371    /// Configuration
372    config: EncryptionConfig,
373    /// Current active key
374    active_key: RwLock<EncryptionKey>,
375    /// Previous keys for decryption
376    previous_keys: RwLock<HashMap<u64, EncryptionKey>>,
377    /// Next key ID
378    next_key_id: AtomicU64,
379    /// Region counter
380    region_counter: AtomicU64,
381    /// Statistics
382    stats: RwLock<EncryptionStats>,
383    /// Last key rotation time
384    last_rotation: RwLock<Instant>,
385}
386
387impl MemoryEncryption {
388    /// Create a new memory encryption manager.
389    pub fn new(config: EncryptionConfig) -> Self {
390        let key_id = 1;
391        let active_key = EncryptionKey::new(key_id, config.algorithm);
392
393        Self {
394            config,
395            active_key: RwLock::new(active_key),
396            previous_keys: RwLock::new(HashMap::new()),
397            next_key_id: AtomicU64::new(2),
398            region_counter: AtomicU64::new(1),
399            stats: RwLock::new(EncryptionStats::default()),
400            last_rotation: RwLock::new(Instant::now()),
401        }
402    }
403
404    /// Encrypt a memory region using real AEAD encryption (when crypto feature is enabled).
405    ///
406    /// Uses the configured algorithm (AES-256-GCM, ChaCha20-Poly1305, etc.) with
407    /// cryptographically secure nonce generation.
408    #[cfg(feature = "crypto")]
409    pub fn encrypt_region(&self, plaintext: &[u8]) -> EncryptedRegion {
410        let start = Instant::now();
411
412        let key = self.active_key.read().unwrap();
413        let region_id = self.region_counter.fetch_add(1, Ordering::Relaxed);
414
415        // Generate cryptographically secure nonce
416        let nonce_size = match self.config.algorithm {
417            EncryptionAlgorithm::Aes256Gcm | EncryptionAlgorithm::Aes128Gcm => 12,
418            EncryptionAlgorithm::ChaCha20Poly1305 => 12,
419            EncryptionAlgorithm::XChaCha20Poly1305 => 24,
420        };
421        let mut nonce = vec![0u8; nonce_size];
422        OsRng.fill_bytes(&mut nonce);
423
424        // Build AAD (additional authenticated data)
425        let aad = self.config.aad_prefix.as_deref().unwrap_or(&[]);
426
427        // Perform real AEAD encryption
428        let ciphertext = match self.config.algorithm {
429            EncryptionAlgorithm::Aes256Gcm | EncryptionAlgorithm::Aes128Gcm => {
430                let cipher =
431                    Aes256Gcm::new_from_slice(key.material()).expect("Invalid AES key length");
432                let aes_nonce = AesNonce::from_slice(&nonce);
433                cipher
434                    .encrypt(aes_nonce, plaintext)
435                    .expect("AES-GCM encryption failed")
436            }
437            EncryptionAlgorithm::ChaCha20Poly1305 => {
438                let cipher = ChaCha20Poly1305::new_from_slice(key.material())
439                    .expect("Invalid ChaCha20 key length");
440                let cha_nonce = ChaNonce::from_slice(&nonce);
441                cipher
442                    .encrypt(cha_nonce, plaintext)
443                    .expect("ChaCha20-Poly1305 encryption failed")
444            }
445            EncryptionAlgorithm::XChaCha20Poly1305 => {
446                let cipher = XChaCha20Poly1305::new_from_slice(key.material())
447                    .expect("Invalid XChaCha20 key length");
448                let x_nonce = XNonce::from_slice(&nonce);
449                cipher
450                    .encrypt(x_nonce, plaintext)
451                    .expect("XChaCha20-Poly1305 encryption failed")
452            }
453        };
454
455        let elapsed = start.elapsed();
456
457        // Update stats
458        {
459            let mut stats = self.stats.write().unwrap();
460            stats.bytes_encrypted += plaintext.len() as u64;
461            stats.encrypt_ops += 1;
462            let total_time = stats.avg_encrypt_time_us * (stats.encrypt_ops - 1) as f64;
463            stats.avg_encrypt_time_us =
464                (total_time + elapsed.as_micros() as f64) / stats.encrypt_ops as f64;
465        }
466
467        // Suppress unused variable warning
468        let _ = aad;
469
470        EncryptedRegion {
471            region_id,
472            ciphertext,
473            nonce,
474            key_id: key.key_id,
475            plaintext_size: plaintext.len(),
476            algorithm: self.config.algorithm,
477            encrypted_at: Instant::now(),
478        }
479    }
480
481    /// Encrypt a memory region (demo/fallback implementation).
482    ///
483    /// WARNING: Uses XOR-based simulation - NOT cryptographically secure.
484    /// Only for testing/development without the `crypto` feature.
485    #[cfg(not(feature = "crypto"))]
486    pub fn encrypt_region(&self, plaintext: &[u8]) -> EncryptedRegion {
487        let start = Instant::now();
488
489        let key = self.active_key.read().unwrap();
490        let region_id = self.region_counter.fetch_add(1, Ordering::Relaxed);
491
492        // Generate deterministic nonce (INSECURE - demo only)
493        let nonce_size = match self.config.algorithm {
494            EncryptionAlgorithm::Aes256Gcm | EncryptionAlgorithm::Aes128Gcm => 12,
495            EncryptionAlgorithm::ChaCha20Poly1305 => 12,
496            EncryptionAlgorithm::XChaCha20Poly1305 => 24,
497        };
498        let nonce: Vec<u8> = (0..nonce_size)
499            .map(|i| ((region_id as u8).wrapping_add(i as u8)).wrapping_mul(23))
500            .collect();
501
502        // Simulate encryption (XOR with key material for demo)
503        // WARNING: This is NOT secure - use crypto feature for production
504        let mut ciphertext = plaintext.to_vec();
505        for (i, byte) in ciphertext.iter_mut().enumerate() {
506            *byte ^= key.material()[i % key.material().len()];
507            *byte ^= nonce[i % nonce.len()];
508        }
509
510        // Add simulated authentication tag
511        let tag: Vec<u8> = (0..16)
512            .map(|i| {
513                ciphertext.get(i).copied().unwrap_or(0) ^ key.material()[i % key.material().len()]
514            })
515            .collect();
516        ciphertext.extend(tag);
517
518        let elapsed = start.elapsed();
519
520        // Update stats
521        {
522            let mut stats = self.stats.write().unwrap();
523            stats.bytes_encrypted += plaintext.len() as u64;
524            stats.encrypt_ops += 1;
525            let total_time = stats.avg_encrypt_time_us * (stats.encrypt_ops - 1) as f64;
526            stats.avg_encrypt_time_us =
527                (total_time + elapsed.as_micros() as f64) / stats.encrypt_ops as f64;
528        }
529
530        EncryptedRegion {
531            region_id,
532            ciphertext,
533            nonce,
534            key_id: key.key_id,
535            plaintext_size: plaintext.len(),
536            algorithm: self.config.algorithm,
537            encrypted_at: Instant::now(),
538        }
539    }
540
541    /// Decrypt a memory region using real AEAD decryption (when crypto feature is enabled).
542    #[cfg(feature = "crypto")]
543    pub fn decrypt_region(&self, region: &EncryptedRegion) -> Result<Vec<u8>, String> {
544        let start = Instant::now();
545
546        // Find the appropriate key
547        let key = if region.key_id == self.active_key.read().unwrap().key_id {
548            self.active_key.read().unwrap().clone()
549        } else {
550            self.previous_keys
551                .read()
552                .unwrap()
553                .get(&region.key_id)
554                .cloned()
555                .ok_or_else(|| format!("Key {} not found", region.key_id))?
556        };
557
558        // Perform real AEAD decryption
559        let plaintext = match region.algorithm {
560            EncryptionAlgorithm::Aes256Gcm | EncryptionAlgorithm::Aes128Gcm => {
561                let cipher = Aes256Gcm::new_from_slice(key.material())
562                    .map_err(|e| format!("Invalid AES key: {}", e))?;
563                let aes_nonce = AesNonce::from_slice(&region.nonce);
564                cipher
565                    .decrypt(aes_nonce, region.ciphertext.as_ref())
566                    .map_err(|_| {
567                        "AES-GCM decryption failed: authentication tag mismatch".to_string()
568                    })?
569            }
570            EncryptionAlgorithm::ChaCha20Poly1305 => {
571                let cipher = ChaCha20Poly1305::new_from_slice(key.material())
572                    .map_err(|e| format!("Invalid ChaCha20 key: {}", e))?;
573                let cha_nonce = ChaNonce::from_slice(&region.nonce);
574                cipher
575                    .decrypt(cha_nonce, region.ciphertext.as_ref())
576                    .map_err(|_| {
577                        "ChaCha20-Poly1305 decryption failed: authentication tag mismatch"
578                            .to_string()
579                    })?
580            }
581            EncryptionAlgorithm::XChaCha20Poly1305 => {
582                let cipher = XChaCha20Poly1305::new_from_slice(key.material())
583                    .map_err(|e| format!("Invalid XChaCha20 key: {}", e))?;
584                let x_nonce = XNonce::from_slice(&region.nonce);
585                cipher
586                    .decrypt(x_nonce, region.ciphertext.as_ref())
587                    .map_err(|_| {
588                        "XChaCha20-Poly1305 decryption failed: authentication tag mismatch"
589                            .to_string()
590                    })?
591            }
592        };
593
594        let elapsed = start.elapsed();
595
596        // Update stats
597        {
598            let mut stats = self.stats.write().unwrap();
599            stats.bytes_decrypted += plaintext.len() as u64;
600            stats.decrypt_ops += 1;
601            let total_time = stats.avg_decrypt_time_us * (stats.decrypt_ops - 1) as f64;
602            stats.avg_decrypt_time_us =
603                (total_time + elapsed.as_micros() as f64) / stats.decrypt_ops as f64;
604        }
605
606        Ok(plaintext)
607    }
608
609    /// Decrypt a memory region (demo/fallback implementation).
610    ///
611    /// WARNING: Uses XOR-based simulation - NOT cryptographically secure.
612    #[cfg(not(feature = "crypto"))]
613    pub fn decrypt_region(&self, region: &EncryptedRegion) -> Result<Vec<u8>, String> {
614        let start = Instant::now();
615
616        // Find the appropriate key
617        let key = if region.key_id == self.active_key.read().unwrap().key_id {
618            self.active_key.read().unwrap().clone()
619        } else {
620            self.previous_keys
621                .read()
622                .unwrap()
623                .get(&region.key_id)
624                .cloned()
625                .ok_or_else(|| format!("Key {} not found", region.key_id))?
626        };
627
628        // Verify and remove tag
629        if region.ciphertext.len() < 16 {
630            return Err("Ciphertext too short".to_string());
631        }
632        let (ciphertext, _tag) = region.ciphertext.split_at(region.ciphertext.len() - 16);
633
634        // Simulate decryption (reverse XOR)
635        // WARNING: This is NOT secure - use crypto feature for production
636        let mut plaintext = ciphertext.to_vec();
637        for (i, byte) in plaintext.iter_mut().enumerate() {
638            *byte ^= region.nonce[i % region.nonce.len()];
639            *byte ^= key.material()[i % key.material().len()];
640        }
641
642        let elapsed = start.elapsed();
643
644        // Update stats
645        {
646            let mut stats = self.stats.write().unwrap();
647            stats.bytes_decrypted += plaintext.len() as u64;
648            stats.decrypt_ops += 1;
649            let total_time = stats.avg_decrypt_time_us * (stats.decrypt_ops - 1) as f64;
650            stats.avg_decrypt_time_us =
651                (total_time + elapsed.as_micros() as f64) / stats.decrypt_ops as f64;
652        }
653
654        Ok(plaintext)
655    }
656
657    /// Rotate encryption keys.
658    pub fn rotate_keys(&self) {
659        let mut active = self.active_key.write().unwrap();
660        let mut previous = self.previous_keys.write().unwrap();
661
662        // Move current key to previous
663        let old_key = active.clone();
664        previous.insert(old_key.key_id, old_key);
665
666        // Generate new key
667        let new_key_id = self.next_key_id.fetch_add(1, Ordering::Relaxed);
668        *active = EncryptionKey::new(new_key_id, self.config.algorithm);
669
670        // Update rotation time
671        *self.last_rotation.write().unwrap() = Instant::now();
672
673        // Update stats
674        self.stats.write().unwrap().key_rotations += 1;
675
676        // Clean up old keys (keep last 10)
677        while previous.len() > 10 {
678            if let Some(oldest_id) = previous.keys().min().copied() {
679                previous.remove(&oldest_id);
680            }
681        }
682    }
683
684    /// Check if key rotation is needed.
685    pub fn needs_rotation(&self) -> bool {
686        let last = *self.last_rotation.read().unwrap();
687        last.elapsed() >= self.config.key_rotation_interval
688    }
689
690    /// Get encryption statistics.
691    pub fn stats(&self) -> EncryptionStats {
692        self.stats.read().unwrap().clone()
693    }
694
695    /// Get the current key ID.
696    pub fn current_key_id(&self) -> u64 {
697        self.active_key.read().unwrap().key_id
698    }
699
700    /// Get the configuration.
701    pub fn config(&self) -> &EncryptionConfig {
702        &self.config
703    }
704}
705
706impl fmt::Debug for MemoryEncryption {
707    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708        f.debug_struct("MemoryEncryption")
709            .field("config", &self.config)
710            .field("current_key_id", &self.current_key_id())
711            .field("stats", &self.stats())
712            .finish()
713    }
714}
715
716// ============================================================================
717// Kernel Sandboxing
718// ============================================================================
719
720/// Access control for kernel operations.
721#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
722pub enum AccessLevel {
723    /// No access
724    Deny,
725    /// Read-only access
726    ReadOnly,
727    /// Read-write access
728    #[default]
729    ReadWrite,
730    /// Full access including execute
731    Full,
732}
733
734/// Resource limits for sandboxed kernels.
735#[derive(Debug, Clone)]
736pub struct ResourceLimits {
737    /// Maximum GPU memory in bytes
738    pub max_memory_bytes: u64,
739    /// Maximum execution time
740    pub max_execution_time: Duration,
741    /// Maximum messages per second
742    pub max_messages_per_sec: u32,
743    /// Maximum concurrent K2K connections
744    pub max_k2k_connections: u32,
745    /// Maximum checkpoint size
746    pub max_checkpoint_size: u64,
747    /// Maximum queue depth
748    pub max_queue_depth: u32,
749}
750
751impl Default for ResourceLimits {
752    fn default() -> Self {
753        Self {
754            max_memory_bytes: 1024 * 1024 * 1024, // 1GB
755            max_execution_time: Duration::from_secs(60),
756            max_messages_per_sec: 10000,
757            max_k2k_connections: 100,
758            max_checkpoint_size: 100 * 1024 * 1024, // 100MB
759            max_queue_depth: 4096,
760        }
761    }
762}
763
764impl ResourceLimits {
765    /// Create new resource limits.
766    pub fn new() -> Self {
767        Self::default()
768    }
769
770    /// Set maximum memory.
771    pub fn with_max_memory(mut self, bytes: u64) -> Self {
772        self.max_memory_bytes = bytes;
773        self
774    }
775
776    /// Set maximum execution time.
777    pub fn with_max_execution_time(mut self, duration: Duration) -> Self {
778        self.max_execution_time = duration;
779        self
780    }
781
782    /// Set maximum messages per second.
783    pub fn with_max_messages_per_sec(mut self, count: u32) -> Self {
784        self.max_messages_per_sec = count;
785        self
786    }
787
788    /// Set maximum K2K connections.
789    pub fn with_max_k2k_connections(mut self, count: u32) -> Self {
790        self.max_k2k_connections = count;
791        self
792    }
793
794    /// Restrictive limits for untrusted kernels.
795    pub fn restrictive() -> Self {
796        Self {
797            max_memory_bytes: 256 * 1024 * 1024, // 256MB
798            max_execution_time: Duration::from_secs(10),
799            max_messages_per_sec: 1000,
800            max_k2k_connections: 10,
801            max_checkpoint_size: 10 * 1024 * 1024, // 10MB
802            max_queue_depth: 256,
803        }
804    }
805
806    /// Permissive limits for trusted kernels.
807    pub fn permissive() -> Self {
808        Self {
809            max_memory_bytes: 8 * 1024 * 1024 * 1024, // 8GB
810            max_execution_time: Duration::from_secs(3600),
811            max_messages_per_sec: 1_000_000,
812            max_k2k_connections: 1000,
813            max_checkpoint_size: 1024 * 1024 * 1024, // 1GB
814            max_queue_depth: 65536,
815        }
816    }
817}
818
819/// Sandbox policy defining what a kernel can access.
820#[derive(Debug, Clone)]
821pub struct SandboxPolicy {
822    /// Resource limits
823    pub limits: ResourceLimits,
824    /// Allowed K2K destinations (empty = all allowed)
825    pub allowed_k2k_destinations: HashSet<String>,
826    /// Denied K2K destinations
827    pub denied_k2k_destinations: HashSet<String>,
828    /// Memory region access levels
829    pub memory_access: HashMap<String, AccessLevel>,
830    /// Whether the kernel can create checkpoints
831    pub can_checkpoint: bool,
832    /// Whether the kernel can be migrated
833    pub can_migrate: bool,
834    /// Whether the kernel can spawn child kernels
835    pub can_spawn: bool,
836    /// Whether the kernel can access host memory
837    pub can_access_host: bool,
838    /// Allowed system calls (for future use)
839    pub allowed_syscalls: HashSet<String>,
840}
841
842impl Default for SandboxPolicy {
843    fn default() -> Self {
844        Self {
845            limits: ResourceLimits::default(),
846            allowed_k2k_destinations: HashSet::new(),
847            denied_k2k_destinations: HashSet::new(),
848            memory_access: HashMap::new(),
849            can_checkpoint: true,
850            can_migrate: true,
851            can_spawn: false,
852            can_access_host: false,
853            allowed_syscalls: HashSet::new(),
854        }
855    }
856}
857
858impl SandboxPolicy {
859    /// Create a new sandbox policy.
860    pub fn new() -> Self {
861        Self::default()
862    }
863
864    /// Set resource limits.
865    pub fn with_limits(mut self, limits: ResourceLimits) -> Self {
866        self.limits = limits;
867        self
868    }
869
870    /// Set memory limit.
871    pub fn with_memory_limit(mut self, bytes: u64) -> Self {
872        self.limits.max_memory_bytes = bytes;
873        self
874    }
875
876    /// Set execution timeout.
877    pub fn with_execution_timeout(mut self, timeout: Duration) -> Self {
878        self.limits.max_execution_time = timeout;
879        self
880    }
881
882    /// Allow K2K to specific destinations.
883    pub fn allow_k2k_to(mut self, destinations: &[&str]) -> Self {
884        self.allowed_k2k_destinations
885            .extend(destinations.iter().map(|s| s.to_string()));
886        self
887    }
888
889    /// Deny K2K to specific destinations.
890    pub fn deny_k2k_to(mut self, destinations: &[&str]) -> Self {
891        self.denied_k2k_destinations
892            .extend(destinations.iter().map(|s| s.to_string()));
893        self
894    }
895
896    /// Set memory region access level.
897    pub fn with_memory_access(mut self, region: &str, access: AccessLevel) -> Self {
898        self.memory_access.insert(region.to_string(), access);
899        self
900    }
901
902    /// Enable/disable checkpointing.
903    pub fn with_checkpoint(mut self, enabled: bool) -> Self {
904        self.can_checkpoint = enabled;
905        self
906    }
907
908    /// Enable/disable migration.
909    pub fn with_migration(mut self, enabled: bool) -> Self {
910        self.can_migrate = enabled;
911        self
912    }
913
914    /// Enable/disable spawning.
915    pub fn with_spawn(mut self, enabled: bool) -> Self {
916        self.can_spawn = enabled;
917        self
918    }
919
920    /// Enable/disable host memory access.
921    pub fn with_host_access(mut self, enabled: bool) -> Self {
922        self.can_access_host = enabled;
923        self
924    }
925
926    /// Create a restrictive policy for untrusted kernels.
927    pub fn restrictive() -> Self {
928        Self {
929            limits: ResourceLimits::restrictive(),
930            allowed_k2k_destinations: HashSet::new(),
931            denied_k2k_destinations: HashSet::new(),
932            memory_access: HashMap::new(),
933            can_checkpoint: false,
934            can_migrate: false,
935            can_spawn: false,
936            can_access_host: false,
937            allowed_syscalls: HashSet::new(),
938        }
939    }
940
941    /// Create a permissive policy for trusted kernels.
942    pub fn permissive() -> Self {
943        Self {
944            limits: ResourceLimits::permissive(),
945            allowed_k2k_destinations: HashSet::new(),
946            denied_k2k_destinations: HashSet::new(),
947            memory_access: HashMap::new(),
948            can_checkpoint: true,
949            can_migrate: true,
950            can_spawn: true,
951            can_access_host: true,
952            allowed_syscalls: HashSet::new(),
953        }
954    }
955
956    /// Check if K2K to destination is allowed.
957    pub fn is_k2k_allowed(&self, destination: &str) -> bool {
958        // If denied, always reject
959        if self.denied_k2k_destinations.contains(destination) {
960            return false;
961        }
962        // If allowed list is empty, allow all (except denied)
963        if self.allowed_k2k_destinations.is_empty() {
964            return true;
965        }
966        // Otherwise, must be in allowed list
967        self.allowed_k2k_destinations.contains(destination)
968    }
969}
970
971/// Sandbox violation type.
972#[derive(Debug, Clone, PartialEq, Eq)]
973pub enum ViolationType {
974    /// Memory limit exceeded
975    MemoryLimitExceeded {
976        /// Amount of memory used in bytes
977        used: u64,
978        /// Maximum allowed memory in bytes
979        limit: u64,
980    },
981    /// Execution time exceeded
982    ExecutionTimeExceeded {
983        /// Elapsed execution time
984        elapsed: Duration,
985        /// Maximum allowed execution time
986        limit: Duration,
987    },
988    /// Message rate exceeded
989    MessageRateExceeded {
990        /// Current message rate per second
991        rate: u32,
992        /// Maximum allowed rate per second
993        limit: u32,
994    },
995    /// Unauthorized K2K destination
996    UnauthorizedK2K {
997        /// The destination kernel that was blocked
998        destination: String,
999    },
1000    /// Unauthorized memory access
1001    UnauthorizedMemoryAccess {
1002        /// The memory region that was accessed
1003        region: String,
1004        /// The access level that was requested
1005        requested: AccessLevel,
1006    },
1007    /// Checkpoint not allowed
1008    CheckpointNotAllowed,
1009    /// Migration not allowed
1010    MigrationNotAllowed,
1011    /// Spawn not allowed
1012    SpawnNotAllowed,
1013    /// Host access not allowed
1014    HostAccessNotAllowed,
1015}
1016
1017impl fmt::Display for ViolationType {
1018    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1019        match self {
1020            Self::MemoryLimitExceeded { used, limit } => {
1021                write!(f, "Memory limit exceeded: {} > {} bytes", used, limit)
1022            }
1023            Self::ExecutionTimeExceeded { elapsed, limit } => {
1024                write!(f, "Execution time exceeded: {:?} > {:?}", elapsed, limit)
1025            }
1026            Self::MessageRateExceeded { rate, limit } => {
1027                write!(f, "Message rate exceeded: {} > {} msg/s", rate, limit)
1028            }
1029            Self::UnauthorizedK2K { destination } => {
1030                write!(f, "Unauthorized K2K to: {}", destination)
1031            }
1032            Self::UnauthorizedMemoryAccess { region, requested } => {
1033                write!(
1034                    f,
1035                    "Unauthorized {:?} access to region: {}",
1036                    requested, region
1037                )
1038            }
1039            Self::CheckpointNotAllowed => write!(f, "Checkpointing not allowed"),
1040            Self::MigrationNotAllowed => write!(f, "Migration not allowed"),
1041            Self::SpawnNotAllowed => write!(f, "Spawning not allowed"),
1042            Self::HostAccessNotAllowed => write!(f, "Host memory access not allowed"),
1043        }
1044    }
1045}
1046
1047/// A recorded sandbox violation.
1048#[derive(Debug, Clone)]
1049pub struct SandboxViolation {
1050    /// Violation type
1051    pub violation_type: ViolationType,
1052    /// Kernel that violated the policy
1053    pub kernel_id: KernelId,
1054    /// When the violation occurred
1055    pub timestamp: Instant,
1056    /// Additional context
1057    pub context: Option<String>,
1058}
1059
1060/// Statistics for sandbox enforcement.
1061#[derive(Debug, Clone, Default)]
1062pub struct SandboxStats {
1063    /// Total policy checks performed
1064    pub total_checks: u64,
1065    /// Number of violations detected
1066    pub violations_detected: u64,
1067    /// Number of operations blocked
1068    pub operations_blocked: u64,
1069    /// Current memory usage
1070    pub current_memory_usage: u64,
1071    /// Current message rate
1072    pub current_message_rate: u32,
1073}
1074
1075/// Kernel sandbox for isolation and resource control.
1076pub struct KernelSandbox {
1077    /// The sandbox policy
1078    policy: SandboxPolicy,
1079    /// Kernel this sandbox applies to
1080    kernel_id: Option<KernelId>,
1081    /// Statistics
1082    stats: RwLock<SandboxStats>,
1083    /// Recorded violations
1084    violations: RwLock<Vec<SandboxViolation>>,
1085    /// Start time for execution tracking
1086    start_time: RwLock<Option<Instant>>,
1087    /// Message count for rate limiting
1088    message_count: AtomicU64,
1089    /// Last rate check time
1090    last_rate_check: RwLock<Instant>,
1091}
1092
1093impl KernelSandbox {
1094    /// Create a new kernel sandbox.
1095    pub fn new(policy: SandboxPolicy) -> Self {
1096        Self {
1097            policy,
1098            kernel_id: None,
1099            stats: RwLock::new(SandboxStats::default()),
1100            violations: RwLock::new(Vec::new()),
1101            start_time: RwLock::new(None),
1102            message_count: AtomicU64::new(0),
1103            last_rate_check: RwLock::new(Instant::now()),
1104        }
1105    }
1106
1107    /// Apply sandbox to a kernel.
1108    pub fn apply_to_kernel(&mut self, kernel_id: KernelId) {
1109        self.kernel_id = Some(kernel_id);
1110        *self.start_time.write().unwrap() = Some(Instant::now());
1111    }
1112
1113    /// Check memory usage against limits.
1114    pub fn check_memory(&self, bytes: u64) -> Result<(), SandboxViolation> {
1115        self.stats.write().unwrap().total_checks += 1;
1116
1117        if bytes > self.policy.limits.max_memory_bytes {
1118            let violation = SandboxViolation {
1119                violation_type: ViolationType::MemoryLimitExceeded {
1120                    used: bytes,
1121                    limit: self.policy.limits.max_memory_bytes,
1122                },
1123                kernel_id: self
1124                    .kernel_id
1125                    .clone()
1126                    .unwrap_or_else(|| KernelId("unknown".to_string())),
1127                timestamp: Instant::now(),
1128                context: None,
1129            };
1130            self.record_violation(violation.clone());
1131            return Err(violation);
1132        }
1133
1134        self.stats.write().unwrap().current_memory_usage = bytes;
1135        Ok(())
1136    }
1137
1138    /// Check execution time against limits.
1139    pub fn check_execution_time(&self) -> Result<(), SandboxViolation> {
1140        self.stats.write().unwrap().total_checks += 1;
1141
1142        if let Some(start) = *self.start_time.read().unwrap() {
1143            let elapsed = start.elapsed();
1144            if elapsed > self.policy.limits.max_execution_time {
1145                let violation = SandboxViolation {
1146                    violation_type: ViolationType::ExecutionTimeExceeded {
1147                        elapsed,
1148                        limit: self.policy.limits.max_execution_time,
1149                    },
1150                    kernel_id: self
1151                        .kernel_id
1152                        .clone()
1153                        .unwrap_or_else(|| KernelId("unknown".to_string())),
1154                    timestamp: Instant::now(),
1155                    context: None,
1156                };
1157                self.record_violation(violation.clone());
1158                return Err(violation);
1159            }
1160        }
1161        Ok(())
1162    }
1163
1164    /// Check K2K destination against policy.
1165    pub fn check_k2k(&self, destination: &str) -> Result<(), SandboxViolation> {
1166        self.stats.write().unwrap().total_checks += 1;
1167
1168        if !self.policy.is_k2k_allowed(destination) {
1169            let violation = SandboxViolation {
1170                violation_type: ViolationType::UnauthorizedK2K {
1171                    destination: destination.to_string(),
1172                },
1173                kernel_id: self
1174                    .kernel_id
1175                    .clone()
1176                    .unwrap_or_else(|| KernelId("unknown".to_string())),
1177                timestamp: Instant::now(),
1178                context: None,
1179            };
1180            self.record_violation(violation.clone());
1181            return Err(violation);
1182        }
1183        Ok(())
1184    }
1185
1186    /// Check if checkpointing is allowed.
1187    pub fn check_checkpoint(&self) -> Result<(), SandboxViolation> {
1188        self.stats.write().unwrap().total_checks += 1;
1189
1190        if !self.policy.can_checkpoint {
1191            let violation = SandboxViolation {
1192                violation_type: ViolationType::CheckpointNotAllowed,
1193                kernel_id: self
1194                    .kernel_id
1195                    .clone()
1196                    .unwrap_or_else(|| KernelId("unknown".to_string())),
1197                timestamp: Instant::now(),
1198                context: None,
1199            };
1200            self.record_violation(violation.clone());
1201            return Err(violation);
1202        }
1203        Ok(())
1204    }
1205
1206    /// Check if migration is allowed.
1207    pub fn check_migration(&self) -> Result<(), SandboxViolation> {
1208        self.stats.write().unwrap().total_checks += 1;
1209
1210        if !self.policy.can_migrate {
1211            let violation = SandboxViolation {
1212                violation_type: ViolationType::MigrationNotAllowed,
1213                kernel_id: self
1214                    .kernel_id
1215                    .clone()
1216                    .unwrap_or_else(|| KernelId("unknown".to_string())),
1217                timestamp: Instant::now(),
1218                context: None,
1219            };
1220            self.record_violation(violation.clone());
1221            return Err(violation);
1222        }
1223        Ok(())
1224    }
1225
1226    /// Record a message for rate limiting.
1227    pub fn record_message(&self) -> Result<(), SandboxViolation> {
1228        self.message_count.fetch_add(1, Ordering::Relaxed);
1229
1230        // Check rate every second
1231        let mut last_check = self.last_rate_check.write().unwrap();
1232        if last_check.elapsed() >= Duration::from_secs(1) {
1233            let count = self.message_count.swap(0, Ordering::Relaxed) as u32;
1234            *last_check = Instant::now();
1235
1236            self.stats.write().unwrap().current_message_rate = count;
1237
1238            if count > self.policy.limits.max_messages_per_sec {
1239                let violation = SandboxViolation {
1240                    violation_type: ViolationType::MessageRateExceeded {
1241                        rate: count,
1242                        limit: self.policy.limits.max_messages_per_sec,
1243                    },
1244                    kernel_id: self
1245                        .kernel_id
1246                        .clone()
1247                        .unwrap_or_else(|| KernelId("unknown".to_string())),
1248                    timestamp: Instant::now(),
1249                    context: None,
1250                };
1251                self.record_violation(violation.clone());
1252                return Err(violation);
1253            }
1254        }
1255        Ok(())
1256    }
1257
1258    /// Record a violation.
1259    fn record_violation(&self, violation: SandboxViolation) {
1260        let mut stats = self.stats.write().unwrap();
1261        stats.violations_detected += 1;
1262        stats.operations_blocked += 1;
1263
1264        self.violations.write().unwrap().push(violation);
1265    }
1266
1267    /// Get all recorded violations.
1268    pub fn violations(&self) -> Vec<SandboxViolation> {
1269        self.violations.read().unwrap().clone()
1270    }
1271
1272    /// Get sandbox statistics.
1273    pub fn stats(&self) -> SandboxStats {
1274        self.stats.read().unwrap().clone()
1275    }
1276
1277    /// Get the policy.
1278    pub fn policy(&self) -> &SandboxPolicy {
1279        &self.policy
1280    }
1281
1282    /// Reset statistics and violations.
1283    pub fn reset(&self) {
1284        *self.stats.write().unwrap() = SandboxStats::default();
1285        self.violations.write().unwrap().clear();
1286        self.message_count.store(0, Ordering::Relaxed);
1287    }
1288}
1289
1290impl fmt::Debug for KernelSandbox {
1291    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1292        f.debug_struct("KernelSandbox")
1293            .field("policy", &self.policy)
1294            .field("kernel_id", &self.kernel_id)
1295            .field("stats", &self.stats())
1296            .field("violations_count", &self.violations.read().unwrap().len())
1297            .finish()
1298    }
1299}
1300
1301// ============================================================================
1302// Compliance Reports
1303// ============================================================================
1304
1305/// Compliance standard for reporting.
1306#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1307pub enum ComplianceStandard {
1308    /// SOC 2 Type II
1309    SOC2,
1310    /// GDPR (General Data Protection Regulation)
1311    GDPR,
1312    /// HIPAA (Health Insurance Portability and Accountability Act)
1313    HIPAA,
1314    /// PCI DSS (Payment Card Industry Data Security Standard)
1315    PCIDSS,
1316    /// ISO 27001
1317    ISO27001,
1318    /// FedRAMP
1319    FedRAMP,
1320    /// NIST Cybersecurity Framework
1321    NIST,
1322}
1323
1324impl fmt::Display for ComplianceStandard {
1325    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1326        match self {
1327            Self::SOC2 => write!(f, "SOC 2 Type II"),
1328            Self::GDPR => write!(f, "GDPR"),
1329            Self::HIPAA => write!(f, "HIPAA"),
1330            Self::PCIDSS => write!(f, "PCI DSS"),
1331            Self::ISO27001 => write!(f, "ISO 27001"),
1332            Self::FedRAMP => write!(f, "FedRAMP"),
1333            Self::NIST => write!(f, "NIST CSF"),
1334        }
1335    }
1336}
1337
1338/// Report output format.
1339#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
1340pub enum ReportFormat {
1341    /// JSON format
1342    #[default]
1343    Json,
1344    /// HTML format
1345    Html,
1346    /// Markdown format
1347    Markdown,
1348    /// PDF format (requires external renderer)
1349    Pdf,
1350    /// CSV format (for data export)
1351    Csv,
1352}
1353
1354/// Compliance check result.
1355#[derive(Debug, Clone)]
1356pub enum ComplianceStatus {
1357    /// Fully compliant
1358    Compliant,
1359    /// Partially compliant with notes
1360    PartiallyCompliant {
1361        /// Notes describing partial compliance
1362        notes: Vec<String>,
1363    },
1364    /// Non-compliant with reasons
1365    NonCompliant {
1366        /// Reasons for non-compliance
1367        reasons: Vec<String>,
1368    },
1369    /// Not applicable
1370    NotApplicable,
1371}
1372
1373impl ComplianceStatus {
1374    /// Check if compliant.
1375    pub fn is_compliant(&self) -> bool {
1376        matches!(self, Self::Compliant | Self::NotApplicable)
1377    }
1378}
1379
1380/// A single compliance check.
1381#[derive(Debug, Clone)]
1382pub struct ComplianceCheck {
1383    /// Check identifier
1384    pub id: String,
1385    /// Check name
1386    pub name: String,
1387    /// Standard this check belongs to
1388    pub standard: ComplianceStandard,
1389    /// Check description
1390    pub description: String,
1391    /// Check status
1392    pub status: ComplianceStatus,
1393    /// Evidence collected
1394    pub evidence: Vec<String>,
1395    /// Recommendations
1396    pub recommendations: Vec<String>,
1397    /// When the check was performed
1398    pub checked_at: SystemTime,
1399}
1400
1401/// Summary statistics for a compliance report.
1402#[derive(Debug, Clone)]
1403pub struct ComplianceSummary {
1404    /// Total checks performed
1405    pub total_checks: usize,
1406    /// Number compliant
1407    pub compliant: usize,
1408    /// Number partially compliant
1409    pub partially_compliant: usize,
1410    /// Number non-compliant
1411    pub non_compliant: usize,
1412    /// Number not applicable
1413    pub not_applicable: usize,
1414    /// Overall compliance percentage
1415    pub compliance_percentage: f64,
1416}
1417
1418/// A complete compliance report.
1419#[derive(Debug, Clone)]
1420pub struct ComplianceReport {
1421    /// Report ID
1422    pub id: String,
1423    /// Report title
1424    pub title: String,
1425    /// Standards covered
1426    pub standards: Vec<ComplianceStandard>,
1427    /// Individual checks
1428    pub checks: Vec<ComplianceCheck>,
1429    /// Summary statistics
1430    pub summary: ComplianceSummary,
1431    /// Report generation time
1432    pub generated_at: SystemTime,
1433    /// Report period start
1434    pub period_start: SystemTime,
1435    /// Report period end
1436    pub period_end: SystemTime,
1437    /// Additional metadata
1438    pub metadata: HashMap<String, String>,
1439}
1440
1441impl ComplianceReport {
1442    /// Export report to specified format.
1443    pub fn export(&self, format: ReportFormat) -> String {
1444        match format {
1445            ReportFormat::Json => self.to_json(),
1446            ReportFormat::Html => self.to_html(),
1447            ReportFormat::Markdown => self.to_markdown(),
1448            ReportFormat::Pdf => self.to_markdown(), // PDF requires external renderer
1449            ReportFormat::Csv => self.to_csv(),
1450        }
1451    }
1452
1453    fn to_json(&self) -> String {
1454        let mut json = String::new();
1455        json.push_str("{\n");
1456        json.push_str(&format!("  \"id\": \"{}\",\n", self.id));
1457        json.push_str(&format!("  \"title\": \"{}\",\n", self.title));
1458        json.push_str(&format!(
1459            "  \"standards\": [{}],\n",
1460            self.standards
1461                .iter()
1462                .map(|s| format!("\"{}\"", s))
1463                .collect::<Vec<_>>()
1464                .join(", ")
1465        ));
1466        json.push_str("  \"summary\": {\n");
1467        json.push_str(&format!(
1468            "    \"total_checks\": {},\n",
1469            self.summary.total_checks
1470        ));
1471        json.push_str(&format!("    \"compliant\": {},\n", self.summary.compliant));
1472        json.push_str(&format!(
1473            "    \"partially_compliant\": {},\n",
1474            self.summary.partially_compliant
1475        ));
1476        json.push_str(&format!(
1477            "    \"non_compliant\": {},\n",
1478            self.summary.non_compliant
1479        ));
1480        json.push_str(&format!(
1481            "    \"compliance_percentage\": {:.1}\n",
1482            self.summary.compliance_percentage
1483        ));
1484        json.push_str("  },\n");
1485        json.push_str(&format!("  \"checks_count\": {}\n", self.checks.len()));
1486        json.push_str("}\n");
1487        json
1488    }
1489
1490    fn to_html(&self) -> String {
1491        let mut html = String::new();
1492        html.push_str("<!DOCTYPE html>\n<html>\n<head>\n");
1493        html.push_str(&format!("<title>{}</title>\n", self.title));
1494        html.push_str("<style>body { font-family: sans-serif; } .compliant { color: green; } .non-compliant { color: red; }</style>\n");
1495        html.push_str("</head>\n<body>\n");
1496        html.push_str(&format!("<h1>{}</h1>\n", self.title));
1497        html.push_str(&format!("<p>Report ID: {}</p>\n", self.id));
1498        html.push_str("<h2>Summary</h2>\n");
1499        html.push_str("<table>\n");
1500        html.push_str(&format!(
1501            "<tr><td>Total Checks</td><td>{}</td></tr>\n",
1502            self.summary.total_checks
1503        ));
1504        html.push_str(&format!(
1505            "<tr><td>Compliant</td><td class=\"compliant\">{}</td></tr>\n",
1506            self.summary.compliant
1507        ));
1508        html.push_str(&format!(
1509            "<tr><td>Non-Compliant</td><td class=\"non-compliant\">{}</td></tr>\n",
1510            self.summary.non_compliant
1511        ));
1512        html.push_str(&format!(
1513            "<tr><td>Compliance</td><td>{:.1}%</td></tr>\n",
1514            self.summary.compliance_percentage
1515        ));
1516        html.push_str("</table>\n");
1517        html.push_str("<h2>Checks</h2>\n");
1518        for check in &self.checks {
1519            html.push_str(&format!("<h3>{}</h3>\n", check.name));
1520            html.push_str(&format!("<p>{}</p>\n", check.description));
1521        }
1522        html.push_str("</body>\n</html>\n");
1523        html
1524    }
1525
1526    fn to_markdown(&self) -> String {
1527        let mut md = String::new();
1528        md.push_str(&format!("# {}\n\n", self.title));
1529        md.push_str(&format!("**Report ID:** {}\n\n", self.id));
1530        md.push_str("## Summary\n\n");
1531        md.push_str("| Metric | Value |\n");
1532        md.push_str("|--------|-------|\n");
1533        md.push_str(&format!(
1534            "| Total Checks | {} |\n",
1535            self.summary.total_checks
1536        ));
1537        md.push_str(&format!("| Compliant | {} |\n", self.summary.compliant));
1538        md.push_str(&format!(
1539            "| Partially Compliant | {} |\n",
1540            self.summary.partially_compliant
1541        ));
1542        md.push_str(&format!(
1543            "| Non-Compliant | {} |\n",
1544            self.summary.non_compliant
1545        ));
1546        md.push_str(&format!(
1547            "| Compliance | {:.1}% |\n",
1548            self.summary.compliance_percentage
1549        ));
1550        md.push_str("\n## Detailed Checks\n\n");
1551        for check in &self.checks {
1552            let status_icon = match &check.status {
1553                ComplianceStatus::Compliant => "✅",
1554                ComplianceStatus::PartiallyCompliant { .. } => "⚠️",
1555                ComplianceStatus::NonCompliant { .. } => "❌",
1556                ComplianceStatus::NotApplicable => "➖",
1557            };
1558            md.push_str(&format!("### {} {}\n\n", status_icon, check.name));
1559            md.push_str(&format!("{}\n\n", check.description));
1560        }
1561        md
1562    }
1563
1564    fn to_csv(&self) -> String {
1565        let mut csv = String::new();
1566        csv.push_str("ID,Name,Standard,Status,Description\n");
1567        for check in &self.checks {
1568            let status = match &check.status {
1569                ComplianceStatus::Compliant => "Compliant",
1570                ComplianceStatus::PartiallyCompliant { .. } => "Partially Compliant",
1571                ComplianceStatus::NonCompliant { .. } => "Non-Compliant",
1572                ComplianceStatus::NotApplicable => "N/A",
1573            };
1574            csv.push_str(&format!(
1575                "\"{}\",\"{}\",\"{}\",\"{}\",\"{}\"\n",
1576                check.id, check.name, check.standard, status, check.description
1577            ));
1578        }
1579        csv
1580    }
1581}
1582
1583/// Compliance reporter for generating compliance documentation.
1584pub struct ComplianceReporter {
1585    /// Standards to report on
1586    standards: HashSet<ComplianceStandard>,
1587    /// Organization name
1588    organization: String,
1589    /// Report metadata
1590    metadata: HashMap<String, String>,
1591    /// Custom checks
1592    custom_checks: Vec<Box<dyn Fn() -> ComplianceCheck + Send + Sync>>,
1593}
1594
1595impl ComplianceReporter {
1596    /// Create a new compliance reporter.
1597    pub fn new() -> Self {
1598        Self {
1599            standards: HashSet::new(),
1600            organization: "Unknown".to_string(),
1601            metadata: HashMap::new(),
1602            custom_checks: Vec::new(),
1603        }
1604    }
1605
1606    /// Add a compliance standard.
1607    pub fn with_standard(mut self, standard: ComplianceStandard) -> Self {
1608        self.standards.insert(standard);
1609        self
1610    }
1611
1612    /// Set organization name.
1613    pub fn with_organization(mut self, org: &str) -> Self {
1614        self.organization = org.to_string();
1615        self
1616    }
1617
1618    /// Add metadata.
1619    pub fn with_metadata(mut self, key: &str, value: &str) -> Self {
1620        self.metadata.insert(key.to_string(), value.to_string());
1621        self
1622    }
1623
1624    /// Generate a compliance report.
1625    pub fn generate_report(&self, _format: ReportFormat) -> ComplianceReport {
1626        let mut checks = Vec::new();
1627        let now = SystemTime::now();
1628
1629        // Generate checks for each standard
1630        for standard in &self.standards {
1631            checks.extend(self.generate_standard_checks(*standard));
1632        }
1633
1634        // Run custom checks
1635        for check_fn in &self.custom_checks {
1636            checks.push(check_fn());
1637        }
1638
1639        // Calculate summary
1640        let total = checks.len();
1641        let compliant = checks
1642            .iter()
1643            .filter(|c| matches!(c.status, ComplianceStatus::Compliant))
1644            .count();
1645        let partial = checks
1646            .iter()
1647            .filter(|c| matches!(c.status, ComplianceStatus::PartiallyCompliant { .. }))
1648            .count();
1649        let non_compliant = checks
1650            .iter()
1651            .filter(|c| matches!(c.status, ComplianceStatus::NonCompliant { .. }))
1652            .count();
1653        let na = checks
1654            .iter()
1655            .filter(|c| matches!(c.status, ComplianceStatus::NotApplicable))
1656            .count();
1657
1658        let applicable = total - na;
1659        let compliance_pct = if applicable > 0 {
1660            ((compliant as f64 + partial as f64 * 0.5) / applicable as f64) * 100.0
1661        } else {
1662            100.0
1663        };
1664
1665        ComplianceReport {
1666            id: format!(
1667                "RPT-{}",
1668                now.duration_since(SystemTime::UNIX_EPOCH)
1669                    .unwrap()
1670                    .as_secs()
1671            ),
1672            title: format!("{} Compliance Report", self.organization),
1673            standards: self.standards.iter().copied().collect(),
1674            checks,
1675            summary: ComplianceSummary {
1676                total_checks: total,
1677                compliant,
1678                partially_compliant: partial,
1679                non_compliant,
1680                not_applicable: na,
1681                compliance_percentage: compliance_pct,
1682            },
1683            generated_at: now,
1684            period_start: now - Duration::from_secs(30 * 24 * 60 * 60), // 30 days ago
1685            period_end: now,
1686            metadata: self.metadata.clone(),
1687        }
1688    }
1689
1690    fn generate_standard_checks(&self, standard: ComplianceStandard) -> Vec<ComplianceCheck> {
1691        let now = SystemTime::now();
1692
1693        match standard {
1694            ComplianceStandard::SOC2 => vec![
1695                ComplianceCheck {
1696                    id: "SOC2-CC1.1".to_string(),
1697                    name: "Control Environment".to_string(),
1698                    standard,
1699                    description:
1700                        "The entity demonstrates commitment to integrity and ethical values."
1701                            .to_string(),
1702                    status: ComplianceStatus::Compliant,
1703                    evidence: vec![
1704                        "Audit logging enabled".to_string(),
1705                        "Access controls implemented".to_string(),
1706                    ],
1707                    recommendations: vec![],
1708                    checked_at: now,
1709                },
1710                ComplianceCheck {
1711                    id: "SOC2-CC6.1".to_string(),
1712                    name: "Logical Access Controls".to_string(),
1713                    standard,
1714                    description:
1715                        "Logical access security software, infrastructure, and architectures."
1716                            .to_string(),
1717                    status: ComplianceStatus::Compliant,
1718                    evidence: vec![
1719                        "Kernel sandboxing available".to_string(),
1720                        "Memory encryption available".to_string(),
1721                    ],
1722                    recommendations: vec![],
1723                    checked_at: now,
1724                },
1725                ComplianceCheck {
1726                    id: "SOC2-CC7.2".to_string(),
1727                    name: "System Monitoring".to_string(),
1728                    standard,
1729                    description: "System components are monitored and anomalies are identified."
1730                        .to_string(),
1731                    status: ComplianceStatus::Compliant,
1732                    evidence: vec![
1733                        "Health monitoring enabled".to_string(),
1734                        "GPU memory dashboard available".to_string(),
1735                    ],
1736                    recommendations: vec![],
1737                    checked_at: now,
1738                },
1739            ],
1740            ComplianceStandard::GDPR => vec![
1741                ComplianceCheck {
1742                    id: "GDPR-32".to_string(),
1743                    name: "Security of Processing".to_string(),
1744                    standard,
1745                    description: "Implement appropriate technical and organizational measures."
1746                        .to_string(),
1747                    status: ComplianceStatus::Compliant,
1748                    evidence: vec!["Memory encryption available".to_string()],
1749                    recommendations: vec!["Consider enabling encryption by default".to_string()],
1750                    checked_at: now,
1751                },
1752                ComplianceCheck {
1753                    id: "GDPR-33".to_string(),
1754                    name: "Breach Notification".to_string(),
1755                    standard,
1756                    description: "Notify supervisory authority of personal data breach."
1757                        .to_string(),
1758                    status: ComplianceStatus::PartiallyCompliant {
1759                        notes: vec!["Audit logging available but breach detection not automated"
1760                            .to_string()],
1761                    },
1762                    evidence: vec!["Audit logging enabled".to_string()],
1763                    recommendations: vec!["Add automated breach detection".to_string()],
1764                    checked_at: now,
1765                },
1766            ],
1767            ComplianceStandard::HIPAA => vec![
1768                ComplianceCheck {
1769                    id: "HIPAA-164.312(a)".to_string(),
1770                    name: "Access Control".to_string(),
1771                    standard,
1772                    description: "Implement technical policies for electronic PHI access."
1773                        .to_string(),
1774                    status: ComplianceStatus::Compliant,
1775                    evidence: vec![
1776                        "Kernel sandboxing available".to_string(),
1777                        "Access levels configurable".to_string(),
1778                    ],
1779                    recommendations: vec![],
1780                    checked_at: now,
1781                },
1782                ComplianceCheck {
1783                    id: "HIPAA-164.312(e)".to_string(),
1784                    name: "Transmission Security".to_string(),
1785                    standard,
1786                    description: "Implement security measures for ePHI transmission.".to_string(),
1787                    status: ComplianceStatus::Compliant,
1788                    evidence: vec!["Memory encryption for data at rest".to_string()],
1789                    recommendations: vec!["Implement TLS for network K2K".to_string()],
1790                    checked_at: now,
1791                },
1792            ],
1793            ComplianceStandard::PCIDSS => vec![
1794                ComplianceCheck {
1795                    id: "PCI-3.4".to_string(),
1796                    name: "Render PAN Unreadable".to_string(),
1797                    standard,
1798                    description: "Render PAN unreadable anywhere it is stored.".to_string(),
1799                    status: ComplianceStatus::Compliant,
1800                    evidence: vec!["AES-256-GCM encryption available".to_string()],
1801                    recommendations: vec![],
1802                    checked_at: now,
1803                },
1804                ComplianceCheck {
1805                    id: "PCI-10.1".to_string(),
1806                    name: "Audit Trails".to_string(),
1807                    standard,
1808                    description: "Implement audit trails to link access to individual users."
1809                        .to_string(),
1810                    status: ComplianceStatus::Compliant,
1811                    evidence: vec!["Comprehensive audit logging".to_string()],
1812                    recommendations: vec![],
1813                    checked_at: now,
1814                },
1815            ],
1816            ComplianceStandard::ISO27001 => vec![ComplianceCheck {
1817                id: "ISO-A.10.1".to_string(),
1818                name: "Cryptographic Controls".to_string(),
1819                standard,
1820                description: "Policy on use of cryptographic controls.".to_string(),
1821                status: ComplianceStatus::Compliant,
1822                evidence: vec!["Multiple encryption algorithms supported".to_string()],
1823                recommendations: vec![],
1824                checked_at: now,
1825            }],
1826            ComplianceStandard::FedRAMP => vec![ComplianceCheck {
1827                id: "FedRAMP-SC-28".to_string(),
1828                name: "Protection of Information at Rest".to_string(),
1829                standard,
1830                description: "Protect confidentiality and integrity of information at rest."
1831                    .to_string(),
1832                status: ComplianceStatus::Compliant,
1833                evidence: vec!["FIPS-compliant algorithms available".to_string()],
1834                recommendations: vec![],
1835                checked_at: now,
1836            }],
1837            ComplianceStandard::NIST => vec![
1838                ComplianceCheck {
1839                    id: "NIST-PR.DS-1".to_string(),
1840                    name: "Data-at-rest Protection".to_string(),
1841                    standard,
1842                    description: "Data-at-rest is protected.".to_string(),
1843                    status: ComplianceStatus::Compliant,
1844                    evidence: vec!["Memory encryption module".to_string()],
1845                    recommendations: vec![],
1846                    checked_at: now,
1847                },
1848                ComplianceCheck {
1849                    id: "NIST-DE.CM-1".to_string(),
1850                    name: "Network Monitoring".to_string(),
1851                    standard,
1852                    description: "The network is monitored to detect cybersecurity events."
1853                        .to_string(),
1854                    status: ComplianceStatus::Compliant,
1855                    evidence: vec![
1856                        "Observability context".to_string(),
1857                        "GPU profiler integration".to_string(),
1858                    ],
1859                    recommendations: vec![],
1860                    checked_at: now,
1861                },
1862            ],
1863        }
1864    }
1865}
1866
1867impl Default for ComplianceReporter {
1868    fn default() -> Self {
1869        Self::new()
1870    }
1871}
1872
1873impl fmt::Debug for ComplianceReporter {
1874    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1875        f.debug_struct("ComplianceReporter")
1876            .field("standards", &self.standards)
1877            .field("organization", &self.organization)
1878            .field("metadata", &self.metadata)
1879            .field("custom_checks_count", &self.custom_checks.len())
1880            .finish()
1881    }
1882}
1883
1884// ============================================================================
1885// Tests
1886// ============================================================================
1887
1888#[cfg(test)]
1889mod tests {
1890    use super::*;
1891
1892    // Memory Encryption Tests
1893
1894    #[test]
1895    fn test_encryption_config_builder() {
1896        let config = EncryptionConfig::new()
1897            .with_algorithm(EncryptionAlgorithm::ChaCha20Poly1305)
1898            .with_key_rotation_interval(Duration::from_secs(7200))
1899            .with_control_block_encryption(false);
1900
1901        assert_eq!(config.algorithm, EncryptionAlgorithm::ChaCha20Poly1305);
1902        assert_eq!(config.key_rotation_interval, Duration::from_secs(7200));
1903        assert!(!config.encrypt_control_blocks);
1904    }
1905
1906    #[test]
1907    fn test_encryption_key_creation() {
1908        let key = EncryptionKey::new(1, EncryptionAlgorithm::Aes256Gcm);
1909        assert_eq!(key.key_id, 1);
1910        assert_eq!(key.key_size(), 32);
1911        assert!(!key.is_expired());
1912    }
1913
1914    #[test]
1915    fn test_encrypt_decrypt_roundtrip() {
1916        let encryption = MemoryEncryption::new(EncryptionConfig::default());
1917        let plaintext = b"Hello, GPU World!";
1918
1919        let encrypted = encryption.encrypt_region(plaintext);
1920        assert_ne!(encrypted.ciphertext[..plaintext.len()], plaintext[..]);
1921
1922        let decrypted = encryption.decrypt_region(&encrypted).unwrap();
1923        assert_eq!(decrypted, plaintext);
1924    }
1925
1926    #[test]
1927    fn test_key_rotation() {
1928        let encryption = MemoryEncryption::new(EncryptionConfig::default());
1929        let initial_key_id = encryption.current_key_id();
1930
1931        encryption.rotate_keys();
1932        assert_eq!(encryption.current_key_id(), initial_key_id + 1);
1933
1934        // Stats should reflect rotation
1935        let stats = encryption.stats();
1936        assert_eq!(stats.key_rotations, 1);
1937    }
1938
1939    #[test]
1940    fn test_decrypt_with_old_key() {
1941        let encryption = MemoryEncryption::new(EncryptionConfig::default());
1942        let plaintext = b"Secret data";
1943
1944        let encrypted = encryption.encrypt_region(plaintext);
1945        let old_key_id = encrypted.key_id;
1946
1947        // Rotate key
1948        encryption.rotate_keys();
1949        assert_ne!(encryption.current_key_id(), old_key_id);
1950
1951        // Should still decrypt with old key
1952        let decrypted = encryption.decrypt_region(&encrypted).unwrap();
1953        assert_eq!(decrypted, plaintext);
1954    }
1955
1956    #[test]
1957    fn test_encryption_stats() {
1958        let encryption = MemoryEncryption::new(EncryptionConfig::default());
1959        let data = vec![0u8; 1024];
1960
1961        for _ in 0..10 {
1962            let encrypted = encryption.encrypt_region(&data);
1963            let _ = encryption.decrypt_region(&encrypted);
1964        }
1965
1966        let stats = encryption.stats();
1967        assert_eq!(stats.encrypt_ops, 10);
1968        assert_eq!(stats.decrypt_ops, 10);
1969        assert_eq!(stats.bytes_encrypted, 10240);
1970    }
1971
1972    // Kernel Sandboxing Tests
1973
1974    #[test]
1975    fn test_resource_limits_builder() {
1976        let limits = ResourceLimits::new()
1977            .with_max_memory(512 * 1024 * 1024)
1978            .with_max_execution_time(Duration::from_secs(30));
1979
1980        assert_eq!(limits.max_memory_bytes, 512 * 1024 * 1024);
1981        assert_eq!(limits.max_execution_time, Duration::from_secs(30));
1982    }
1983
1984    #[test]
1985    fn test_sandbox_policy_k2k() {
1986        let policy = SandboxPolicy::new()
1987            .allow_k2k_to(&["trusted_kernel", "another_trusted"])
1988            .deny_k2k_to(&["malicious_kernel"]);
1989
1990        assert!(policy.is_k2k_allowed("trusted_kernel"));
1991        assert!(policy.is_k2k_allowed("another_trusted"));
1992        assert!(!policy.is_k2k_allowed("malicious_kernel"));
1993        assert!(!policy.is_k2k_allowed("unknown_kernel")); // Not in allowed list
1994    }
1995
1996    #[test]
1997    fn test_sandbox_memory_check() {
1998        let policy = SandboxPolicy::new().with_memory_limit(1024);
1999        let sandbox = KernelSandbox::new(policy);
2000
2001        // Should pass
2002        assert!(sandbox.check_memory(512).is_ok());
2003
2004        // Should fail
2005        let result = sandbox.check_memory(2048);
2006        assert!(result.is_err());
2007
2008        if let Err(violation) = result {
2009            assert!(matches!(
2010                violation.violation_type,
2011                ViolationType::MemoryLimitExceeded { .. }
2012            ));
2013        }
2014    }
2015
2016    #[test]
2017    fn test_sandbox_k2k_check() {
2018        let policy = SandboxPolicy::new().deny_k2k_to(&["blocked"]);
2019        let sandbox = KernelSandbox::new(policy);
2020
2021        assert!(sandbox.check_k2k("allowed_dest").is_ok());
2022        assert!(sandbox.check_k2k("blocked").is_err());
2023    }
2024
2025    #[test]
2026    fn test_sandbox_checkpoint_check() {
2027        let policy = SandboxPolicy::restrictive();
2028        let sandbox = KernelSandbox::new(policy);
2029
2030        assert!(sandbox.check_checkpoint().is_err());
2031
2032        let permissive = SandboxPolicy::permissive();
2033        let sandbox2 = KernelSandbox::new(permissive);
2034        assert!(sandbox2.check_checkpoint().is_ok());
2035    }
2036
2037    #[test]
2038    fn test_sandbox_stats() {
2039        let policy = SandboxPolicy::new().with_memory_limit(1024);
2040        let sandbox = KernelSandbox::new(policy);
2041
2042        let _ = sandbox.check_memory(512);
2043        let _ = sandbox.check_memory(2048); // Violation
2044        let _ = sandbox.check_k2k("dest");
2045
2046        let stats = sandbox.stats();
2047        assert_eq!(stats.total_checks, 3);
2048        assert_eq!(stats.violations_detected, 1);
2049    }
2050
2051    #[test]
2052    fn test_sandbox_violations_list() {
2053        let policy = SandboxPolicy::restrictive();
2054        let sandbox = KernelSandbox::new(policy);
2055
2056        let _ = sandbox.check_checkpoint();
2057        let _ = sandbox.check_migration();
2058
2059        let violations = sandbox.violations();
2060        assert_eq!(violations.len(), 2);
2061    }
2062
2063    // Compliance Reports Tests
2064
2065    #[test]
2066    fn test_compliance_reporter_creation() {
2067        let reporter = ComplianceReporter::new()
2068            .with_standard(ComplianceStandard::SOC2)
2069            .with_standard(ComplianceStandard::GDPR)
2070            .with_organization("Test Org");
2071
2072        assert_eq!(reporter.standards.len(), 2);
2073        assert!(reporter.standards.contains(&ComplianceStandard::SOC2));
2074        assert!(reporter.standards.contains(&ComplianceStandard::GDPR));
2075    }
2076
2077    #[test]
2078    fn test_generate_soc2_report() {
2079        let reporter = ComplianceReporter::new()
2080            .with_standard(ComplianceStandard::SOC2)
2081            .with_organization("Acme Corp");
2082
2083        let report = reporter.generate_report(ReportFormat::Json);
2084
2085        assert!(!report.checks.is_empty());
2086        assert!(report.summary.total_checks > 0);
2087        assert!(report.title.contains("Acme Corp"));
2088    }
2089
2090    #[test]
2091    fn test_report_json_export() {
2092        let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::HIPAA);
2093
2094        let report = reporter.generate_report(ReportFormat::Json);
2095        let json = report.export(ReportFormat::Json);
2096
2097        assert!(json.contains("\"id\""));
2098        assert!(json.contains("\"summary\""));
2099    }
2100
2101    #[test]
2102    fn test_report_markdown_export() {
2103        let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::NIST);
2104
2105        let report = reporter.generate_report(ReportFormat::Markdown);
2106        let md = report.export(ReportFormat::Markdown);
2107
2108        assert!(md.contains("# "));
2109        assert!(md.contains("## Summary"));
2110        assert!(md.contains("| Metric | Value |"));
2111    }
2112
2113    #[test]
2114    fn test_report_html_export() {
2115        let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::PCIDSS);
2116
2117        let report = reporter.generate_report(ReportFormat::Html);
2118        let html = report.export(ReportFormat::Html);
2119
2120        assert!(html.contains("<!DOCTYPE html>"));
2121        assert!(html.contains("<h1>"));
2122    }
2123
2124    #[test]
2125    fn test_report_csv_export() {
2126        let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::ISO27001);
2127
2128        let report = reporter.generate_report(ReportFormat::Csv);
2129        let csv = report.export(ReportFormat::Csv);
2130
2131        assert!(csv.contains("ID,Name,Standard,Status,Description"));
2132    }
2133
2134    #[test]
2135    fn test_compliance_summary_calculation() {
2136        let reporter = ComplianceReporter::new()
2137            .with_standard(ComplianceStandard::SOC2)
2138            .with_standard(ComplianceStandard::GDPR)
2139            .with_standard(ComplianceStandard::HIPAA);
2140
2141        let report = reporter.generate_report(ReportFormat::Json);
2142
2143        let sum = report.summary.compliant
2144            + report.summary.partially_compliant
2145            + report.summary.non_compliant
2146            + report.summary.not_applicable;
2147        assert_eq!(sum, report.summary.total_checks);
2148    }
2149
2150    #[test]
2151    fn test_compliance_status_is_compliant() {
2152        assert!(ComplianceStatus::Compliant.is_compliant());
2153        assert!(ComplianceStatus::NotApplicable.is_compliant());
2154        assert!(!ComplianceStatus::NonCompliant { reasons: vec![] }.is_compliant());
2155        assert!(!ComplianceStatus::PartiallyCompliant { notes: vec![] }.is_compliant());
2156    }
2157
2158    #[test]
2159    fn test_all_standards() {
2160        let reporter = ComplianceReporter::new()
2161            .with_standard(ComplianceStandard::SOC2)
2162            .with_standard(ComplianceStandard::GDPR)
2163            .with_standard(ComplianceStandard::HIPAA)
2164            .with_standard(ComplianceStandard::PCIDSS)
2165            .with_standard(ComplianceStandard::ISO27001)
2166            .with_standard(ComplianceStandard::FedRAMP)
2167            .with_standard(ComplianceStandard::NIST);
2168
2169        let report = reporter.generate_report(ReportFormat::Json);
2170        assert_eq!(report.standards.len(), 7);
2171    }
2172}