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