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}