mls_spec/
lib.rs

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