// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // Copyright by contributors to this project. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
//By default, the path field of a Commit MUST be populated. The path field MAY be omitted if //(a) it covers at least one proposal and (b) none of the proposals covered by the Commit are //of "path required" types. A proposal type requires a path if it cannot change the group //membership in a way that requires the forward secrecy and post-compromise security guarantees //that an UpdatePath provides. The only proposal types defined in this document that do not //require a path are:
// add // psk // reinit pub(crate) fn path_update_required(proposals: &ProposalBundle) -> bool { let res = proposals.external_init_proposals().first().is_some();
#[cfg(feature = "by_ref_proposal")] let res = res || !proposals.update_proposals().is_empty();
res || proposals.length() == 0
|| proposals.group_context_extensions_proposal().is_some()
|| !proposals.remove_proposals().is_empty()
}
#[cfg(feature = "state_update")] impl StateUpdate { /// Changes to the roster as a result of proposals. pubfn roster_update(&self) -> &RosterUpdate {
&self.roster_update
}
#[cfg(feature = "psk")] /// Pre-shared keys that have been added to the group. pubfn added_psks(&self) -> &[ExternalPskId] {
&self.added_psks
}
/// Flag to indicate if the group is now pending reinitialization due to /// receiving a [`ReInit`](crate::group::proposal::Proposal::ReInit) /// proposal. pubfn is_pending_reinit(&self) -> bool { self.pending_reinit.is_some()
}
/// Flag to indicate the group is still active. This will be false if the /// member processing the commit has been removed from the group. pubfn is_active(&self) -> bool { self.active
}
/// The new epoch of the group state. pubfn new_epoch(&self) -> u64 { self.epoch
}
/// Custom proposals that were committed to. #[cfg(feature = "custom_proposal")] pubfn custom_proposals(&self) -> &[ProposalInfo<CustomProposal>] {
&self.custom_proposals
}
/// Proposals that were received in the prior epoch but not committed to. #[cfg(feature = "by_ref_proposal")] pubfn unused_proposals(&self) -> &[crate::mls_rules::ProposalInfo<Proposal>] {
&self.unused_proposals
}
// #[cfg_attr( // all(feature = "ffi", not(test)), // safer_ffi_gen::ffi_type(clone, opaque) // )] #[derive(Debug, Clone)] #[allow(clippy::large_enum_variant)] /// An event generated as a result of processing a message for a group with /// [`Group::process_incoming_message`](crate::group::Group::process_incoming_message). pubenum ReceivedMessage { /// An application message was decrypted.
ApplicationMessage(ApplicationMessageDescription), /// A new commit was processed creating a new group state.
Commit(CommitMessageDescription), /// A proposal was received.
Proposal(ProposalMessageDescription), /// Validated GroupInfo object
GroupInfo(GroupInfo), /// Validated welcome message
Welcome, /// Validated key package
KeyPackage(KeyPackage),
}
impl TryFrom<ApplicationMessageDescription> for ReceivedMessage { type Error = MlsError;
// #[cfg_attr( // all(feature = "ffi", not(test)), // safer_ffi_gen::ffi_type(clone, opaque) // )] #[derive(Clone, PartialEq, Eq)] /// Description of a MLS application message. pubstruct ApplicationMessageDescription { /// Index of this user in the group state. pub sender_index: u32, /// Received application data.
data: ApplicationData, /// Plaintext authenticated data in the received MLS packet. pub authenticated_data: Vec<u8>,
}
// #[cfg_attr( // all(feature = "ffi", not(test)), // safer_ffi_gen::ffi_type(clone, opaque) // )] #[derive(Clone, PartialEq)] #[non_exhaustive] /// Description of a processed MLS commit message. pubstruct CommitMessageDescription { /// True if this is the result of an external commit. pub is_external: bool, /// The index in the group state of the member who performed this commit. pub committer: u32, /// A full description of group state changes as a result of this commit. pub state_update: StateUpdate, /// Plaintext authenticated data in the received MLS packet. pub authenticated_data: Vec<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)] /// Proposal sender type. pubenum ProposalSender { /// A current member of the group by index in the group state.
Member(u32), /// An external entity by index within an /// [`ExternalSendersExt`](crate::extension::built_in::ExternalSendersExt).
External(u32), /// A new member proposing their addition to the group.
NewMember,
}
impl TryFrom<Sender> for ProposalSender { type Error = MlsError;
type MlsRules: MlsRules; type IdentityProvider: IdentityProvider; type CipherSuiteProvider: CipherSuiteProvider; type PreSharedKeyStorage: PreSharedKeyStorage;
// Update the new GroupContext's confirmed and interim transcript hashes using the new Commit. let (interim_transcript_hash, confirmed_transcript_hash) = transcript_hashes( self.cipher_suite_provider(),
&self.group_state().interim_transcript_hash,
&auth_content,
)
.await?;
#[cfg(any(feature = "private_message", feature = "by_ref_proposal"))] let commit = match auth_content.content.content {
Content::Commit(commit) => Ok(commit),
_ => Err(MlsError::UnexpectedMessageType),
}?;
#[cfg(not(any(feature = "private_message", feature = "by_ref_proposal")))] let Content::Commit(commit) = auth_content.content.content;
let group_state = self.group_state(); let id_provider = self.identity_provider();
#[cfg(feature = "by_ref_proposal")] let proposals = group_state
.proposals
.resolve_for_commit(auth_content.content.sender, commit.proposals)?;
#[cfg(not(feature = "by_ref_proposal"))] let proposals = resolve_for_commit(auth_content.content.sender, commit.proposals)?;
#[cfg(not(feature = "state_update"))] let state_update = StateUpdate {};
//Verify that the path value is populated if the proposals vector contains any Update // or Remove proposals, or if it's empty. Otherwise, the path value MAY be omitted. if path_update_required(&provisional_state.applied_proposals) && commit.path.is_none() { return Err(MlsError::CommitMissingPath);
}
let new_secrets = match update_path {
Some(update_path) => { self.apply_update_path(sender, &update_path, &mut provisional_state)
.await
}
None => Ok(None),
}?;
// Update the transcript hash to get the new context.
provisional_state.group_context.confirmed_transcript_hash = confirmed_transcript_hash;
// Update the parent hashes in the new context
provisional_state
.public_tree
.update_hashes(&[sender], self.cipher_suite_provider())
.await?;
// Update the tree hash in the new context
provisional_state.group_context.tree_hash = provisional_state
.public_tree
.tree_hash(self.cipher_suite_provider())
.await?;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.