core_crypto_ffi/core_crypto_context/
e2ei.rs

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