2019-01-20 19:22:18 +00:00
|
|
|
#[cfg(feature = "logging")]
|
|
|
|
use crate::log::{debug, trace};
|
2023-03-27 19:36:53 +00:00
|
|
|
use crate::{key, DistinguishedName};
|
2023-01-25 09:44:19 +00:00
|
|
|
use crate::{CertificateError, Error};
|
2017-05-12 20:12:45 +00:00
|
|
|
|
2021-07-12 20:45:59 +00:00
|
|
|
/// A trust anchor, commonly known as a "Root Certificate."
|
2017-06-05 14:05:14 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2017-05-12 20:12:45 +00:00
|
|
|
pub struct OwnedTrustAnchor {
|
2023-03-27 19:36:53 +00:00
|
|
|
subject: DistinguishedName,
|
2017-05-12 20:12:45 +00:00
|
|
|
spki: Vec<u8>,
|
|
|
|
name_constraints: Option<Vec<u8>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl OwnedTrustAnchor {
|
2020-10-07 05:43:12 +00:00
|
|
|
/// Get a `webpki::TrustAnchor` by borrowing the owned elements.
|
2021-06-15 11:53:23 +00:00
|
|
|
pub(crate) fn to_trust_anchor(&self) -> webpki::TrustAnchor {
|
2017-05-12 20:12:45 +00:00
|
|
|
webpki::TrustAnchor {
|
2023-03-27 19:36:53 +00:00
|
|
|
subject: self.subject.as_ref(),
|
2017-05-12 20:12:45 +00:00
|
|
|
spki: &self.spki,
|
2021-03-30 09:09:14 +00:00
|
|
|
name_constraints: self.name_constraints.as_deref(),
|
2017-05-12 20:12:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-12 20:45:59 +00:00
|
|
|
/// Constructs an `OwnedTrustAnchor` from its components.
|
|
|
|
///
|
2022-06-12 16:57:32 +00:00
|
|
|
/// All inputs are DER-encoded.
|
2021-07-12 20:45:59 +00:00
|
|
|
///
|
2022-06-12 16:57:32 +00:00
|
|
|
/// `subject` is the [Subject] field of the trust anchor.
|
2021-07-12 20:45:59 +00:00
|
|
|
///
|
2022-06-12 16:57:32 +00:00
|
|
|
/// `spki` is the [SubjectPublicKeyInfo] field of the trust anchor.
|
|
|
|
///
|
|
|
|
/// `name_constraints` is the [Name Constraints] to
|
2021-07-12 20:45:59 +00:00
|
|
|
/// apply for this trust anchor, if any.
|
2022-06-12 16:57:32 +00:00
|
|
|
///
|
|
|
|
/// [Subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
|
|
|
|
/// [SubjectPublicKeyInfo]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.7
|
|
|
|
/// [Name Constraints]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10
|
2021-07-12 20:45:59 +00:00
|
|
|
pub fn from_subject_spki_name_constraints(
|
|
|
|
subject: impl Into<Vec<u8>>,
|
|
|
|
spki: impl Into<Vec<u8>>,
|
|
|
|
name_constraints: Option<impl Into<Vec<u8>>>,
|
|
|
|
) -> Self {
|
2021-06-15 11:53:23 +00:00
|
|
|
Self {
|
2023-04-28 20:53:52 +00:00
|
|
|
subject: DistinguishedName::new(&subject.into()),
|
2021-07-12 20:45:59 +00:00
|
|
|
spki: spki.into(),
|
|
|
|
name_constraints: name_constraints.map(|x| x.into()),
|
2021-06-15 11:53:23 +00:00
|
|
|
}
|
2020-10-07 05:43:12 +00:00
|
|
|
}
|
2022-06-12 17:20:16 +00:00
|
|
|
|
|
|
|
/// Return the subject field.
|
|
|
|
///
|
2023-03-02 18:23:51 +00:00
|
|
|
/// This can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
|
2022-06-12 17:20:16 +00:00
|
|
|
///
|
|
|
|
/// ```ignore
|
2023-03-02 18:23:51 +00:00
|
|
|
/// use x509_parser::prelude::FromDer;
|
2022-06-12 17:20:16 +00:00
|
|
|
/// println!("{}", x509_parser::x509::X509Name::from_der(anchor.subject())?.1);
|
|
|
|
/// ```
|
2023-03-27 19:36:53 +00:00
|
|
|
pub fn subject(&self) -> &DistinguishedName {
|
2022-06-12 17:20:16 +00:00
|
|
|
&self.subject
|
|
|
|
}
|
2020-10-07 05:43:12 +00:00
|
|
|
}
|
|
|
|
|
2017-05-12 20:12:45 +00:00
|
|
|
/// A container for root certificates able to provide a root-of-trust
|
|
|
|
/// for connection authentication.
|
2017-06-05 14:05:14 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2017-05-12 20:12:45 +00:00
|
|
|
pub struct RootCertStore {
|
2017-06-10 20:29:19 +00:00
|
|
|
/// The list of roots.
|
2017-05-12 20:12:45 +00:00
|
|
|
pub roots: Vec<OwnedTrustAnchor>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RootCertStore {
|
|
|
|
/// Make a new, empty `RootCertStore`.
|
2021-06-16 19:09:05 +00:00
|
|
|
pub fn empty() -> Self {
|
|
|
|
Self { roots: Vec::new() }
|
2017-05-12 20:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Return true if there are no certificates.
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.len() == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Say how many certificates are in the container.
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.roots.len()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add a single DER-encoded certificate to the store.
|
2023-03-24 21:35:50 +00:00
|
|
|
///
|
|
|
|
/// This is suitable for a small set of root certificates that are expected to parse
|
2023-03-24 22:04:46 +00:00
|
|
|
/// successfully. For large collections of roots (for example from a system store) it
|
|
|
|
/// is expected that some of them might not be valid according to the rules rustls
|
|
|
|
/// implements. As long as a relatively limited number of certificates are affected,
|
|
|
|
/// this should not be a cause for concern. Use [`RootCertStore::add_parsable_certificates`]
|
|
|
|
/// in order to add as many valid roots as possible and to understand how many certificates
|
|
|
|
/// have been diagnosed as malformed.
|
2023-01-25 09:44:19 +00:00
|
|
|
pub fn add(&mut self, der: &key::Certificate) -> Result<(), Error> {
|
|
|
|
let ta = webpki::TrustAnchor::try_from_cert_der(&der.0)
|
|
|
|
.map_err(|_| Error::InvalidCertificate(CertificateError::BadEncoding))?;
|
2021-07-12 20:45:59 +00:00
|
|
|
let ota = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
|
|
|
ta.subject,
|
|
|
|
ta.spki,
|
|
|
|
ta.name_constraints,
|
|
|
|
);
|
2017-05-12 20:12:45 +00:00
|
|
|
self.roots.push(ota);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Adds all the given TrustAnchors `anchors`. This does not
|
|
|
|
/// fail.
|
2021-07-12 20:45:59 +00:00
|
|
|
pub fn add_server_trust_anchors(
|
|
|
|
&mut self,
|
|
|
|
trust_anchors: impl Iterator<Item = OwnedTrustAnchor>,
|
|
|
|
) {
|
2023-02-10 05:05:12 +00:00
|
|
|
self.roots.extend(trust_anchors);
|
2017-05-12 20:12:45 +00:00
|
|
|
}
|
|
|
|
|
2020-12-28 15:15:44 +00:00
|
|
|
/// Parse the given DER-encoded certificates and add all that can be parsed
|
|
|
|
/// in a best-effort fashion.
|
2017-05-12 20:12:45 +00:00
|
|
|
///
|
|
|
|
/// This is because large collections of root certificates often
|
2020-12-28 15:15:44 +00:00
|
|
|
/// include ancient or syntactically invalid certificates.
|
2017-05-12 20:12:45 +00:00
|
|
|
///
|
2020-12-28 15:15:44 +00:00
|
|
|
/// Returns the number of certificates added, and the number that were ignored.
|
2021-03-30 09:09:14 +00:00
|
|
|
pub fn add_parsable_certificates(&mut self, der_certs: &[Vec<u8>]) -> (usize, usize) {
|
2017-05-12 20:12:45 +00:00
|
|
|
let mut valid_count = 0;
|
|
|
|
let mut invalid_count = 0;
|
|
|
|
|
2020-12-28 15:15:44 +00:00
|
|
|
for der_cert in der_certs {
|
2019-01-03 20:27:10 +00:00
|
|
|
#[cfg_attr(not(feature = "logging"), allow(unused_variables))]
|
2020-12-28 15:15:44 +00:00
|
|
|
match self.add(&key::Certificate(der_cert.clone())) {
|
2017-05-12 20:12:45 +00:00
|
|
|
Ok(_) => valid_count += 1,
|
|
|
|
Err(err) => {
|
2020-12-28 15:15:44 +00:00
|
|
|
trace!("invalid cert der {:?}", der_cert);
|
2017-09-09 22:27:04 +00:00
|
|
|
debug!("certificate parsing failed: {:?}", err);
|
2023-02-10 05:05:12 +00:00
|
|
|
invalid_count += 1;
|
2017-05-12 20:12:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-22 12:42:12 +00:00
|
|
|
debug!(
|
2020-12-28 15:15:44 +00:00
|
|
|
"add_parsable_certificates processed {} valid and {} invalid certs",
|
2020-11-22 12:42:12 +00:00
|
|
|
valid_count, invalid_count
|
|
|
|
);
|
2017-05-12 20:12:45 +00:00
|
|
|
|
2020-12-28 15:15:44 +00:00
|
|
|
(valid_count, invalid_count)
|
2017-05-12 20:12:45 +00:00
|
|
|
}
|
|
|
|
}
|
2023-04-28 20:53:52 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
#[test]
|
|
|
|
fn owned_trust_anchor_subject_is_correctly_encoding_dn() {
|
|
|
|
let ota = super::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
|
|
|
b"subject".to_owned(),
|
|
|
|
b"".to_owned(),
|
|
|
|
None::<Vec<u8>>,
|
|
|
|
);
|
|
|
|
assert_eq!(ota.subject().as_ref(), b"\x30\x07subject");
|
|
|
|
}
|
|
|
|
}
|