Skip to main content

mls_spec/messages/
content_encryption.rs

1use crate::{
2    defs::{Epoch, Generation, LeafIndex},
3    group::GroupIdRef,
4    messages::{ContentType, ContentTypeInner, FramedContentAuthData},
5};
6
7pub type ReuseGuard = [u8; 4];
8
9#[derive(Debug, Clone)]
10pub struct PrivateMessageContent {
11    pub inner: ContentTypeInner,
12    pub auth: FramedContentAuthData,
13    pub padding_len: usize,
14}
15
16impl PartialEq for PrivateMessageContent {
17    fn eq(&self, other: &Self) -> bool {
18        self.inner == other.inner && self.auth == other.auth
19    }
20}
21impl Eq for PrivateMessageContent {}
22
23impl tls_codec::Size for PrivateMessageContent {
24    fn tls_serialized_len(&self) -> usize {
25        self.inner.tls_serialized_len() + self.auth.tls_serialized_len() + self.padding_len
26    }
27}
28
29impl tls_codec::Serialize for PrivateMessageContent {
30    fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
31        let mut written = 0;
32        written += self.inner.tls_serialize(writer)?;
33        written += self.auth.tls_serialize(writer)?;
34        writer.write_all(&vec![0u8; self.padding_len][..])?;
35        written += self.padding_len;
36        Ok(written)
37    }
38}
39
40impl PrivateMessageContent {
41    pub(crate) fn consume_padding<R: std::io::Read>(
42        bytes: &mut R,
43    ) -> Result<usize, tls_codec::Error> {
44        let mut padding = Vec::new();
45        bytes.read_to_end(&mut padding).map_err(|_| {
46            tls_codec::Error::DecodingError("Cannot decode padding past MessageContent".into())
47        })?;
48
49        let padding_len = padding.len();
50        if padding.into_iter().any(|b| b != 0x00) {
51            return Err(tls_codec::Error::DecodingError(
52                "MessageContent padding isn't all zeroes!".into(),
53            ));
54        }
55
56        Ok(padding_len)
57    }
58
59    pub fn tls_deserialize_with_content_type<R: std::io::Read>(
60        bytes: &mut R,
61        content_type: ContentType,
62    ) -> Result<Self, tls_codec::Error> {
63        use tls_codec::Deserialize as _;
64
65        let inner = match content_type {
66            ContentType::Reserved => {
67                return Err(tls_codec::Error::DecodingError(
68                    "Tried to deserialize a ContentType::RESERVED, which is invalid".into(),
69                ));
70            }
71            ContentType::Application => ContentTypeInner::Application {
72                application_data: crate::tlspl::bytes::tls_deserialize(bytes)?,
73            },
74            ContentType::Proposal => ContentTypeInner::Proposal {
75                proposal: <_>::tls_deserialize(bytes)?,
76            },
77            ContentType::Commit => ContentTypeInner::Commit {
78                commit: <_>::tls_deserialize(bytes)?,
79            },
80            #[cfg(feature = "draft-mahy-mls-new-content-types")]
81            ContentType::Status => ContentTypeInner::Status {
82                application_data: crate::tlspl::bytes::tls_deserialize(bytes)?,
83            },
84            #[cfg(feature = "draft-mahy-mls-new-content-types")]
85            ContentType::Ephemeral => ContentTypeInner::Ephemeral {
86                application_data: crate::tlspl::bytes::tls_deserialize(bytes)?,
87            },
88            #[cfg(feature = "draft-mularczyk-mls-splitcommit")]
89            ContentType::SplitCommit => ContentTypeInner::SplitCommit {
90                split_commit: <_>::tls_deserialize(bytes)?,
91            },
92        };
93        let auth = FramedContentAuthData::tls_deserialize_with_content_type(bytes, content_type)?;
94
95        let padding_len = Self::consume_padding(bytes)?;
96
97        Ok(Self {
98            inner,
99            auth,
100            padding_len,
101        })
102    }
103}
104
105/// PrivateMessage content AAD struct
106///
107/// <https://www.rfc-editor.org/rfc/rfc9420.html#section-6.3.1-9>
108///
109/// # TLS Presentation Language
110///
111/// ```notrust,ignore
112/// struct {
113///     opaque group_id<V>;
114///     uint64 epoch;
115///     ContentType content_type;
116///     opaque authenticated_data<V>;
117/// } PrivateContentAAD;
118/// ````
119#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
120pub struct PrivateContentAAD<'a> {
121    #[tls_codec(with = "crate::tlspl::bytes")]
122    pub group_id: GroupIdRef<'a>,
123    pub epoch: &'a Epoch,
124    pub content_type: &'a ContentType,
125    #[tls_codec(with = "crate::tlspl::bytes")]
126    pub authenticated_data: &'a [u8],
127}
128
129/// SenderData struct
130///
131/// <https://www.rfc-editor.org/rfc/rfc9420.html#name-sender-data-encryption>
132///
133/// # TLS Presentation Language
134///
135/// ```notrust,ignore
136/// struct {
137///     uint32 leaf_index;
138///     uint32 generation;
139///     opaque reuse_guard[4];
140/// } SenderData;
141/// ```
142#[derive(
143    Debug,
144    Clone,
145    PartialEq,
146    Eq,
147    tls_codec::TlsSerialize,
148    tls_codec::TlsDeserialize,
149    tls_codec::TlsSize,
150)]
151pub struct SenderData {
152    pub leaf_index: LeafIndex,
153    pub generation: Generation,
154    pub reuse_guard: ReuseGuard,
155}
156
157/// SenderData AAD struct
158///
159/// <https://www.rfc-editor.org/rfc/rfc9420.html#section-6.3.2-7>
160///
161/// # TLS Presentation Language
162///
163/// ```notrust,ignore
164/// struct {
165///     opaque group_id<V>;
166///     uint64 epoch;
167///     ContentType content_type;
168/// } SenderDataAAD;
169/// ````
170#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
171pub struct SenderDataAAD<'a> {
172    pub group_id: GroupIdRef<'a>,
173    pub epoch: &'a Epoch,
174    pub content_type: &'a ContentType,
175}