use der::Decode as _;
use pkix_path::{DefaultVerifier, TrustAnchor, ValidationPolicy};
use pkix_path_builder::{build_path, CertPool};
use x509_cert::Certificate;
const PKITS_NOW: u64 = 1_580_000_000;
fn pkits_cert(name: &str) -> Certificate {
let path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../pkix-path/tests/pkits/certs")
.join(format!("{}.crt", name));
let der_bytes = std::fs::read(&path)
.unwrap_or_else(|e| panic!("fixture not found at {}: {}", path.display(), e));
Certificate::from_der(&der_bytes).unwrap_or_else(|e| panic!("failed to parse cert {name}: {e}"))
}
fn pkits_trust_anchor() -> TrustAnchor {
TrustAnchor::from(&pkits_cert("TrustAnchorRootCertificate"))
}
#[test]
fn test_build_path_two_cert_chain() {
let ee = pkits_cert("ValidCertificatePathTest1EE");
let intermediate = pkits_cert("GoodCACert");
let anchor = pkits_trust_anchor();
let mut pool = CertPool::new();
pool.add(intermediate);
let path = build_path(&ee, &pool, &[anchor.clone()])
.expect("build_path should succeed for PKITS §4.1.1 chain");
assert!(
path.len() >= 2,
"path should contain at least EE + intermediate"
);
let policy = ValidationPolicy::new(PKITS_NOW);
let verifier = DefaultVerifier;
pkix_path::validate_path(&path, &[anchor], &policy, &verifier)
.expect("validate_path should succeed on the built chain");
}
#[test]
fn test_build_path_shuffled_order() {
let ee = pkits_cert("ValidCertificatePathTest1EE");
let intermediate = pkits_cert("GoodCACert");
let anchor = pkits_trust_anchor();
let mut pool = CertPool::new();
pool.add(intermediate);
let path = build_path(&ee, &pool, &[anchor.clone()])
.expect("build_path should succeed regardless of pool insertion order");
assert!(path.len() >= 2);
let policy = ValidationPolicy::new(PKITS_NOW);
let verifier = DefaultVerifier;
pkix_path::validate_path(&path, &[anchor], &policy, &verifier)
.expect("validate_path should succeed");
}
#[test]
fn test_build_path_no_path() {
let ee = pkits_cert("ValidCertificatePathTest1EE");
let anchor = pkits_trust_anchor();
let pool = CertPool::new();
let err =
build_path(&ee, &pool, &[anchor]).expect_err("build_path should fail with an empty pool");
assert!(
matches!(err, pkix_path_builder::Error::NoPathFound),
"expected NoPathFound, got {err}"
);
}
#[test]
fn test_build_path_self_signed_non_anchor_in_pool() {
let ee = pkits_cert("ValidCertificatePathTest1EE");
let intermediate = pkits_cert("GoodCACert");
let bad_ca = pkits_cert("BadSignedCACert");
let anchor = pkits_trust_anchor();
let mut pool = CertPool::new();
pool.add(intermediate);
pool.add(bad_ca);
let path = build_path(&ee, &pool, &[anchor.clone()])
.expect("build_path must find the correct path ignoring the self-signed non-anchor");
let policy = pkix_path::ValidationPolicy::new(PKITS_NOW);
let verifier = pkix_path::DefaultVerifier;
pkix_path::validate_path(&path, &[anchor], &policy, &verifier)
.expect("validate_path should succeed on the built chain");
}
#[test]
fn test_build_path_wrong_pool() {
let ee = pkits_cert("ValidCertificatePathTest1EE");
let anchor = pkits_trust_anchor();
let wrong_cert = pkits_cert("BadSignedCACert");
let mut pool = CertPool::new();
pool.add(wrong_cert);
let err = build_path(&ee, &pool, &[anchor])
.expect_err("build_path should fail when pool contains unrelated cert");
assert!(
matches!(err, pkix_path_builder::Error::NoPathFound),
"expected NoPathFound, got {err}"
);
}