-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gosling: added fuzz test for gosling identity server
- Loading branch information
Richard Pospesel
committed
Oct 15, 2023
1 parent
0e17ffd
commit 4d5dce4
Showing
6 changed files
with
1,187 additions
and
1 deletion.
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 |
---|---|---|
@@ -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,31 @@ | ||
[package] | ||
name = "gosling-fuzz" | ||
version = "0.0.0" | ||
publish = false | ||
edition = "2021" | ||
|
||
[package.metadata] | ||
cargo-fuzz = true | ||
|
||
[dependencies] | ||
bson = "2.2.0" | ||
data-encoding = "2.3.2" | ||
libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] } | ||
tor-interface = { path = "../../tor-interface" } | ||
honk-rpc = { path = "../../honk-rpc" } | ||
|
||
[dependencies.gosling] | ||
path = ".." | ||
|
||
# Prevent this from interfering with workspaces | ||
[workspace] | ||
members = ["."] | ||
|
||
[profile.release] | ||
debug = 1 | ||
|
||
[[bin]] | ||
name = "fuzz_identity_server" | ||
path = "fuzz_targets/fuzz_identity_server.rs" | ||
test = false | ||
doc = false |
191 changes: 191 additions & 0 deletions
191
source/gosling/crates/gosling/fuzz/fuzz_targets/arbitrary_types.rs
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,191 @@ | ||
// extern | ||
use bson::Document; | ||
use bson::spec::BinarySubtype::Generic; | ||
use tor_interface::tor_crypto::*; | ||
|
||
// fuzzing | ||
use libfuzzer_sys::arbitrary; | ||
use libfuzzer_sys::arbitrary::{Arbitrary, Error, Unstructured}; | ||
|
||
// Generate Arbitray Types | ||
|
||
// Ed25519 Private Key | ||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryEd25519PrivateKey { | ||
pub value: Ed25519PrivateKey, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryEd25519PrivateKey { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let mut raw: [u8; 64] = [0u8; 64]; | ||
u.fill_buffer(&mut raw)?; | ||
|
||
raw[0] &= 248; | ||
raw[31] &= 63; | ||
raw[31] |= 64; | ||
|
||
let value = Ed25519PrivateKey::from_raw(&raw).unwrap(); | ||
|
||
Ok(ArbitraryEd25519PrivateKey{value}) | ||
} | ||
} | ||
|
||
// Ed25519 Public Key | ||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryEd25519PublicKey { | ||
pub value: Ed25519PublicKey, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryEd25519PublicKey { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let private = ArbitraryEd25519PrivateKey::arbitrary(u)?; | ||
let value = Ed25519PublicKey::from_private_key(&private.value); | ||
|
||
Ok(ArbitraryEd25519PublicKey{value}) | ||
} | ||
} | ||
|
||
// Ed25519 Signature | ||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryEd25519Signature { | ||
pub value: Ed25519Signature, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryEd25519Signature { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let mut message: [u8; 32] = [0u8; 32]; | ||
u.fill_buffer(&mut message)?; | ||
|
||
let private = ArbitraryEd25519PrivateKey::arbitrary(u)?; | ||
let value = private.value.sign_message(&message); | ||
|
||
Ok(ArbitraryEd25519Signature{value}) | ||
} | ||
} | ||
|
||
// V3OnionServicId | ||
// x25519 Private Key | ||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryV3OnionServiceId { | ||
pub value: V3OnionServiceId, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryV3OnionServiceId { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let private = ArbitraryEd25519PrivateKey::arbitrary(u)?; | ||
let value = V3OnionServiceId::from_private_key(&private.value); | ||
|
||
Ok(ArbitraryV3OnionServiceId{value}) | ||
} | ||
} | ||
|
||
// x25519 Private Key | ||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryX25519PrivateKey { | ||
pub value: X25519PrivateKey, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryX25519PrivateKey { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let mut raw: [u8; 32] = [0u8; 32]; | ||
u.fill_buffer(&mut raw)?; | ||
|
||
raw[0] &= 240; | ||
raw[31] &= 127; | ||
raw[31] |= 64; | ||
|
||
let value = X25519PrivateKey::from_raw(&raw).unwrap(); | ||
|
||
Ok(ArbitraryX25519PrivateKey{value}) | ||
} | ||
} | ||
|
||
// x25519 Public Key | ||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryX25519PublicKey { | ||
pub value: X25519PublicKey, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryX25519PublicKey { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let mut raw: [u8; 32] = [0u8; 32]; | ||
u.fill_buffer(&mut raw)?; | ||
|
||
let value = X25519PublicKey::from_raw(&raw); | ||
|
||
Ok(ArbitraryX25519PublicKey{value}) | ||
} | ||
} | ||
|
||
// Bson | ||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryBSON { | ||
pub value: bson::Bson, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryBSON { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
#[derive(Arbitrary)] | ||
enum BSONType { | ||
Null, // 0 | ||
Boolean, // 1 | ||
Int32, // 2 | ||
Int64, // 3 | ||
Double, // 4 | ||
String, // 5 | ||
Binary, // 6 | ||
Array, // 7 | ||
Document, // 8 | ||
} | ||
|
||
let value = match BSONType::arbitrary(u)? { | ||
BSONType::Null => bson::Bson::Null, | ||
BSONType::Boolean => bson::Bson::Boolean(bool::arbitrary(u)?), | ||
BSONType::Int32 => bson::Bson::Int32(i32::arbitrary(u)?), | ||
BSONType::Int64 => bson::Bson::Int64(i64::arbitrary(u)?), | ||
BSONType::Double => bson::Bson::Double(f64::arbitrary(u)?), | ||
BSONType::String => { | ||
match std::ffi::CString::arbitrary(u)?.into_string() { | ||
Ok(value) => bson::Bson::String(value), | ||
Err(_) => bson::Bson::Null, | ||
} | ||
}, | ||
BSONType::Binary => bson::Bson::Binary(bson::Binary {subtype: Generic, bytes: Vec::<u8>::arbitrary(u)?}), | ||
BSONType::Array => bson::Bson::Array(Vec::<ArbitraryBSON>::arbitrary(u)?.drain(..).map(|val| val.value).collect()), | ||
BSONType::Document => bson::Bson::Document(ArbitraryBSONDocument::arbitrary(u)?.value), | ||
}; | ||
|
||
Ok(ArbitraryBSON{value}) | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub(crate) struct ArbitraryBSONDocument { | ||
pub value: Document, | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for ArbitraryBSONDocument { | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let mut value = Document::new(); | ||
for key in Vec::<std::ffi::CString>::arbitrary(u)?.drain(..) { | ||
match key.into_string() { | ||
Ok(key) => value.insert(key, ArbitraryBSON::arbitrary(u)?.value), | ||
Err(_) => None, | ||
}; | ||
} | ||
Ok(ArbitraryBSONDocument{value}) | ||
} | ||
} | ||
|
||
// argument for | ||
#[derive(Arbitrary, Debug)] | ||
pub(crate) enum Argument<T> { | ||
// no value | ||
Missing, | ||
// a valid value | ||
Valid, | ||
// an invalid value of the same type | ||
Invalid(T), | ||
// an invalid value of an arbitrary type | ||
Random(ArbitraryBSON), | ||
} |
Oops, something went wrong.