From d541a7d401fced018f575d518ae94a517c10407a Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Tue, 11 Jun 2024 12:21:06 -0400 Subject: [PATCH] webpki-ccadb: distrust any CA with a distrust after date This commit update the CCADB codegen to consider any root CA with a distrust for TLS after date as not trusted, irrespective of the distrust date. The rustls/webpki ecosystem this crate supports does not have the capability to enforce a "active distrust" of a TLS trust anchor in the Mozilla root program that has a "Distrust for TLS After Date" date in CCADB. Given this constraint we choose to remove roots immediately when they are given a distrust after date. This is _more_ aggressive than the Mozilla root program but requires no new features implemented in downstream crates. Users needing more nuanced root program enforcement should consider using the rustls-platform-verifier crate. --- webpki-ccadb/src/lib.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/webpki-ccadb/src/lib.rs b/webpki-ccadb/src/lib.rs index 4b883a4..f7ca135 100644 --- a/webpki-ccadb/src/lib.rs +++ b/webpki-ccadb/src/lib.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use std::collections::{BTreeMap, HashSet}; -use chrono::{NaiveDate, Utc}; +use chrono::NaiveDate; use num_bigint::BigUint; use pki_types::CertificateDer; use serde::Deserialize; @@ -58,7 +58,7 @@ pub async fn fetch_ccadb_roots() -> BTreeMap { // Filter for just roots with the TLS trust bit that are not distrusted as of today's date. let trusted_tls_roots = metadata .into_iter() - .filter(|root| root.trusted_for_tls(&Utc::now().naive_utc().date())) + .filter(CertificateMetadata::trusted_for_tls) .collect::>(); // Create an ordered BTreeMap of the roots, panicking for any duplicates. @@ -103,26 +103,22 @@ pub struct CertificateMetadata { impl CertificateMetadata { /// Returns true iff the certificate has valid TrustBits that include TrustBits::Websites, - /// and the certificate has no distrust for TLS after date, or has a valid distrust - /// for TLS after date that is in the future compared to `now`. In all other cases this function + /// and the certificate has no distrust for TLS after date. In all other cases this function /// returns false. - fn trusted_for_tls(&self, now: &NaiveDate) -> bool { + /// + /// Notably this means a trust anchor with a distrust after date _in the future_ is treated + /// as untrusted irrespective of the distrust after date. An end-to-end distrust after solution + /// is NYI: https://github.com/rustls/webpki/issues/259 + fn trusted_for_tls(&self) -> bool { let has_tls_trust_bit = self.trust_bits().contains(&TrustBits::Websites); match (has_tls_trust_bit, self.tls_distrust_after()) { // No website trust bit - not trusted for tls. (false, _) => false, + // Trust bit, populated distrust after - not trusted for tls. + (true, Some(_)) => false, // Has website trust bit, no distrust after - trusted for tls. (true, None) => true, - // Trust bit, populated distrust after - need to check date to decide. - (true, Some(tls_distrust_after)) => { - match now.cmp(&tls_distrust_after).is_ge() { - // We're past the distrust date - skip. - true => false, - // We haven't yet reached the distrust date - include. - false => true, - } - } } }