Skip to main content

openmls/group/mls_group/
branch.rs

1//! Sub-group branching (RFC 9420 ยง11.3).
2//!
3//! Branching a sub-group off a parent group needs a small, fixed set of values
4//! from the parent's current epoch. Rather than threading the live parent
5//! [`MlsGroup`](crate::group::MlsGroup) through the branch APIs, the parent
6//! exports these values once into a [`BranchInfo`] via
7//! [`MlsGroup::branch_info`](crate::group::MlsGroup::branch_info), and hands the
8//! owned struct to the sender ([`MlsGroupBuilder::branch`](crate::group::MlsGroupBuilder::branch))
9//! and receiver ([`StagedWelcome::build_from_branch`](crate::group::StagedWelcome::build_from_branch)).
10
11use crate::{
12    credentials::Credential,
13    group::{GroupEpoch, GroupId},
14    schedule::ResumptionPskSecret,
15    versions::ProtocolVersion,
16};
17use openmls_traits::types::Ciphersuite;
18
19/// The information a sub-group branch needs from its parent group.
20///
21/// Export this from the parent group with
22/// [`MlsGroup::branch_info`](crate::group::MlsGroup::branch_info) and pass it to
23/// the branch APIs: the sender uses
24/// [`MlsGroupBuilder::branch`](crate::group::MlsGroupBuilder::branch) and the
25/// receiver uses
26/// [`StagedWelcome::build_from_branch`](crate::group::StagedWelcome::build_from_branch).
27///
28/// This is an owned snapshot, so it does not borrow the parent group and can
29/// outlive it.
30///
31/// This carries the parent's resumption PSK secret, which is sensitive key
32/// material and must be handled accordingly.
33#[derive(Debug, Clone)]
34pub struct BranchInfo {
35    pub(crate) version: ProtocolVersion,
36    pub(crate) ciphersuite: Ciphersuite,
37    pub(crate) group_id: GroupId,
38    pub(crate) epoch: GroupEpoch,
39    pub(crate) resumption_psk_secret: ResumptionPskSecret,
40    pub(crate) member_credentials: Vec<Credential>,
41}
42
43impl BranchInfo {
44    /// The protocol version of the parent group.
45    pub fn version(&self) -> ProtocolVersion {
46        self.version
47    }
48
49    /// The ciphersuite of the parent group.
50    pub fn ciphersuite(&self) -> Ciphersuite {
51        self.ciphersuite
52    }
53
54    /// The group ID of the parent group.
55    pub fn group_id(&self) -> &GroupId {
56        &self.group_id
57    }
58
59    /// The epoch of the parent group from which this branch is taken.
60    pub fn epoch(&self) -> GroupEpoch {
61        self.epoch
62    }
63
64    /// The parent group's resumption PSK secret for [`Self::epoch`].
65    ///
66    /// This is sensitive key material.
67    pub(crate) fn resumption_psk_secret(&self) -> &ResumptionPskSecret {
68        &self.resumption_psk_secret
69    }
70
71    /// The credentials of the parent group's members, used by the receiver to
72    /// check that every sub-group member is also a parent-group member.
73    pub(crate) fn member_credentials(&self) -> &[Credential] {
74        &self.member_credentials
75    }
76}