core_crypto_ffi/core_crypto_context/
e2ei.rs1use 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 #[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 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 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}