1#[cfg(feature = "logging")]
2use crate::log::{debug, trace};
3use crate::x509;
4use crate::{key, DistinguishedName};
5use crate::{CertificateError, Error};
6
7#[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    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    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    pub fn subject(&self) -> &DistinguishedName {
70        &self.subject_dn
71    }
72}
73
74#[derive(Debug, Clone)]
77pub struct RootCertStore {
78    pub roots: Vec<OwnedTrustAnchor>,
80}
81
82impl RootCertStore {
83    pub fn empty() -> Self {
85        Self { roots: Vec::new() }
86    }
87
88    pub fn is_empty(&self) -> bool {
90        self.len() == 0
91    }
92
93    pub fn len(&self) -> usize {
95        self.roots.len()
96    }
97
98    pub fn add(&mut self, der: &key::Certificate) -> Result<(), Error> {
108        self.add_internal(&der.0)
109    }
110
111    pub fn add_trust_anchors(&mut self, trust_anchors: impl Iterator<Item = OwnedTrustAnchor>) {
114        self.roots.extend(trust_anchors);
115    }
116
117    #[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    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}