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        Ok(proteus.session_exists(session_id, &inner.transaction).await)
100    }
101
102    /// Decrypts a proteus message envelope
103    ///
104    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
105    /// will be returned
106    pub async fn proteus_decrypt(&self, session_id: &str, ciphertext: &[u8]) -> Result<Vec<u8>> {
107        let inner = self.inner().await?;
108        let mut guard = inner.core_crypto.proteus.lock().await;
109        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
110        proteus
111            .decrypt(&inner.transaction, session_id, ciphertext)
112            .await
113            .map_err(RecursiveError::root("decrypting proteus message"))
114            .map_err(Into::into)
115    }
116
117    /// Encrypts proteus message for a given session ID
118    ///
119    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
120    /// will be returned
121    pub async fn proteus_encrypt(&self, session_id: &str, plaintext: &[u8]) -> Result<Vec<u8>> {
122        let inner = self.inner().await?;
123        let mut guard = inner.core_crypto.proteus.lock().await;
124        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
125        proteus
126            .encrypt(&inner.transaction, session_id, plaintext)
127            .await
128            .map_err(RecursiveError::root("encrypting proteus message"))
129            .map_err(Into::into)
130    }
131
132    /// Encrypts a proteus message for several sessions ID. This is more efficient than other methods as the calls are
133    /// batched. This also reduces the rountrips when crossing over the FFI
134    ///
135    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
136    /// will be returned
137    pub async fn proteus_encrypt_batched(
138        &self,
139        sessions: &[impl AsRef<str>],
140        plaintext: &[u8],
141    ) -> Result<std::collections::HashMap<String, Vec<u8>>> {
142        let inner = self.inner().await?;
143        let mut guard = inner.core_crypto.proteus.lock().await;
144        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
145        proteus
146            .encrypt_batched(&inner.transaction, sessions, plaintext)
147            .await
148            .map_err(RecursiveError::root("batch encrypting proteus message"))
149            .map_err(Into::into)
150    }
151
152    /// Creates a new Proteus prekey and returns the CBOR-serialized version of the prekey bundle
153    ///
154    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
155    /// will be returned
156    pub async fn proteus_new_prekey(&self, prekey_id: u16) -> Result<Vec<u8>> {
157        let inner = self.inner().await?;
158        let mut guard = inner.core_crypto.proteus.lock().await;
159        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
160        proteus
161            .new_prekey(prekey_id, &inner.transaction)
162            .await
163            .map_err(RecursiveError::root("new proteus prekey"))
164            .map_err(Into::into)
165    }
166
167    /// Creates a new Proteus prekey with an automatically incremented ID and returns the CBOR-serialized version of the
168    /// prekey bundle
169    ///
170    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
171    /// will be returned
172    pub async fn proteus_new_prekey_auto(&self) -> Result<(u16, Vec<u8>)> {
173        let inner = self.inner().await?;
174        let mut guard = inner.core_crypto.proteus.lock().await;
175        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
176        proteus
177            .new_prekey_auto(&inner.transaction)
178            .await
179            .map_err(RecursiveError::root("proteus new prekey auto"))
180            .map_err(Into::into)
181    }
182
183    /// Returns the last resort prekey
184    pub async fn proteus_last_resort_prekey(&self) -> Result<Vec<u8>> {
185        let inner = self.inner().await?;
186        let mut guard = inner.core_crypto.proteus.lock().await;
187        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
188
189        proteus
190            .last_resort_prekey(&inner.transaction)
191            .await
192            .map_err(RecursiveError::root("getting proteus last resort prekey"))
193            .map_err(Into::into)
194    }
195
196    /// Returns the proteus last resort prekey id (u16::MAX = 65535)
197    pub fn proteus_last_resort_prekey_id() -> u16 {
198        ProteusCentral::last_resort_prekey_id()
199    }
200
201    /// Returns the proteus identity's public key fingerprint
202    ///
203    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
204    /// will be returned
205    pub async fn proteus_fingerprint(&self) -> Result<String> {
206        let inner = self.inner().await?;
207        let mut guard = inner.core_crypto.proteus.lock().await;
208        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
209        Ok(proteus.fingerprint())
210    }
211
212    /// Returns the proteus identity's public key fingerprint
213    ///
214    /// Warning: The Proteus client **MUST** be initialized with [TransactionContext::proteus_init] first or an error
215    /// will be returned
216    pub async fn proteus_fingerprint_local(&self, session_id: &str) -> Result<String> {
217        let inner = self.inner().await?;
218        let mut guard = inner.core_crypto.proteus.lock().await;
219        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
220        proteus
221            .fingerprint_local(session_id, &inner.transaction)
222            .await
223            .map_err(RecursiveError::root("getting proteus fingerprint local"))
224            .map_err(Into::into)
225    }
226
227    /// Returns the proteus identity's public key fingerprint
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_fingerprint_remote(&self, session_id: &str) -> Result<String> {
232        let inner = self.inner().await?;
233        let mut guard = inner.core_crypto.proteus.lock().await;
234        let proteus = guard.as_mut().ok_or(Error::ProteusNotInitialized)?;
235        proteus
236            .fingerprint_remote(session_id, &inner.transaction)
237            .await
238            .map_err(RecursiveError::root("geeting proteus fingerprint remote"))
239            .map_err(Into::into)
240    }
241}