Skip to main content

mls_spec/defs/
mod.rs

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
12/// MLS GREASE values to check implementation robustness
13///
14/// <https://www.rfc-editor.org/rfc/rfc9420.html#section-13.5>
15pub 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    Hash,
29    Default,
30    tls_codec::TlsSerialize,
31    tls_codec::TlsDeserialize,
32    tls_codec::TlsSize,
33    strum::IntoStaticStr,
34    strum::Display,
35    strum::EnumString,
36)]
37#[cfg_attr(
38    feature = "serde",
39    derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
40)]
41#[repr(u16)]
42#[non_exhaustive]
43pub enum ProtocolVersion {
44    Reserved = 0x0000,
45    #[strum(serialize = "MLS 1.0")]
46    #[default]
47    Mls10 = 0x0001,
48}
49
50impl ProtocolVersion {
51    #[must_use]
52    pub fn all_without_spec_default() -> Vec<Self> {
53        vec![Self::Mls10]
54    }
55}
56
57impl_spec_enum! {
58    CiphersuiteId(u16);
59    serde_repr "u16";
60    reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeCiphersuite;
61    default_range None;
62    SPEC_RESERVED = 0x0000,
63    MLS_128_DHKEMX25519_AES128GCM_SHA256_ED25519 = 0x0001,
64    MLS_128_DHKEMP256_AES128GCM_SHA256_P256 = 0x0002,
65    MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_ED25519 = 0x0003,
66    MLS_256_DHKEMX448_AES256GCM_SHA512_ED448 = 0x0004,
67    MLS_256_DHKEMP521_AES256GCM_SHA512_P521 = 0x0005,
68    MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_ED448 = 0x0006,
69    MLS_256_DHKEMP384_AES256GCM_SHA384_P384 = 0x0007
70}
71
72impl Default for CiphersuiteId {
73    fn default() -> Self {
74        Self(Self::MLS_128_DHKEMX25519_AES128GCM_SHA256_ED25519)
75    }
76}
77
78impl_spec_enum! {
79    ExtensionType(u16);
80    serde_repr "u16";
81    reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeExtensionType;
82    default_range Some(0x0001..=0x0005);
83    SPEC_RESERVED = 0x0000,
84    APPLICATION_ID = 0x0001,
85    RATCHET_TREE = 0x0002,
86    REQUIRED_CAPABILITIES = 0x0003,
87    EXTERNAL_PUB = 0x0004,
88    EXTERNAL_SENDERS = 0x0005,
89    #[cfg(feature = "draft-ietf-mls-extensions")]
90    APPLICATION_DATA_DICTIONARY = crate::drafts::mls_extensions::EXTENSION_APP_DATA_DICT,
91    #[cfg(feature = "draft-ietf-mls-extensions")]
92    SUPPORTED_WIRE_FORMATS = crate::drafts::mls_extensions::EXTENSION_SUPPORTED_WIRE_FORMATS,
93    #[cfg(feature = "draft-ietf-mls-extensions")]
94    REQUIRED_WIRE_FORMATS = crate::drafts::mls_extensions::EXTENSION_REQUIRED_WIRE_FORMATS,
95    #[cfg(feature = "draft-mahy-mls-ratchet-tree-options")]
96    RATCHET_TREE_SOURCE_DOMAINS = crate::drafts::ratchet_tree_options::EXTENSION_RATCHET_TREE_SOURCE_DOMAINS,
97    #[cfg(feature = "draft-mahy-mls-new-content-types")]
98    SUPPORTED_CONTENT_TYPES = crate::drafts::new_content_types::EXTENSION_SUPPORTED_CONTENT_TYPES,
99    #[cfg(feature = "draft-mahy-mls-new-content-types")]
100    REQUIRED_CONTENT_TYPES = crate::drafts::new_content_types::EXTENSION_REQUIRED_CONTENT_TYPES
101}
102
103impl Default for ExtensionType {
104    fn default() -> Self {
105        Self(Self::SPEC_RESERVED)
106    }
107}
108
109impl_spec_enum! {
110    ProposalType(u16);
111    serde_repr "u16";
112    reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeProposalType;
113    default_range Some(0x0001..=0x0007);
114    SPEC_RESERVED = 0x0000,
115    ADD = 0x0001,
116    UPDATE = 0x0002,
117    REMOVE = 0x0003,
118    PSK = 0x0004,
119    REINIT = 0x0005,
120    EXTERNAL_INIT = 0x0006,
121    GROUP_CONTEXT_EXTENSIONS = 0x0007,
122    #[cfg(feature = "draft-ietf-mls-extensions")]
123    APP_DATA_UPDATE = crate::drafts::mls_extensions::PROPOSAL_APP_DATA_UPDATE,
124    #[cfg(feature = "draft-ietf-mls-extensions")]
125    APP_EPHEMERAL = crate::drafts::mls_extensions::PROPOSAL_APP_EPHEMERAL,
126    #[cfg(feature = "draft-ietf-mls-extensions")]
127    SELF_REMOVE = crate::drafts::mls_extensions::PROPOSAL_SELF_REMOVE
128}
129
130impl ProposalType {
131    #[inline]
132    pub fn is_allowed_in_external_proposals(&self) -> bool {
133        #[allow(unused_mut)]
134        let mut allowed = matches!(
135            self.0,
136            Self::ADD | Self::REMOVE | Self::PSK | Self::REINIT | Self::GROUP_CONTEXT_EXTENSIONS
137        );
138
139        #[cfg(feature = "draft-ietf-mls-extensions")]
140        {
141            allowed |= matches!(self.0, Self::APP_DATA_UPDATE | Self::APP_EPHEMERAL);
142        }
143
144        allowed
145    }
146
147    #[inline]
148    pub fn needs_update_path(&self) -> bool {
149        #[allow(unused_mut)]
150        let mut needs_update_path = matches!(
151            self.0,
152            Self::UPDATE | Self::REMOVE | Self::EXTERNAL_INIT | Self::GROUP_CONTEXT_EXTENSIONS
153        );
154
155        #[cfg(feature = "draft-ietf-mls-extensions")]
156        {
157            needs_update_path |= matches!(self.0, Self::SELF_REMOVE);
158        }
159
160        needs_update_path
161    }
162}
163
164impl_spec_enum! {
165    CredentialType(u16);
166    serde_repr "u16";
167    reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeCredentialType;
168    default_range None;
169    SPEC_RESERVED = 0x0000,
170    BASIC = 0x0001,
171    X509 = 0x0002,
172    #[cfg(feature = "draft-ietf-mls-extensions")]
173    MULTI_CREDENTIAL = crate::drafts::mls_extensions::multi_credentials::MULTI_CREDENTIAL,
174    #[cfg(feature = "draft-ietf-mls-extensions")]
175    WEAK_MULTI_CREDENTIAL= crate::drafts::mls_extensions::multi_credentials::WEAK_MULTI_CREDENTIAL,
176    #[cfg(feature = "draft-mahy-mls-sd-cwt-credential")]
177    SD_CWT_CREDENTIAL = crate::drafts::sd_cwt_credential::CREDENTIAL_SD_CWT,
178    #[cfg(feature = "draft-mahy-mls-sd-cwt-credential")]
179    SD_JWT_CREDENTIAL = crate::drafts::sd_cwt_credential::CREDENTIAL_SD_JWT
180}
181
182impl Default for CredentialType {
183    fn default() -> Self {
184        Self(Self::BASIC)
185    }
186}
187
188impl_spec_enum! {
189    WireFormat(u16);
190    serde_repr "u16";
191    reserved_priv 0xF000..=0xFFFF => crate::MlsSpecError::InvalidPrivateRangeWireFormat;
192    default_range None;
193    SPEC_RESERVED = 0x0000,
194    MLS_PUBLIC_MESSAGE = 0x0001,
195    MLS_PRIVATE_MESSAGE = 0x0002,
196    MLS_WELCOME = 0x0003,
197    MLS_GROUP_INFO = 0x0004,
198    MLS_KEY_PACKAGE = 0x0005,
199    #[cfg(feature = "draft-ietf-mls-targeted-messages")]
200    MLS_TARGETED_MESSAGE = crate::drafts::targeted_messages::WIRE_FORMAT_MLS_TARGETED_MESSAGE,
201    #[cfg(feature = "draft-mahy-mls-semiprivatemessage")]
202    MLS_SEMIPRIVATE_MESSAGE = crate::drafts::semiprivate_message::WIRE_FORMAT_MLS_SEMIPRIVATE_MESSAGE,
203    #[cfg(feature = "draft-mularczyk-mls-splitcommit")]
204    MLS_SPLIT_COMMIT = crate::drafts::split_commit::WIRE_FORMAT_MLS_SPLIT_COMMIT,
205    #[cfg(feature = "draft-pham-mls-additional-wire-formats")]
206    MLS_MESSAGE_WITHOUT_AAD = crate::drafts::additional_wire_formats::WIRE_FORMAT_MLS_MESSAGE_WITHOUT_AAD,
207    #[cfg(feature = "draft-mahy-mls-private-external")]
208    MLS_PRIVATE_EXTERNAL_MESSAGE = crate::drafts::private_external::WIRE_FORMAT_MLS_PRIVATE_EXTERNAL_MESSAGE,
209    #[cfg(feature = "draft-kohbrok-mls-leaf-operation-intents")]
210    MLS_LEAF_OPERATION_INTENT = crate::drafts::leaf_operation_intents::WIRE_FORMAT_MLS_LEAF_OPERATION_INTENT
211}
212
213#[derive(
214    Debug,
215    Clone,
216    PartialEq,
217    Eq,
218    Hash,
219    tls_codec::TlsSerialize,
220    tls_codec::TlsDeserialize,
221    tls_codec::TlsSize,
222)]
223#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
224pub struct Capabilities {
225    pub versions: Vec<ProtocolVersion>,
226    pub ciphersuites: Vec<CiphersuiteId>,
227    pub extensions: Vec<ExtensionType>,
228    pub proposals: Vec<ProposalType>,
229    pub credentials: Vec<CredentialType>,
230}