core_crypto/transaction_context/
proteus.rs

1//! This module contains all [super::TransactionContext] methods concerning proteus.
2
3use super::{Error, Result, TransactionContext};
4use crate::{
5    RecursiveError,
6    group_store::GroupStoreValue,
7    proteus::{ProteusCentral, ProteusConversationSession},
8};
9
10impl TransactionContext {
11    /// Initializes the proteus client
12    pub async fn proteus_init(&self) -> Result<()> {
13        let keystore = self.keystore().await?;
14        let proteus_client = ProteusCentral::try_new(&keystore)
15            .await
16            .map_err(RecursiveError::root("creating new proteus client"))?;
17
18        // ? Make sure the last resort prekey exists
19        let _ = proteus_client
20            .last_resort_prekey(&keystore)
21            .await
22            .map_err(RecursiveError::root("getting last resort prekey"))?;
23
24        let mutex = self.proteus_central().await?;
25        let mut guard = mutex.lock().await;
26        *guard = Some(proteus_client);
27        Ok(())
28    }
29
30    /// Reloads the sessions from the key store
31    ///
32    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or it will do
33    /// nothing
34    pub async fn proteus_reload_sessions(&self) -> Result<()> {
35        let arc = self.proteus_central().await?;
36        let mut mutex = arc.lock().await;
37        let Some(proteus) = mutex.as_mut() else { return Ok(()) };
38        let keystore = self.keystore().await?;
39        proteus
40            .reload_sessions(&keystore)
41            .await
42            .map_err(RecursiveError::root("reloading proteus session"))
43            .map_err(Into::into)
44    }
45
46    /// Creates a proteus session from a prekey
47    ///
48    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
49    /// will be returned
50    pub async fn proteus_session_from_prekey(
51        &self,
52        session_id: &str,
53        prekey: &[u8],
54    ) -> Result<GroupStoreValue<ProteusConversationSession>> {
55        let arc = self.proteus_central().await?;
56        let mut mutex = arc.lock().await;
57        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
58        let keystore = self.keystore().await?;
59        let session = proteus
60            .session_from_prekey(session_id, prekey)
61            .await
62            .map_err(RecursiveError::root("creating proteus session from prekey"))?;
63        ProteusCentral::session_save_by_ref(&keystore, session.clone())
64            .await
65            .map_err(RecursiveError::root("saving proteus session by ref"))?;
66
67        Ok(session)
68    }
69
70    /// Creates a proteus session from a Proteus message envelope
71    ///
72    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
73    /// will be returned
74    pub async fn proteus_session_from_message(
75        &self,
76        session_id: &str,
77        envelope: &[u8],
78    ) -> Result<(GroupStoreValue<ProteusConversationSession>, Vec<u8>)> {
79        let arc = self.proteus_central().await?;
80        let mut mutex = arc.lock().await;
81        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
82        let mut keystore = self.keystore().await?;
83        let (session, message) = proteus
84            .session_from_message(&mut keystore, session_id, envelope)
85            .await
86            .map_err(RecursiveError::root("creating proteus sesseion from message"))?;
87        ProteusCentral::session_save_by_ref(&keystore, session.clone())
88            .await
89            .map_err(RecursiveError::root("saving proteus session by ref"))?;
90
91        Ok((session, message))
92    }
93
94    /// Saves a proteus session in the keystore
95    ///
96    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
97    /// will be returned
98    pub async fn proteus_session_save(&self, session_id: &str) -> Result<()> {
99        let arc = self.proteus_central().await?;
100        let mut mutex = arc.lock().await;
101        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
102        let keystore = self.keystore().await?;
103        proteus
104            .session_save(&keystore, session_id)
105            .await
106            .map_err(RecursiveError::root("saving proteus session"))
107            .map_err(Into::into)
108    }
109
110    /// Deletes a proteus session from the keystore
111    ///
112    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
113    /// will be returned
114    pub async fn proteus_session_delete(&self, session_id: &str) -> Result<()> {
115        let arc = self.proteus_central().await?;
116        let mut mutex = arc.lock().await;
117        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
118        let keystore = self.keystore().await?;
119        proteus
120            .session_delete(&keystore, session_id)
121            .await
122            .map_err(RecursiveError::root("deleting proteus session"))
123            .map_err(Into::into)
124    }
125
126    /// Proteus session accessor
127    ///
128    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
129    /// will be returned
130    pub async fn proteus_session(
131        &self,
132        session_id: &str,
133    ) -> Result<Option<GroupStoreValue<ProteusConversationSession>>> {
134        let arc = self.proteus_central().await?;
135        let mut mutex = arc.lock().await;
136        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
137        let keystore = self.keystore().await?;
138        proteus
139            .session(session_id, &keystore)
140            .await
141            .map_err(RecursiveError::root("getting proteus session"))
142            .map_err(Into::into)
143    }
144
145    /// Proteus session exists
146    ///
147    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
148    /// will be returned
149    pub async fn proteus_session_exists(&self, session_id: &str) -> Result<bool> {
150        let arc = self.proteus_central().await?;
151        let mut mutex = arc.lock().await;
152        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
153        let keystore = self.keystore().await?;
154        Ok(proteus.session_exists(session_id, &keystore).await)
155    }
156
157    /// Decrypts a proteus message envelope
158    ///
159    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
160    /// will be returned
161    pub async fn proteus_decrypt(&self, session_id: &str, ciphertext: &[u8]) -> Result<Vec<u8>> {
162        let arc = self.proteus_central().await?;
163        let mut mutex = arc.lock().await;
164        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
165        let mut keystore = self.keystore().await?;
166        proteus
167            .decrypt(&mut keystore, session_id, ciphertext)
168            .await
169            .map_err(RecursiveError::root("decrypting proteus message"))
170            .map_err(Into::into)
171    }
172
173    /// Encrypts proteus message for a given session ID
174    ///
175    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
176    /// will be returned
177    pub async fn proteus_encrypt(&self, session_id: &str, plaintext: &[u8]) -> Result<Vec<u8>> {
178        let arc = self.proteus_central().await?;
179        let mut mutex = arc.lock().await;
180        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
181        let mut keystore = self.keystore().await?;
182        proteus
183            .encrypt(&mut keystore, session_id, plaintext)
184            .await
185            .map_err(RecursiveError::root("encrypting proteus message"))
186            .map_err(Into::into)
187    }
188
189    /// Encrypts a proteus message for several sessions ID. This is more efficient than other methods as the calls are
190    /// batched. This also reduces the rountrips when crossing over the FFI
191    ///
192    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
193    /// will be returned
194    pub async fn proteus_encrypt_batched(
195        &self,
196        sessions: &[impl AsRef<str>],
197        plaintext: &[u8],
198    ) -> Result<std::collections::HashMap<String, Vec<u8>>> {
199        let arc = self.proteus_central().await?;
200        let mut mutex = arc.lock().await;
201        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
202        let mut keystore = self.keystore().await?;
203        proteus
204            .encrypt_batched(&mut keystore, sessions, plaintext)
205            .await
206            .map_err(RecursiveError::root("batch encrypting proteus message"))
207            .map_err(Into::into)
208    }
209
210    /// Creates a new Proteus prekey and returns the CBOR-serialized version of the prekey bundle
211    ///
212    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
213    /// will be returned
214    pub async fn proteus_new_prekey(&self, prekey_id: u16) -> Result<Vec<u8>> {
215        let arc = self.proteus_central().await?;
216        let mut mutex = arc.lock().await;
217        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
218        let keystore = self.keystore().await?;
219        proteus
220            .new_prekey(prekey_id, &keystore)
221            .await
222            .map_err(RecursiveError::root("new proteus prekey"))
223            .map_err(Into::into)
224    }
225
226    /// Creates a new Proteus prekey with an automatically incremented ID and returns the CBOR-serialized version of the
227    /// prekey bundle
228    ///
229    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
230    /// will be returned
231    pub async fn proteus_new_prekey_auto(&self) -> Result<(u16, Vec<u8>)> {
232        let arc = self.proteus_central().await?;
233        let mut mutex = arc.lock().await;
234        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
235        let keystore = self.keystore().await?;
236        proteus
237            .new_prekey_auto(&keystore)
238            .await
239            .map_err(RecursiveError::root("proteus new prekey auto"))
240            .map_err(Into::into)
241    }
242
243    /// Returns the last resort prekey
244    pub async fn proteus_last_resort_prekey(&self) -> Result<Vec<u8>> {
245        let arc = self.proteus_central().await?;
246        let mut mutex = arc.lock().await;
247        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
248        let keystore = self.keystore().await?;
249
250        proteus
251            .last_resort_prekey(&keystore)
252            .await
253            .map_err(RecursiveError::root("getting proteus last resort prekey"))
254            .map_err(Into::into)
255    }
256
257    /// Returns the proteus last resort prekey id (u16::MAX = 65535)
258    pub fn proteus_last_resort_prekey_id() -> u16 {
259        ProteusCentral::last_resort_prekey_id()
260    }
261
262    /// Returns the proteus identity's public key fingerprint
263    ///
264    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
265    /// will be returned
266    pub async fn proteus_fingerprint(&self) -> Result<String> {
267        let arc = self.proteus_central().await?;
268        let mut mutex = arc.lock().await;
269        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
270        Ok(proteus.fingerprint())
271    }
272
273    /// Returns the proteus identity's public key fingerprint
274    ///
275    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
276    /// will be returned
277    pub async fn proteus_fingerprint_local(&self, session_id: &str) -> Result<String> {
278        let arc = self.proteus_central().await?;
279        let mut mutex = arc.lock().await;
280        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
281        let keystore = self.keystore().await?;
282        proteus
283            .fingerprint_local(session_id, &keystore)
284            .await
285            .map_err(RecursiveError::root("getting proteus fingerprint local"))
286            .map_err(Into::into)
287    }
288
289    /// Returns the proteus identity's public key fingerprint
290    ///
291    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
292    /// will be returned
293    pub async fn proteus_fingerprint_remote(&self, session_id: &str) -> Result<String> {
294        let arc = self.proteus_central().await?;
295        let mut mutex = arc.lock().await;
296        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
297        let keystore = self.keystore().await?;
298        proteus
299            .fingerprint_remote(session_id, &keystore)
300            .await
301            .map_err(RecursiveError::root("geeting proteus fingerprint remote"))
302            .map_err(Into::into)
303    }
304}