openmls/extensions/
required_capabilities.rs

1use tls_codec::{TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize};
2
3use crate::{credentials::CredentialType, messages::proposals::ProposalType};
4
5use super::{Deserialize, ExtensionType, Serialize};
6
7/// # Required Capabilities Extension.
8///
9/// The configuration of a group imposes certain requirements on clients in the
10/// group.  At a minimum, all members of the group need to support the ciphersuite
11/// and protocol version in use.  Additional requirements can be imposed by
12/// including a required capabilities extension in the `GroupContext`.
13///
14/// This extension lists the extensions and proposal types that must be supported by
15/// all members of the group.  For new members, it is enforced by existing members during the
16/// application of Add commits.  Existing members should of course be in compliance
17/// already.  In order to ensure this continues to be the case even as the group's
18/// extensions can be updated, a GroupContextExtensions proposal is invalid if it
19/// contains a required capabilities extension that requires capabilities not
20/// supported by all current members.
21///
22/// ```c
23/// // draft-ietf-mls-protocol-17
24/// struct {
25///     ExtensionType extension_types<V>;
26///     ProposalType proposal_types<V>;
27///     CredentialType credential_types<V>;
28/// } RequiredCapabilities;
29/// ```
30#[derive(
31    PartialEq,
32    Eq,
33    Clone,
34    Debug,
35    Default,
36    Serialize,
37    Deserialize,
38    TlsSerialize,
39    TlsDeserialize,
40    TlsDeserializeBytes,
41    TlsSize,
42)]
43pub struct RequiredCapabilitiesExtension {
44    extension_types: Vec<ExtensionType>,
45    proposal_types: Vec<ProposalType>,
46    credential_types: Vec<CredentialType>,
47}
48
49impl RequiredCapabilitiesExtension {
50    /// Creates a new [`RequiredCapabilitiesExtension`] from extension and proposal types.
51    pub fn new(
52        extension_types: &[ExtensionType],
53        proposal_types: &[ProposalType],
54        credential_types: &[CredentialType],
55    ) -> Self {
56        Self {
57            extension_types: extension_types.into(),
58            proposal_types: proposal_types.into(),
59            credential_types: credential_types.into(),
60        }
61    }
62
63    /// Get a slice with the required extension types.
64    pub fn extension_types(&self) -> &[ExtensionType] {
65        self.extension_types.as_slice()
66    }
67
68    /// Get a slice with the required proposal types.
69    pub fn proposal_types(&self) -> &[ProposalType] {
70        self.proposal_types.as_slice()
71    }
72
73    /// Get a slice with the required credential types.
74    pub fn credential_types(&self) -> &[CredentialType] {
75        self.credential_types.as_slice()
76    }
77
78    /// Checks whether support for the provided extension type is required.
79    pub(crate) fn requires_extension_type_support(&self, ext_type: ExtensionType) -> bool {
80        self.extension_types.contains(&ext_type)
81    }
82}