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