diff --git a/rustls-platform-verifier/src/tests/mod.rs b/rustls-platform-verifier/src/tests/mod.rs index 134a20f..b9035a7 100644 --- a/rustls-platform-verifier/src/tests/mod.rs +++ b/rustls-platform-verifier/src/tests/mod.rs @@ -62,8 +62,8 @@ pub fn assert_cert_error_eq( /// we know the test certificates are valid. This must be updated if the mock certificates /// are regenerated. pub(crate) fn verification_time() -> pki_types::UnixTime { - // Sat, 3 January 2026 14:20:06 UTC - pki_types::UnixTime::since_unix_epoch(Duration::from_secs(1_767_450_006)) + // Thu, 29 January 2026 04:14:44 UTC + pki_types::UnixTime::since_unix_epoch(Duration::from_secs(1_769_660_084)) } fn test_provider() -> Arc { diff --git a/rustls-platform-verifier/src/tests/verification_mock/ca.go b/rustls-platform-verifier/src/tests/verification_mock/ca.go index ec3b4de..240bfde 100644 --- a/rustls-platform-verifier/src/tests/verification_mock/ca.go +++ b/rustls-platform-verifier/src/tests/verification_mock/ca.go @@ -69,7 +69,7 @@ func doIt() error { var err error = nil - root1_key, err := generateRoot("root1", now) + root1_key, err := generateRoot("root1", now, "") if err != nil { return err } @@ -96,6 +96,11 @@ func doIt() error { } } + _, err = generateRoot("root2", now, "example.com") + if err != nil { + return err + } + return nil } @@ -210,11 +215,12 @@ func generateInt(intName string, serial int64, now time.Time, caKey crypto.Signe return intKey, nil } -func generateRoot(name string, now time.Time) (crypto.Signer, error) { +func generateRoot(name string, now time.Time, commonName string) (crypto.Signer, error) { caKey, err := generateKey() if err != nil { return nil, err } + template := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ @@ -227,6 +233,14 @@ func generateRoot(name string, now time.Time) (crypto.Signer, error) { BasicConstraintsValid: true, } + if len(commonName) != 0 { + template.Subject.CommonName = commonName + template.KeyUsage = 0 + // See `generateEndEntity` for list of macOS requirements. + template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} + template.DNSNames = []string{commonName} + } + cert, err := x509.CreateCertificate(rand.Reader, &template, &template, caKey.Public(), caKey) if err != nil { return nil, err diff --git a/rustls-platform-verifier/src/tests/verification_mock/mod.rs b/rustls-platform-verifier/src/tests/verification_mock/mod.rs index 38a2686..0e8e322 100644 --- a/rustls-platform-verifier/src/tests/verification_mock/mod.rs +++ b/rustls-platform-verifier/src/tests/verification_mock/mod.rs @@ -28,7 +28,7 @@ use std::net::{Ipv4Addr, Ipv6Addr}; use std::sync::Arc; use rustls::client::danger::ServerCertVerifier; -use rustls::pki_types; +use rustls::pki_types::{self, CertificateDer}; #[cfg(not(any(target_vendor = "apple", windows)))] use rustls::pki_types::{DnsName, ServerName}; use rustls::{CertificateError, Error as TlsError, OtherError}; @@ -80,13 +80,17 @@ macro_rules! no_error { }; } -const ROOT1: pki_types::CertificateDer<'static> = - pki_types::CertificateDer::from_slice(include_bytes!("root1.crt")); +const ROOT1: CertificateDer = CertificateDer::from_slice(include_bytes!("root1.crt")); const ROOT1_INT1: &[u8] = include_bytes!("root1-int1.crt"); const ROOT1_INT1_EXAMPLE_COM_GOOD: &[u8] = include_bytes!("root1-int1-ee_example.com-good.crt"); const ROOT1_INT1_LOCALHOST_IPV4_GOOD: &[u8] = include_bytes!("root1-int1-ee_127.0.0.1-good.crt"); const ROOT1_INT1_LOCALHOST_IPV6_GOOD: &[u8] = include_bytes!("root1-int1-ee_1-good.crt"); +// `ffi-testing` is currently only used for Android, which doesn't support extra roots yet. +#[cfg_attr(feature = "ffi-testing", allow(unused))] +#[cfg(not(any(target_os = "android", target_os = "windows")))] +const ROOT2: CertificateDer = CertificateDer::from_slice(include_bytes!("root2.crt")); + const EXAMPLE_COM: &str = "example.com"; const LOCALHOST_IPV4: &str = "127.0.0.1"; const LOCALHOST_IPV6: &str = "::1"; @@ -111,8 +115,8 @@ pub(super) fn verification_without_mock_root() { let verifier = Verifier::new(crypto_provider).unwrap(); let server_name = pki_types::ServerName::try_from(EXAMPLE_COM).unwrap(); - let end_entity = pki_types::CertificateDer::from(ROOT1_INT1_EXAMPLE_COM_GOOD); - let intermediates = [pki_types::CertificateDer::from(ROOT1_INT1)]; + let end_entity = CertificateDer::from(ROOT1_INT1_EXAMPLE_COM_GOOD); + let intermediates = [CertificateDer::from(ROOT1_INT1)]; // Fails because the server cert has no trust root in Windows, and can't since it uses a self-signed CA. // Similarly on UNIX platforms using the Webpki verifier, it can't fetch extra certificates through @@ -139,6 +143,45 @@ fn test_verification_without_mock_root() { verification_without_mock_root() } +#[cfg(not(any(target_os = "android", target_os = "windows")))] +#[test] +fn test_selfsigned_cert_with_extra_roots() { + let crypto_provider = test_provider(); + + let selfsigned = ROOT2; + let roots = vec![selfsigned.clone()]; + let server_name = pki_types::ServerName::try_from(EXAMPLE_COM).unwrap(); + + let verifier = Verifier::new_with_extra_roots(roots, crypto_provider).unwrap(); + + verifier + .verify_server_cert(&selfsigned, &[], &server_name, &[], verification_time()) + .expect("failed to validate singular extra root certificate chain"); +} + +#[cfg(not(target_os = "android"))] +#[test] +fn test_chain_signed_with_extra_roots() { + let crypto_provider = test_provider(); + + let server_name = pki_types::ServerName::try_from(EXAMPLE_COM).unwrap(); + let end_entity = CertificateDer::from(ROOT1_INT1_EXAMPLE_COM_GOOD); + let intermediates = [CertificateDer::from(ROOT1_INT1)]; + let roots = vec![ROOT1]; + + let verifier = Verifier::new_with_extra_roots(roots, crypto_provider).unwrap(); + + verifier + .verify_server_cert( + &end_entity, + &intermediates, + &server_name, + &[], + verification_time(), + ) + .expect("failed to validate extra root-only certificate chain"); +} + // Note: Android does not currently support IP address hosts, so these tests are disabled for // Android. // Verifies that our test trust anchor(s) are not trusted when `Verifier::new()` @@ -349,10 +392,10 @@ fn test_with_mock_root( let mut chain = test_case .chain .iter() - .map(|bytes| pki_types::CertificateDer::from(*bytes)); + .map(|bytes| CertificateDer::from(*bytes)); let end_entity = chain.next().unwrap(); - let intermediates: Vec> = chain.collect(); + let intermediates: Vec> = chain.collect(); let server_name = pki_types::ServerName::try_from(test_case.reference_id).unwrap(); diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.crt index 0968a95..5dd93cb 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.ocsp index 66e49a7..3028e4b 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.ocsp and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.ocsp differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.crt index b4f4012..ae7723a 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp index 3b4aa06..30be5af 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt index b547d64..efcb092 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt index 70b398f..9dd7947 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp index e920cd3..baeafb8 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt index 156afaa..8978ef0 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp index 6dff38e..a194517 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt index 17bdbc0..841a17b 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.crt index 0c2364f..c1f6c5b 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp index 028baa2..a05efbe 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt index bf6c751..3349e9e 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp index bbd64a3..59e7278 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt index e311b4f..80dd67a 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1-int1.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1.crt index 7c059e5..6b2159b 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1-int1.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1-int1.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root1.crt b/rustls-platform-verifier/src/tests/verification_mock/root1.crt index 0292e4c..d84653d 100644 Binary files a/rustls-platform-verifier/src/tests/verification_mock/root1.crt and b/rustls-platform-verifier/src/tests/verification_mock/root1.crt differ diff --git a/rustls-platform-verifier/src/tests/verification_mock/root2.crt b/rustls-platform-verifier/src/tests/verification_mock/root2.crt new file mode 100644 index 0000000..19427fa Binary files /dev/null and b/rustls-platform-verifier/src/tests/verification_mock/root2.crt differ