1use alloc::vec::Vec;
2use alloc::{fmt, format};
34use pki_types::{CertificateDer, TrustAnchor};
5use webpki::anchor_from_trusted_cert;
67use super::pki_error;
8use crate::log::{debug, trace};
9use crate::{DistinguishedName, Error};
1011/// A container for root certificates able to provide a root-of-trust
12/// for connection authentication.
13#[derive(Clone)]
14pub struct RootCertStore {
15/// The list of roots.
16pub roots: Vec<TrustAnchor<'static>>,
17}
1819impl RootCertStore {
20/// Make a new, empty `RootCertStore`.
21pub fn empty() -> Self {
22Self { roots: Vec::new() }
23 }
2425/// Parse the given DER-encoded certificates and add all that can be parsed
26 /// in a best-effort fashion.
27 ///
28 /// This is because large collections of root certificates often
29 /// include ancient or syntactically invalid certificates.
30 ///
31 /// Returns the number of certificates added, and the number that were ignored.
32pub fn add_parsable_certificates<'a>(
33&mut self,
34 der_certs: impl IntoIterator<Item = CertificateDer<'a>>,
35 ) -> (usize, usize) {
36let mut valid_count = 0;
37let mut invalid_count = 0;
3839for der_cert in der_certs {
40#[cfg_attr(not(feature = "logging"), allow(unused_variables))]
41match anchor_from_trusted_cert(&der_cert) {
42Ok(anchor) => {
43self.roots.push(anchor.to_owned());
44 valid_count += 1;
45 }
46Err(err) => {
47trace!("invalid cert der {:?}", der_cert.as_ref());
48debug!("certificate parsing failed: {:?}", err);
49 invalid_count += 1;
50 }
51 };
52 }
5354debug!(
55"add_parsable_certificates processed {} valid and {} invalid certs",
56 valid_count, invalid_count
57 );
5859 (valid_count, invalid_count)
60 }
6162/// Add a single DER-encoded certificate to the store.
63 ///
64 /// This is suitable for a small set of root certificates that are expected to parse
65 /// successfully. For large collections of roots (for example from a system store) it
66 /// is expected that some of them might not be valid according to the rules rustls
67 /// implements. As long as a relatively limited number of certificates are affected,
68 /// this should not be a cause for concern. Use [`RootCertStore::add_parsable_certificates`]
69 /// in order to add as many valid roots as possible and to understand how many certificates
70 /// have been diagnosed as malformed.
71pub fn add(&mut self, der: CertificateDer<'_>) -> Result<(), Error> {
72self.roots.push(
73 anchor_from_trusted_cert(&der)
74 .map_err(pki_error)?
75.to_owned(),
76 );
77Ok(())
78 }
7980/// Return the DER encoded [`DistinguishedName`] of each trust anchor subject in the root
81 /// cert store.
82 ///
83 /// Each [`DistinguishedName`] will be a DER-encoded X.500 distinguished name, per
84 /// [RFC 5280 A.1], including the outer `SEQUENCE`.
85 ///
86 /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1
87pub fn subjects(&self) -> Vec<DistinguishedName> {
88self.roots
89 .iter()
90 .map(|ta| DistinguishedName::in_sequence(ta.subject.as_ref()))
91 .collect()
92 }
9394/// Return true if there are no certificates.
95pub fn is_empty(&self) -> bool {
96self.len() == 0
97}
9899/// Say how many certificates are in the container.
100pub fn len(&self) -> usize {
101self.roots.len()
102 }
103}
104105impl FromIterator<TrustAnchor<'static>> for RootCertStore {
106fn from_iter<T: IntoIterator<Item = TrustAnchor<'static>>>(iter: T) -> Self {
107Self {
108 roots: iter.into_iter().collect(),
109 }
110 }
111}
112113impl Extend<TrustAnchor<'static>> for RootCertStore {
114fn extend<T: IntoIterator<Item = TrustAnchor<'static>>>(&mut self, iter: T) {
115self.roots.extend(iter);
116 }
117}
118119impl fmt::Debug for RootCertStore {
120fn 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}
126127#[test]
128fn root_cert_store_debug() {
129use core::iter;
130131use pki_types::Der;
132133let ta = TrustAnchor {
134 subject: Der::from_slice(&[]),
135 subject_public_key_info: Der::from_slice(&[]),
136 name_constraints: None,
137 };
138let store = RootCertStore::from_iter(iter::repeat(ta).take(138));
139140assert_eq!(
141format!("{:?}", store),
142"RootCertStore { roots: \"(138 roots)\" }"
143);
144}