forked from mozilla/neqo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/mozilla/neqo into patch-1
- Loading branch information
Showing
25 changed files
with
419 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
[workspace] | ||
members = [ | ||
"fuzz", | ||
"neqo-bin", | ||
"neqo-common", | ||
"neqo-crypto", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
target | ||
corpus | ||
artifacts | ||
coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
[package] | ||
name = "fuzz" | ||
authors.workspace = true | ||
homepage.workspace = true | ||
repository.workspace = true | ||
version.workspace = true | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
license.workspace = true | ||
|
||
[package.metadata] | ||
cargo-fuzz = true | ||
|
||
[dependencies] | ||
neqo-common = { path = "../neqo-common" } | ||
neqo-crypto = { path = "../neqo-crypto" } | ||
neqo-transport = { path = "../neqo-transport" } | ||
test-fixture = { path = "../test-fixture" } | ||
|
||
[target.'cfg(not(windows))'.dependencies] | ||
libfuzzer-sys = { version = "0.4" } | ||
|
||
[lints] | ||
workspace = true | ||
|
||
[[bin]] | ||
name = "packet" | ||
path = "fuzz_targets/packet.rs" | ||
test = false | ||
doc = false | ||
bench = false | ||
|
||
[[bin]] | ||
name = "frame" | ||
path = "fuzz_targets/frame.rs" | ||
test = false | ||
doc = false | ||
bench = false | ||
|
||
[[bin]] | ||
name = "client_initial" | ||
path = "fuzz_targets/client_initial.rs" | ||
test = false | ||
doc = false | ||
bench = false | ||
|
||
[[bin]] | ||
name = "server_initial" | ||
path = "fuzz_targets/server_initial.rs" | ||
test = false | ||
doc = false | ||
bench = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#![cfg_attr(all(fuzzing, not(windows)), no_main)] | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
use libfuzzer_sys::fuzz_target; | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
fuzz_target!(|data: &[u8]| { | ||
use neqo_common::{Datagram, Encoder, Role}; | ||
use neqo_transport::Version; | ||
use test_fixture::{ | ||
default_client, default_server, | ||
header_protection::{ | ||
apply_header_protection, decode_initial_header, initial_aead_and_hp, | ||
remove_header_protection, | ||
}, | ||
now, | ||
}; | ||
|
||
let mut client = default_client(); | ||
let ci = client.process(None, now()).dgram().expect("a datagram"); | ||
let Some((header, d_cid, s_cid, payload)) = decode_initial_header(&ci, Role::Client) else { | ||
return; | ||
}; | ||
let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client); | ||
let (_, pn) = remove_header_protection(&hp, header, payload); | ||
|
||
let mut payload_enc = Encoder::with_capacity(1200); | ||
payload_enc.encode(data); // Add fuzzed data. | ||
|
||
// Make a new header with a 1 byte packet number length. | ||
let mut header_enc = Encoder::new(); | ||
header_enc | ||
.encode_byte(0xc0) // Initial with 1 byte packet number. | ||
.encode_uint(4, Version::default().wire_version()) | ||
.encode_vec(1, d_cid) | ||
.encode_vec(1, s_cid) | ||
.encode_vvec(&[]) | ||
.encode_varint(u64::try_from(payload_enc.len() + aead.expansion() + 1).unwrap()) | ||
.encode_byte(u8::try_from(pn).unwrap()); | ||
|
||
let mut ciphertext = header_enc.as_ref().to_vec(); | ||
ciphertext.resize(header_enc.len() + payload_enc.len() + aead.expansion(), 0); | ||
let v = aead | ||
.encrypt( | ||
pn, | ||
header_enc.as_ref(), | ||
payload_enc.as_ref(), | ||
&mut ciphertext[header_enc.len()..], | ||
) | ||
.unwrap(); | ||
assert_eq!(header_enc.len() + v.len(), ciphertext.len()); | ||
// Pad with zero to get up to 1200. | ||
ciphertext.resize(1200, 0); | ||
|
||
apply_header_protection( | ||
&hp, | ||
&mut ciphertext, | ||
(header_enc.len() - 1)..header_enc.len(), | ||
); | ||
let fuzzed_ci = Datagram::new( | ||
ci.source(), | ||
ci.destination(), | ||
ci.tos(), | ||
ci.ttl(), | ||
ciphertext, | ||
); | ||
|
||
let mut server = default_server(); | ||
let _response = server.process(Some(&fuzzed_ci), now()); | ||
}); | ||
|
||
#[cfg(any(not(fuzzing), windows))] | ||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#![cfg_attr(all(fuzzing, not(windows)), no_main)] | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
use libfuzzer_sys::fuzz_target; | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
fuzz_target!(|data: &[u8]| { | ||
use neqo_common::Decoder; | ||
use neqo_transport::frame::Frame; | ||
|
||
// Run the fuzzer | ||
let mut decoder = Decoder::new(data); | ||
let _ = Frame::decode(&mut decoder); | ||
}); | ||
|
||
#[cfg(any(not(fuzzing), windows))] | ||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#![cfg_attr(all(fuzzing, not(windows)), no_main)] | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
use libfuzzer_sys::fuzz_target; | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
fuzz_target!(|data: &[u8]| { | ||
use std::sync::OnceLock; | ||
|
||
use neqo_transport::{packet::PublicPacket, RandomConnectionIdGenerator}; | ||
|
||
static DECODER: OnceLock<RandomConnectionIdGenerator> = OnceLock::new(); | ||
let decoder = DECODER.get_or_init(|| RandomConnectionIdGenerator::new(20)); | ||
neqo_crypto::init().unwrap(); | ||
|
||
// Run the fuzzer | ||
let _ = PublicPacket::decode(data, decoder); | ||
}); | ||
|
||
#[cfg(any(not(fuzzing), windows))] | ||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#![cfg_attr(all(fuzzing, not(windows)), no_main)] | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
use libfuzzer_sys::fuzz_target; | ||
|
||
#[cfg(all(fuzzing, not(windows)))] | ||
fuzz_target!(|data: &[u8]| { | ||
use neqo_common::{Datagram, Encoder, Role}; | ||
use neqo_transport::Version; | ||
use test_fixture::{ | ||
default_client, default_server, | ||
header_protection::{ | ||
apply_header_protection, decode_initial_header, initial_aead_and_hp, | ||
remove_header_protection, | ||
}, | ||
now, | ||
}; | ||
|
||
let mut client = default_client(); | ||
let ci = client.process(None, now()).dgram().expect("a datagram"); | ||
let mut server = default_server(); | ||
let si = server | ||
.process(Some(&ci), now()) | ||
.dgram() | ||
.expect("a datagram"); | ||
|
||
let Some((header, d_cid, s_cid, payload)) = decode_initial_header(&si, Role::Server) else { | ||
return; | ||
}; | ||
let (aead, hp) = initial_aead_and_hp(d_cid, Role::Server); | ||
let (_, pn) = remove_header_protection(&hp, header, payload); | ||
|
||
let mut payload_enc = Encoder::with_capacity(1200); | ||
payload_enc.encode(data); // Add fuzzed data. | ||
|
||
// Make a new header with a 1 byte packet number length. | ||
let mut header_enc = Encoder::new(); | ||
header_enc | ||
.encode_byte(0xc0) // Initial with 1 byte packet number. | ||
.encode_uint(4, Version::default().wire_version()) | ||
.encode_vec(1, d_cid) | ||
.encode_vec(1, s_cid) | ||
.encode_vvec(&[]) | ||
.encode_varint(u64::try_from(payload_enc.len() + aead.expansion() + 1).unwrap()) | ||
.encode_byte(u8::try_from(pn).unwrap()); | ||
|
||
let mut ciphertext = header_enc.as_ref().to_vec(); | ||
ciphertext.resize(header_enc.len() + payload_enc.len() + aead.expansion(), 0); | ||
let v = aead | ||
.encrypt( | ||
pn, | ||
header_enc.as_ref(), | ||
payload_enc.as_ref(), | ||
&mut ciphertext[header_enc.len()..], | ||
) | ||
.unwrap(); | ||
assert_eq!(header_enc.len() + v.len(), ciphertext.len()); | ||
// Pad with zero to get up to 1200. | ||
ciphertext.resize(1200, 0); | ||
|
||
apply_header_protection( | ||
&hp, | ||
&mut ciphertext, | ||
(header_enc.len() - 1)..header_enc.len(), | ||
); | ||
let fuzzed_si = Datagram::new( | ||
si.source(), | ||
si.destination(), | ||
si.tos(), | ||
si.ttl(), | ||
ciphertext, | ||
); | ||
let _response = client.process(Some(&fuzzed_si), now()); | ||
}); | ||
|
||
#[cfg(any(not(fuzzing), windows))] | ||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use std::{ | ||
collections::hash_map::DefaultHasher, | ||
fs::File, | ||
hash::{Hash, Hasher}, | ||
io::Write, | ||
path::Path, | ||
}; | ||
|
||
/// Write a data item `data` for the fuzzing target `target` to the fuzzing corpus. The caller needs | ||
/// to make sure that `target` is the correct fuzzing target name for the data written. | ||
/// | ||
/// # Panics | ||
/// | ||
/// Panics if the corpus directory does not exist or if the corpus item cannot be written. | ||
pub fn write_item_to_fuzzing_corpus(target: &str, data: &[u8]) { | ||
// This bakes in the assumption that we're executing in the root of the neqo workspace. | ||
// Unfortunately, `cargo fuzz` doesn't provide a way to learn the location of the corpus | ||
// directory. | ||
let corpus = Path::new("../fuzz/corpus").join(target); | ||
if !corpus.exists() { | ||
std::fs::create_dir_all(&corpus).expect("failed to create corpus directory"); | ||
} | ||
|
||
// Hash the data to get a unique name for the corpus item. | ||
let mut hasher = DefaultHasher::new(); | ||
data.hash(&mut hasher); | ||
let item_name = hex::encode(hasher.finish().to_be_bytes()); | ||
let item_path = corpus.join(item_name); | ||
if item_path.exists() { | ||
// Don't overwrite existing corpus items. | ||
return; | ||
} | ||
|
||
// Write the data to the corpus item. | ||
let mut file = File::create(item_path).expect("failed to create corpus item"); | ||
Write::write_all(&mut file, data).expect("failed to write to corpus item"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.