-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
216 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
[package] | ||
name = "qos_crypto_fuzz" | ||
version = "0.0.0" | ||
publish = false | ||
edition = "2021" | ||
|
||
[package.metadata] | ||
cargo-fuzz = true | ||
|
||
[dependencies] | ||
libfuzzer-sys = "0.4" | ||
arbitrary = { version = "1", features = ["derive"] } | ||
|
||
[dependencies.qos_crypto] | ||
path = ".." | ||
|
||
# Prevent this from interfering with workspaces | ||
[workspace] | ||
members = ["."] | ||
|
||
[profile.release] | ||
# enable arithmetic checks at runtime | ||
overflow-check = 1 | ||
|
||
[[bin]] | ||
name = "1_shamir_generate_reconstruct" | ||
path = "fuzz_targets/1_shamir_generate_reconstruct.rs" | ||
test = false | ||
doc = false | ||
|
||
|
||
[[bin]] | ||
name = "2_shamir_input_reconstruct_two_shares" | ||
path = "fuzz_targets/2_shamir_input_reconstruct_two_shares.rs" | ||
test = false | ||
doc = false | ||
|
||
[[bin]] | ||
name = "3_shamir_input_reconstruct_three_shares" | ||
path = "fuzz_targets/3_shamir_input_reconstruct_three_shares.rs" | ||
test = false | ||
doc = false |
72 changes: 72 additions & 0 deletions
72
src/qos_crypto/fuzz/fuzz_targets/1_shamir_generate_reconstruct.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,72 @@ | ||
#![no_main] | ||
|
||
use libfuzzer_sys::fuzz_target; | ||
use qos_crypto::shamir::*; | ||
|
||
#[derive(Clone, Debug, arbitrary::Arbitrary)] | ||
pub struct FuzzShamirStruct { | ||
pub n: usize, | ||
pub k: usize, | ||
secret: Box<[u8]>, | ||
} | ||
|
||
use std::{convert::TryFrom, iter}; | ||
|
||
// let the fuzzer control the number of shares, share threshold number, and secret | ||
fuzz_target!(|fuzzerdata: FuzzShamirStruct| { | ||
let n = fuzzerdata.n; | ||
let k = fuzzerdata.k; | ||
let secret = fuzzerdata.secret; | ||
|
||
// FUZZER NOTE the effort to reconstruct shares is O(n²) so inputs with a large n | ||
// are particularly slow | ||
|
||
// FUZZER TODO artificial limit n to avoid slow inputs, reconsider | ||
if n > 64 { | ||
return; | ||
} | ||
|
||
// FUZZER NOTE the shares_generate() function uses RNG internally and is | ||
// therefore non-deterministic, which may limit the reproducibility and effectiveness of this harness | ||
let all_shares_res = shares_generate(&secret, n, k); | ||
|
||
match all_shares_res { | ||
Err(_) => {} | ||
Ok(all_shares) => { | ||
// Reconstruct with all the shares | ||
let shares = all_shares.clone(); | ||
let reconstructed = | ||
shares_reconstruct(&shares).expect("should succeed"); | ||
// expect the reconstruction to work | ||
assert_eq!(secret.to_vec(), reconstructed); | ||
|
||
// Reconstruct with enough shares | ||
let shares = &all_shares[..k]; | ||
let reconstructed = | ||
shares_reconstruct(shares).expect("should succeed"); | ||
|
||
// expect the reconstruction to work | ||
assert_eq!(secret.to_vec(), reconstructed); | ||
|
||
// Reconstruct with not enough shares | ||
let shares = &all_shares[..(k - 1)]; | ||
|
||
// although this function returns a Result<>, it does not automatically detect that is has received | ||
// an insufficent number of shares and Err() out - instead, it returns Ok() with an incorrect result | ||
let reconstructed_res = shares_reconstruct(shares); | ||
|
||
match reconstructed_res { | ||
// error case is not interesting | ||
Err(_) => {} | ||
// OK case is common | ||
Ok(reconstructed) => { | ||
// if we managed to reconstruct the secret with less than the minimum number of shares | ||
// the something is wrong, or we have a random collision | ||
if reconstructed == secret.to_vec() { | ||
panic!("reconstructed the secret with less than k shares, this should not happen") | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}); |
41 changes: 41 additions & 0 deletions
41
src/qos_crypto/fuzz/fuzz_targets/2_shamir_input_reconstruct_two_shares.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,41 @@ | ||
#![no_main] | ||
|
||
use libfuzzer_sys::fuzz_target; | ||
use qos_crypto::shamir::*; | ||
|
||
/// let the fuzzer come up with two different shares of arbitrary length | ||
#[derive(Clone, Debug, arbitrary::Arbitrary)] | ||
pub struct FuzzShareReconstruct { | ||
share_one: Box<[u8]>, | ||
share_two: Box<[u8]>, | ||
} | ||
|
||
// let the fuzzer control the share data in a two share reconstruction scenario | ||
fuzz_target!(|fuzzerdata: FuzzShareReconstruct| { | ||
let mut shares: Vec<Vec<u8>> = Vec::new(); | ||
|
||
// FUZZER NOTE the effort to reconstruct shares is O(n²) so inputs with a large n | ||
// are particularly slow | ||
|
||
// this construction with three shares covers more edge cases than the two share variant | ||
let mut share_one: Vec<u8> = Vec::new(); | ||
let mut share_two: Vec<u8> = Vec::new(); | ||
let mut share_three: Vec<u8> = Vec::new(); | ||
|
||
share_one.extend_from_slice(&fuzzerdata.share_one); | ||
share_two.extend_from_slice(&fuzzerdata.share_two); | ||
|
||
shares.push(share_one); | ||
shares.push(share_two); | ||
|
||
// Reconstruct with the shares, we expect this to error out often | ||
let reconstructed_res = shares_reconstruct(&shares); | ||
if !reconstructed_res.is_err() { | ||
let _reconstructed = reconstructed_res.unwrap(); | ||
|
||
// debug print is useful for manual evaluation | ||
// println!("reconstructed {:?}", _reconstructed); | ||
// println!("from shares: {:?}", shares); | ||
// println!(""); | ||
} | ||
}); |
51 changes: 51 additions & 0 deletions
51
src/qos_crypto/fuzz/fuzz_targets/3_shamir_input_reconstruct_three_shares.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,51 @@ | ||
#![no_main] | ||
|
||
use libfuzzer_sys::fuzz_target; | ||
use qos_crypto::shamir::*; | ||
|
||
/// let the fuzzer come up with three different shares of arbitrary length | ||
#[derive(Clone, Debug, arbitrary::Arbitrary)] | ||
pub struct FuzzShareReconstruct { | ||
share_one: Box<[u8]>, | ||
share_two: Box<[u8]>, | ||
share_three: Box<[u8]>, | ||
} | ||
|
||
// let the fuzzer control the share data in a three share reconstruction scenario | ||
fuzz_target!(|fuzzerdata: FuzzShareReconstruct| { | ||
let mut shares: Vec<Vec<u8>> = Vec::new(); | ||
|
||
// note that the effort to reconstruct shares is O(n²) so inputs with a large n | ||
// are particularly slow | ||
// here we have n == 3, so this is not a problem | ||
|
||
// this construction with three shares covers more edge cases than the two share variant | ||
let mut share_one: Vec<u8> = Vec::new(); | ||
let mut share_two: Vec<u8> = Vec::new(); | ||
let mut share_three: Vec<u8> = Vec::new(); | ||
|
||
share_one.extend_from_slice(&fuzzerdata.share_one); | ||
share_two.extend_from_slice(&fuzzerdata.share_two); | ||
share_three.extend_from_slice(&fuzzerdata.share_three); | ||
|
||
// Fuzz workaround for issue in vsss-rs <= 4.3.5 | ||
// the bug is fixed in vsss-rs 4.3.6 | ||
// if(share_one.len() != share_two.len() ) || (share_one.len() != share_three.len() ) { | ||
// return; | ||
// } | ||
|
||
shares.push(share_one); | ||
shares.push(share_two); | ||
shares.push(share_three); | ||
|
||
// Reconstruct with the shares, we expect this to error out often | ||
let reconstructed_res = shares_reconstruct(&shares); | ||
if !reconstructed_res.is_err() { | ||
// let _reconstructed = reconstructed_res.unwrap(); | ||
|
||
// debug print is useful for manual evaluation | ||
// println!("reconstructed {:?}", _reconstructed); | ||
// println!("from shares: {:?}", shares); | ||
// println!(""); | ||
} | ||
}); |