core_crypto_ffi/generic/context/
e2ei.rs1use 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pub async fn e2ei_is_pki_env_setup(&self) -> CoreCryptoResult<bool> {
197 Ok(self.context.e2ei_is_pki_env_setup().await?)
198 }
199
200 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 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 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 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}