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

Meadowcap #32

Merged
merged 28 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0de909a
Add meadowcap crate, CommunalCapability.
sgwilym Jul 29, 2024
10adb9b
Update meadowcap/src/lib.rs
sgwilym Jul 30, 2024
e407a57
Update meadowcap/src/lib.rs
sgwilym Jul 30, 2024
e399d8f
fix that
sgwilym Jul 30, 2024
a80678d
Add dedicated Delegation type
sgwilym Jul 30, 2024
8b341e2
Errors with helpful field names
sgwilym Jul 30, 2024
11c97c1
Unwrap consumer results in handover
sgwilym Jul 30, 2024
12ed973
Use signature crate
sgwilym Jul 30, 2024
d62bc06
Box<[u8]> for handover
sgwilym Jul 30, 2024
41f5fba
Add OwnedCapability
sgwilym Jul 30, 2024
0ce9b64
McCapability
sgwilym Jul 30, 2024
5882a35
Merge syncificate into meadowcap
sgwilym Jul 31, 2024
0a4ae60
syncify meadowcap
sgwilym Jul 31, 2024
b4474ae
Add McAuthorisationToken
sgwilym Jul 31, 2024
9f18a6c
Add Silly Signature scheme for fuzzing
sgwilym Aug 1, 2024
727d340
Delegation fuzz tests
sgwilym Aug 1, 2024
a4c6105
Add fuzz test for appending delegations
sgwilym Aug 1, 2024
ea11ea4
Even Sillier Signature Scheme
sgwilym Aug 2, 2024
69773ae
McAuthorisationToken improvements + fuzz tests
sgwilym Aug 2, 2024
a4a4ba1
McCapability encoding
sgwilym Aug 2, 2024
038ef25
Add McSubspaceCapability + fuzz tests
sgwilym Aug 3, 2024
c3814c7
Derive arbitrary for McCapability
sgwilym Aug 5, 2024
9442fae
Add unsafe keyword to McCapability::authorisation_token_unchecked
sgwilym Aug 5, 2024
eac8b60
McSubspaceCabiliity::delegations returns Iterator
sgwilym Aug 5, 2024
1d8c7e3
Strict encoding for McCapability
sgwilym Aug 5, 2024
c976bd4
Make subspace cap encoding strict
sgwilym Aug 5, 2024
538973a
Refactor NotAWriteCapabilityError
sgwilym Aug 5, 2024
393c592
Refactor delegations return type, add delegations_len
sgwilym Aug 5, 2024
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
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[workspace]

members = ["data-model", "earthstar", "fuzz"]
members = ["data-model", "earthstar", "fuzz", "meadowcap"]
resolver = "2"

[workspace.lints.clippy]
type_complexity = "allow"
type_complexity = "allow"
2 changes: 1 addition & 1 deletion data-model/src/encoding/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use syncify::syncify;

#[syncify(encoding_sync)]
pub(super) mod encoding {
pub mod encoding {

use crate::encoding::error::DecodeError;

Expand Down
2 changes: 1 addition & 1 deletion data-model/src/encoding/compact_width.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ use syncify::syncify;
use syncify::syncify_replace;

#[syncify(encoding_sync)]
pub(super) mod encoding {
pub mod encoding {
use super::*;

#[syncify_replace(use ufotofu::sync::{BulkConsumer, BulkProducer};)]
Expand Down
3 changes: 1 addition & 2 deletions data-model/src/encoding/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ pub mod unsigned_int;
pub mod max_power;
pub mod max_power_sync {
use super::max_power;

pub use max_power::encoding_sync::*;
pub use max_power::max_power;
}
}
2 changes: 1 addition & 1 deletion data-model/src/grouping/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ where

/// A grouping of entries.
/// [Definition](https://willowprotocol.org/specs/grouping-entries/index.html#areas).
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Area<const MCL: usize, const MCC: usize, const MPL: usize, S: SubspaceId> {
/// To be included in this [`Area`], an [`Entry`]’s `subspace_id` must be equal to the subspace_id, unless it is any.
subspace: AreaSubspace<S>,
Expand Down
24 changes: 24 additions & 0 deletions data-model/src/grouping/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ impl<const MCL: usize, const MCC: usize, const MPL: usize> PartialOrd<RangeEnd<P
}
}

impl<T> Clone for RangeEnd<T>
sgwilym marked this conversation as resolved.
Show resolved Hide resolved
where
T: Ord + Clone,
{
fn clone(&self) -> Self {
match self {
RangeEnd::Closed(val) => RangeEnd::Closed(val.clone()),
RangeEnd::Open => RangeEnd::Open,
}
}
}

#[cfg(feature = "dev")]
impl<'a, T> Arbitrary<'a> for RangeEnd<T>
where
Expand Down Expand Up @@ -235,6 +247,18 @@ impl<T: Ord> PartialOrd for Range<T> {
}
}

impl<T> Clone for Range<T>
sgwilym marked this conversation as resolved.
Show resolved Hide resolved
where
T: Ord + Clone,
{
fn clone(&self) -> Self {
Self {
start: self.start.clone(),
end: self.end.clone(),
}
}
}

#[cfg(feature = "dev")]
impl<'a, T> Arbitrary<'a> for Range<T>
where
Expand Down
1 change: 1 addition & 0 deletions data-model/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ pub trait IsAuthorisedWrite<
PD: PayloadDigest,
>
{
/// Determine whether this type (nominally a [`AuthorisationToken`](https://willowprotocol.org/specs/data-model/index.html#AuthorisationToken)) is able to prove write permission for a given [`Entry`].
fn is_authorised_write(&self, entry: &Entry<MCL, MCC, MPL, N, S, PD>) -> bool;
}
69 changes: 69 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@ ufotofu = { version = "0.3.0", features=["dev"]}
smol = "2.0.0"
arbitrary = { version = "1.0.2", features = ["derive"] }
libfuzzer-sys = { version = "0.4", features = ["arbitrary-derive"] }
signature = "2.2.0"
syncify = "0.1.0"


[dependencies.willow-data-model]
path = "../data-model"
features = ["dev"]

[dependencies.meadowcap]
path = "../meadowcap"
features = ["dev"]

[dependencies.earthstar]
path = "../earthstar"

Expand Down Expand Up @@ -318,3 +324,66 @@ path = "fuzz_targets/range3d_rel_rang3d_encoding_random.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_capability_delegation"
path = "fuzz_targets/mc_capability_delegation.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_capability_append_delegation"
path = "fuzz_targets/mc_capability_append_delegation.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_is_authorised_write"
path = "fuzz_targets/mc_is_authorised_write.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_capability_rel_area_encoding"
path = "fuzz_targets/mc_capability_rel_area_encoding.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_capability_rel_area_encoding_random"
path = "fuzz_targets/mc_capability_rel_area_encoding_random.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_subspace_capability_delegation"
path = "fuzz_targets/mc_subspace_capability_delegation.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_subspace_capability_append_delegation"
path = "fuzz_targets/mc_subspace_capability_append_delegation.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_subspace_capability_encoding"
path = "fuzz_targets/mc_subspace_capability_encoding.rs"
test = false
doc = false
bench = false

[[bin]]
name = "mc_subspace_capability_encoding_random"
path = "fuzz_targets/mc_subspace_capability_encoding_random.rs"
test = false
doc = false
bench = false
90 changes: 90 additions & 0 deletions fuzz/fuzz_targets/mc_capability_append_delegation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#![no_main]

use libfuzzer_sys::fuzz_target;
use meadowcap::{mc_capability::McCapability, Delegation, InvalidDelegationError};
use willow_data_model_fuzz::silly_sigs::{SillyPublicKey, SillySig};

fuzz_target!(|data: (
Delegation<16, 16, 16, SillyPublicKey, SillySig>,
McCapability<16, 16, 16, SillyPublicKey, SillySig, SillyPublicKey, SillySig>,
Vec<SillyPublicKey>
)| {
let (delegation, mc_cap, delegees) = data;

let mut mut_cap = mc_cap.clone();

let mut last_receiver = mut_cap.receiver().clone();
let granted_area = mut_cap.granted_area();

for delegee in delegees {
mut_cap = mut_cap
.delegate(
&last_receiver.corresponding_secret_key(),
&delegee,
&granted_area,
AljoschaMeyer marked this conversation as resolved.
Show resolved Hide resolved
)
.unwrap();
last_receiver = delegee;
}

let claimed_area = delegation.area().clone();
let delegation_user = delegation.user().clone();
let delegation_sig = delegation.signature().clone();

let granted_area_includes_delegation = mut_cap.granted_area().includes_area(delegation.area());

let actual_receiver_secret = mut_cap.receiver().corresponding_secret_key();

let cap_before_delegation = mut_cap.clone();

match mut_cap.append_existing_delegation(delegation) {
Ok(_) => {
assert!(granted_area_includes_delegation);

// Because there is only one user who can delegate a given capability, we know what it should look like given the same new_area and new_user.
let expected_cap = cap_before_delegation.delegate(
&actual_receiver_secret,
&delegation_user,
&claimed_area,
);

match expected_cap {
Ok(cap) => {
assert_eq!(cap, mut_cap);
}
Err(_) => {
panic!("The delegation should not have been possible")
}
}
}
Err(err) => match err {
InvalidDelegationError::AreaNotIncluded {
excluded_area,
claimed_receiver: _,
} => {
assert!(!granted_area_includes_delegation);
assert_eq!(excluded_area, claimed_area);
}
InvalidDelegationError::InvalidSignature {
expected_signatory,
claimed_receiver,
signature: _,
} => {
assert_eq!(&expected_signatory, mut_cap.receiver());
assert_eq!(delegation_user, claimed_receiver);

// Because there is only one user who can delegate a given capability, we know what it should look like given the same new_area and new_user.
let expected_cap =
mut_cap.delegate(&actual_receiver_secret, &delegation_user, &claimed_area);

match expected_cap {
Ok(cap) => {
let valid_delegation = cap.delegations().last().unwrap();
assert!(valid_delegation.signature() != &delegation_sig);
}
Err(_) => panic!("The expected cap should have been fine..."),
}
}
},
}
});
57 changes: 57 additions & 0 deletions fuzz/fuzz_targets/mc_capability_delegation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#![no_main]

use libfuzzer_sys::fuzz_target;
use meadowcap::{mc_capability::McCapability, FailedDelegationError};
use willow_data_model::grouping::area::Area;
use willow_data_model_fuzz::silly_sigs::{SillyPublicKey, SillySecret, SillySig};

fuzz_target!(|data: (
SillySecret,
SillyPublicKey,
Area<16, 16, 16, SillyPublicKey>,
McCapability<16, 16, 16, SillyPublicKey, SillySig, SillyPublicKey, SillySig>,
Vec<SillyPublicKey>
)| {
let (secret, new_user, area, mc_cap, delegees) = data;

let mut cap_with_delegees = mc_cap.clone();
let mut last_receiver = mc_cap.receiver().clone();
let granted_area = mc_cap.granted_area();

for delegee in delegees {
cap_with_delegees = cap_with_delegees
.delegate(
&last_receiver.corresponding_secret_key(),
&delegee,
&granted_area,
)
.unwrap();
last_receiver = delegee;
}

let area_is_included = cap_with_delegees.granted_area().includes_area(&area);
let is_correct_secret = cap_with_delegees.receiver() == &secret.corresponding_public_key();

match cap_with_delegees.delegate(&secret, &new_user, &area) {
Ok(delegated_cap) => {
assert!(area_is_included);
assert!(is_correct_secret);

assert_eq!(delegated_cap.granted_area(), area);
assert_eq!(delegated_cap.receiver(), &new_user);
}
Err(err) => match err {
FailedDelegationError::AreaNotIncluded {
excluded_area,
claimed_receiver: _,
} => {
assert!(!area_is_included);
assert_eq!(excluded_area, area);
}
FailedDelegationError::WrongSecretForUser(pub_key) => {
assert_eq!(&pub_key, cap_with_delegees.receiver());
assert!(secret.corresponding_public_key() != pub_key)
}
},
}
});
Loading