core_crypto/e2e_identity/
pki_env.rs1use crate::KeystoreError;
2
3use super::{Error, Result};
4use core_crypto_keystore::{
5 connection::FetchFromDatabase,
6 entities::{E2eiAcmeCA, E2eiCrl, E2eiIntermediateCert},
7};
8use std::collections::HashSet;
9use wire_e2e_identity::prelude::x509::revocation::{PkiEnvironment, PkiEnvironmentParams};
10use x509_cert::der::{Decode, EncodePem, pem::LineEnding};
11
12#[derive(Debug, Clone, derive_more::From, derive_more::Into, derive_more::Deref, derive_more::DerefMut)]
14pub struct NewCrlDistributionPoints(Option<HashSet<String>>);
15
16impl From<NewCrlDistributionPoints> for Option<Vec<String>> {
17 fn from(mut dp: NewCrlDistributionPoints) -> Self {
18 dp.take().map(|d| d.into_iter().collect())
19 }
20}
21
22impl IntoIterator for NewCrlDistributionPoints {
23 type Item = String;
24
25 type IntoIter = std::collections::hash_set::IntoIter<String>;
26
27 fn into_iter(self) -> Self::IntoIter {
28 let items = self.0.unwrap_or_default();
29 items.into_iter()
30 }
31}
32
33#[derive(Debug, Clone)]
34pub struct E2eiDumpedPkiEnv {
36 pub root_ca: String,
38 pub intermediates: Vec<String>,
40 pub crls: Vec<String>,
42}
43
44impl E2eiDumpedPkiEnv {
45 pub(crate) async fn from_pki_env(pki_env: &PkiEnvironment) -> Result<Option<E2eiDumpedPkiEnv>> {
46 let Some(root) = pki_env
47 .get_trust_anchors()
48 .map_err(Error::certificate_validation("getting pki trust anchors"))?
49 .pop()
50 else {
51 return Ok(None);
52 };
53
54 let x509_cert::anchor::TrustAnchorChoice::Certificate(root) = &root.decoded_ta else {
55 return Ok(None);
56 };
57
58 let root_ca = root.to_pem(LineEnding::LF)?;
59
60 let intermediates = pki_env
61 .get_intermediates()
62 .map_err(Error::certificate_validation("getting pki intermediates"))?
63 .into_iter()
64 .map(|inter| inter.decoded_cert.to_pem(LineEnding::LF))
65 .collect::<Result<Vec<_>, _>>()?;
66
67 let crls = pki_env
68 .get_all_crls()
69 .map_err(Error::certificate_validation("getting all crls"))?
70 .iter()
71 .map(|crl_bytes| {
72 x509_cert::der::pem::encode_string("X509 CRL", LineEnding::LF, crl_bytes)
73 .map_err(Error::certificate_validation("encoding crl title to pem"))
74 })
75 .collect::<Result<Vec<_>, _>>()?;
76
77 Ok(Some(E2eiDumpedPkiEnv {
78 root_ca,
79 intermediates,
80 crls,
81 }))
82 }
83}
84
85pub(crate) async fn restore_pki_env(data_provider: &impl FetchFromDatabase) -> Result<Option<PkiEnvironment>> {
86 let mut trust_roots = vec![];
87 let Ok(ta_raw) = data_provider.find_unique::<E2eiAcmeCA>().await else {
88 return Ok(None);
89 };
90
91 trust_roots.push(
92 x509_cert::Certificate::from_der(&ta_raw.content).map(x509_cert::anchor::TrustAnchorChoice::Certificate)?,
93 );
94
95 let intermediates = data_provider
96 .find_all::<E2eiIntermediateCert>(Default::default())
97 .await
98 .map_err(KeystoreError::wrap("finding intermediate certificates"))?
99 .into_iter()
100 .map(|inter| x509_cert::Certificate::from_der(&inter.content))
101 .collect::<Result<Vec<_>, _>>()?;
102
103 let crls = data_provider
104 .find_all::<E2eiCrl>(Default::default())
105 .await
106 .map_err(KeystoreError::wrap("finding crls"))?
107 .into_iter()
108 .map(|crl| x509_cert::crl::CertificateList::from_der(&crl.content))
109 .collect::<Result<Vec<_>, _>>()?;
110
111 let params = PkiEnvironmentParams {
112 trust_roots: &trust_roots,
113 intermediates: &intermediates,
114 crls: &crls,
115 time_of_interest: None,
116 };
117
118 Ok(Some(PkiEnvironment::init(params)?))
119}