From 67eeedd54a29a9ef72dabf27604a1849df7973bc Mon Sep 17 00:00:00 2001 From: peg Date: Thu, 16 Apr 2026 12:35:54 +0200 Subject: [PATCH] Dont allow unknown issuer when we have a custom root-of-trust --- crates/attested-tls/src/lib.rs | 100 +++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 16 deletions(-) diff --git a/crates/attested-tls/src/lib.rs b/crates/attested-tls/src/lib.rs index 1260e0b..a7ded0c 100644 --- a/crates/attested-tls/src/lib.rs +++ b/crates/attested-tls/src/lib.rs @@ -663,20 +663,13 @@ impl ServerCertVerifier for AttestedCertificateVerifier { now: UnixTime, ) -> Result { if let Some(server_inner) = &self.server_inner { - match server_inner.verify_server_cert( + server_inner.verify_server_cert( end_entity, intermediates, server_name, ocsp_response, now, - ) { - Err(rustls::Error::InvalidCertificate(rustls::CertificateError::UnknownIssuer)) => { - // handle self-signed certs differently - Self::verify_server_cert_constraints(end_entity, server_name, now)?; - } - Err(err) => return Err(err), - Ok(_) => {} - } + )?; } else { Self::verify_server_cert_constraints(end_entity, server_name, now)?; } @@ -741,13 +734,7 @@ impl ClientCertVerifier for AttestedCertificateVerifier { now: UnixTime, ) -> Result { if let Some(client_inner) = &self.client_inner { - match client_inner.verify_client_cert(end_entity, intermediates, now) { - Err(rustls::Error::InvalidCertificate(rustls::CertificateError::UnknownIssuer)) => { - Self::verify_cert_time_validity(end_entity, now)?; - } - Err(err) => return Err(err), - Ok(_) => {} - } + client_inner.verify_client_cert(end_entity, intermediates, now)?; } else { Self::verify_cert_time_validity(end_entity, now)?; } @@ -853,6 +840,20 @@ mod tests { ) } + /// Test helper to verify a client certificate + fn verify_client_cert_direct( + verifier: &AttestedCertificateVerifier, + end_entity: &CertificateDer<'_>, + now: UnixTime, + ) -> Result { + rustls::server::danger::ClientCertVerifier::verify_client_cert( + verifier, + end_entity, + &[], + now, + ) + } + #[tokio::test(flavor = "multi_thread")] async fn certificate_resolver_creates_initial_certificate() { let provider: Arc = aws_lc_rs::default_provider().into(); @@ -1190,6 +1191,73 @@ mod tests { assert_eq!(result.unwrap_err(), Error::InvalidCertificate(CertificateError::BadEncoding)); } + #[tokio::test(flavor = "multi_thread")] + async fn private_ca_verifier_rejects_untrusted_self_signed_attested_server_cert() { + let provider: Arc = aws_lc_rs::default_provider().into(); + let ca = test_ca(); + let ca_cert = CertificateDer::from_pem_slice(ca.pem_cert.as_bytes()).unwrap(); + let resolver = AttestedCertificateResolver::new_with_provider( + AttestationGenerator::new(AttestationType::DcapTdx, None).unwrap(), + None, + "foo".to_string(), + vec![], + provider.clone(), + Duration::from_secs(4), + ) + .await + .unwrap(); + let cert = resolver.state.certificate.read().unwrap().first().unwrap().clone(); + + let mut roots = RootCertStore::empty(); + roots.add(ca_cert).unwrap(); + let verifier = AttestedCertificateVerifier::new_with_provider( + Some(roots), + AttestationVerifier::mock(), + provider, + ) + .unwrap(); + + let result = verify_server_cert_direct( + &verifier, + &cert, + &ServerName::try_from("foo").unwrap(), + UnixTime::now(), + ); + + assert_eq!(result.unwrap_err(), Error::InvalidCertificate(CertificateError::UnknownIssuer)); + } + + #[tokio::test(flavor = "multi_thread")] + async fn private_ca_verifier_rejects_untrusted_self_signed_attested_client_cert() { + let provider: Arc = aws_lc_rs::default_provider().into(); + let ca = test_ca(); + let ca_cert = CertificateDer::from_pem_slice(ca.pem_cert.as_bytes()).unwrap(); + let resolver = AttestedCertificateResolver::new_with_provider( + AttestationGenerator::new(AttestationType::DcapTdx, None).unwrap(), + None, + "client".to_string(), + vec![], + provider.clone(), + Duration::from_secs(4), + ) + .await + .unwrap(); + let cert = resolver.state.certificate.read().unwrap().first().unwrap().clone(); + + let mut roots = RootCertStore::empty(); + roots.add(ca_cert).unwrap(); + let verifier = AttestedCertificateVerifier::new_with_provider( + Some(roots), + AttestationVerifier::mock(), + provider, + ) + .unwrap(); + + let result = verify_client_cert_direct(&verifier, &cert, UnixTime::now()); + + assert_eq!(result.unwrap_err(), Error::InvalidCertificate(CertificateError::UnknownIssuer)); + } + #[tokio::test(flavor = "multi_thread")] async fn self_signed_attested_certificate_with_wrong_name_is_rejected() { let provider: Arc = aws_lc_rs::default_provider().into();