Skip to content
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
29 changes: 29 additions & 0 deletions .changeset/cyan-donkeys-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
"@germ-network/two-mls-pq": patch
---

Bump mls-rs to the `germ-integration` pin, and keep `APP_DATA_UPDATE` pathless

The fork's `main` was resynced with upstream `awslabs/mls-rs`, and the Germ changes were
recomposed on top of it as `germ-integration`. The pin moves from `ec69dc25` to
`c6ede1ce`, picking up the crypto providers, a recovered cryptokit build fix, the Safe
Extensions exporter tree, and attachment CEK derivation.

The resync requires one behavioural fix. Upstream added
`MlsRules::custom_proposal_requires_update_path` with a default of `true`, so
`APP_DATA_UPDATE` — an attestation that changes no group membership — began forcing an
updatePath. On the PQ half that put an ML-KEM updatePath on a commit that must stay
pathless: the bind commit grew past a whole ML-KEM-768 ciphertext. `TwoMlsRules` now
overrides the hook to `false`, restoring the behaviour `apq` was written against. Where a
path _is_ wanted — the FULL commit discharging an owed bind on the classical half —
`commit_options` still pins it explicitly, which is where that decision belongs.

Also drops `serde` — both the `mls-rs` feature and the unused `[workspace.dependencies]`
entry. Nothing in the workspace consumes either: no `.rs` file references serde and no
member crate declares it. mls-rs's serde derives are `cfg_attr`-attached, so they never
participate in `MlsEncode`/`MlsDecode`; removing the feature cannot move a byte of the
stored format. Archiving goes through the crate's own `MlsEncode`/`MlsDecode` wire
structs, which are untouched.

No wire, FFI, or error-variant change. Group state written by the previous pin still
loads.
12 changes: 5 additions & 7 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,20 @@ strip = "symbols"
mls-rs = { version = "0.55", features = [
"psk",
"private_message",
"serde",
"safe_extensions",
] }
mls-rs-core = { version = "0.27", git = "https://github.com/germ-network/mls-rs", rev = "ec69dc251db66ae6eb117079564814998bb55dec" }
mls-rs-crypto-awslc = { version = "0.25", git = "https://github.com/germ-network/mls-rs", rev = "ec69dc251db66ae6eb117079564814998bb55dec", features = [
mls-rs-core = { version = "0.27", git = "https://github.com/germ-network/mls-rs", rev = "b43703fbf1244140fe9e5e43e41c373e34191758" }
mls-rs-crypto-awslc = { version = "0.25", git = "https://github.com/germ-network/mls-rs", rev = "b43703fbf1244140fe9e5e43e41c373e34191758", features = [
"post-quantum",
] }
mls-rs-crypto-cryptokit = { version = "0.11", git = "https://github.com/germ-network/mls-rs", rev = "ec69dc251db66ae6eb117079564814998bb55dec", features = [
mls-rs-crypto-cryptokit = { version = "0.11", git = "https://github.com/germ-network/mls-rs", rev = "b43703fbf1244140fe9e5e43e41c373e34191758", features = [
"post-quantum",
] }
mls-rs-crypto-traits = { version = "0.22", git = "https://github.com/germ-network/mls-rs", rev = "ec69dc251db66ae6eb117079564814998bb55dec" }
serde = { version = "1", features = ["derive"] }
mls-rs-crypto-traits = { version = "0.22", git = "https://github.com/germ-network/mls-rs", rev = "b43703fbf1244140fe9e5e43e41c373e34191758" }
sha2 = "0.10"
thiserror = "1"
uniffi = "0.31"
zeroize = { version = "1", features = ["derive"] }

[patch.crates-io]
mls-rs = { git = "https://github.com/germ-network/mls-rs", rev = "ec69dc251db66ae6eb117079564814998bb55dec" }
mls-rs = { git = "https://github.com/germ-network/mls-rs", rev = "b43703fbf1244140fe9e5e43e41c373e34191758" }
25 changes: 24 additions & 1 deletion rust/apq/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use mls_rs::{
error::IntoAnyError,
group::{GroupContext, Roster, Sender},
group::{proposal::ProposalType, GroupContext, Roster, Sender},
mls_rules::{CommitDirection, CommitOptions, CommitSource, EncryptionOptions, ProposalBundle},
MlsRules,
};
Expand Down Expand Up @@ -74,6 +74,29 @@ pub struct TwoMlsRules;
impl MlsRules for TwoMlsRules {
type Error = RuleError;

/// `APP_DATA_UPDATE` never forces an updatePath.
///
/// It carries an attestation only — it does not change group membership — so RFC 9420
/// §12.4 leaves the path at the committer's discretion. The PQ half depends on that:
/// a bind commit must stay pathless, or it carries an ML-KEM updatePath and grows past
/// a whole ML-KEM-768 ciphertext (`test_bind_pq_commit_is_pathless`).
///
/// Where a path IS wanted on the classical half — the FULL commit discharging an owed
/// bind — [`Self::commit_options`] pins it explicitly. That is the one place this
/// decision belongs.
///
/// mls-rs added this hook in awslabs/mls-rs#364 with a default of `true`, which would
/// silently put a path on every custom proposal. Overriding it restores the behaviour
/// this crate was written against; it is not a new policy.
fn custom_proposal_requires_update_path(&self, custom_proposal_type: ProposalType) -> bool {
debug_assert_eq!(
custom_proposal_type, APP_DATA_UPDATE,
"filter_proposals rejects every other custom proposal type"
);
let _ = custom_proposal_type;
false
}

fn filter_proposals(
&self,
_direction: CommitDirection,
Expand Down
Loading