1use crate::{
2 SensitiveBytes,
3 defs::{Epoch, LeafIndex, ProtocolVersion, WireFormat, labels::KdfLabelKind},
4 group::{GroupId, GroupIdRef},
5};
6
7pub const WIRE_FORMAT_MLS_TARGETED_MESSAGE: u16 = 0x0006;
8
9#[derive(
10 Debug,
11 Clone,
12 PartialEq,
13 Eq,
14 tls_codec::TlsSerialize,
15 tls_codec::TlsDeserialize,
16 tls_codec::TlsSize,
17)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct TargetedMessageSenderAuthData {
20 pub sender_leaf_index: LeafIndex,
21 pub signature: SensitiveBytes,
22 pub kem_output: SensitiveBytes,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
26pub struct TargetedMessageTBM<'a> {
27 #[tls_codec(with = "crate::tlspl::bytes")]
28 pub group_id: GroupIdRef<'a>,
29 pub epoch: &'a Epoch,
30 pub recipient_leaf_index: &'a LeafIndex,
31 #[tls_codec(with = "crate::tlspl::bytes")]
32 pub authenticated_data: &'a [u8],
33 pub sender_auth_data: &'a TargetedMessageSenderAuthData,
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct TargetedMessageTBS<'a> {
38 pub group_id: GroupIdRef<'a>,
39 pub epoch: &'a Epoch,
40 pub recipient_leaf_index: &'a LeafIndex,
41 pub authenticated_data: &'a [u8],
42 pub sender_leaf_index: &'a LeafIndex,
43 pub kem_output: &'a [u8],
44 pub ciphertext: &'a [u8],
45}
46
47impl<'a> tls_codec::Size for TargetedMessageTBS<'a> {
48 fn tls_serialized_len(&self) -> usize {
49 ProtocolVersion::Mls10.tls_serialized_len()
50 + WireFormat::new_unchecked(WireFormat::MLS_TARGETED_MESSAGE).tls_serialized_len()
51 + crate::tlspl::bytes::tls_serialized_len(self.group_id)
52 + self.epoch.tls_serialized_len()
53 + self.recipient_leaf_index.tls_serialized_len()
54 + crate::tlspl::bytes::tls_serialized_len(self.authenticated_data)
55 + self.sender_leaf_index.tls_serialized_len()
56 + crate::tlspl::bytes::tls_serialized_len(self.kem_output)
57 + crate::tlspl::bytes::tls_serialized_len(self.ciphertext)
58 }
59}
60
61impl<'a> tls_codec::Serialize for TargetedMessageTBS<'a> {
62 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
63 let mut written = ProtocolVersion::Mls10.tls_serialize(writer)?;
64 written +=
65 WireFormat::new_unchecked(WireFormat::MLS_TARGETED_MESSAGE).tls_serialize(writer)?;
66 written += crate::tlspl::bytes::tls_serialize(self.group_id, writer)?;
67 written += self.epoch.tls_serialize(writer)?;
68 written += self.recipient_leaf_index.tls_serialize(writer)?;
69 written += crate::tlspl::bytes::tls_serialize(self.authenticated_data, writer)?;
70 written += self.sender_leaf_index.tls_serialize(writer)?;
71 written += crate::tlspl::bytes::tls_serialize(self.kem_output, writer)?;
72 written += crate::tlspl::bytes::tls_serialize(self.ciphertext, writer)?;
73
74 Ok(written)
75 }
76}
77
78#[derive(
79 Debug,
80 Clone,
81 PartialEq,
82 Eq,
83 tls_codec::TlsSerialize,
84 tls_codec::TlsDeserialize,
85 tls_codec::TlsSize,
86)]
87#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
88pub struct TargetedMessage {
89 pub group_id: GroupId,
90 pub epoch: Epoch,
91 pub recipient_leaf_index: LeafIndex,
92 pub authenticated_data: SensitiveBytes,
93 pub encrypted_sender_auth_data: SensitiveBytes,
94 pub ciphertext: SensitiveBytes,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
98pub struct TargetedMessagePreSharedKeyId<'a> {
99 #[tls_codec(with = "crate::tlspl::bytes")]
100 pub group_id: GroupIdRef<'a>,
101 pub epoch: &'a Epoch,
102}
103
104impl TargetedMessagePreSharedKeyId<'_> {
105 pub const LABEL: KdfLabelKind = KdfLabelKind::TargetedMessagePsk;
106}
107
108#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
109pub struct TargetedMessageSenderAuthDataAAD<'a> {
110 #[tls_codec(with = "crate::tlspl::bytes")]
111 pub group_id: GroupIdRef<'a>,
112 pub epoch: &'a Epoch,
113 pub recipient_leaf_index: &'a LeafIndex,
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118pub struct TargetedMessageContent {
119 pub application_data: Vec<u8>,
120 pub padding_len: usize,
121}
122
123impl tls_codec::Size for TargetedMessageContent {
124 fn tls_serialized_len(&self) -> usize {
125 crate::tlspl::tls_serialized_len_as_vlvec(self.application_data.len()) + self.padding_len
126 }
127}
128
129impl tls_codec::Serialize for TargetedMessageContent {
130 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
131 let mut written = crate::tlspl::bytes::tls_serialize(&self.application_data, writer)?;
132 writer.write_all(&vec![0u8; self.padding_len][..])?;
133 written += self.padding_len;
134 Ok(written)
135 }
136}
137
138impl tls_codec::Deserialize for TargetedMessageContent {
139 fn tls_deserialize<R: std::io::Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
140 where
141 Self: Sized,
142 {
143 let application_data = crate::tlspl::bytes::tls_deserialize(bytes)?;
144 let padding_len = crate::messages::PrivateMessageContent::consume_padding(bytes)?;
145 Ok(Self {
146 application_data,
147 padding_len,
148 })
149 }
150}