Skip to main content

mls_spec/
key_schedule.rs

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    /// Allows for initialization with an arbitrary group id
33    pub fn with_group_id(group_id: GroupId) -> Self {
34        Self {
35            group_id,
36            ..Default::default()
37        }
38    }
39
40    // 8.1 -> The `group_id` field is constant
41    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}