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")]
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")]
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/// | Value           | Name                     | Recommended | Reference                              |
111/// |-----------------|--------------------------|-------------|----------------------------------------|
112/// | 0x0000          | RESERVED                 | N/A         | RFC 9420                               |
113/// | 0x0001          | mls_plaintext            | Y           | RFC 9420                               |
114/// | 0x0002          | mls_ciphertext           | Y           | RFC 9420                               |
115/// | 0x0003          | mls_welcome              | Y           | RFC 9420                               |
116/// | 0x0004          | mls_group_info           | Y           | RFC 9420                               |
117/// | 0x0005          | mls_key_package          | Y           | RFC 9420                               |
118/// | 0x0006          | mls_targeted_message     | Y           | draft-ietf-mls-targeted-messages       |
119/// | 0xf000 - 0xffff | Reserved for Private Use | N/A         | RFC 9420                               |
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    /// Targeted message (draft-ietf-mls-targeted-messages)
146    #[cfg(feature = "targeted-messages-draft")]
147    #[cfg_attr(docsrs, doc(cfg(feature = "targeted-messages-draft")))]
148    TargetedMessage = 6,
149}
150
151/// This struct is used to group common framing parameters
152/// in order to reduce the number of arguments in function calls.
153#[derive(Clone, Copy, PartialEq, Debug)]
154pub(crate) struct FramingParameters<'a> {
155    aad: &'a [u8],
156    wire_format: WireFormat,
157}
158
159impl<'a> FramingParameters<'a> {
160    pub(crate) fn new(aad: &'a [u8], wire_format: impl Into<WireFormat>) -> Self {
161        Self {
162            aad,
163            wire_format: wire_format.into(),
164        }
165    }
166
167    pub(crate) fn aad(&self) -> &'a [u8] {
168        self.aad
169    }
170    pub(crate) fn wire_format(&self) -> WireFormat {
171        self.wire_format
172    }
173}
174
175/// ```c
176/// enum {
177///     reserved(0),
178///     application(1),
179///     proposal(2),
180///     commit(3),
181///     (255)
182/// } ContentType;
183/// ```
184#[derive(
185    PartialEq,
186    Eq,
187    Clone,
188    Copy,
189    Debug,
190    Serialize,
191    Deserialize,
192    TlsDeserialize,
193    TlsDeserializeBytes,
194    TlsSerialize,
195    TlsSize,
196)]
197#[repr(u8)]
198pub enum ContentType {
199    /// Application message
200    Application = 1,
201    /// Proposal
202    Proposal = 2,
203    /// Commit
204    Commit = 3,
205}
206
207impl TryFrom<u8> for ContentType {
208    type Error = tls_codec::Error;
209    fn try_from(value: u8) -> Result<Self, tls_codec::Error> {
210        match value {
211            1 => Ok(ContentType::Application),
212            2 => Ok(ContentType::Proposal),
213            3 => Ok(ContentType::Commit),
214            _ => Err(tls_codec::Error::DecodingError(format!(
215                "{value} is not a valid content type"
216            ))),
217        }
218    }
219}
220
221impl ContentType {
222    /// Returns `true` if this is a handshake message and `false` otherwise.
223    pub(crate) fn is_handshake_message(&self) -> bool {
224        self == &ContentType::Proposal || self == &ContentType::Commit
225    }
226}