1 | use alloc::vec::Vec; |
2 | use alloc::{fmt, format}; |
3 | |
4 | use pki_types::{CertificateDer, TrustAnchor}; |
5 | use webpki::anchor_from_trusted_cert; |
6 | |
7 | use super::pki_error; |
8 | #[cfg (feature = "logging" )] |
9 | use crate::log::{debug, trace}; |
10 | use crate::{DistinguishedName, Error}; |
11 | |
12 | /// A container for root certificates able to provide a root-of-trust |
13 | /// for connection authentication. |
14 | #[derive (Clone)] |
15 | pub struct RootCertStore { |
16 | /// The list of roots. |
17 | pub roots: Vec<TrustAnchor<'static>>, |
18 | } |
19 | |
20 | impl RootCertStore { |
21 | /// Make a new, empty `RootCertStore`. |
22 | pub fn empty() -> Self { |
23 | Self { roots: Vec::new() } |
24 | } |
25 | |
26 | /// Parse the given DER-encoded certificates and add all that can be parsed |
27 | /// in a best-effort fashion. |
28 | /// |
29 | /// This is because large collections of root certificates often |
30 | /// include ancient or syntactically invalid certificates. |
31 | /// |
32 | /// Returns the number of certificates added, and the number that were ignored. |
33 | 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 | /// Add a single DER-encoded certificate to the store. |
64 | /// |
65 | /// This is suitable for a small set of root certificates that are expected to parse |
66 | /// successfully. For large collections of roots (for example from a system store) it |
67 | /// is expected that some of them might not be valid according to the rules rustls |
68 | /// implements. As long as a relatively limited number of certificates are affected, |
69 | /// this should not be a cause for concern. Use [`RootCertStore::add_parsable_certificates`] |
70 | /// in order to add as many valid roots as possible and to understand how many certificates |
71 | /// have been diagnosed as malformed. |
72 | 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 | /// Return the DER encoded [`DistinguishedName`] of each trust anchor subject in the root |
82 | /// cert store. |
83 | /// |
84 | /// Each [`DistinguishedName`] will be a DER-encoded X.500 distinguished name, per |
85 | /// [RFC 5280 A.1], including the outer `SEQUENCE`. |
86 | /// |
87 | /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1 |
88 | 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 | /// Return true if there are no certificates. |
96 | pub fn is_empty(&self) -> bool { |
97 | self.len() == 0 |
98 | } |
99 | |
100 | /// Say how many certificates are in the container. |
101 | pub fn len(&self) -> usize { |
102 | self.roots.len() |
103 | } |
104 | } |
105 | |
106 | impl 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 | |
112 | impl fmt::Debug for RootCertStore { |
113 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
114 | f&mut DebugStruct<'_, '_>.debug_struct("RootCertStore" ) |
115 | .field(name:"roots" , &format!("( {} roots)" , &self.roots.len())) |
116 | .finish() |
117 | } |
118 | } |
119 | |
120 | #[test ] |
121 | fn root_cert_store_debug() { |
122 | use core::iter; |
123 | use pki_types::Der; |
124 | |
125 | let mut store: RootCertStore = RootCertStore::empty(); |
126 | let ta: TrustAnchor<'_> = TrustAnchor { |
127 | subject: Der::from_slice(&[]), |
128 | subject_public_key_info: Der::from_slice(&[]), |
129 | name_constraints: None, |
130 | }; |
131 | store.extend(iter:iter::repeat(elt:ta).take(138)); |
132 | |
133 | assert_eq!( |
134 | format!(" {:?}" , store), |
135 | "RootCertStore { roots: \"(138 roots) \" }" |
136 | ); |
137 | } |
138 | |