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::root("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::root("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::root("creating proteus session from prekey"))?;
37        ProteusCentral::session_save_by_ref(&inner.transaction, session)
38            .await
39            .map_err(RecursiveError::root("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::root("creating proteus sesseion from message"))?;
55        ProteusCentral::session_save_by_ref(&inner.transaction, session)
56            .await
57            .map_err(RecursiveError::root("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::root("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::root("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::root("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::root("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::root("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::root("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    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
159    /// will be returned
160    pub async fn proteus_new_prekey(&self, prekey_id: u16) -> Result<Vec<u8>> {
161        let inner = self.inner().await?;
162        let mut guard = inner.core_crypto.proteus.lock().await;
163        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
164        proteus
165            .new_prekey(prekey_id, &inner.transaction)
166            .await
167            .map_err(RecursiveError::root("new proteus prekey"))
168            .map_err(Into::into)
169    }
170
171    /// Creates a new Proteus prekey with an automatically incremented ID and returns the CBOR-serialized version of the
172    /// prekey bundle
173    ///
174    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
175    /// will be returned
176    pub async fn proteus_new_prekey_auto(&self) -> Result<(u16, Vec<u8>)> {
177        let inner = self.inner().await?;
178        let mut guard = inner.core_crypto.proteus.lock().await;
179        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
180        proteus
181            .new_prekey_auto(&inner.transaction)
182            .await
183            .map_err(RecursiveError::root("proteus new prekey auto"))
184            .map_err(Into::into)
185    }
186
187    /// Returns the last resort prekey
188    pub async fn proteus_last_resort_prekey(&self) -> Result<Vec<u8>> {
189        let inner = self.inner().await?;
190        let mut guard = inner.core_crypto.proteus.lock().await;
191        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
192
193        proteus
194            .last_resort_prekey(&inner.transaction)
195            .await
196            .map_err(RecursiveError::root("getting proteus last resort prekey"))
197            .map_err(Into::into)
198    }
199
200    /// Returns the proteus last resort prekey id (u16::MAX = 65535)
201    pub fn proteus_last_resort_prekey_id() -> u16 {
202        ProteusCentral::last_resort_prekey_id()
203    }
204
205    /// Returns the proteus identity's public key fingerprint
206    ///
207    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
208    /// will be returned
209    pub async fn proteus_fingerprint(&self) -> Result<String> {
210        let inner = self.inner().await?;
211        let mut guard = inner.core_crypto.proteus.lock().await;
212        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
213        Ok(proteus.fingerprint())
214    }
215
216    /// Returns the proteus identity's public key fingerprint
217    ///
218    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
219    /// will be returned
220    pub async fn proteus_fingerprint_local(&self, session_id: &str) -> Result<String> {
221        let inner = self.inner().await?;
222        let mut guard = inner.core_crypto.proteus.lock().await;
223        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
224        proteus
225            .fingerprint_local(session_id, &inner.transaction)
226            .await
227            .map_err(RecursiveError::root("getting proteus fingerprint local"))
228            .map_err(Into::into)
229    }
230
231    /// Returns the proteus identity's public key fingerprint
232    ///
233    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
234    /// will be returned
235    pub async fn proteus_fingerprint_remote(&self, session_id: &str) -> Result<String> {
236        let inner = self.inner().await?;
237        let mut guard = inner.core_crypto.proteus.lock().await;
238        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
239        proteus
240            .fingerprint_remote(session_id, &inner.transaction)
241            .await
242            .map_err(RecursiveError::root("geeting proteus fingerprint remote"))
243            .map_err(Into::into)
244    }
245}