core_crypto_ffi/generic/context/
e2ei.rs

1use std::{collections::HashMap, ops::DerefMut};
2
3use crate::{
4    CoreCryptoError, NewCrlDistributionPoints,
5    generic::{
6        Ciphersuite, ClientId, CoreCryptoResult, CrlRegistration, E2eiConversationState, E2eiDumpedPkiEnv,
7        E2eiEnrollment, MlsCredentialType, WireIdentity, context::CoreCryptoContext,
8    },
9};
10use core_crypto::mls::conversation::Conversation as _;
11use core_crypto::{RecursiveError, prelude::VerifiableGroupInfo};
12use tls_codec::Deserialize;
13
14#[uniffi::export]
15impl CoreCryptoContext {
16    /// See [core_crypto::context::CentralContext::e2ei_new_enrollment]
17    pub async fn e2ei_new_enrollment(
18        &self,
19        client_id: String,
20        display_name: String,
21        handle: String,
22        team: Option<String>,
23        expiry_sec: u32,
24        ciphersuite: Ciphersuite,
25    ) -> CoreCryptoResult<E2eiEnrollment> {
26        self.context
27            .e2ei_new_enrollment(
28                client_id.into_bytes().into(),
29                display_name,
30                handle,
31                team,
32                expiry_sec,
33                ciphersuite.into(),
34            )
35            .await
36            .map(async_lock::RwLock::new)
37            .map(std::sync::Arc::new)
38            .map(E2eiEnrollment)
39            .map_err(Into::into)
40    }
41
42    /// See [core_crypto::context::CentralContext::e2ei_new_activation_enrollment]
43    pub async fn e2ei_new_activation_enrollment(
44        &self,
45        display_name: String,
46        handle: String,
47        team: Option<String>,
48        expiry_sec: u32,
49        ciphersuite: Ciphersuite,
50    ) -> CoreCryptoResult<E2eiEnrollment> {
51        Ok(self
52            .context
53            .e2ei_new_activation_enrollment(display_name, handle, team, expiry_sec, ciphersuite.into())
54            .await
55            .map(async_lock::RwLock::new)
56            .map(std::sync::Arc::new)
57            .map(E2eiEnrollment)?)
58    }
59
60    /// See [core_crypto::context::CentralContext::e2ei_new_rotate_enrollment]
61    pub async fn e2ei_new_rotate_enrollment(
62        &self,
63        display_name: Option<String>,
64        handle: Option<String>,
65        team: Option<String>,
66        expiry_sec: u32,
67        ciphersuite: Ciphersuite,
68    ) -> CoreCryptoResult<E2eiEnrollment> {
69        Ok(self
70            .context
71            .e2ei_new_rotate_enrollment(display_name, handle, team, expiry_sec, ciphersuite.into())
72            .await
73            .map(async_lock::RwLock::new)
74            .map(std::sync::Arc::new)
75            .map(E2eiEnrollment)?)
76    }
77
78    /// See [core_crypto::context::CentralContext::e2ei_register_acme_ca]
79    pub async fn e2ei_register_acme_ca(&self, trust_anchor_pem: String) -> CoreCryptoResult<()> {
80        self.context.e2ei_register_acme_ca(trust_anchor_pem).await?;
81        Ok(())
82    }
83
84    /// See [core_crypto::context::CentralContext::e2ei_register_intermediate_ca_pem]
85    pub async fn e2ei_register_intermediate_ca(&self, cert_pem: String) -> CoreCryptoResult<NewCrlDistributionPoints> {
86        Ok(self
87            .context
88            .e2ei_register_intermediate_ca_pem(cert_pem)
89            .await
90            .map(|new_crl_distribution_point| -> Option<Vec<_>> { new_crl_distribution_point.into() })?
91            .into())
92    }
93
94    /// See [core_crypto::context::CentralContext::e2ei_register_crl]
95    pub async fn e2ei_register_crl(&self, crl_dp: String, crl_der: Vec<u8>) -> CoreCryptoResult<CrlRegistration> {
96        Ok(self.context.e2ei_register_crl(crl_dp, crl_der).await.map(Into::into)?)
97    }
98
99    /// See [core_crypto::context::CentralContext::e2ei_mls_init_only]
100    pub async fn e2ei_mls_init_only(
101        &self,
102        enrollment: std::sync::Arc<E2eiEnrollment>,
103        certificate_chain: String,
104        nb_key_package: Option<u32>,
105    ) -> CoreCryptoResult<NewCrlDistributionPoints> {
106        let nb_key_package = nb_key_package
107            .map(usize::try_from)
108            .transpose()
109            .map_err(CoreCryptoError::generic())?;
110
111        Ok(self
112            .context
113            .e2ei_mls_init_only(
114                enrollment.0.write().await.deref_mut(),
115                certificate_chain,
116                nb_key_package,
117            )
118            .await
119            .map(|new_crl_distribution_point| -> Option<Vec<_>> { new_crl_distribution_point.into() })?
120            .into())
121    }
122
123    /// See [core_crypto::mls::conversation::ConversationGuard::e2ei_rotate]
124    pub async fn e2ei_rotate(&self, conversation_id: Vec<u8>) -> CoreCryptoResult<()> {
125        Ok(self
126            .context
127            .conversation(&conversation_id)
128            .await?
129            .e2ei_rotate(None)
130            .await?)
131    }
132
133    /// See [core_crypto::context::CentralContext::save_x509_credential]
134    pub async fn save_x509_credential(
135        &self,
136        enrollment: std::sync::Arc<E2eiEnrollment>,
137        certificate_chain: String,
138    ) -> CoreCryptoResult<NewCrlDistributionPoints> {
139        Ok(self
140            .context
141            .save_x509_credential(enrollment.0.write().await.deref_mut(), certificate_chain)
142            .await
143            .map(|new_crl_distribution_point| -> Option<Vec<_>> { new_crl_distribution_point.into() })?
144            .into())
145    }
146
147    /// See [core_crypto::context::CentralContext::delete_stale_key_packages]
148    pub async fn delete_stale_key_packages(&self, ciphersuite: Ciphersuite) -> CoreCryptoResult<()> {
149        self.context
150            .delete_stale_key_packages(ciphersuite.into())
151            .await
152            .map_err(Into::into)
153    }
154
155    /// See [core_crypto::context::CentralContext::e2ei_enrollment_stash]
156    pub async fn e2ei_enrollment_stash(&self, enrollment: std::sync::Arc<E2eiEnrollment>) -> CoreCryptoResult<Vec<u8>> {
157        let enrollment = std::sync::Arc::into_inner(enrollment).ok_or_else(|| {
158            CoreCryptoError::Other("enrollment had multiple strong refs and could not be unpacked".into())
159        })?;
160        let enrollment = std::sync::Arc::into_inner(enrollment.0)
161            .ok_or_else(|| {
162                CoreCryptoError::Other("enrollment.0 had multiple strong refs and could not be unpacked".into())
163            })?
164            .into_inner();
165
166        Ok(self.context.e2ei_enrollment_stash(enrollment).await?)
167    }
168
169    /// See [core_crypto::context::CentralContext::e2ei_enrollment_stash_pop]
170    pub async fn e2ei_enrollment_stash_pop(&self, handle: Vec<u8>) -> CoreCryptoResult<E2eiEnrollment> {
171        Ok(self
172            .context
173            .e2ei_enrollment_stash_pop(handle)
174            .await
175            .map(async_lock::RwLock::new)
176            .map(std::sync::Arc::new)
177            .map(E2eiEnrollment)?)
178    }
179
180    /// See [core_crypto::mls::conversation::conversation_guard::ConversationGuard::e2ei_conversation_state]
181    pub async fn e2ei_conversation_state(&self, conversation_id: Vec<u8>) -> CoreCryptoResult<E2eiConversationState> {
182        Ok(self
183            .context
184            .conversation(&conversation_id)
185            .await?
186            .e2ei_conversation_state()
187            .await
188            .map(Into::into)?)
189    }
190
191    pub async fn e2ei_dump_pki_env(&self) -> CoreCryptoResult<Option<E2eiDumpedPkiEnv>> {
192        Ok(self.context.e2ei_dump_pki_env().await?.map(Into::into))
193    }
194
195    /// See [core_crypto::mls::MlsCentral::e2ei_is_pki_env_setup]
196    pub async fn e2ei_is_pki_env_setup(&self) -> CoreCryptoResult<bool> {
197        Ok(self.context.e2ei_is_pki_env_setup().await?)
198    }
199
200    /// See [core_crypto::mls::MlsCentral::e2ei_is_enabled]
201    pub async fn e2ei_is_enabled(&self, ciphersuite: Ciphersuite) -> CoreCryptoResult<bool> {
202        let sc = core_crypto::prelude::MlsCiphersuite::from(core_crypto::prelude::CiphersuiteName::from(ciphersuite))
203            .signature_algorithm();
204        Ok(self.context.e2ei_is_enabled(sc).await?)
205    }
206
207    /// See [core_crypto::mls::MlsCentral::get_device_identities]
208    pub async fn get_device_identities(
209        &self,
210        conversation_id: Vec<u8>,
211        device_ids: Vec<ClientId>,
212    ) -> CoreCryptoResult<Vec<WireIdentity>> {
213        let device_ids = device_ids.into_iter().map(|cid| cid.0).collect::<Vec<_>>();
214        Ok(self
215            .context
216            .conversation(&conversation_id)
217            .await?
218            .get_device_identities(&device_ids[..])
219            .await?
220            .into_iter()
221            .map(Into::into)
222            .collect::<Vec<_>>())
223    }
224
225    /// See [core_crypto::mls::MlsCentral::get_user_identities]
226    pub async fn get_user_identities(
227        &self,
228        conversation_id: Vec<u8>,
229        user_ids: Vec<String>,
230    ) -> CoreCryptoResult<HashMap<String, Vec<WireIdentity>>> {
231        Ok(self
232            .context
233            .conversation(&conversation_id)
234            .await?
235            .get_user_identities(&user_ids[..])
236            .await?
237            .into_iter()
238            .map(|(k, v)| (k, v.into_iter().map(Into::into).collect()))
239            .collect::<HashMap<String, Vec<WireIdentity>>>())
240    }
241
242    /// See [core_crypto::mls::MlsCentral::get_credential_in_use]
243    pub async fn get_credential_in_use(
244        &self,
245        group_info: Vec<u8>,
246        credential_type: MlsCredentialType,
247    ) -> CoreCryptoResult<E2eiConversationState> {
248        let group_info = VerifiableGroupInfo::tls_deserialize(&mut group_info.as_slice())
249            .map_err(core_crypto::mls::conversation::Error::tls_deserialize(
250                "verifiable group info",
251            ))
252            .map_err(RecursiveError::mls_conversation("getting credential in use"))?;
253        Ok(self
254            .context
255            .get_credential_in_use(group_info, credential_type.into())
256            .await?
257            .into())
258    }
259}