// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // Copyright by contributors to this project. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
#[cfg(feature = "std")] use std::collections::HashSet;
#[cfg(mls_build_async)] use futures::{stream::FuturesUnordered, TryStreamExt};
use alloc::{vec, vec::Vec};
use mls_rs_core::{
crypto::{CipherSuite, SignatureSecretKey},
error::IntoAnyError,
extension::ExtensionList,
identity::{IdentityProvider, SigningIdentity},
protocol_version::ProtocolVersion,
};
/// /// Create a sub-group from a subset of the current group members. /// /// Membership within the resulting sub-group is indicated by providing a /// key package that produces the same /// [identity](crate::IdentityProvider::identity) value /// as an existing group member. The identity value of each key package /// is determined using the /// [`IdentityProvider`](crate::IdentityProvider) /// that is currently in use by this group instance. #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pubasyncfn branch(
&self,
sub_group_id: Vec<u8>,
new_key_packages: Vec<MlsMessage>,
timestamp: Option<MlsTime>,
) -> Result<(Group<C>, Vec<MlsMessage>), MlsError> { self.branch_group_creator(timestamp, sub_group_id)?
.create(
new_key_packages, // TODO investigate if it's worth updating your own signing identity here self.current_member_signing_identity()?.clone(), self.current_user_leaf_node()?.ungreased_extensions(), self.roster(),
)
.await
}
/// Join a subgroup that was created by [`Group::branch`]. #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pubasyncfn join_subgroup(
&self,
welcome: &MlsMessage,
tree_data: Option<ExportedTree<'_>>,
timestamp: Option<MlsTime>,
) -> Result<(Group<C>, NewMemberInfo), MlsError> { self.branch_group_creator(timestamp, vec![])?
.join(welcome, tree_data, false, self.roster())
.await
}
/// Generate a [`ReinitClient`] that can be used to create or join a new group /// that is based on properties defined by a [`ReInitProposal`] /// committed in a previously accepted commit. This is the only action available /// after accepting such a commit. The old group can no longer be used according to the RFC. /// /// If the [`ReInitProposal`] changes the ciphersuite, then `new_signer` /// and `new_signer_identity` must be set and match the new ciphersuite, as indicated by /// the [`CommitEffect::ReInit`](crate::group::CommitEffect::ReInit) outputted after processing the /// commit to the reinit proposal. The value of [identity](crate::IdentityProvider::identity) /// must be the same for `new_signing_identity` and the current identity in use by this /// group instance. pubfn get_reinit_client( self,
new_signer: Option<SignatureSecretKey>,
new_signing_identity: Option<SigningIdentity>,
) -> Result<ReinitClient<C>, MlsError> { let psk_input = self.resumption_psk_input(ResumptionPSKUsage::Reinit)?;
let new_signing_identity = new_signing_identity
.map(Ok)
.unwrap_or_else(|| self.current_member_signing_identity().cloned())?;
let reinit = self
.state
.pending_reinit
.ok_or(MlsError::PendingReInitNotFound)?;
let new_signer = match new_signer {
Some(signer) => signer,
None => self.signer,
};
let client = Client::new( self.config,
Some(new_signer),
Some((new_signing_identity, reinit.new_cipher_suite())),
reinit.new_version(),
);
let id = JustPreSharedKeyID::Resumption(ResumptionPsk {
usage,
psk_group_id: PskGroupId(self.group_id().to_vec()),
psk_epoch: self.current_epoch(),
});
let id = PreSharedKeyID::new(id, self.cipher_suite_provider())?;
Ok(PskSecretInput { id, psk })
}
}
/// A [`Client`] that can be used to create or join a new group /// that is based on properties defined by a [`ReInitProposal`] /// committed in a previously accepted commit. impl<C: ClientConfig + Clone> ReinitClient<C> { /// Generate a key package for the new group. The key package can /// be used in [`ReinitClient::commit`]. #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pubasyncfn generate_key_package(
&self,
timestamp: Option<MlsTime>,
) -> Result<MlsMessage, MlsError> { self.client
.generate_key_package_message(Default::default(), Default::default(), timestamp)
.await
}
/// Create the new group using new key packages of all group members, possibly /// generated by [`ReinitClient::generate_key_package`]. /// /// # Warning /// /// This function will fail if the number of members in the reinitialized /// group is not the same as the prior group roster. #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pubasyncfn commit( mutself,
new_key_packages: Vec<MlsMessage>,
new_leaf_node_extensions: ExtensionList,
timestamp: Option<MlsTime>,
) -> Result<(Group<C>, Vec<MlsMessage>), MlsError> { let signing_identity = self.client.signing_identity.take(); let old_public_tree = core::mem::take(&mutself.old_public_tree);
self.group_creator(timestamp)
.create(
new_key_packages, // These private fields are created with `Some(x)` by `get_reinit_client`
signing_identity.unwrap().0,
new_leaf_node_extensions,
old_public_tree.roster(),
)
.await
}
/// Join a reinitialized group that was created by [`ReinitClient::commit`]. #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pubasyncfn join( mutself,
welcome: &MlsMessage,
tree_data: Option<ExportedTree<'_>>,
timestamp: Option<MlsTime>,
) -> Result<(Group<C>, NewMemberInfo), MlsError> { let old_public_tree = core::mem::take(&mutself.old_public_tree);
// The version and cipher_suite values in the Welcome message are the same as those used // by the old group. if group.protocol_version() != self.version {
Err(MlsError::ProtocolVersionMismatch)
} elseif group.cipher_suite() != self.cipher_suite {
Err(MlsError::CipherSuiteMismatch)
} // The epoch in the Welcome message MUST be 1. elseif group.current_epoch() != 1 {
Err(MlsError::InitialEpochNotOne)
} elseif verify_group_id && group.group_id() != self.group_id {
Err(MlsError::GroupIdMismatch)
} elseif group.group_state().context.extensions != self.extensions {
Err(MlsError::ReInitExtensionsMismatch)
} else {
Ok((group, new_member_info))
}
}
}
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.