openmls/group/mls_group/
application.rs1use openmls_traits::signatures::Signer;
2
3use crate::storage::OpenMlsProvider;
4
5#[cfg(feature = "virtual-clients-draft")]
6use crate::tree::secret_tree::SecretType;
7
8#[cfg(feature = "virtual-clients-draft")]
9use super::errors::ConfirmMessageError;
10use super::{errors::CreateMessageError, *};
11
12#[cfg(feature = "virtual-clients-draft")]
16#[derive(Debug, Clone)]
17pub struct UnconfirmedMessage {
18 pub message: MlsMessageOut,
20 pub generation: u32,
24 pub generation_id: Option<crate::components::vc_derivation_info::GenerationId>,
31}
32
33impl MlsGroup {
34 #[cfg(not(feature = "virtual-clients-draft"))]
44 pub fn create_message<Provider: OpenMlsProvider>(
45 &mut self,
46 provider: &Provider,
47 signer: &impl Signer,
48 message: &[u8],
49 ) -> Result<MlsMessageOut, CreateMessageError> {
50 let (_, output) =
51 self.create_message_internal::<_, CreateMessageError>(provider, signer, message)?;
52 Ok(output)
53 }
54
55 #[cfg(all(feature = "virtual-clients-draft", any(feature = "test-utils", test)))]
63 pub fn create_message<Provider: OpenMlsProvider>(
64 &mut self,
65 provider: &Provider,
66 signer: &impl Signer,
67 message: &[u8],
68 ) -> Result<MlsMessageOut, CreateMessageError<Provider::StorageError>> {
69 let (generation, _generation_id, output) =
70 self.create_message_internal(provider, signer, message)?;
71 self.confirm_message(provider.storage(), generation)?;
72 Ok(output)
73 }
74
75 #[cfg(not(feature = "virtual-clients-draft"))]
76 fn create_message_internal<Provider: OpenMlsProvider, E>(
77 &mut self,
78 provider: &Provider,
79 signer: &impl Signer,
80 message: &[u8],
81 ) -> Result<(u32, MlsMessageOut), E>
82 where
83 E: From<LibraryError> + From<MlsGroupStateError>,
84 {
85 if !self.is_active() {
86 return Err(MlsGroupStateError::UseAfterEviction.into());
87 }
88 if !self.proposal_store().is_empty() {
89 return Err(MlsGroupStateError::PendingProposal.into());
90 }
91
92 let aad = self.outgoing_authenticated_data()?;
93 let authenticated_content = AuthenticatedContent::new_application(
94 self.own_leaf_index(),
95 &aad,
96 message,
97 self.context(),
98 signer,
99 )?;
100 let EncryptionOutput {
101 generation,
102 private_message,
103 } = self
104 .encrypt(authenticated_content, provider)
105 .map_err(|_| LibraryError::custom("Malformed plaintext"))?;
107
108 let output = MlsMessageOut::from_private_message(private_message, self.version());
109 self.reset_aad();
110 Ok((generation, output))
111 }
112
113 #[cfg(feature = "virtual-clients-draft")]
114 fn create_message_internal<Provider: OpenMlsProvider>(
115 &mut self,
116 provider: &Provider,
117 signer: &impl Signer,
118 message: &[u8],
119 ) -> Result<
120 (
121 u32,
122 Option<crate::components::vc_derivation_info::GenerationId>,
123 MlsMessageOut,
124 ),
125 CreateMessageError<Provider::StorageError>,
126 > {
127 if !self.is_active() {
128 return Err(MlsGroupStateError::UseAfterEviction.into());
129 }
130 if !self.proposal_store().is_empty() {
131 return Err(MlsGroupStateError::PendingProposal.into());
132 }
133
134 let aad = self.outgoing_authenticated_data()?;
135 let authenticated_content = AuthenticatedContent::new_application(
136 self.own_leaf_index(),
137 &aad,
138 message,
139 self.context(),
140 signer,
141 )?;
142 let EncryptionOutput {
143 generation,
144 private_message,
145 generation_id,
146 } = self.encrypt(authenticated_content, provider)?;
147
148 let output = MlsMessageOut::from_private_message(private_message, self.version());
149 self.reset_aad();
150 Ok((generation, generation_id, output))
151 }
152
153 #[cfg(feature = "virtual-clients-draft")]
174 pub fn create_unconfirmed_message<Provider: OpenMlsProvider>(
175 &mut self,
176 provider: &Provider,
177 signer: &impl Signer,
178 message: &[u8],
179 ) -> Result<UnconfirmedMessage, CreateMessageError<Provider::StorageError>> {
180 let (generation, generation_id, message) =
181 self.create_message_internal(provider, signer, message)?;
182 Ok(UnconfirmedMessage {
183 message,
184 generation,
185 generation_id,
186 })
187 }
188
189 #[cfg(feature = "virtual-clients-draft")]
192 pub fn confirm_message<Storage: StorageProvider>(
193 &mut self,
194 storage: &Storage,
195 generation: u32,
196 ) -> Result<(), ConfirmMessageError<Storage::Error>> {
197 let secret_type = SecretType::ApplicationSecret;
199 self.message_secrets_store
200 .message_secrets_mut()
201 .secret_tree_mut()
202 .delete_own_secret_for_generation(secret_type, generation)?;
203 storage
204 .write_message_secrets(self.group_id(), &self.message_secrets_store)
205 .map_err(ConfirmMessageError::StorageError)?;
206 Ok(())
207 }
208}