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