rustls/
anchors.rs

1#[cfg(feature = "logging")]
2use crate::log::{debug, trace};
3use crate::x509;
4use crate::{key, DistinguishedName};
5use crate::{CertificateError, Error};
6
7/// A trust anchor, commonly known as a "Root Certificate."
8#[derive(Debug, Clone)]
9pub struct OwnedTrustAnchor {
10    subject_dn_header_len: usize,
11    subject_dn: DistinguishedName,
12    spki: Vec<u8>,
13    name_constraints: Option<Vec<u8>>,
14}
15
16impl OwnedTrustAnchor {
17    /// Get a `webpki::TrustAnchor` by borrowing the owned elements.
18    pub(crate) fn to_trust_anchor(&self) -> webpki::TrustAnchor {
19        webpki::TrustAnchor {
20            subject: &self.subject_dn.as_ref()[self.subject_dn_header_len..],
21            spki: &self.spki,
22            name_constraints: self.name_constraints.as_deref(),
23        }
24    }
25
26    /// Constructs an `OwnedTrustAnchor` from its components.
27    ///
28    /// All inputs are DER-encoded.
29    ///
30    /// `subject` is the [Subject] field of the trust anchor *without* the outer SEQUENCE
31    /// encoding.
32    ///
33    /// `spki` is the [SubjectPublicKeyInfo] field of the trust anchor.
34    ///
35    /// `name_constraints` is the [Name Constraints] to
36    /// apply for this trust anchor, if any.
37    ///
38    /// [Subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
39    /// [SubjectPublicKeyInfo]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.7
40    /// [Name Constraints]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10
41    pub fn from_subject_spki_name_constraints(
42        subject: impl Into<Vec<u8>>,
43        spki: impl Into<Vec<u8>>,
44        name_constraints: Option<impl Into<Vec<u8>>>,
45    ) -> Self {
46        let (subject_dn, subject_dn_header_len) = {
47            let mut subject = subject.into();
48            let before_len = subject.len();
49            x509::wrap_in_sequence(&mut subject);
50            let header_len = subject.len().saturating_sub(before_len);
51            (DistinguishedName::from(subject), header_len)
52        };
53        Self {
54            subject_dn_header_len,
55            subject_dn,
56            spki: spki.into(),
57            name_constraints: name_constraints.map(|x| x.into()),
58        }
59    }
60
61    /// Return the subject field including its outer SEQUENCE encoding.
62    ///
63    /// This can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
64    ///
65    /// ```ignore
66    /// use x509_parser::prelude::FromDer;
67    /// println!("{}", x509_parser::x509::X509Name::from_der(anchor.subject())?.1);
68    /// ```
69    pub fn subject(&self) -> &DistinguishedName {
70        &self.subject_dn
71    }
72}
73
74/// A container for root certificates able to provide a root-of-trust
75/// for connection authentication.
76#[derive(Debug, Clone)]
77pub struct RootCertStore {
78    /// The list of roots.
79    pub roots: Vec<OwnedTrustAnchor>,
80}
81
82impl RootCertStore {
83    /// Make a new, empty `RootCertStore`.
84    pub fn empty() -> Self {
85        Self { roots: Vec::new() }
86    }
87
88    /// Return true if there are no certificates.
89    pub fn is_empty(&self) -> bool {
90        self.len() == 0
91    }
92
93    /// Say how many certificates are in the container.
94    pub fn len(&self) -> usize {
95        self.roots.len()
96    }
97
98    /// Add a single DER-encoded certificate to the store.
99    ///
100    /// This is suitable for a small set of root certificates that are expected to parse
101    /// successfully. For large collections of roots (for example from a system store) it
102    /// is expected that some of them might not be valid according to the rules rustls
103    /// implements. As long as a relatively limited number of certificates are affected,
104    /// this should not be a cause for concern. Use [`RootCertStore::add_parsable_certificates`]
105    /// in order to add as many valid roots as possible and to understand how many certificates
106    /// have been diagnosed as malformed.
107    pub fn add(&mut self, der: &key::Certificate) -> Result<(), Error> {
108        self.add_internal(&der.0)
109    }
110
111    /// Adds all the given TrustAnchors `anchors`.  This does not
112    /// fail.
113    pub fn add_trust_anchors(&mut self, trust_anchors: impl Iterator<Item = OwnedTrustAnchor>) {
114        self.roots.extend(trust_anchors);
115    }
116
117    /// Adds all the given TrustAnchors `anchors`.  This does not
118    /// fail.
119    #[deprecated(since = "0.21.6", note = "Please use `add_trust_anchors` instead")]
120    pub fn add_server_trust_anchors(
121        &mut self,
122        trust_anchors: impl Iterator<Item = OwnedTrustAnchor>,
123    ) {
124        self.add_trust_anchors(trust_anchors);
125    }
126
127    /// Parse the given DER-encoded certificates and add all that can be parsed
128    /// in a best-effort fashion.
129    ///
130    /// This is because large collections of root certificates often
131    /// include ancient or syntactically invalid certificates.
132    ///
133    /// Returns the number of certificates added, and the number that were ignored.
134    pub fn add_parsable_certificates(&mut self, der_certs: &[impl AsRef<[u8]>]) -> (usize, usize) {
135        let mut valid_count = 0;
136        let mut invalid_count = 0;
137
138        for der_cert in der_certs {
139            #[cfg_attr(not(feature = "logging"), allow(unused_variables))]
140            match self.add_internal(der_cert.as_ref()) {
141                Ok(_) => valid_count += 1,
142                Err(err) => {
143                    trace!("invalid cert der {:?}", der_cert.as_ref());
144                    debug!("certificate parsing failed: {:?}", err);
145                    invalid_count += 1;
146                }
147            }
148        }
149
150        debug!(
151            "add_parsable_certificates processed {} valid and {} invalid certs",
152            valid_count, invalid_count
153        );
154
155        (valid_count, invalid_count)
156    }
157
158    fn add_internal(&mut self, der: &[u8]) -> Result<(), Error> {
159        let ta = webpki::TrustAnchor::try_from_cert_der(der)
160            .map_err(|_| Error::InvalidCertificate(CertificateError::BadEncoding))?;
161        self.roots
162            .push(OwnedTrustAnchor::from_subject_spki_name_constraints(
163                ta.subject,
164                ta.spki,
165                ta.name_constraints,
166            ));
167        Ok(())
168    }
169}
170
171mod tests {
172    #[test]
173    fn ownedtrustanchor_subject_is_correctly_encoding_dn() {
174        let subject = b"subject".to_owned();
175        let ota = super::OwnedTrustAnchor::from_subject_spki_name_constraints(
176            subject,
177            b"".to_owned(),
178            None::<Vec<u8>>,
179        );
180        let expected_prefix = vec![ring::io::der::Tag::Sequence as u8, subject.len() as u8];
181        assert_eq!(
182            ota.subject().as_ref(),
183            [expected_prefix, subject.to_vec()].concat()
184        );
185    }
186}