mls_spec/
lib.rs

1#![allow(clippy::unnecessary_cast, non_upper_case_globals, non_camel_case_types)]
2#![doc = include_str!("../README.md")]
3mod error;
4pub use self::error::*;
5
6pub mod reexports {
7    #[cfg(feature = "draft-ietf-mls-extensions-content-advertisement-parse")]
8    pub use mediatype;
9
10    pub use tls_codec;
11}
12
13pub mod credential;
14pub mod crypto;
15pub mod defs;
16pub mod group;
17pub mod key_package;
18pub mod key_schedule;
19pub mod messages;
20pub mod tree;
21
22pub mod drafts;
23
24pub(crate) mod macros;
25#[cfg(feature = "test-utils")]
26pub mod test_utils;
27
28#[cfg(feature = "tlspl-utils")]
29pub mod tlspl;
30#[cfg(not(feature = "tlspl-utils"))]
31pub(crate) mod tlspl;
32
33mod sensitive_bytes;
34pub use sensitive_bytes::*;
35
36/// This trait allows implementers to automatically get a MLS-specific representation
37/// that takes in account protocol versions and the label format.
38///
39/// For example, the MLS 1.0 format is `MLS 1.0 {label}`.
40pub trait ToPrefixedLabel: std::fmt::Display {
41    fn to_prefixed_string(&self, protocol_version: crate::defs::ProtocolVersion) -> String {
42        format!("{protocol_version} {self}")
43    }
44}
45
46#[async_trait::async_trait]
47/// Delegate trait for implementors to implement spec-compliant validation of credentials
48/// with their Authentication Service (MLS AS)
49pub trait AuthenticationServiceDelegate: Send + Sync {
50    async fn validate_credential(&self, credential: &crate::credential::Credential) -> bool;
51}
52
53/// Trait that exposes TLS serialization
54pub trait Serializable {
55    fn to_tls_bytes(&self) -> MlsSpecResult<Vec<u8>>;
56}
57
58impl<T> Serializable for T
59where
60    T: tls_codec::Serialize,
61{
62    fn to_tls_bytes(&self) -> MlsSpecResult<Vec<u8>> {
63        Ok(self.tls_serialize_detached()?)
64    }
65}
66
67/// Trait that exposes TLS deserialization
68pub trait Parsable {
69    fn from_tls_bytes(bytes: &[u8]) -> MlsSpecResult<Self>
70    where
71        Self: Sized;
72}
73
74impl<T> Parsable for T
75where
76    T: tls_codec::Deserialize,
77{
78    fn from_tls_bytes(mut bytes: &[u8]) -> MlsSpecResult<Self>
79    where
80        Self: Sized,
81    {
82        Ok(T::tls_deserialize(&mut bytes)?)
83    }
84}
85
86#[cfg(feature = "mls-rs-compat")]
87pub mod mls_rs_compat {
88    use crate::Serializable;
89
90    /// Trait that allows to move from mls-spec data structs to mls-rs
91    /// It is inefficient by nature because in order to bypass the Rust type system,
92    /// we're using serialization/deserialization as a "boundary break"
93    ///
94    /// Additionally, none of the trait implementations are done here because we don't want to
95    /// depend directly on `mls_rs`. So you'll have to implement it on *your* side like such:
96    ///
97    /// ```rust,ignore
98    /// impl mls_spec::mls_rs_compat::MlsRsTranscode for mls_rs::MlsMessage {
99    ///     type Target = mls_spec::messages::MlsMessage;
100    /// }
101    /// ```
102    ///
103    pub trait MlsRsTranscode: mls_rs_codec::MlsDecode + mls_rs_codec::MlsEncode {
104        type Target: crate::Parsable + crate::Serializable;
105
106        fn transcode_from_mls_spec(item: &Self::Target) -> Result<Self, crate::MlsSpecError>
107        where
108            Self: Sized,
109        {
110            let tls_bytes = item.to_tls_bytes()?;
111            Ok(Self::mls_decode(&mut &tls_bytes[..])?)
112        }
113
114        fn transcode_to_mls_spec(&self) -> Result<Self::Target, crate::MlsSpecError> {
115            use crate::Parsable as _;
116            let tls_bytes = self.mls_encode_to_vec()?;
117            Self::Target::from_tls_bytes(&tls_bytes)
118        }
119    }
120}