core_crypto/e2e_identity/
pki_env.rs

1use 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/// New Certificate Revocation List distribution points.
13#[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)]
34/// Dump of the PKI environemnt as PEM
35pub struct E2eiDumpedPkiEnv {
36    /// Root CA in use (i.e. Trust Anchor)
37    pub root_ca: String,
38    /// Intermediate CAs that are loaded
39    pub intermediates: Vec<String>,
40    /// CRLs registered in the PKI env
41    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}