Skip to main content

mls_spec/
lib.rs

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