#![no_main] use libfuzzer_sys::fuzz_target; use soliton::streaming::stream_decrypt_init; const FUZZ_KEY: [u8; 32] = [0x42; 32]; fuzz_target!(|data: &[u8]| { // Fuzz the streaming decryptor with adversarial header + chunk data. // Exercises header parsing (version, flags, reserved-bit rejection), // AEAD authentication, decompression bounds, and tag-byte validation. if data.len() < 26 + 2 { return; } let header: [u8; 26] = data[..26].try_into().unwrap(); let rest = &data[26..]; let mut dec = match stream_decrypt_init(&FUZZ_KEY, &header, b"fuzz-aad") { Ok(d) => d, Err(_) => return, }; // Variable-length chunk splitting: each iteration consumes a 2-byte BE // length prefix followed by that many bytes as a chunk. This allows the // fuzzer to discover valid chunk sizes (including STREAM_CHUNK_SIZE + 17 // for non-final chunks) through mutation, unlike fixed-size splitting. let mut cursor = 0; while cursor + 2 <= rest.len() { let chunk_len = u16::from_be_bytes([rest[cursor], rest[cursor + 1]]) as usize; cursor += 2; if cursor + chunk_len > rest.len() { break; } let chunk_data = &rest[cursor..cursor + chunk_len]; cursor += chunk_len; match dec.decrypt_chunk(chunk_data) { Ok((_, true)) => return, // finalized Ok((_, false)) => {} Err(_) => return, } } });