1use alloc::vec::Vec;
2use alloc::{fmt, format};
3
4use pki_types::{CertificateDer, TrustAnchor};
5use webpki::anchor_from_trusted_cert;
6
7use super::pki_error;
8use crate::log::{debug, trace};
9use crate::{DistinguishedName, Error};
10
11#[derive(Clone)]
14pub struct RootCertStore {
15    pub roots: Vec<TrustAnchor<'static>>,
17}
18
19impl RootCertStore {
20    pub fn empty() -> Self {
22        Self { roots: Vec::new() }
23    }
24
25    pub fn add_parsable_certificates<'a>(
33        &mut self,
34        der_certs: impl IntoIterator<Item = CertificateDer<'a>>,
35    ) -> (usize, usize) {
36        let mut valid_count = 0;
37        let mut invalid_count = 0;
38
39        for der_cert in der_certs {
40            #[cfg_attr(not(feature = "logging"), allow(unused_variables))]
41            match anchor_from_trusted_cert(&der_cert) {
42                Ok(anchor) => {
43                    self.roots.push(anchor.to_owned());
44                    valid_count += 1;
45                }
46                Err(err) => {
47                    trace!("invalid cert der {:?}", der_cert.as_ref());
48                    debug!("certificate parsing failed: {:?}", err);
49                    invalid_count += 1;
50                }
51            };
52        }
53
54        debug!(
55            "add_parsable_certificates processed {} valid and {} invalid certs",
56            valid_count, invalid_count
57        );
58
59        (valid_count, invalid_count)
60    }
61
62    pub fn add(&mut self, der: CertificateDer<'_>) -> Result<(), Error> {
72        self.roots.push(
73            anchor_from_trusted_cert(&der)
74                .map_err(pki_error)?
75                .to_owned(),
76        );
77        Ok(())
78    }
79
80    pub fn subjects(&self) -> Vec<DistinguishedName> {
88        self.roots
89            .iter()
90            .map(|ta| DistinguishedName::in_sequence(ta.subject.as_ref()))
91            .collect()
92    }
93
94    pub fn is_empty(&self) -> bool {
96        self.len() == 0
97    }
98
99    pub fn len(&self) -> usize {
101        self.roots.len()
102    }
103}
104
105impl FromIterator<TrustAnchor<'static>> for RootCertStore {
106    fn from_iter<T: IntoIterator<Item = TrustAnchor<'static>>>(iter: T) -> Self {
107        Self {
108            roots: iter.into_iter().collect(),
109        }
110    }
111}
112
113impl Extend<TrustAnchor<'static>> for RootCertStore {
114    fn extend<T: IntoIterator<Item = TrustAnchor<'static>>>(&mut self, iter: T) {
115        self.roots.extend(iter);
116    }
117}
118
119impl fmt::Debug for RootCertStore {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        f.debug_struct("RootCertStore")
122            .field("roots", &format!("({} roots)", &self.roots.len()))
123            .finish()
124    }
125}
126
127#[test]
128fn root_cert_store_debug() {
129    use core::iter;
130
131    use pki_types::Der;
132
133    let ta = TrustAnchor {
134        subject: Der::from_slice(&[]),
135        subject_public_key_info: Der::from_slice(&[]),
136        name_constraints: None,
137    };
138    let store = RootCertStore::from_iter(iter::repeat(ta).take(138));
139
140    assert_eq!(
141        format!("{:?}", store),
142        "RootCertStore { roots: \"(138 roots)\" }"
143    );
144}