Skip to main content

core_crypto/transaction_context/
proteus.rs

1//! This module contains all [super::TransactionContext] methods concerning proteus.
2
3use super::{Error, Result, TransactionContext};
4use crate::{RecursiveError, proteus::ProteusCentral};
5
6impl TransactionContext {
7    /// Initializes the proteus client
8    pub async fn proteus_init(&self) -> Result<()> {
9        let inner = self.inner().await?;
10        let proteus_client = ProteusCentral::try_new(&inner.transaction)
11            .await
12            .map_err(RecursiveError::context("creating new proteus client"))?;
13
14        // ? Make sure the last resort prekey exists
15        let _ = proteus_client
16            .last_resort_prekey(&inner.transaction)
17            .await
18            .map_err(RecursiveError::context("getting last resort prekey"))?;
19
20        let mut guard = inner.core_crypto.proteus.lock().await;
21        *guard = Some(proteus_client);
22        Ok(())
23    }
24
25    /// Creates a proteus session from a prekey
26    ///
27    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
28    /// will be returned
29    pub async fn proteus_session_from_prekey(&self, session_id: &str, prekey: &[u8]) -> Result<()> {
30        let inner = self.inner().await?;
31        let mut guard = inner.core_crypto.proteus.lock().await;
32        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
33        let session = proteus
34            .session_from_prekey(session_id, prekey)
35            .await
36            .map_err(RecursiveError::context("creating proteus session from prekey"))?;
37        ProteusCentral::session_save_by_ref(&inner.transaction, session)
38            .await
39            .map_err(RecursiveError::context("saving proteus session by ref"))?;
40        Ok(())
41    }
42
43    /// Creates a proteus session from a Proteus message envelope, returning the decrypted payload
44    ///
45    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
46    /// will be returned
47    pub async fn proteus_session_from_message(&self, session_id: &str, envelope: &[u8]) -> Result<Vec<u8>> {
48        let inner = self.inner().await?;
49        let mut guard = inner.core_crypto.proteus.lock().await;
50        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
51        let (session, message) = proteus
52            .session_from_message(&inner.transaction, session_id, envelope)
53            .await
54            .map_err(RecursiveError::context("creating proteus sesseion from message"))?;
55        ProteusCentral::session_save_by_ref(&inner.transaction, session)
56            .await
57            .map_err(RecursiveError::context("saving proteus session by ref"))?;
58        Ok(message)
59    }
60
61    /// Saves a proteus session in the keystore
62    ///
63    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
64    /// will be returned
65    pub async fn proteus_session_save(&self, session_id: &str) -> Result<()> {
66        let inner = self.inner().await?;
67        let mut guard = inner.core_crypto.proteus.lock().await;
68        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
69        proteus
70            .session_save(&inner.transaction, session_id)
71            .await
72            .map_err(RecursiveError::context("saving proteus session"))
73            .map_err(Into::into)
74    }
75
76    /// Deletes a proteus session from the keystore
77    ///
78    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
79    /// will be returned
80    pub async fn proteus_session_delete(&self, session_id: &str) -> Result<()> {
81        let inner = self.inner().await?;
82        let mut guard = inner.core_crypto.proteus.lock().await;
83        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
84        proteus
85            .session_delete(&inner.transaction, session_id)
86            .await
87            .map_err(RecursiveError::context("deleting proteus session"))
88            .map_err(Into::into)
89    }
90
91    /// Proteus session exists
92    ///
93    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
94    /// will be returned
95    pub async fn proteus_session_exists(&self, session_id: &str) -> Result<bool> {
96        let inner = self.inner().await?;
97        let mut guard = inner.core_crypto.proteus.lock().await;
98        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
99        proteus
100            .session_exists(session_id, &inner.transaction)
101            .await
102            .map_err(RecursiveError::context("checking whether proteus session exists"))
103            .map_err(Into::into)
104    }
105
106    /// Decrypts a proteus message envelope
107    ///
108    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
109    /// will be returned
110    pub async fn proteus_decrypt(&self, session_id: &str, ciphertext: &[u8]) -> Result<Vec<u8>> {
111        let inner = self.inner().await?;
112        let mut guard = inner.core_crypto.proteus.lock().await;
113        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
114        proteus
115            .decrypt(&inner.transaction, session_id, ciphertext)
116            .await
117            .map_err(RecursiveError::context("decrypting proteus message"))
118            .map_err(Into::into)
119    }
120
121    /// Encrypts proteus message for a given session ID
122    ///
123    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
124    /// will be returned
125    pub async fn proteus_encrypt(&self, session_id: &str, plaintext: &[u8]) -> Result<Vec<u8>> {
126        let inner = self.inner().await?;
127        let mut guard = inner.core_crypto.proteus.lock().await;
128        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
129        proteus
130            .encrypt(&inner.transaction, session_id, plaintext)
131            .await
132            .map_err(RecursiveError::context("encrypting proteus message"))
133            .map_err(Into::into)
134    }
135
136    /// Encrypts a proteus message for several sessions ID. This is more efficient than other methods as the calls are
137    /// batched. This also reduces the rountrips when crossing over the FFI
138    ///
139    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
140    /// will be returned
141    pub async fn proteus_encrypt_batched(
142        &self,
143        sessions: &[impl AsRef<str>],
144        plaintext: &[u8],
145    ) -> Result<std::collections::HashMap<String, Vec<u8>>> {
146        let inner = self.inner().await?;
147        let mut guard = inner.core_crypto.proteus.lock().await;
148        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
149        proteus
150            .encrypt_batched(&inner.transaction, sessions, plaintext)
151            .await
152            .map_err(RecursiveError::context("batch encrypting proteus message"))
153            .map_err(Into::into)
154    }
155
156    /// Creates a new Proteus prekey and returns the CBOR-serialized version of the prekey bundle
157    ///
158    /// Fails if `prekey_id` is already in use. Prekeys are reusable but not replaceable: the id has been
159    /// published to peers in a bundle, and overwriting it would strand anyone still holding that
160    /// bundle. Use [Self::proteus_new_prekey_auto] to have a free id chosen instead.
161    ///
162    /// To free a prekey which has been claimed, delete the old prekey for that ID before inserting a new one.
163    ///
164    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
165    /// will be returned
166    pub async fn proteus_new_prekey(&self, prekey_id: u16) -> Result<Vec<u8>> {
167        let inner = self.inner().await?;
168        let mut guard = inner.core_crypto.proteus.lock().await;
169        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
170        proteus
171            .new_prekey(prekey_id, &inner.transaction)
172            .await
173            .map_err(RecursiveError::context("new proteus prekey"))
174            .map_err(Into::into)
175    }
176
177    /// Creates a new Proteus prekey with an automatically incremented ID and returns the CBOR-serialized version of the
178    /// prekey bundle
179    ///
180    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
181    /// will be returned
182    pub async fn proteus_new_prekey_auto(&self) -> Result<(u16, Vec<u8>)> {
183        let inner = self.inner().await?;
184        let mut guard = inner.core_crypto.proteus.lock().await;
185        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
186        proteus
187            .new_prekey_auto(&inner.transaction)
188            .await
189            .map_err(RecursiveError::context("proteus new prekey auto"))
190            .map_err(Into::into)
191    }
192
193    /// Returns the last resort prekey
194    pub async fn proteus_last_resort_prekey(&self) -> Result<Vec<u8>> {
195        let inner = self.inner().await?;
196        let mut guard = inner.core_crypto.proteus.lock().await;
197        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
198
199        proteus
200            .last_resort_prekey(&inner.transaction)
201            .await
202            .map_err(RecursiveError::context("getting proteus last resort prekey"))
203            .map_err(Into::into)
204    }
205
206    /// Returns the proteus last resort prekey id (u16::MAX = 65535)
207    pub fn proteus_last_resort_prekey_id() -> u16 {
208        ProteusCentral::last_resort_prekey_id()
209    }
210
211    /// Returns the proteus identity's public key fingerprint
212    ///
213    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
214    /// will be returned
215    pub async fn proteus_fingerprint(&self) -> Result<String> {
216        let inner = self.inner().await?;
217        let mut guard = inner.core_crypto.proteus.lock().await;
218        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
219        Ok(proteus.fingerprint())
220    }
221
222    /// Returns the proteus identity's public key fingerprint
223    ///
224    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
225    /// will be returned
226    pub async fn proteus_fingerprint_local(&self, session_id: &str) -> Result<String> {
227        let inner = self.inner().await?;
228        let mut guard = inner.core_crypto.proteus.lock().await;
229        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
230        proteus
231            .fingerprint_local(session_id, &inner.transaction)
232            .await
233            .map_err(RecursiveError::context("getting proteus fingerprint local"))
234            .map_err(Into::into)
235    }
236
237    /// Returns the proteus identity's public key fingerprint
238    ///
239    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
240    /// will be returned
241    pub async fn proteus_fingerprint_remote(&self, session_id: &str) -> Result<String> {
242        let inner = self.inner().await?;
243        let mut guard = inner.core_crypto.proteus.lock().await;
244        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
245        proteus
246            .fingerprint_remote(session_id, &inner.transaction)
247            .await
248            .map_err(RecursiveError::context("geeting proteus fingerprint remote"))
249            .map_err(Into::into)
250    }
251}