1use crate::macros::impl_spec_enum;
2
3pub mod labels;
4
5pub type LeafIndex = u32;
6pub type SenderIndex = u32;
7pub type Generation = u32;
8pub type Epoch = u64;
9
10pub const MLS_MIME_TYPE: &str = "message/mls";
11
12pub const GREASE_VALUES: [u16; 15] = [
16 0x0A0A, 0x1A1A, 0x2A2A, 0x3A3A, 0x4A4A, 0x5A5A, 0x6A6A, 0x7A7A, 0x8A8A, 0x9A9A, 0xAAAA, 0xBABA,
17 0xCACA, 0xDADA, 0xEAEA,
18];
19
20#[derive(
21 Debug,
22 Clone,
23 Copy,
24 PartialEq,
25 Eq,
26 PartialOrd,
27 Ord,
28 Default,
29 tls_codec::TlsSerialize,
30 tls_codec::TlsDeserialize,
31 tls_codec::TlsSize,
32 strum::IntoStaticStr,
33 strum::Display,
34 strum::EnumString,
35)]
36#[cfg_attr(
37 feature = "serde",
38 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
39)]
40#[repr(u16)]
41#[non_exhaustive]
42pub enum ProtocolVersion {
43 Reserved = 0x0000,
44 #[strum(serialize = "MLS 1.0")]
45 #[default]
46 Mls10 = 0x0001,
47}
48
49impl ProtocolVersion {
50 #[must_use]
51 pub fn all_without_spec_default() -> Vec<Self> {
52 vec![Self::Mls10]
53 }
54}
55
56impl_spec_enum! {
57 CiphersuiteId(u16);
58 serde_repr "u16";
59 reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeCiphersuite;
60 default_range None;
61 SPEC_RESERVED = 0x0000,
62 MLS_128_DHKEMX25519_AES128GCM_SHA256_ED25519 = 0x0001,
63 MLS_128_DHKEMP256_AES128GCM_SHA256_P256 = 0x0002,
64 MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_ED25519 = 0x0003,
65 MLS_256_DHKEMX448_AES256GCM_SHA512_ED448 = 0x0004,
66 MLS_256_DHKEMP521_AES256GCM_SHA512_P521 = 0x0005,
67 MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_ED448 = 0x0006,
68 MLS_256_DHKEMP384_AES256GCM_SHA384_P384 = 0x0007
69}
70
71impl Default for CiphersuiteId {
72 fn default() -> Self {
73 Self(Self::MLS_128_DHKEMX25519_AES128GCM_SHA256_ED25519)
74 }
75}
76
77impl_spec_enum! {
78 ExtensionType(u16);
79 serde_repr "u16";
80 reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeExtensionType;
81 default_range Some(0x0001..=0x0005);
82 SPEC_RESERVED = 0x0000,
83 APPLICATION_ID = 0x0001,
84 RATCHET_TREE = 0x0002,
85 REQUIRED_CAPABILITIES = 0x0003,
86 EXTERNAL_PUB = 0x0004,
87 EXTERNAL_SENDERS = 0x0005,
88 #[cfg(feature = "draft-ietf-mls-extensions")]
89 APPLICATION_DATA_DICTIONARY = crate::drafts::mls_extensions::EXTENSION_APP_DATA_DICT,
90 #[cfg(feature = "draft-ietf-mls-extensions")]
91 SUPPORTED_WIRE_FORMATS = crate::drafts::mls_extensions::EXTENSION_SUPPORTED_WIRE_FORMATS,
92 #[cfg(feature = "draft-ietf-mls-extensions")]
93 REQUIRED_WIRE_FORMATS = crate::drafts::mls_extensions::EXTENSION_REQUIRED_WIRE_FORMATS,
94 #[cfg(feature = "draft-ietf-mls-extensions")]
95 TARGETED_MESSAGES_CAPABILITY = crate::drafts::mls_extensions::EXTENSION_TARGETED_MESSAGES_CAPABILITY
96}
97
98impl Default for ExtensionType {
99 fn default() -> Self {
100 Self(Self::SPEC_RESERVED)
101 }
102}
103
104impl_spec_enum! {
105 ProposalType(u16);
106 serde_repr "u16";
107 reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeProposalType;
108 default_range Some(0x0001..=0x0007);
109 SPEC_RESERVED = 0x0000,
110 ADD = 0x0001,
111 UPDATE = 0x0002,
112 REMOVE = 0x0003,
113 PSK = 0x0004,
114 REINIT = 0x0005,
115 EXTERNAL_INIT = 0x0006,
116 GROUP_CONTEXT_EXTENSIONS = 0x0007,
117 #[cfg(feature = "draft-ietf-mls-extensions")]
118 APP_DATA_UPDATE = crate::drafts::mls_extensions::PROPOSAL_APP_DATA_UPDATE,
119 #[cfg(feature = "draft-ietf-mls-extensions")]
120 APP_EPHEMERAL = crate::drafts::mls_extensions::PROPOSAL_APP_EPHEMERAL,
121 #[cfg(feature = "draft-ietf-mls-extensions")]
122 SELF_REMOVE = crate::drafts::mls_extensions::PROPOSAL_SELF_REMOVE
123}
124
125impl ProposalType {
126 #[inline]
127 pub fn is_allowed_in_external_proposals(&self) -> bool {
128 #[allow(unused_mut)]
129 let mut allowed = matches!(
130 self.0,
131 Self::ADD | Self::REMOVE | Self::PSK | Self::REINIT | Self::GROUP_CONTEXT_EXTENSIONS
132 );
133
134 allowed
135 }
136
137 #[inline]
138 pub fn needs_update_path(&self) -> bool {
139 #[allow(unused_mut)]
140 let mut needs_update_path = matches!(
141 self.0,
142 Self::UPDATE | Self::REMOVE | Self::EXTERNAL_INIT | Self::GROUP_CONTEXT_EXTENSIONS
143 );
144
145 #[cfg(feature = "draft-ietf-mls-extensions")]
146 {
147 needs_update_path |= matches!(self.0, Self::SELF_REMOVE);
148 }
149
150 needs_update_path
151 }
152}
153
154impl_spec_enum! {
155 CredentialType(u16);
156 serde_repr "u16";
157 reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeCredentialType;
158 default_range None;
159 SPEC_RESERVED = 0x0000,
160 BASIC = 0x0001,
161 X509 = 0x0002,
162 #[cfg(feature = "draft-ietf-mls-extensions")]
163 MULTI_CREDENTIAL = crate::drafts::mls_extensions::multi_credentials::MULTI_CREDENTIAL,
164 #[cfg(feature = "draft-ietf-mls-extensions")]
165 WEAK_MULTI_CREDENTIAL= crate::drafts::mls_extensions::multi_credentials::WEAK_MULTI_CREDENTIAL,
166 #[cfg(feature = "draft-mahy-mls-sd-cwt-credential")]
167 SD_CWT_CREDENTIAL = crate::drafts::sd_cwt_credential::CREDENTIAL_SD_CWT,
168 #[cfg(feature = "draft-mahy-mls-sd-cwt-credential")]
169 SD_JWT_CREDENTIAL = crate::drafts::sd_cwt_credential::CREDENTIAL_SD_JWT
170}
171
172impl Default for CredentialType {
173 fn default() -> Self {
174 Self(Self::BASIC)
175 }
176}
177
178impl_spec_enum! {
179 WireFormat(u16);
180 serde_repr "u16";
181 reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeWireFormat;
182 default_range None;
183 SPEC_RESERVED = 0x0000,
184 MLS_PUBLIC_MESSAGE = 0x0001,
185 MLS_PRIVATE_MESSAGE = 0x0002,
186 MLS_WELCOME = 0x0003,
187 MLS_GROUP_INFO = 0x0004,
188 MLS_KEY_PACKAGE = 0x0005,
189 #[cfg(feature = "draft-ietf-mls-extensions")]
190 MLS_TARGETED_MESSAGE = crate::drafts::mls_extensions::WIRE_FORMAT_MLS_TARGETED_MESSAGE,
191 #[cfg(feature = "draft-mahy-mls-semiprivatemessage")]
192 MLS_SEMIPRIVATE_MESSAGE = crate::drafts::semiprivate_message::WIRE_FORMAT_MLS_SEMIPRIVATE_MESSAGE,
193 #[cfg(feature = "draft-mularczyk-mls-splitcommit")]
194 MLS_SPLIT_COMMIT = crate::drafts::split_commit::WIRE_FORMAT_MLS_SPLIT_COMMIT,
195 #[cfg(feature = "draft-pham-mls-additional-wire-formats")]
196 MLS_MESSAGE_WITHOUT_AAD = crate::drafts::additional_wire_formats::WIRE_FORMAT_MLS_MESSAGE_WITHOUT_AAD
197}
198
199#[derive(
200 Debug,
201 Clone,
202 PartialEq,
203 Eq,
204 tls_codec::TlsSerialize,
205 tls_codec::TlsDeserialize,
206 tls_codec::TlsSize,
207)]
208#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
209pub struct Capabilities {
210 pub versions: Vec<ProtocolVersion>,
211 pub ciphersuites: Vec<CiphersuiteId>,
212 pub extensions: Vec<ExtensionType>,
213 pub proposals: Vec<ProposalType>,
214 pub credentials: Vec<CredentialType>,
215}