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}