#![no_main] use libfuzzer_sys::fuzz_target; use soliton::storage::{encrypt_blob, decrypt_blob, StorageKey, StorageKeyRing}; const FUZZ_KEY: [u8; 32] = [0x42; 32]; fuzz_target!(|data: &[u8]| { if data.is_empty() { return; } // Cap input size to prevent OOM on CI runners — compress_to_vec allocates // working buffers proportional to input size (~2× for zstd). if data.len() > 1_048_576 { return; } let key = StorageKey::new(1, FUZZ_KEY).unwrap(); let compress = data[0] & 0x01 != 0; let plaintext = &data[1..]; // encrypt_blob must never panic regardless of plaintext size, content, or // compress flag. Exercises: capacity calculation, optional ruzstd compression, // nonce generation, AAD construction, XChaCha20-Poly1305 encryption. let blob = match encrypt_blob(&key, plaintext, "fuzz-channel", "fuzz-segment", compress) { Ok(b) => b, Err(_) => return, }; // Roundtrip verification: decrypt must recover the original plaintext. // Catches malformed blob layout, wrong AAD, header byte errors, and // compression flag mismatches that a crash-only target would miss. let keyring = StorageKeyRing::new(StorageKey::new(1, FUZZ_KEY).unwrap()).unwrap(); let recovered = decrypt_blob(&keyring, &blob, "fuzz-channel", "fuzz-segment") .expect("decrypt_blob failed on freshly encrypted blob"); assert_eq!(&*recovered, plaintext, "roundtrip mismatch"); });