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