diff --git a/Cargo.toml b/Cargo.toml index 98bdd949..5d3bc3f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ include = [ "tests/dns_name_tests.rs", "tests/integration.rs", + "tests/misc/selfsigned.der", "tests/misc/serial_neg.der", "tests/misc/serial_zero.der", "tests/netflix/ca.der", diff --git a/src/verify_cert.rs b/src/verify_cert.rs index 1a52b7b1..17906046 100644 --- a/src/verify_cert.rs +++ b/src/verify_cert.rs @@ -28,13 +28,17 @@ pub fn build_chain( ) -> Result<(), Error> { let used_as_ca = used_as_ca(&cert.ee_or_ca); - check_issuer_independent_properties( + let must_be_self_signed = match check_issuer_independent_properties( cert, time, used_as_ca, sub_ca_count, required_eku_if_present, - )?; + ) { + Ok(()) => false, + Err(Error::CAUsedAsEndEntity) => true, + Err(e) => return Err(e), + }; // TODO: HPKP checks. @@ -71,6 +75,10 @@ pub fn build_chain( check_signatures(supported_sig_algs, cert, trust_anchor_spki)?; + if must_be_self_signed && trust_anchor_subject != cert.subject { + return Err(Error::CAUsedAsEndEntity); + } + Ok(()) }) { Ok(()) => { @@ -81,6 +89,10 @@ pub fn build_chain( } } + if must_be_self_signed { + return Err(Error::CAUsedAsEndEntity); + } + loop_while_non_fatal_error(intermediate_certs, |cert_der| { let potential_issuer = cert::parse_cert(untrusted::Input::from(*cert_der), EndEntityOrCA::CA(&cert))?; diff --git a/tests/integration.rs b/tests/integration.rs index 8e7abddc..f0053b68 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -84,6 +84,23 @@ fn read_root_with_neg_serial() { .expect("idcat cert should parse as anchor"); } +#[test] +fn selfsigned() { + let cert = include_bytes!("misc/selfsigned.der"); + + let anchors = vec![webpki::trust_anchor_util::cert_der_as_trust_anchor(cert).unwrap()]; + let anchors = webpki::TLSServerTrustAnchors(&anchors); + + #[allow(clippy::unreadable_literal)] // TODO: Make this clear. + let time = webpki::Time::from_seconds_since_unix_epoch(1610233207); + + let cert = webpki::EndEntityCert::from(cert).unwrap(); + assert_eq!( + Ok(()), + cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[], time) + ); +} + #[cfg(feature = "std")] #[test] fn time_constructor() { diff --git a/tests/misc/selfsigned.der b/tests/misc/selfsigned.der new file mode 100644 index 00000000..1e0a5023 Binary files /dev/null and b/tests/misc/selfsigned.der differ