Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SHAKE128 and SHAKE256 #21

Merged
merged 6 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ authors = ["brycx <[email protected]>"]
edition = "2018"

[dependencies]
honggfuzz = "0.5.55"
honggfuzz = "0.5.56"
rand = "0.8.3"
rand_chacha = "0.3.0"
sodiumoxide = "0.2.6"
ring = "0.16.20"
ring = "0.17.8"
blake2-rfc = "0.2.18"
chacha = "0.3.0"
rust-argon2 = "0.8.3"
x25519-dalek = "1.2.0"
rust-argon2 = "2.1.0"
x25519-dalek = "2.0.1"
bincode = "1.3.3"
serde = "1.0.124"
sha3 = "0.10.6"
Expand Down Expand Up @@ -63,5 +63,9 @@ path = "src/ecc.rs"
name = "serde"
path = "src/serde.rs"

[[bin]]
name = "xof"
path = "src/xof.rs"

[profile.release]
opt-level = 3
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018-2023 brycx
Copyright (c) 2018-2024 brycx

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ Fuzzing is done using [honggfuzz-rs](https://github.com/rust-fuzz/honggfuzz-rs).
To start fuzzing, you must install the same version of honggfuzz as the one specified in the `Cargo.toml`:

```
cargo install --force honggfuzz --vers 0.5.51
cargo install --force honggfuzz --vers 0.5.56
```

By default, the master branch of orion is used for fuzzing. If another version needs to be fuzzed, specify the version
in the `Cargo.toml` accordingly.

Some fuzzing targets use [sodiumoxide](https://github.com/sodiumoxide/sodiumoxide) to cross-verify results. Any target
Some fuzzing targets use [sodiumoxide](https://github.com/sodiumoxide/sodiumoxide) to cross-verify results. Any target
that uses sodiumoxide requires libsodium to be installed on the system as well.


Expand Down Expand Up @@ -44,4 +44,4 @@ All the above examples run the `aead` target. This can be any fuzzing target in

```
HFUZZ_RUN_ARGS="--minimize" cargo hfuzz run aead
```
```
22 changes: 7 additions & 15 deletions src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,10 @@ use orion::hazardous::hash::sha2::sha256::{Digest as Sha256Digest, Sha256, SHA25
use orion::hazardous::hash::sha2::sha384::{Digest as Sha384Digest, Sha384, SHA384_BLOCKSIZE};
use orion::hazardous::hash::sha2::sha512::{Digest as Sha512Digest, Sha512, SHA512_BLOCKSIZE};

use orion::hazardous::hash::sha3::sha3_224::{
Digest as Sha3_224Digest, Sha3_224, SHA3_224_RATE,
};
use orion::hazardous::hash::sha3::sha3_256::{
Digest as Sha3_256Digest, Sha3_256, SHA3_256_RATE,
};
use orion::hazardous::hash::sha3::sha3_384::{
Digest as Sha3_384Digest, Sha3_384, SHA3_384_RATE,
};
use orion::hazardous::hash::sha3::sha3_512::{
Digest as Sha3_512Digest, Sha3_512, SHA3_512_RATE,
};
use orion::hazardous::hash::sha3::sha3_224::{Digest as Sha3_224Digest, Sha3_224, SHA3_224_RATE};
use orion::hazardous::hash::sha3::sha3_256::{Digest as Sha3_256Digest, Sha3_256, SHA3_256_RATE};
use orion::hazardous::hash::sha3::sha3_384::{Digest as Sha3_384Digest, Sha3_384, SHA3_384_RATE};
use orion::hazardous::hash::sha3::sha3_512::{Digest as Sha3_512Digest, Sha3_512, SHA3_512_RATE};

use orion::{errors::UnknownCryptoError, hazardous::hash::blake2::blake2b};
use std::marker::PhantomData;
Expand Down Expand Up @@ -93,7 +85,7 @@ trait ShaFuzzType<T: PartialEq> {
}

/// A trait for the other implementation that Orion should be fuzzed against.
/// This is used for SHA3 as it's not compatible with the apporahc used for SHA2.
/// This is used for SHA3 as it's not compatible with the approach used for SHA2.
trait ShaComparableType<T>
where
T: AsRef<[u8]>,
Expand Down Expand Up @@ -257,10 +249,10 @@ where
T: ShaFuzzType<R>,
O: ShaComparableType<R>,
{
pub fn new(sha2_initial_state: T) -> Self {
pub fn new(sha3_initial_state: T) -> Self {
Self {
_return_type: PhantomData,
own_context: sha2_initial_state,
own_context: sha3_initial_state,
_other_impl: PhantomData,
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ extern crate orion;
extern crate ring;
pub mod utils;

use argon2::{Config, ThreadMode, Variant, Version};
use argon2::{Config, Variant, Version};
use orion::hazardous::{
hash::sha2::{sha256::SHA256_OUTSIZE, sha384::SHA384_OUTSIZE, sha512::SHA512_OUTSIZE},
kdf::{argon2i as orion_argon2i, hkdf, pbkdf2},
Expand Down Expand Up @@ -176,7 +176,6 @@ fn fuzz_argon2(fuzzer_input: &[u8], seeded_rng: &mut ChaChaRng) {
mem_cost: memory,
time_cost: passes,
lanes,
thread_mode: ThreadMode::Sequential,
secret: &secret,
ad: &ad,
hash_length: outsize,
Expand Down
156 changes: 156 additions & 0 deletions src/xof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#[macro_use]
extern crate honggfuzz;

extern crate orion;
use sha3 as other_sha3;

pub mod utils;
use orion::errors::UnknownCryptoError;
use orion::hazardous::hash::sha3::shake128::{Shake128, SHAKE_128_RATE};
use orion::hazardous::hash::sha3::shake256::{Shake256, SHAKE_256_RATE};
use std::marker::PhantomData;
use utils::{make_seeded_rng, ChaChaRng, Rng};

// A wrapper trait to reduce duplicate functional test-code when fuzzing SHAKE128/SHAK256.
trait XofFuzzType {
fn reset(&mut self);

fn absorb(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError>;

fn squeeze(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError>;

fn get_blocksize() -> usize;
}

/// A trait for the other implementation that Orion should be fuzzed against.
trait XofComparableType {
fn digest(data: &[u8], dest: &mut [u8]);
}

macro_rules! impl_shake_fuzztype_trait (($shake_variant:ident, $shake_bs:expr) => (
impl XofFuzzType for $shake_variant {
fn reset(&mut self) {
self.reset();
}

fn absorb(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> {
self.absorb(data)
}

fn squeeze(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> {
self.squeeze(dest)
}

fn get_blocksize() -> usize {
$shake_bs
}
}
));

impl_shake_fuzztype_trait!(Shake128, SHAKE_128_RATE);
impl_shake_fuzztype_trait!(Shake256, SHAKE_256_RATE);

impl XofComparableType for other_sha3::Shake128 {
fn digest(data: &[u8], dest: &mut [u8]) {
use other_sha3::digest::{ExtendableOutput, Update, XofReader};

let mut hasher = other_sha3::Shake128::default();
hasher.update(data);
let mut reader = hasher.finalize_xof();
reader.read(dest);
}
}

impl XofComparableType for other_sha3::Shake256 {
fn digest(data: &[u8], dest: &mut [u8]) {
use other_sha3::digest::{ExtendableOutput, Update, XofReader};

let mut hasher = other_sha3::Shake256::default();
hasher.update(data);
let mut reader = hasher.finalize_xof();
reader.read(dest);
}
}

/// A SHAKE fuzzer.
struct ShakeFuzzer<T, O> {
// The initial context to base further calls upon.
own_context: T,
_other_impl: PhantomData<O>,
}

impl<T, O> ShakeFuzzer<T, O>
where
T: XofFuzzType,
O: XofComparableType,
{
pub fn new(shake_initial_state: T) -> Self {
Self {
own_context: shake_initial_state,
_other_impl: PhantomData,
}
}

/// Fuzz the Orion implementation and check results with RustCrypto's `sha3` crate.
pub fn fuzz(&mut self, fuzzer_input: &[u8], seeded_rng: &mut ChaChaRng) {
// Clear the state
self.own_context.reset();
let mut collected_data: Vec<u8> = Vec::new();

// Incremental absorbation:
collected_data.extend_from_slice(fuzzer_input);
self.own_context.absorb(fuzzer_input).unwrap();

if fuzzer_input.len() > T::get_blocksize() {
collected_data.extend_from_slice(b"");
self.own_context.absorb(b"").unwrap();
}
if fuzzer_input.len() > T::get_blocksize() * 2 {
collected_data.extend_from_slice(b"Extra");
self.own_context.absorb(b"Extra").unwrap();
}
if fuzzer_input.len() > T::get_blocksize() * 3 {
collected_data.extend_from_slice(&[0u8; 256]);
self.own_context.absorb(&[0u8; 256]).unwrap();
}
if fuzzer_input.len() > T::get_blocksize() * 4 {
collected_data.extend_from_slice(&vec![0u8; T::get_blocksize() - 1]);
self.own_context
.absorb(&vec![0u8; T::get_blocksize() - 1])
.unwrap();
}

// Incremental squeezing:
let dest_size: usize = seeded_rng.gen_range(1..=16320);
let squeeze_size: usize = seeded_rng.gen_range(1..=dest_size);

let mut squeeze_dest_own = vec![0u8; dest_size];
let mut squeeze_dest_other = vec![0u8; dest_size];

O::digest(&collected_data, &mut squeeze_dest_other);

for out_chunk in squeeze_dest_own.chunks_mut(squeeze_size) {
self.own_context.squeeze(out_chunk).unwrap();
}

assert_eq!(squeeze_dest_own, squeeze_dest_other);
}
}

fn main() {
let mut shake128_fuzzer: ShakeFuzzer<Shake128, other_sha3::Shake128> =
ShakeFuzzer::new(Shake128::new());
let mut shake256_fuzzer: ShakeFuzzer<Shake256, other_sha3::Shake256> =
ShakeFuzzer::new(Shake256::new());

loop {
fuzz!(|data: &[u8]| {
// Seed the RNG
let mut seeded_rng = make_seeded_rng(data);

// Test `orion::hazardous::hash::sha3::shake*`
shake128_fuzzer.fuzz(data, &mut seeded_rng);
shake256_fuzzer.fuzz(data, &mut seeded_rng);
});
}
}