diff --git a/fuzz/README.md b/fuzz/README.md index 92b029b..03b8112 100644 --- a/fuzz/README.md +++ b/fuzz/README.md @@ -23,7 +23,7 @@ of the root workspace, requires nightly Rust, and is not built by | `decode_echo_reply` | `decode_echo_reply` against a deterministic, bounded `Params` matrix, unauthenticated and HMAC-authenticated | | `decode_params` | `Params::decode` and `Params::decode_with_presence`, plus an encode/decode round trip | | `decode_varint` | `varint::decode_uvarint`/`decode_varint` and their round trip through `encode_uvarint`/`encode_varint` | -| `server_core_datagrams` | A bounded mix of raw datagrams and production-encoded Open/Echo/Close requests against one `ServerCore`; it varies IPv4/IPv6 peers and session/HMAC configuration, authenticates keyed requests, reuses issued tokens, and asserts the session cap | +| `server_core_datagrams` | A bounded mix of raw datagrams and production-encoded Open/Echo/Close requests against one `ServerCore`; it varies IPv4/IPv6 peers, session configuration, and bounded (up to 128-byte) HMAC keys, authenticates keyed requests, reuses issued tokens, and asserts the session cap | The invariant every target asserts is: **arbitrary bytes must never panic**. Returning `Err` is normal and expected; a successful decode is also normal. diff --git a/fuzz/fuzz_targets/server_core_datagrams.rs b/fuzz/fuzz_targets/server_core_datagrams.rs index a746bc7..abd8ff7 100644 --- a/fuzz/fuzz_targets/server_core_datagrams.rs +++ b/fuzz/fuzz_targets/server_core_datagrams.rs @@ -17,7 +17,7 @@ const MAX_INPUT_LEN: usize = 32 * 1024; const MAX_DATAGRAMS: usize = 16; const MAX_DATAGRAM_LEN: usize = 2 * 1024; const MAX_SESSIONS: u8 = 8; -const FUZZ_HMAC_KEY: &[u8] = b"fuzz-server-core-key"; +const MAX_HMAC_KEY_LEN: usize = 128; #[derive(Clone)] struct FuzzSession { @@ -35,11 +35,16 @@ fuzz_target!(|data: &[u8]| { let Ok(mut config) = config(&mut input) else { return; }; - let hmac_key = input - .arbitrary::() - .ok() - .filter(|enabled| *enabled) - .map(|_| FUZZ_HMAC_KEY); + let hmac_key = match input.arbitrary::() { + Ok(true) => { + let Ok(length) = input.int_in_range(1..=MAX_HMAC_KEY_LEN) else { + return; + }; + input.bytes(length).ok() + } + Ok(false) => None, + Err(_) => return, + }; if let Some(key) = hmac_key { config = config.with_hmac_key(key); }