1use crate::{
2 SensitiveBytes,
3 crypto::{HpkePublicKey, HpkePublicKeyRef},
4 defs::SenderIndex,
5 group::ExternalSender,
6 key_schedule::GroupContext,
7};
8
9use super::mls_extensions::safe_application::{Component, ComponentId};
10
11pub const COMPONENT_ID: ComponentId = 0xFAAE_0000; static_assertions::const_assert!(
13 *super::mls_extensions::COMPONENT_RESERVED_PRIVATE_RANGE.start() <= COMPONENT_ID
14 && COMPONENT_ID <= *super::mls_extensions::COMPONENT_RESERVED_PRIVATE_RANGE.end()
15);
16
17#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSize, tls_codec::TlsSerialize)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize))]
19pub struct AssociatedPartyEntryTBS<'a> {
20 pub encryption_key: HpkePublicKeyRef<'a>,
21 pub external_sender_index: &'a SenderIndex,
22}
23
24#[derive(
25 Debug,
26 Clone,
27 PartialEq,
28 Eq,
29 tls_codec::TlsSize,
30 tls_codec::TlsSerialize,
31 tls_codec::TlsDeserialize,
32)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34pub struct AssociatedPartyEntry {
35 pub encryption_key: HpkePublicKey,
36 pub external_sender_index: SenderIndex,
37 pub signature: SensitiveBytes,
38}
39
40impl AssociatedPartyEntry {
41 pub fn to_tbs(&self) -> AssociatedPartyEntryTBS {
42 AssociatedPartyEntryTBS {
43 encryption_key: &self.encryption_key,
44 external_sender_index: &self.external_sender_index,
45 }
46 }
47
48 pub fn related_external_sender_from_group_context<'a>(
52 &self,
53 ctx: &'a GroupContext,
54 ) -> Option<&'a ExternalSender> {
55 ctx.external_senders()
56 .get(self.external_sender_index as usize)
57 }
58}
59
60#[derive(
61 Debug,
62 Clone,
63 PartialEq,
64 Eq,
65 tls_codec::TlsSize,
66 tls_codec::TlsSerialize,
67 tls_codec::TlsDeserialize,
68)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70pub struct AssociatedParties {
71 pub associated_parties: Vec<AssociatedPartyEntry>,
72}
73
74impl Component for AssociatedParties {
75 fn component_id() -> ComponentId {
76 COMPONENT_ID
77 }
78}
79
80pub mod proposals {
81 use crate::defs::LeafIndex;
82
83 use super::AssociatedPartyEntry;
84
85 #[derive(
86 Debug,
87 Clone,
88 PartialEq,
89 Eq,
90 tls_codec::TlsSize,
91 tls_codec::TlsSerialize,
92 tls_codec::TlsDeserialize,
93 )]
94 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
95 pub struct AddAssociatedPartyProposal {
96 pub new_party: AssociatedPartyEntry,
97 }
98
99 #[derive(
100 Debug,
101 Clone,
102 Copy,
103 PartialEq,
104 Eq,
105 tls_codec::TlsSize,
106 tls_codec::TlsSerialize,
107 tls_codec::TlsDeserialize,
108 )]
109 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
110 pub struct RemoveAssociatedPartyProposal {
111 pub removed_party_index: LeafIndex,
112 }
113
114 #[derive(
115 Debug,
116 Clone,
117 PartialEq,
118 Eq,
119 tls_codec::TlsSize,
120 tls_codec::TlsSerialize,
121 tls_codec::TlsDeserialize,
122 )]
123 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
124 pub struct UpdateAssociatedPartyProposal {
125 pub updated_party: AssociatedPartyEntry,
126 }
127}
128
129pub mod key_schedule {
130 use crate::{SensitiveBytes, defs::LeafIndex, key_schedule::GroupContext};
131
132 use super::AssociatedPartyEntry;
133
134 #[derive(Debug, Clone, Copy, PartialEq, Eq, tls_codec::TlsSize, tls_codec::TlsSerialize)]
135 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
136 pub struct AssociatedPartyExportContext<'a> {
137 pub ap_index: &'a LeafIndex,
138 pub ap_entry: &'a AssociatedPartyEntry,
139 }
140
141 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
142 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
143 pub struct AssociatedPartyEncryptionContext<'a> {
144 pub group_context: &'a GroupContext,
145 pub ap_commit_secret_id: &'a [u8],
146 }
147
148 impl AssociatedPartyEncryptionContext<'_> {
149 pub const LABEL: &'static [u8] = b"AP Commit Secret";
150 }
151
152 impl tls_codec::Size for AssociatedPartyEncryptionContext<'_> {
153 fn tls_serialized_len(&self) -> usize {
154 crate::tlspl::tls_serialized_len_as_vlvec(Self::LABEL.len())
155 + self.group_context.tls_serialized_len()
156 + crate::tlspl::tls_serialized_len_as_vlvec(self.ap_commit_secret_id.len())
157 }
158 }
159
160 impl tls_codec::Serialize for AssociatedPartyEncryptionContext<'_> {
161 fn tls_serialize<W: std::io::Write>(
162 &self,
163 writer: &mut W,
164 ) -> Result<usize, tls_codec::Error> {
165 let mut written = crate::tlspl::bytes::tls_serialize(Self::LABEL, writer)?;
166 written += self.group_context.tls_serialize(writer)?;
167 written += crate::tlspl::bytes::tls_serialize(self.ap_commit_secret_id, writer)?;
168 Ok(written)
169 }
170 }
171
172 #[derive(
173 Debug,
174 Clone,
175 PartialEq,
176 Eq,
177 tls_codec::TlsSize,
178 tls_codec::TlsSerialize,
179 tls_codec::TlsDeserialize,
180 )]
181 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
182 pub struct AssociatedPartySecret {
183 pub associated_party_proposal_secret: SensitiveBytes,
184 }
185
186 #[derive(
187 Debug,
188 Clone,
189 PartialEq,
190 Eq,
191 tls_codec::TlsSize,
192 tls_codec::TlsSerialize,
193 tls_codec::TlsDeserialize,
194 )]
195 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
196 pub struct AssociatedPartySecrets {
197 pub associated_party_init_secret: SensitiveBytes,
198 }
199}