webpki-roots
Advanced tools
| { | ||
| "git": { | ||
| "sha1": "e37165d9958757a6a1a96155c1eaad50cf40d768" | ||
| "sha1": "65a47ac297fb378a602472d447b1260439253bd4" | ||
| }, | ||
| "path_in_vcs": "webpki-roots" | ||
| } |
+11
-1
@@ -801,3 +801,3 @@ # This file is automatically @generated by Cargo. | ||
| name = "webpki-roots" | ||
| version = "0.26.10" | ||
| version = "0.26.11" | ||
| dependencies = [ | ||
@@ -812,2 +812,3 @@ "hex", | ||
| "tokio", | ||
| "webpki-roots 1.0.0", | ||
| "x509-parser", | ||
@@ -818,2 +819,11 @@ "yasna", | ||
| [[package]] | ||
| name = "webpki-roots" | ||
| version = "1.0.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" | ||
| dependencies = [ | ||
| "rustls-pki-types", | ||
| ] | ||
| [[package]] | ||
| name = "which" | ||
@@ -820,0 +830,0 @@ version = "4.4.2" |
+9
-9
@@ -15,3 +15,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "webpki-roots" | ||
| version = "0.26.10" | ||
| version = "0.26.11" | ||
| build = false | ||
@@ -34,13 +34,8 @@ autolib = false | ||
| [[test]] | ||
| name = "codegen" | ||
| path = "tests/codegen.rs" | ||
| [[test]] | ||
| name = "verify" | ||
| path = "tests/verify.rs" | ||
| [dependencies.pki-types] | ||
| version = "1.8" | ||
| default-features = false | ||
| package = "rustls-pki-types" | ||
| [dependencies.parent] | ||
| version = "1" | ||
| package = "webpki-roots" | ||
@@ -53,2 +48,7 @@ [dev-dependencies.hex] | ||
| [dev-dependencies.pki-types] | ||
| version = "1.8" | ||
| default-features = false | ||
| package = "rustls-pki-types" | ||
| [dev-dependencies.rcgen] | ||
@@ -55,0 +55,0 @@ version = "0.13" |
-172
| use std::ascii::escape_default; | ||
| use std::fmt::Write; | ||
| use std::fs; | ||
| use pki_types::CertificateDer; | ||
| use ring::digest; | ||
| use webpki::anchor_from_trusted_cert; | ||
| use webpki_ccadb::fetch_ccadb_roots; | ||
| use x509_parser::prelude::AttributeTypeAndValue; | ||
| use x509_parser::x509::X509Name; | ||
| #[tokio::test] | ||
| async fn new_generated_code_is_fresh() { | ||
| let tls_roots_map = fetch_ccadb_roots().await; | ||
| let mut code = String::with_capacity(256 * 1_024); | ||
| code.push_str(HEADER); | ||
| code.push_str("pub const TLS_SERVER_ROOTS: &[TrustAnchor<'static>] = &[\n"); | ||
| let (mut subject, mut spki, mut name_constraints) = | ||
| (String::new(), String::new(), String::new()); | ||
| for root in tls_roots_map.values() { | ||
| // Verify the DER FP matches the metadata FP. | ||
| let der = root.der(); | ||
| let calculated_fp = digest::digest(&digest::SHA256, &der); | ||
| let metadata_fp = hex::decode(&root.sha256_fingerprint).expect("malformed fingerprint"); | ||
| assert_eq!(calculated_fp.as_ref(), metadata_fp.as_slice()); | ||
| let ta_der = CertificateDer::from(der.as_ref()); | ||
| let ta = anchor_from_trusted_cert(&ta_der).expect("malformed trust anchor der"); | ||
| subject.clear(); | ||
| for &b in ta.subject.as_ref() { | ||
| write!(&mut subject, "{}", escape_default(b)).unwrap(); | ||
| } | ||
| spki.clear(); | ||
| for &b in ta.subject_public_key_info.as_ref() { | ||
| write!(&mut spki, "{}", escape_default(b)).unwrap(); | ||
| } | ||
| name_constraints.clear(); | ||
| if let Some(nc) = &root.mozilla_applied_constraints() { | ||
| for &b in nc.iter() { | ||
| write!(&mut name_constraints, "{}", escape_default(b)).unwrap(); | ||
| } | ||
| } | ||
| let (_, parsed_cert) = | ||
| x509_parser::parse_x509_certificate(&der).expect("malformed x509 der"); | ||
| let issuer = name_to_string(parsed_cert.issuer()); | ||
| let subject_str = name_to_string(parsed_cert.subject()); | ||
| let label = root.common_name_or_certificate_name.clone(); | ||
| let serial = root.serial().to_string(); | ||
| let sha256_fp = root.sha256_fp(); | ||
| // Write comment | ||
| code.push_str(" /*\n"); | ||
| code.push_str(&format!(" * Issuer: {issuer}\n")); | ||
| code.push_str(&format!(" * Subject: {subject_str}\n")); | ||
| code.push_str(&format!(" * Label: {label:?}\n")); | ||
| code.push_str(&format!(" * Serial: {serial}\n")); | ||
| code.push_str(&format!(" * SHA256 Fingerprint: {sha256_fp}\n")); | ||
| for ln in root.pem().lines() { | ||
| code.push_str(" * "); | ||
| code.push_str(ln.trim()); | ||
| code.push('\n'); | ||
| } | ||
| code.push_str(" */\n"); | ||
| // Write the code | ||
| code.push_str(" TrustAnchor {\n"); | ||
| code.write_fmt(format_args!( | ||
| " subject: Der::from_slice(b\"{subject}\"),\n" | ||
| )) | ||
| .unwrap(); | ||
| code.write_fmt(format_args!( | ||
| " subject_public_key_info: Der::from_slice(b\"{spki}\"),\n" | ||
| )) | ||
| .unwrap(); | ||
| match name_constraints.is_empty() { | ||
| false => code | ||
| .write_fmt(format_args!( | ||
| " name_constraints: Some(Der::from_slice(b\"{name_constraints}\"))\n" | ||
| )) | ||
| .unwrap(), | ||
| true => code.push_str(" name_constraints: None\n"), | ||
| } | ||
| code.push_str(" },\n\n"); | ||
| } | ||
| code.push_str("];\n"); | ||
| // Check that the generated code matches the checked-in code | ||
| let old = fs::read_to_string("src/lib.rs").unwrap(); | ||
| if old != code { | ||
| fs::write("src/lib.rs", code).unwrap(); | ||
| panic!("generated code changed"); | ||
| } | ||
| } | ||
| /// The built-in x509_parser::X509Name Display impl uses a different sort order than | ||
| /// the one historically used by mkcert.org^[0]. We re-create that sort order here to | ||
| /// avoid unnecessary churn in the generated code. | ||
| /// | ||
| /// [0]: <https://github.com/Lukasa/mkcert/blob/6911a8f68681f4d6a795c1f6db7b063f75b03b5a/certs/convert_mozilla_certdata.go#L405-L428> | ||
| fn name_to_string(name: &X509Name) -> String { | ||
| let mut ret = String::with_capacity(256); | ||
| if let Some(cn) = name | ||
| .iter_common_name() | ||
| .next() | ||
| .and_then(|cn| cn.as_str().ok()) | ||
| { | ||
| write!(ret, "CN={cn}").unwrap(); | ||
| } | ||
| let mut append_attrs = |attrs: Vec<&AttributeTypeAndValue>, label| { | ||
| let str_parts = attrs | ||
| .iter() | ||
| .filter_map(|attr| attr.as_str().ok()) | ||
| .collect::<Vec<_>>() | ||
| .join("/"); | ||
| if !str_parts.is_empty() { | ||
| if !ret.is_empty() { | ||
| ret.push(' '); | ||
| } | ||
| write!(ret, "{label}={str_parts}").unwrap(); | ||
| } | ||
| }; | ||
| append_attrs(name.iter_organization().collect(), "O"); | ||
| append_attrs(name.iter_organizational_unit().collect(), "OU"); | ||
| ret | ||
| } | ||
| const HEADER: &str = r#"//! A compiled-in copy of the root certificates trusted by Mozilla. | ||
| //! | ||
| //! To use this library with rustls 0.22: | ||
| //! | ||
| //! ```rust | ||
| //! let root_store = rustls::RootCertStore { | ||
| //! roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(), | ||
| //! }; | ||
| //! ``` | ||
| //! | ||
| //! This library is suitable for use in applications that can always be recompiled and instantly deployed. | ||
| //! For applications that are deployed to end-users and cannot be recompiled, or which need certification | ||
| //! before deployment, consider a library that uses the platform native certificate verifier such as | ||
| //! [rustls-platform-verifier]. This has the additional benefit of supporting OS provided CA constraints | ||
| //! and revocation data. | ||
| //! | ||
| //! [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier | ||
| // | ||
| // This library is automatically generated from the Mozilla | ||
| // IncludedCACertificateReportPEMCSV report via ccadb.org. Don't edit it. | ||
| // | ||
| // The generation is done deterministically so you can verify it | ||
| // yourself by inspecting and re-running the generation process. | ||
| #![no_std] | ||
| #![forbid(unsafe_code, unstable_features)] | ||
| #![deny( | ||
| elided_lifetimes_in_paths, | ||
| trivial_casts, | ||
| trivial_numeric_casts, | ||
| unused_import_braces, | ||
| unused_extern_crates, | ||
| unused_qualifications | ||
| )] | ||
| use pki_types::{Der, TrustAnchor}; | ||
| "#; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display