1use rustls_pki_types::pem::PemObject;
2use rustls_pki_types::{CertificateDer, ServerName, UnixTime};
3use webpki::{EndEntityCert, KeyUsage, anchor_from_trusted_cert};
4
5fn cert(path: &str) -> CertificateDer<'static> {
6 CertificateDer::from_pem_file(path).expect(path)
7}
8
9/// Path building and validation as rustls does it: signatures, validity, CA and
10/// key usage constraints, then the host name. Returns the error, if any.
11fn verify(leaf: &str, intermediates: &[&str], root: &str, host: &str) -> Result<(), webpki::Error> {
12 let root = cert(root);
13 let anchors = [anchor_from_trusted_cert(&root)?];
14 let intermediates: Vec<_> = intermediates.iter().map(|p| cert(p)).collect();
15 let leaf_der = cert(leaf);
16 let leaf = EndEntityCert::try_from(&leaf_der)?;
17 leaf.verify_for_usage(
18 webpki::ALL_VERIFICATION_ALGS, // ring-backed algorithms (feature "ring")
19 &anchors,
20 &intermediates,
21 UnixTime::now(),
22 KeyUsage::server_auth(),
23 None, // revocation: no CRLs for a test CA
24 None,
25 )?;
26 leaf.verify_is_valid_for_subject_name(&ServerName::try_from(host).expect("host name"))
27}
28
29fn main() {
30 println!("good chain: {:?}", verify("leaf.pem", &["intermediate.pem"], "root.pem", "api.example.com"));
31 println!("impostor root: {:?}", verify("leaf.pem", &["intermediate.pem"], "impostor-root.pem", "api.example.com"));
32 println!("expired leaf: {:?}", verify("expired.pem", &["intermediate.pem"], "root.pem", "expired.example.com"));
33 println!("missing intermediate: {:?}", verify("leaf.pem", &[], "root.pem", "api.example.com"));
34 println!("wrong host: {:?}", verify("leaf.pem", &["intermediate.pem"], "root.pem", "example.org"));
35}
36