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