Skip to main content

openmls/framing/
mod.rs

1//! # Message framing
2//!
3//! This module contains framing-related operations for MLS messages, including
4//! validation logic.
5//!
6//! The general structure of the framing process in OpenMLS closely follows the
7//! design described in Section 7 of the MLS specification. It can be visualized
8//! as follows:
9//!
10//! ```text
11//!                               Proposal        Commit     Application Data
12//!                                  |              |              |
13//!                                  +--------------+--------------+
14//!                                                 |
15//!                                                 V
16//!                                          FramedContent
17//!                                              |  |                -.
18//!                                              |  |                  |
19//!                                     +--------+  |                  |
20//!                                     |           |                  |
21//!                                     V           |                  +-- Asymmetric
22//!                           FramedContentAuthData |                  |   Sign / Verify
23//!                                     |           |                  |
24//!                                     +--------+  |                  |
25//!                                              |  |                  |
26//!                                              V  V                -'
27//!                                        AuthenticatedContent
28//!                                                 |                -.
29//!                                                 |                  |
30//!                                                 |                  |
31//!                                        +--------+--------+         +-- Symmetric
32//!                                        |                 |         |   Protect / Unprotect
33//!                                        V                 V         |
34//! Welcome  KeyPackage  GroupInfo   PublicMessage    PrivateMessage -'
35//!    |          |          |             |                 |
36//!    |          |          |             |                 |
37//!    +----------+----------+----+--------+-----------------+
38//!                               |
39//!                               V
40//!                           MLSMessage
41//! ```
42//!
43//!  - [`MlsMessageIn`]/[`MlsMessageOut`]: Unified message type for incoming & outgoing MLS messages
44//!  - [`ApplicationMessage`]: Application message received through a [`ProcessedMessage`]
45
46use serde::{Deserialize, Serialize};
47use tls_codec::*;
48
49use crate::{
50    ciphersuite::*,
51    credentials::*,
52    group::*,
53    messages::{proposals::*, *},
54    schedule::{message_secrets::*, *},
55};
56
57pub(crate) mod codec;
58
59pub(crate) mod message_in;
60pub(crate) mod message_out;
61pub(crate) mod mls_auth_content;
62pub(crate) mod mls_auth_content_in;
63pub(crate) mod mls_content;
64pub(crate) mod mls_content_in;
65pub(crate) mod private_message;
66pub(crate) mod private_message_in;
67pub(crate) mod public_message;
68pub(crate) mod public_message_in;
69#[cfg(feature = "extensions-draft-08")]
70pub(crate) mod safe_aad;
71pub(crate) mod sender;
72pub(crate) mod validation;
73pub(crate) use errors::*;
74
75#[cfg(test)]
76pub(crate) use mls_auth_content::*;
77#[cfg(test)]
78pub(crate) use mls_auth_content_in::*;
79
80#[cfg(test)]
81pub(crate) use mls_content::*;
82#[cfg(test)]
83pub(crate) use mls_content_in::*;
84
85// Crate
86#[cfg(feature = "virtual-clients-draft")]
87pub(crate) use private_message::EmulatorReuseGuardCtx;
88pub(crate) use sender::*;
89
90// Public
91pub mod errors;
92
93pub use message_in::*;
94pub use message_out::*;
95pub use private_message::*;
96pub use private_message_in::*;
97pub use public_message::*;
98pub use public_message_in::*;
99#[cfg(feature = "extensions-draft-08")]
100pub use safe_aad::{SafeAad, SafeAadError, SafeAadItem};
101pub use sender::*;
102pub use validation::*;
103
104// Tests
105#[cfg(test)]
106pub(crate) mod tests;
107
108/// Wire format of MLS messages.
109///
110/// // draft-ietf-mls-protocol-17
111/// | Value           | Name                     | Recommended | Reference |
112/// |-----------------|--------------------------|-------------|-----------|
113/// | 0x0000          | RESERVED                 | N/A         | RFC XXXX  |
114/// | 0x0001          | mls_plaintext            | Y           | RFC XXXX  |
115/// | 0x0002          | mls_ciphertext           | Y           | RFC XXXX  |
116/// | 0x0003          | mls_welcome              | Y           | RFC XXXX  |
117/// | 0x0004          | mls_group_info           | Y           | RFC XXXX  |
118/// | 0x0005          | mls_key_package          | Y           | RFC XXXX  |
119/// | 0xf000 - 0xffff | Reserved for Private Use | N/A         | RFC XXXX  |
120#[derive(
121    PartialEq,
122    Eq,
123    Clone,
124    Copy,
125    Debug,
126    Serialize,
127    Deserialize,
128    TlsDeserialize,
129    TlsDeserializeBytes,
130    TlsSerialize,
131    TlsSize,
132)]
133#[repr(u16)]
134pub enum WireFormat {
135    /// Plaintext message
136    PublicMessage = 1,
137    /// Encrypted message
138    PrivateMessage = 2,
139    /// Welcome message
140    Welcome = 3,
141    /// Group information
142    GroupInfo = 4,
143    /// KeyPackage
144    KeyPackage = 5,
145}
146
147/// This struct is used to group common framing parameters
148/// in order to reduce the number of arguments in function calls.
149#[derive(Clone, Copy, PartialEq, Debug)]
150pub(crate) struct FramingParameters<'a> {
151    aad: &'a [u8],
152    wire_format: WireFormat,
153}
154
155impl<'a> FramingParameters<'a> {
156    pub(crate) fn new(aad: &'a [u8], wire_format: impl Into<WireFormat>) -> Self {
157        Self {
158            aad,
159            wire_format: wire_format.into(),
160        }
161    }
162
163    pub(crate) fn aad(&self) -> &'a [u8] {
164        self.aad
165    }
166    pub(crate) fn wire_format(&self) -> WireFormat {
167        self.wire_format
168    }
169}
170
171/// ```c
172/// // draft-ietf-mls-protocol-17
173/// enum {
174///     reserved(0),
175///     application(1),
176///     proposal(2),
177///     commit(3),
178///     (255)
179/// } ContentType;
180/// ```
181#[derive(
182    PartialEq,
183    Eq,
184    Clone,
185    Copy,
186    Debug,
187    Serialize,
188    Deserialize,
189    TlsDeserialize,
190    TlsDeserializeBytes,
191    TlsSerialize,
192    TlsSize,
193)]
194#[repr(u8)]
195pub enum ContentType {
196    /// Application message
197    Application = 1,
198    /// Proposal
199    Proposal = 2,
200    /// Commit
201    Commit = 3,
202}
203
204impl TryFrom<u8> for ContentType {
205    type Error = tls_codec::Error;
206    fn try_from(value: u8) -> Result<Self, tls_codec::Error> {
207        match value {
208            1 => Ok(ContentType::Application),
209            2 => Ok(ContentType::Proposal),
210            3 => Ok(ContentType::Commit),
211            _ => Err(tls_codec::Error::DecodingError(format!(
212                "{value} is not a valid content type"
213            ))),
214        }
215    }
216}
217
218impl ContentType {
219    /// Returns `true` if this is a handshake message and `false` otherwise.
220    pub(crate) fn is_handshake_message(&self) -> bool {
221        self == &ContentType::Proposal || self == &ContentType::Commit
222    }
223}