1use crate::{
2 SensitiveBytes,
3 defs::{CiphersuiteId, Epoch, ProtocolVersion, WireFormat, labels::KdfLabelKind},
4 group::{ExternalSender, GroupId, RequiredCapabilities, extensions::Extension},
5 messages::FramedContent,
6 tree::TreeHash,
7};
8
9#[derive(
10 Debug,
11 Clone,
12 PartialEq,
13 Eq,
14 Default,
15 tls_codec::TlsSerialize,
16 tls_codec::TlsDeserialize,
17 tls_codec::TlsSize,
18)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub struct GroupContext {
21 pub version: ProtocolVersion,
22 pub cipher_suite: CiphersuiteId,
23 #[tls_codec(with = "crate::tlspl::bytes")]
24 group_id: GroupId,
25 pub epoch: u64,
26 pub tree_hash: TreeHash,
27 pub confirmed_transcript_hash: TranscriptHash,
28 pub extensions: Vec<Extension>,
29}
30
31impl GroupContext {
32 pub fn with_group_id(group_id: GroupId) -> Self {
34 Self {
35 group_id,
36 ..Default::default()
37 }
38 }
39
40 pub fn group_id(&self) -> &[u8] {
42 &self.group_id
43 }
44
45 pub fn external_senders(&self) -> &[ExternalSender] {
46 self.extensions
47 .iter()
48 .find_map(|ext| {
49 if let Extension::ExternalSenders(ext_senders) = ext {
50 Some(ext_senders.as_slice())
51 } else {
52 None
53 }
54 })
55 .unwrap_or_default()
56 }
57
58 pub fn required_capabilities(&self) -> Option<&RequiredCapabilities> {
59 self.extensions.iter().find_map(|ext| {
60 if let Extension::RequiredCapabilities(required_caps) = ext {
61 Some(required_caps)
62 } else {
63 None
64 }
65 })
66 }
67}
68
69#[derive(Debug, Copy, Clone, PartialEq, Eq)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71#[repr(u8)]
72pub enum EpochSecretExport {
73 SenderDataSecret,
74 EncryptionSecret,
75 ExporterSecret,
76 ExternalSecret,
77 ConfirmationKey,
78 MembershipKey,
79 ResumptionPsk,
80 EpochAuthenticator,
81 #[cfg(feature = "draft-kohbrok-mls-associated-parties")]
82 AssociatedPartiesSecret,
83}
84
85impl From<EpochSecretExport> for KdfLabelKind {
86 fn from(value: EpochSecretExport) -> Self {
87 match value {
88 EpochSecretExport::SenderDataSecret => KdfLabelKind::SenderData,
89 EpochSecretExport::EncryptionSecret => KdfLabelKind::Encryption,
90 EpochSecretExport::ExporterSecret => KdfLabelKind::Exporter,
91 EpochSecretExport::ExternalSecret => KdfLabelKind::External,
92 EpochSecretExport::ConfirmationKey => KdfLabelKind::Confirm,
93 EpochSecretExport::MembershipKey => KdfLabelKind::Membership,
94 EpochSecretExport::ResumptionPsk => KdfLabelKind::Resumption,
95 EpochSecretExport::EpochAuthenticator => KdfLabelKind::Authentication,
96 #[cfg(feature = "draft-kohbrok-mls-associated-parties")]
97 EpochSecretExport::AssociatedPartiesSecret => KdfLabelKind::AssociatedPartyEpochSecret,
98 }
99 }
100}
101
102pub type TranscriptHash = SensitiveBytes;
103
104#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
105#[cfg_attr(feature = "serde", derive(serde::Serialize))]
106pub struct ConfirmedTranscriptHashInput<'a> {
107 pub wire_format: &'a WireFormat,
108 pub content: &'a FramedContent,
109 pub signature: &'a [u8],
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
113#[cfg_attr(feature = "serde", derive(serde::Serialize))]
114pub struct InterimTranscriptHashInput<'a> {
115 pub confirmation_tag: &'a [u8],
116}
117
118impl<'a> From<&'a [u8]> for InterimTranscriptHashInput<'a> {
119 fn from(confirmation_tag: &'a [u8]) -> Self {
120 Self { confirmation_tag }
121 }
122}
123
124#[derive(
125 Debug,
126 Copy,
127 Clone,
128 PartialEq,
129 Eq,
130 tls_codec::TlsSerialize,
131 tls_codec::TlsDeserialize,
132 tls_codec::TlsSize,
133)]
134#[cfg_attr(
135 feature = "serde",
136 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
137)]
138#[repr(u8)]
139pub enum PskType {
140 Reserved = 0x00,
141 External = 0x01,
142 Resumption = 0x02,
143 #[cfg(feature = "draft-ietf-mls-extensions")]
144 Application = 0x03,
145}
146
147#[derive(
148 Debug,
149 Copy,
150 Clone,
151 PartialEq,
152 Eq,
153 Hash,
154 tls_codec::TlsSerialize,
155 tls_codec::TlsDeserialize,
156 tls_codec::TlsSize,
157)]
158#[cfg_attr(
159 feature = "serde",
160 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
161)]
162#[repr(u8)]
163pub enum ResumptionPskUsage {
164 Reserved = 0x00,
165 Application = 0x01,
166 ReInit = 0x02,
167 Branch = 0x03,
168}
169
170#[derive(
171 Debug,
172 Clone,
173 PartialEq,
174 Eq,
175 Hash,
176 tls_codec::TlsSerialize,
177 tls_codec::TlsDeserialize,
178 tls_codec::TlsSize,
179 zeroize::Zeroize,
180 zeroize::ZeroizeOnDrop,
181)]
182#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
183#[repr(u8)]
184pub enum PreSharedKeyIdPskType {
185 #[tls_codec(discriminant = "PskType::External")]
186 External(ExternalPsk),
187 #[tls_codec(discriminant = "PskType::Resumption")]
188 Resumption(ResumptionPsk),
189 #[cfg(feature = "draft-ietf-mls-extensions")]
190 #[tls_codec(discriminant = "PskType::Application")]
191 Application(ApplicationPsk),
192}
193
194#[derive(
195 Debug,
196 Clone,
197 PartialEq,
198 Eq,
199 Hash,
200 tls_codec::TlsSerialize,
201 tls_codec::TlsDeserialize,
202 tls_codec::TlsSize,
203 zeroize::Zeroize,
204 zeroize::ZeroizeOnDrop,
205)]
206#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
207pub struct ExternalPsk {
208 #[tls_codec(with = "crate::tlspl::bytes")]
209 pub psk_id: Vec<u8>,
210}
211
212#[derive(
213 Debug,
214 Clone,
215 PartialEq,
216 Eq,
217 Hash,
218 tls_codec::TlsSerialize,
219 tls_codec::TlsDeserialize,
220 tls_codec::TlsSize,
221 zeroize::Zeroize,
222 zeroize::ZeroizeOnDrop,
223)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
225pub struct ResumptionPsk {
226 #[zeroize(skip)]
227 pub usage: ResumptionPskUsage,
228 #[tls_codec(with = "crate::tlspl::bytes")]
229 pub psk_group_id: GroupId,
230 pub psk_epoch: Epoch,
231}
232
233#[cfg(feature = "draft-ietf-mls-extensions")]
234#[derive(
235 Debug,
236 Clone,
237 PartialEq,
238 Eq,
239 Hash,
240 tls_codec::TlsSerialize,
241 tls_codec::TlsDeserialize,
242 tls_codec::TlsSize,
243 zeroize::Zeroize,
244 zeroize::ZeroizeOnDrop,
245)]
246#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
247pub struct ApplicationPsk {
248 #[zeroize(skip)]
249 pub component_id: crate::drafts::mls_extensions::safe_application::ComponentId,
250 #[tls_codec(with = "crate::tlspl::bytes")]
251 pub psk_id: Vec<u8>,
252}
253
254#[derive(
255 Debug,
256 Clone,
257 PartialEq,
258 Eq,
259 Hash,
260 tls_codec::TlsSerialize,
261 tls_codec::TlsDeserialize,
262 tls_codec::TlsSize,
263 zeroize::Zeroize,
264 zeroize::ZeroizeOnDrop,
265)]
266#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
267pub struct PreSharedKeyId {
268 pub psktype: PreSharedKeyIdPskType,
269 pub psk_nonce: SensitiveBytes,
270}
271
272impl PreSharedKeyId {
273 pub fn with_default_nonce(&self) -> Self {
274 Self {
275 psktype: self.psktype.clone(),
276 psk_nonce: SensitiveBytes::default(),
277 }
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
282#[cfg_attr(feature = "serde", derive(serde::Serialize))]
283pub struct PskLabel<'a> {
284 pub id: &'a PreSharedKeyId,
285 pub index: u16,
286 pub count: u16,
287}