core_crypto/transaction_context/e2e_identity/
init_certificates.rs1use super::{Error, Result};
2use crate::e2e_identity::E2eiDumpedPkiEnv;
3use crate::{
4 KeystoreError, MlsError, RecursiveError,
5 e2e_identity::{CrlRegistration, NewCrlDistributionPoints, restore_pki_env},
6 transaction_context::TransactionContext,
7};
8use core_crypto_keystore::{
9 connection::FetchFromDatabase,
10 entities::{E2eiAcmeCA, E2eiCrl, E2eiIntermediateCert},
11};
12use openmls_traits::OpenMlsCryptoProvider;
13use wire_e2e_identity::prelude::x509::{
14 extract_crl_uris, extract_expiration_from_crl,
15 revocation::{PkiEnvironment, PkiEnvironmentParams},
16};
17use x509_cert::der::Decode;
18
19impl TransactionContext {
20 pub async fn e2ei_is_pki_env_setup(&self) -> Result<bool> {
22 Ok(self
23 .mls_provider()
24 .await
25 .map_err(RecursiveError::transaction("getting mls provider"))?
26 .authentication_service()
27 .is_env_setup()
28 .await)
29 }
30
31 pub async fn e2ei_dump_pki_env(&self) -> Result<Option<E2eiDumpedPkiEnv>> {
33 if !self.e2ei_is_pki_env_setup().await? {
34 return Ok(None);
35 }
36 let mls_provider = self
37 .mls_provider()
38 .await
39 .map_err(RecursiveError::transaction("getting mls provider"))?;
40 let Some(pki_env) = &*mls_provider.authentication_service().borrow().await else {
41 return Ok(None);
42 };
43 E2eiDumpedPkiEnv::from_pki_env(pki_env)
44 .await
45 .map_err(RecursiveError::e2e_identity("dumping pki env"))
46 .map_err(Into::into)
47 }
48
49 pub async fn e2ei_register_acme_ca(&self, trust_anchor_pem: String) -> Result<()> {
57 {
58 if self
59 .mls_provider()
60 .await
61 .map_err(RecursiveError::transaction("getting mls provider"))?
62 .keystore()
63 .find_unique::<E2eiAcmeCA>()
64 .await
65 .is_ok()
66 {
67 return Err(Error::TrustAnchorAlreadyRegistered);
68 }
69 }
70
71 let pki_env = PkiEnvironment::init(PkiEnvironmentParams {
72 intermediates: Default::default(),
73 trust_roots: Default::default(),
74 crls: Default::default(),
75 time_of_interest: Default::default(),
76 })?;
77
78 let root_cert = PkiEnvironment::decode_pem_cert(trust_anchor_pem)?;
80
81 pki_env.validate_trust_anchor_cert(&root_cert)?;
83
84 let cert_der = PkiEnvironment::encode_cert_to_der(&root_cert)?;
86 let acme_ca = E2eiAcmeCA { content: cert_der };
87 self.mls_provider()
88 .await
89 .map_err(RecursiveError::transaction("getting mls provider"))?
90 .keystore()
91 .save(acme_ca)
92 .await
93 .map_err(KeystoreError::wrap("saving acme ca"))?;
94
95 self.init_pki_env().await?;
97
98 Ok(())
99 }
100
101 pub(crate) async fn init_pki_env(&self) -> Result<()> {
102 if let Some(pki_env) = restore_pki_env(
103 &self
104 .mls_provider()
105 .await
106 .map_err(RecursiveError::transaction("getting mls provider"))?
107 .keystore(),
108 )
109 .await
110 .map_err(RecursiveError::e2e_identity("restoring pki env"))?
111 {
112 let provider = self
113 .mls_provider()
114 .await
115 .map_err(RecursiveError::transaction("getting mls provider"))?;
116 provider
117 .authentication_service()
118 .update_env(pki_env)
119 .await
120 .map_err(MlsError::wrap("updating authentication service env"))?;
121 }
122
123 Ok(())
124 }
125
126 pub async fn e2ei_register_intermediate_ca_pem(&self, cert_pem: String) -> Result<NewCrlDistributionPoints> {
134 let inter_ca = PkiEnvironment::decode_pem_cert(cert_pem)?;
136 self.e2ei_register_intermediate_ca(inter_ca).await
137 }
138
139 pub(crate) async fn e2ei_register_intermediate_ca_der(&self, cert_der: &[u8]) -> Result<NewCrlDistributionPoints> {
140 let inter_ca = x509_cert::Certificate::from_der(cert_der)?;
141 self.e2ei_register_intermediate_ca(inter_ca).await
142 }
143
144 async fn e2ei_register_intermediate_ca(
145 &self,
146 inter_ca: x509_cert::Certificate,
147 ) -> Result<NewCrlDistributionPoints> {
148 let keystore = self
150 .keystore()
151 .await
152 .map_err(RecursiveError::transaction("getting keystore"))?;
153 let trust_anchor = keystore
154 .find_unique::<E2eiAcmeCA>()
155 .await
156 .map_err(KeystoreError::wrap("finding acme ca"))?;
157 let trust_anchor = x509_cert::Certificate::from_der(&trust_anchor.content)?;
158
159 if inter_ca == trust_anchor {
162 return Ok(None.into());
163 }
164
165 let intermediate_crl = extract_crl_uris(&inter_ca)?.map(|s| s.into_iter().collect());
166
167 let (ski, aki) = PkiEnvironment::extract_ski_aki_from_cert(&inter_ca)?;
168
169 let ski_aki_pair = format!("{ski}:{}", aki.unwrap_or_default());
170
171 {
173 let provider = self
174 .mls_provider()
175 .await
176 .map_err(RecursiveError::transaction("getting mls provider"))?;
177 let auth_service_arc = provider.authentication_service().borrow().await;
178 let Some(pki_env) = auth_service_arc.as_ref() else {
179 return Err(Error::PkiEnvironmentUnset);
180 };
181 pki_env.validate_cert_and_revocation(&inter_ca)?;
182 }
183
184 let cert_der = PkiEnvironment::encode_cert_to_der(&inter_ca)?;
186 let intermediate_ca = E2eiIntermediateCert {
187 content: cert_der,
188 ski_aki_pair,
189 };
190 keystore
191 .save(intermediate_ca)
192 .await
193 .map_err(KeystoreError::wrap("saving intermediate ca"))?;
194
195 self.init_pki_env().await?;
196
197 Ok(intermediate_crl.into())
198 }
199
200 pub async fn e2ei_register_crl(&self, crl_dp: String, crl_der: Vec<u8>) -> Result<CrlRegistration> {
212 let crl = {
214 let provider = self
215 .mls_provider()
216 .await
217 .map_err(RecursiveError::transaction("getting mls provider"))?;
218 let auth_service_arc = provider.authentication_service().borrow().await;
219 let Some(pki_env) = auth_service_arc.as_ref() else {
220 return Err(Error::PkiEnvironmentUnset);
221 };
222 pki_env.validate_crl_with_raw(&crl_der)?
223 };
224
225 let expiration = extract_expiration_from_crl(&crl);
226
227 let ks = self
228 .keystore()
229 .await
230 .map_err(RecursiveError::transaction("getting keystore"))?;
231
232 let dirty = ks
233 .find::<E2eiCrl>(crl_dp.as_bytes())
234 .await
235 .ok()
236 .flatten()
237 .map(|existing_crl| {
238 PkiEnvironment::decode_der_crl(existing_crl.content.clone())
239 .map(|old_crl| old_crl.tbs_cert_list.revoked_certificates != crl.tbs_cert_list.revoked_certificates)
240 })
241 .transpose()?
242 .unwrap_or_default();
243
244 let crl_data = E2eiCrl {
246 content: PkiEnvironment::encode_crl_to_der(&crl)?,
247 distribution_point: crl_dp,
248 };
249 ks.save(crl_data).await.map_err(KeystoreError::wrap("saving crl"))?;
250
251 self.init_pki_env().await?;
252
253 Ok(CrlRegistration { expiration, dirty })
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use wasm_bindgen_test::*;
260 use x509_cert::der::EncodePem;
261
262 use crate::test_utils::*;
263
264 use super::super::Error;
265
266 wasm_bindgen_test_configure!(run_in_browser);
267
268 #[apply(all_cred_cipher)]
269 #[wasm_bindgen_test]
270 async fn register_acme_ca_should_fail_when_already_set(case: TestContext) {
271 use x509_cert::der::pem::LineEnding;
272
273 if !case.is_x509() {
274 return;
275 }
276
277 let [alice_central] = case.sessions().await;
278 Box::pin(async move {
279 let alice_test_chain = alice_central.x509_test_chain.as_ref().as_ref().unwrap();
280 let alice_ta = alice_test_chain
281 .trust_anchor
282 .certificate
283 .to_pem(LineEnding::CRLF)
284 .unwrap();
285
286 assert!(matches!(
287 alice_central
288 .transaction
289 .e2ei_register_acme_ca(alice_ta)
290 .await
291 .unwrap_err(),
292 Error::TrustAnchorAlreadyRegistered
293 ));
294 })
295 .await;
296 }
297
298 #[apply(all_cred_cipher)]
299 #[wasm_bindgen_test]
300 async fn x509_restore_should_not_happen_if_basic(case: TestContext) {
301 if case.is_x509() {
302 return;
303 }
304
305 let [alice_ctx] = case.sessions().await;
306 Box::pin(async move {
307 let SessionContext {
308 transaction,
309 x509_test_chain,
310 ..
311 } = alice_ctx;
312
313 assert!(x509_test_chain.is_none());
314 assert!(!transaction.e2ei_is_pki_env_setup().await.unwrap());
315
316 assert!(x509_test_chain.is_none());
319 })
321 .await;
322 }
323}