Skip to main content

b4ae/security/
fuzzing.rs

1//! Comprehensive fuzzing infrastructure for security-hardened B4AE modules
2//!
3//! This module provides fuzzing targets and infrastructure to test the
4//! security-hardened implementations against malformed and adversarial inputs.
5
6use crate::security::{
7    SecurityError, SecurityBuffer, SecurityNetworkParser,
8    SecurityHandshakeStateMachine, SecurityKey, KeyType,
9    SecurityHkdf, SecurityAesGcm, SecurityCompare, MessageType, HandshakeState
10};
11
12/// Fuzzing configuration with comprehensive coverage
13#[derive(Debug, Clone)]
14pub struct FuzzingConfig {
15    /// Ukuran maksimum input fuzzing dalam bytes
16    pub max_input_size: usize,
17    /// Strategi mutasi yang digunakan
18    pub mutation_strategies: Vec<MutationStrategy>,
19    /// Target coverage yang diuji
20    pub coverage_targets: Vec<CoverageTarget>,
21    /// Timeout per test case dalam milidetik
22    pub timeout_ms: u64,
23    /// Jumlah seed input awal
24    pub seed_count: usize,
25}
26
27/// Strategi mutasi input untuk fuzzing
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub enum MutationStrategy {
30    /// Flip bit secara acak
31    BitFlip,
32    /// Flip byte secara acak
33    ByteFlip,
34    /// Operasi aritmetika pada nilai byte
35    Arithmetic,
36    /// Gunakan nilai-nilai menarik (0, 255, INT_MAX, dll)
37    InterestingValues,
38    /// Hapus blok data
39    BlockDeletion,
40    /// Duplikasi blok data
41    BlockDuplication,
42    /// Sisipkan blok data baru
43    BlockInsertion,
44    /// Gunakan kamus kata kunci protokol
45    Dictionary,
46    /// Kombinasi mutasi acak
47    Havoc,
48}
49
50/// Target coverage yang diuji dalam fuzzing
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub enum CoverageTarget {
53    /// Batas-batas operasi buffer
54    BufferBounds,
55    /// Parsing pesan protokol
56    ProtocolParsing,
57    /// Operasi kriptografi
58    CryptographicOperations,
59    /// Transisi state machine handshake
60    StateMachineTransitions,
61    /// Kebersihan memori dan zeroization
62    MemoryHygiene,
63    /// Perlindungan dari resource exhaustion
64    ResourceExhaustion,
65    /// Operasi constant-time untuk mencegah timing attack
66    ConstantTimeOperations,
67}
68
69impl Default for FuzzingConfig {
70    fn default() -> Self {
71        FuzzingConfig {
72            max_input_size: 65536, // 64 KB
73            mutation_strategies: vec![
74                MutationStrategy::BitFlip,
75                MutationStrategy::ByteFlip,
76                MutationStrategy::Arithmetic,
77                MutationStrategy::InterestingValues,
78                MutationStrategy::BlockDeletion,
79                MutationStrategy::BlockDuplication,
80                MutationStrategy::Havoc,
81            ],
82            coverage_targets: vec![
83                CoverageTarget::BufferBounds,
84                CoverageTarget::ProtocolParsing,
85                CoverageTarget::CryptographicOperations,
86                CoverageTarget::StateMachineTransitions,
87                CoverageTarget::MemoryHygiene,
88                CoverageTarget::ResourceExhaustion,
89                CoverageTarget::ConstantTimeOperations,
90            ],
91            timeout_ms: 1000, // 1 second per test case
92            seed_count: 10000,
93        }
94    }
95}
96
97/// Fuzzing harness for SecurityBuffer
98pub struct BufferFuzzingHarness {
99    config: FuzzingConfig,
100    _crash_inputs: Vec<Vec<u8>>,
101    slow_inputs: Vec<Vec<u8>>,
102    coverage_hits: std::collections::HashMap<String, usize>,
103}
104
105impl BufferFuzzingHarness {
106    /// Buat harness fuzzing baru untuk SecurityBuffer
107    pub fn new(config: FuzzingConfig) -> Self {
108        BufferFuzzingHarness {
109            config,
110            _crash_inputs: Vec::new(),
111            slow_inputs: Vec::new(),
112            coverage_hits: std::collections::HashMap::new(),
113        }
114    }
115    
116    /// Fuzz SecurityBuffer creation and operations
117    pub fn fuzz_buffer_operations(&mut self, input: &[u8]) -> FuzzingResult {
118        let start = std::time::Instant::now();
119        
120        // Test buffer creation with various sizes
121        for size in [0, 1, 64, 1024, 65536, 1048576] {
122            match SecurityBuffer::new(size) {
123                Ok(mut buffer) => {
124                    self.record_coverage("buffer_creation_success");
125                    
126                    // Test write operations
127                    if !input.is_empty() && input.len() <= buffer.capacity() {
128                        match buffer.write_slice(input) {
129                            Ok(_) => self.record_coverage("buffer_write_success"),
130                            Err(_) => self.record_coverage("buffer_write_failure"),
131                        }
132                    }
133                    
134                    // Test read operations
135                    if buffer.len() > 0 {
136                        let read_size = (input.len() % buffer.len()).max(1);
137                        match buffer.read_exact(read_size) {
138                            Ok(_) => self.record_coverage("buffer_read_success"),
139                            Err(_) => self.record_coverage("buffer_read_failure"),
140                        }
141                    }
142                    
143                    // Test position operations
144                    let new_pos = input.len() % (buffer.len() + 1);
145                    match buffer.set_position(new_pos) {
146                        Ok(_) => self.record_coverage("buffer_set_position_success"),
147                        Err(_) => self.record_coverage("buffer_set_position_failure"),
148                    }
149                },
150                Err(_) => self.record_coverage("buffer_creation_failure"),
151            }
152        }
153        
154        // Test edge cases
155        self.test_buffer_edge_cases(input);
156        
157        let elapsed = start.elapsed();
158        if elapsed.as_millis() > self.config.timeout_ms as u128 {
159            self.slow_inputs.push(input.to_vec());
160            return FuzzingResult::Slow;
161        }
162        
163        FuzzingResult::Success
164    }
165    
166    fn test_buffer_edge_cases(&mut self, _input: &[u8]) {
167        // Test maximum size buffer
168        match SecurityBuffer::new(1048576) { // 1 MB
169            Ok(mut buffer) => {
170                // Test writing maximum data
171                let large_data = vec![0x42u8; 1048576];
172                match buffer.write_slice(&large_data) {
173                    Ok(_) => self.record_coverage("max_buffer_write"),
174                    Err(_) => self.record_coverage("max_buffer_write_failure"),
175                }
176            },
177            Err(_) => self.record_coverage("max_buffer_creation_failure"),
178        }
179        
180        // Test zero-size buffer
181        match SecurityBuffer::new(0) {
182            Ok(mut buffer) => {
183                match buffer.write_slice(b"test") {
184                    Ok(_) => self.record_coverage("zero_buffer_write_unexpected"),
185                    Err(_) => self.record_coverage("zero_buffer_write_expected"),
186                }
187            },
188            Err(_) => self.record_coverage("zero_buffer_creation_expected"),
189        }
190    }
191    
192    fn record_coverage(&mut self, hit: &str) {
193        *self.coverage_hits.entry(hit.to_string()).or_insert(0) += 1;
194    }
195}
196
197/// Fuzzing harness for network protocol parsing
198pub struct NetworkFuzzingHarness {
199    config: FuzzingConfig,
200    parser: SecurityNetworkParser,
201    protocol_violations: Vec<ProtocolViolation>,
202}
203
204/// Pelanggaran protokol yang terdeteksi saat fuzzing
205#[derive(Debug, Clone)]
206pub struct ProtocolViolation {
207    /// Tipe pelanggaran protokol
208    pub violation_type: String,
209    /// Input yang memicu pelanggaran
210    pub input: Vec<u8>,
211    /// Error keamanan yang dihasilkan
212    pub error: SecurityError,
213}
214
215impl NetworkFuzzingHarness {
216    /// Buat harness fuzzing baru untuk parsing jaringan
217    pub fn new(config: FuzzingConfig) -> Self {
218        NetworkFuzzingHarness {
219            config,
220            parser: SecurityNetworkParser::new(),
221            protocol_violations: Vec::new(),
222        }
223    }
224    
225    /// Fuzz network message parsing
226    pub fn fuzz_network_parsing(&mut self, input: &[u8]) -> FuzzingResult {
227        let start = std::time::Instant::now();
228        
229        // Test various message types
230        self.test_message_parsing(input);
231        self.test_header_parsing(input);
232        self.test_handshake_parsing(input);
233        self.test_data_parsing(input);
234        
235        let elapsed = start.elapsed();
236        if elapsed.as_millis() > self.config.timeout_ms as u128 {
237            return FuzzingResult::Slow;
238        }
239        
240        FuzzingResult::Success
241    }
242    
243    fn test_message_parsing(&mut self, input: &[u8]) {
244        match self.parser.parse_message(input) {
245            Ok(message) => {
246                // Validate message structure
247                if message.header.payload_length as usize != message.payload.len() {
248                    self.record_violation("payload_length_mismatch", input, 
249                        SecurityError::InvalidLength {
250                            expected: message.header.payload_length as usize,
251                            actual: message.payload.len(),
252                        });
253                }
254            },
255            Err(error) => {
256                // Expected errors for malformed input
257                match error {
258                    SecurityError::BufferTooSmall { .. } => {},
259                    SecurityError::InvalidProtocolVersion { .. } => {},
260                    SecurityError::InvalidMessageType(_) => {},
261                    _ => self.record_violation("unexpected_parse_error", input, error),
262                }
263            }
264        }
265    }
266    
267    fn test_header_parsing(&mut self, input: &[u8]) {
268        if input.len() >= 24 { // Minimum header size
269            match self.parser.parse_header(&input[..24]) {
270                Ok(header) => {
271                    // Validate header fields
272                    if header.payload_length > 1048576 { // 1 MB limit
273                        self.record_violation("excessive_payload_length", input,
274                            SecurityError::ResourceExhaustionProtection {
275                                resource: "payload_length".to_string(),
276                                limit: 1048576,
277                                requested: header.payload_length as usize,
278                            });
279                    }
280                },
281                Err(error) => {
282                    // Expected header parsing errors
283                    match error {
284                        SecurityError::InvalidProtocolVersion { .. } => {},
285                        SecurityError::InvalidMessageType(_) => {},
286                        SecurityError::InvalidCipherSuite(_) => {},
287                        _ => self.record_violation("unexpected_header_error", input, error),
288                    }
289                }
290            }
291        }
292    }
293    
294    fn test_handshake_parsing(&mut self, input: &[u8]) {
295        // Test handshake message parsing
296        let handshake_types = [MessageType::HandshakeInit, MessageType::HandshakeResponse, MessageType::HandshakeComplete];
297        
298        for handshake_type in &handshake_types {
299            match self.parser.parse_handshake_message(input, *handshake_type) {
300                Ok(_) => {
301                    // Valid handshake message parsed
302                },
303                Err(error) => {
304                    // Expected handshake errors
305                    match error {
306                        SecurityError::InvalidMessageType(_) => {},
307                        SecurityError::InvalidCipherSuite(_) => {},
308                        _ => self.record_violation("unexpected_handshake_error", input, error),
309                    }
310                }
311            }
312        }
313    }
314    
315    fn test_data_parsing(&mut self, input: &[u8]) {
316        match self.parser.parse_data_message(input) {
317            Ok(_) => {
318                // Valid data message parsed
319            },
320            Err(error) => {
321                // Expected data message errors
322                    match error {
323                        SecurityError::InvalidMessageType(_) => {},
324                        SecurityError::InvalidHkdfInput { .. } => {},
325                        _ => self.record_violation("unexpected_data_error", input, error),
326                    }
327            }
328        }
329    }
330    
331    fn record_violation(&mut self, violation_type: &str, input: &[u8], error: SecurityError) {
332        self.protocol_violations.push(ProtocolViolation {
333            violation_type: violation_type.to_string(),
334            input: input.to_vec(),
335            error,
336        });
337    }
338}
339
340/// Fuzzing harness for cryptographic operations
341pub struct CryptoFuzzingHarness {
342    config: FuzzingConfig,
343    timing_leaks: Vec<TimingLeak>,
344}
345
346/// Indikasi kebocoran timing pada operasi kriptografi
347#[derive(Debug, Clone)]
348pub struct TimingLeak {
349    /// Nama operasi yang menunjukkan kebocoran
350    pub operation: String,
351    /// Ukuran input saat kebocoran terdeteksi
352    pub input_size: usize,
353    /// Varians timing yang terdeteksi (dalam nanodetik)
354    pub timing_variance: f64,
355}
356
357impl CryptoFuzzingHarness {
358    /// Buat harness fuzzing baru untuk operasi kriptografi
359    pub fn new(config: FuzzingConfig) -> Self {
360        CryptoFuzzingHarness {
361            config,
362            timing_leaks: Vec::new(),
363        }
364    }
365    
366    /// Fuzz cryptographic operations
367    pub fn fuzz_crypto_operations(&mut self, input: &[u8]) -> FuzzingResult {
368        let start = std::time::Instant::now();
369        
370        // Test key operations
371        self.test_key_operations(input);
372        
373        // Test HKDF operations
374        self.test_hkdf_operations(input);
375        
376        // Test AES-GCM operations
377        self.test_aes_gcm_operations(input);
378        
379        // Test constant-time operations
380        self.test_constant_time_operations(input);
381        
382        let elapsed = start.elapsed();
383        if elapsed.as_millis() > self.config.timeout_ms as u128 {
384            return FuzzingResult::Slow;
385        }
386        
387        FuzzingResult::Success
388    }
389    
390    fn test_key_operations(&mut self, input: &[u8]) {
391        // Test key creation with various sizes
392        for key_type in [KeyType::Encryption, KeyType::Authentication, KeyType::Metadata] {
393            match SecurityKey::from_slice(input, key_type) {
394                Ok(key) => {
395                    // Test key operations
396                    let _ = key.as_slice();
397                    let _ = key.key_type();
398                    let _ = key.len();
399                },
400                Err(error) => {
401                    // Expected key errors
402                    match error {
403                        SecurityError::InvalidKey { .. } => {},
404                        _ => println!("Unexpected key error: {:?}", error),
405                    }
406                }
407            }
408        }
409    }
410    
411    fn test_hkdf_operations(&mut self, input: &[u8]) {
412        if input.len() >= 32 { // Minimum IKM size
413            let salt = if input.len() > 32 { Some(&input[32..]) } else { None };
414            let info = b"test info";
415            
416            match SecurityHkdf::derive_keys(input, salt, info, 32) {
417                Ok(_) => {
418                    // HKDF succeeded
419                },
420                Err(error) => {
421                    // Expected HKDF errors
422                    match error {
423                    SecurityError::InvalidHkdfInput { .. } => {},
424                    _ => println!("Unexpected HKDF error: {:?}", error),
425                }
426                }
427            }
428        }
429    }
430    
431    fn test_aes_gcm_operations(&mut self, input: &[u8]) {
432        if input.len() >= 44 { // Minimum for key (32) + nonce (12)
433            let key_data = &input[..32];
434            let nonce = &input[32..44];
435            let plaintext = if input.len() > 44 { &input[44..] } else { b"test" };
436            
437            match SecurityKey::from_slice(key_data, KeyType::Encryption) {
438                Ok(key) => {
439                    // Test encryption
440                    match SecurityAesGcm::encrypt(&key, nonce, plaintext, None) {
441                        Ok(ciphertext) => {
442                            // Test decryption
443                            match SecurityAesGcm::decrypt(&key, nonce, &ciphertext, None) {
444                                Ok(decrypted) => {
445                                    // Verify decryption
446                                    if decrypted != plaintext {
447                                        println!("Decryption mismatch detected");
448                                    }
449                                },
450                                Err(error) => {
451                                    match error {
452                            SecurityError::InvalidHkdfInput { .. } => {},
453                            _ => println!("Unexpected decryption error: {:?}", error),
454                        }
455                                }
456                            }
457                        },
458                        Err(error) => {
459                            match error {
460                            SecurityError::InvalidHkdfInput { .. } => {},
461                            SecurityError::InvalidNonce { .. } => {},
462                            _ => println!("Unexpected encryption error: {:?}", error),
463                        }
464                        }
465                    }
466                },
467                Err(error) => {
468                    match error {
469                        SecurityError::InvalidKey { .. } => {},
470                        _ => println!("Unexpected key error: {:?}", error),
471                    }
472                }
473            }
474        }
475    }
476    
477    fn test_constant_time_operations(&mut self, input: &[u8]) {
478        // Test constant-time comparison
479        if input.len() >= 64 {
480            let a = &input[..32];
481            let b = &input[32..64];
482            
483            // Measure timing multiple times
484            let mut timings = Vec::new();
485            for _ in 0..100 {
486                let start = std::time::Instant::now();
487                let _ = SecurityCompare::constant_time_eq(a, b);
488                let elapsed = start.elapsed();
489                timings.push(elapsed.as_nanos() as f64);
490            }
491            
492            // Calculate timing variance
493            let mean = timings.iter().sum::<f64>() / timings.len() as f64;
494            let variance = timings.iter().map(|t| (t - mean).powi(2)).sum::<f64>() / timings.len() as f64;
495            
496            // Check for potential timing leaks (simplified)
497            if variance > mean * 0.1 {
498                self.timing_leaks.push(TimingLeak {
499                    operation: "constant_time_eq".to_string(),
500                    input_size: a.len(),
501                    timing_variance: variance,
502                });
503            }
504        }
505    }
506}
507
508/// Fuzzing harness for state machine operations
509pub struct StateMachineFuzzingHarness {
510    config: FuzzingConfig,
511    invalid_transitions: Vec<InvalidTransition>,
512}
513
514/// Transisi state machine yang tidak valid
515#[derive(Debug, Clone)]
516pub struct InvalidTransition {
517    /// State asal transisi
518    pub from_state: HandshakeState,
519    /// State tujuan yang tidak valid
520    pub to_state: HandshakeState,
521    /// Input yang memicu transisi tidak valid
522    pub input: Vec<u8>,
523}
524
525impl StateMachineFuzzingHarness {
526    /// Buat harness fuzzing baru untuk state machine
527    pub fn new(config: FuzzingConfig) -> Self {
528        StateMachineFuzzingHarness {
529            config,
530            invalid_transitions: Vec::new(),
531        }
532    }
533    
534    /// Fuzz state machine transitions
535    pub fn fuzz_state_machine(&mut self, input: &[u8]) -> FuzzingResult {
536        let start = std::time::Instant::now();
537        
538        // Test all possible state transitions
539        self.test_all_transitions(input);
540        
541        // Test state machine with various inputs
542        self.test_state_machine_inputs(input);
543        
544        let elapsed = start.elapsed();
545        if elapsed.as_millis() > self.config.timeout_ms as u128 {
546            return FuzzingResult::Slow;
547        }
548        
549        FuzzingResult::Success
550    }
551    
552    fn test_all_transitions(&mut self, input: &[u8]) {
553        let all_states = [
554            HandshakeState::Init,
555            HandshakeState::WaitingResponse,
556            HandshakeState::WaitingComplete,
557            HandshakeState::Completed,
558            HandshakeState::Failed,
559        ];
560        
561        for from_state in &all_states {
562            for to_state in &all_states {
563                let mut sm = match SecurityHandshakeStateMachine::new(16384) {
564                    Ok(sm) => sm,
565                    Err(_) => continue,
566                };
567                
568                // Force state to from_state (implementation detail)
569                // In real implementation, this would be done through proper API
570                
571                match sm.transition_state(*to_state) {
572                    Ok(_) => {
573                        // Valid transition
574                    },
575                    Err(_) => {
576                        // Invalid transition - record for analysis
577                        self.invalid_transitions.push(InvalidTransition {
578                            from_state: *from_state,
579                            to_state: *to_state,
580                            input: input.to_vec(),
581                        });
582                    }
583                }
584            }
585        }
586    }
587    
588    fn test_state_machine_inputs(&mut self, input: &[u8]) {
589        let mut sm = match SecurityHandshakeStateMachine::new(16384) {
590            Ok(sm) => sm,
591            Err(_) => return,
592        };
593        
594        // Test with various input sizes
595        for size in [0, 1, 64, 1024, 16384] {
596            if input.len() >= size {
597                let test_input = &input[..size];
598                
599                // Test init processing
600                match sm.process_init(test_input) {
601                    Ok(_) => {
602                        // Valid init processed
603                    },
604                    Err(error) => {
605                        match error {
606                            SecurityError::ResourceExhaustionProtection { .. } => {},
607                            SecurityError::InvalidHkdfInput { .. } => {},
608                            _ => println!("Unexpected init error: {:?}", error),
609                        }
610                    }
611                }
612                
613                // Reset for next test
614                let _ = sm.reset();
615            }
616        }
617    }
618}
619
620/// Fuzzing result types
621#[derive(Debug, Clone, PartialEq, Eq)]
622pub enum FuzzingResult {
623    /// Test case berhasil diproses tanpa masalah
624    Success,
625    /// Test case menyebabkan crash dengan pesan error
626    Crash(String),
627    /// Test case berjalan lebih lambat dari threshold
628    Slow,
629    /// Test case melebihi batas waktu
630    Timeout,
631    /// Test case menyebabkan memory exhaustion
632    MemoryExhaustion,
633}
634
635/// Comprehensive fuzzing orchestrator
636pub struct SecurityFuzzingOrchestrator {
637    config: FuzzingConfig,
638    buffer_harness: BufferFuzzingHarness,
639    network_harness: NetworkFuzzingHarness,
640    crypto_harness: CryptoFuzzingHarness,
641    state_machine_harness: StateMachineFuzzingHarness,
642    results: FuzzingResults,
643}
644
645/// Akumulasi hasil seluruh fuzzing campaign
646#[derive(Debug, Default, Clone)]
647pub struct FuzzingResults {
648    /// Total jumlah test case yang dijalankan
649    pub total_runs: usize,
650    /// Jumlah test case yang berhasil
651    pub successful_runs: usize,
652    /// Daftar crash beserta input penyebabnya
653    pub crashes: Vec<(String, Vec<u8>)>,
654    /// Input yang menyebabkan eksekusi lambat
655    pub slow_inputs: Vec<Vec<u8>>,
656    /// Pelanggaran protokol yang terdeteksi
657    pub protocol_violations: Vec<ProtocolViolation>,
658    /// Kebocoran timing yang terdeteksi
659    pub timing_leaks: Vec<TimingLeak>,
660    /// Transisi state machine yang tidak valid
661    pub invalid_transitions: Vec<InvalidTransition>,
662    /// Statistik coverage per target
663    pub coverage_stats: std::collections::HashMap<String, usize>,
664}
665
666impl SecurityFuzzingOrchestrator {
667    /// Buat orchestrator fuzzing baru dengan konfigurasi yang diberikan
668    pub fn new(config: FuzzingConfig) -> Self {
669        SecurityFuzzingOrchestrator {
670            config: config.clone(),
671            buffer_harness: BufferFuzzingHarness::new(config.clone()),
672            network_harness: NetworkFuzzingHarness::new(config.clone()),
673            crypto_harness: CryptoFuzzingHarness::new(config.clone()),
674            state_machine_harness: StateMachineFuzzingHarness::new(config.clone()),
675            results: FuzzingResults::default(),
676        }
677    }
678    
679    /// Run comprehensive fuzzing campaign
680    pub fn run_fuzzing_campaign(&mut self, duration_seconds: u64) -> FuzzingResults {
681        let start = std::time::Instant::now();
682        let duration = std::time::Duration::from_secs(duration_seconds);
683        
684        while start.elapsed() < duration {
685            // Generate random input
686            let input = self.generate_random_input();
687            
688            // Run all fuzzing harnesses
689            self.run_all_harnesses(&input);
690            
691            self.results.total_runs += 1;
692        }
693        
694        // Collect results
695        self.collect_results();
696        self.results.clone()
697    }
698    
699    fn generate_random_input(&self) -> Vec<u8> {
700        use rand::Rng;
701        let mut rng = rand::thread_rng();
702        let size = rng.gen_range(0..self.config.max_input_size);
703        (0..size).map(|_| rng.gen()).collect()
704    }
705    
706    fn run_all_harnesses(&mut self, input: &[u8]) {
707        // Run buffer fuzzing
708        match self.buffer_harness.fuzz_buffer_operations(input) {
709            FuzzingResult::Success => self.results.successful_runs += 1,
710            FuzzingResult::Crash(msg) => self.results.crashes.push((msg, input.to_vec())),
711            FuzzingResult::Slow => self.results.slow_inputs.push(input.to_vec()),
712            _ => {},
713        }
714        
715        // Run network fuzzing
716        match self.network_harness.fuzz_network_parsing(input) {
717            FuzzingResult::Success => {},
718            FuzzingResult::Crash(msg) => self.results.crashes.push((msg, input.to_vec())),
719            _ => {},
720        }
721        
722        // Run crypto fuzzing
723        match self.crypto_harness.fuzz_crypto_operations(input) {
724            FuzzingResult::Success => {},
725            FuzzingResult::Crash(msg) => self.results.crashes.push((msg, input.to_vec())),
726            _ => {},
727        }
728        
729        // Run state machine fuzzing
730        match self.state_machine_harness.fuzz_state_machine(input) {
731            FuzzingResult::Success => {},
732            FuzzingResult::Crash(msg) => self.results.crashes.push((msg, input.to_vec())),
733            _ => {},
734        }
735    }
736    
737    fn collect_results(&mut self) {
738        // Collect protocol violations
739        self.results.protocol_violations.extend(
740            self.network_harness.protocol_violations.clone()
741        );
742        
743        // Collect timing leaks
744        self.results.timing_leaks.extend(
745            self.crypto_harness.timing_leaks.clone()
746        );
747        
748        // Collect invalid transitions
749        self.results.invalid_transitions.extend(
750            self.state_machine_harness.invalid_transitions.clone()
751        );
752        
753        // Collect coverage stats
754        self.results.coverage_stats.extend(
755            self.buffer_harness.coverage_hits.clone()
756        );
757    }
758    
759    /// Generate fuzzing report
760    pub fn generate_report(&self) -> String {
761        let mut report = String::new();
762        report.push_str("B4AE Security Fuzzing Report\n");
763        report.push_str("===========================\n\n");
764        
765        report.push_str(&format!("Total runs: {}\n", self.results.total_runs));
766        report.push_str(&format!("Successful runs: {}\n", self.results.successful_runs));
767        report.push_str(&format!("Crashes: {}\n", self.results.crashes.len()));
768        report.push_str(&format!("Slow inputs: {}\n", self.results.slow_inputs.len()));
769        report.push_str(&format!("Protocol violations: {}\n", self.results.protocol_violations.len()));
770        report.push_str(&format!("Timing leaks: {}\n", self.results.timing_leaks.len()));
771        report.push_str(&format!("Invalid transitions: {}\n", self.results.invalid_transitions.len()));
772        
773        if !self.results.crashes.is_empty() {
774            report.push_str("\nCritical Issues Found:\n");
775            for (i, (msg, _)) in self.results.crashes.iter().enumerate() {
776                report.push_str(&format!("  {}. {}\n", i + 1, msg));
777            }
778        }
779        
780        if !self.results.protocol_violations.is_empty() {
781            report.push_str("\nProtocol Violations:\n");
782            for (i, violation) in self.results.protocol_violations.iter().enumerate() {
783                report.push_str(&format!("  {}. {}: {:?}\n", i + 1, violation.violation_type, violation.error));
784            }
785        }
786        
787        report
788    }
789}
790
791#[cfg(test)]
792mod tests {
793    use super::*;
794    
795    #[test]
796    fn test_fuzzing_harness_creation() {
797        let config = FuzzingConfig::default();
798        
799        let _buffer_harness = BufferFuzzingHarness::new(config.clone());
800        let _network_harness = NetworkFuzzingHarness::new(config.clone());
801        let _crypto_harness = CryptoFuzzingHarness::new(config.clone());
802        let _state_machine_harness = StateMachineFuzzingHarness::new(config.clone());
803        
804        let orchestrator = SecurityFuzzingOrchestrator::new(config);
805        
806        // Test basic functionality
807        assert_eq!(orchestrator.results.total_runs, 0);
808        assert_eq!(orchestrator.results.successful_runs, 0);
809    }
810    
811    #[test]
812    fn test_fuzzing_with_sample_inputs() {
813        let config = FuzzingConfig {
814            max_input_size: 1024,
815            seed_count: 100,
816            ..Default::default()
817        };
818        
819        let mut orchestrator = SecurityFuzzingOrchestrator::new(config);
820        
821        // Test with some sample inputs
822        let sample_inputs = vec![
823            vec![], // Empty input
824            vec![0x00], // Single byte
825            vec![0xFF; 100], // All 0xFF
826            vec![0x00, 0x01, 0x02, 0x03], // Sequential
827            b"B4AE_PROTOCOL_HEADER".to_vec(), // Protocol-like
828        ];
829        
830        for input in sample_inputs {
831            orchestrator.run_all_harnesses(&input);
832        }
833        
834        // Should have run without crashes
835        assert!(orchestrator.results.crashes.is_empty());
836        assert!(orchestrator.results.total_runs >= 5);
837    }
838    
839    #[test]
840    fn test_report_generation() {
841        let config = FuzzingConfig::default();
842        let orchestrator = SecurityFuzzingOrchestrator::new(config);
843        
844        let report = orchestrator.generate_report();
845        
846        // Report should contain basic information
847        assert!(report.contains("B4AE Security Fuzzing Report"));
848        assert!(report.contains("Total runs:"));
849        assert!(report.contains("Successful runs:"));
850        assert!(report.contains("Crashes:"));
851    }
852}