X509 Path Finder

X509 Path Finder is a depth-first search certificate path validator for Rust.

CI Status

Depth-first search

Synopsis

X509 Path Finder is inspired by RFC 4158:

Many PKIs are now using complex structures... rather than simple hierarchies. Additionally, some enterprises are gradually moving away from trust lists filled with many trust anchors, and toward an infrastructure with one trust anchor and many cross-certified relationships.... This document suggests using an effective general approach to path building that involves a depth first tree traversal.

X509 Path Finder rejects the notion of a single certificate "chain." Instead, it searches for the first match out of infinity. Once it finds a path it can validate, the search halts and the path is returned to the caller.

The complexity of the path search is constrained by three factors:

  1. Number of certificates preloaded into its local store
  2. Number of certificates it can find and download by following AIA URLs
  3. An arbitrary time limit

When evaluating a path candidate for validation, X509 Path Finder is implementation-agnostic. Once it finds a path that has terminated, it presents it to be validated by a backend authority. If the authority validates the path, the search halts and the path is returned.

X509 Path Finder provides two validators:

  1. DefaultPathValidator - implemented with RustCrypto and Rustls, available by default.
  2. OpenSSLPathValidator - implemented with Rust OpenSSL, available with the openssl feature flag

Usage

By default, the provided DefaultPathValidator validator is available.

text [dependencies] x509_path_finder = { version = "0.5"] }

Enable the openssl feature for access to the provided OpenSSLPathValidator validator.

text [dependencies] x509_path_finder = { version = "0.5", features = ["openssl"] }

Example

```` rust no_run

use rustls::{Certificate as RustlsCertificate, RootCertStore};
use std::time::Duration;
use x509_path_finder::provided::validator::default::DefaultPathValidator;
use x509_path_finder::{X509PathFinder, X509PathFinderConfiguration};

async fn test_find(
    root: Vec<u8>,
    ic: Vec<x509_path_finder::Certificate>,
    ee: x509_path_finder::Certificate,
) -> Result<(), x509_path_finder::X509PathFinderError> {
    // create Rustls store
    let mut store = RootCertStore::empty();

    // add root certificate to store
    let root = RustlsCertificate(root);
    store.add(&root).unwrap();

    // instantiate default validator
    let validator = DefaultPathValidator::new(store);

    // instantiate the finder
    let search = X509PathFinder::new(X509PathFinderConfiguration {
        limit: Duration::default(),
        aia: None,
        validator: &validator,
        certificates: ic,
    });

    // execute the search
    let found = search.find(ee).await?.found.unwrap();

    // path has two certificates
    assert_eq!(2, found.path.len());

    Ok(())
}

````

Configuration

The X509 Path Builder is configured with the X509PathFinderConfiguration struct, which has the following fields:

Resource Management

Because X509 Path Builder can consume AIA URLs from the web, a call to X509PathFinder::find could in theory run forever, or be coerced into downloading large amounts of data. Resource consumption can be managed with the following configuration settings:

Finding Paths

Call X509PathFinder::find to find a path. Supply the target end-entity Certificate to start from. The search will work backward toward the root certificate.

The returning Report contains the following fields:

Found

The Found struct contains following fields:

CertificateOrigin

CertificateOrigin is an enum that describes the origin of each certificate. Can be one of:

  1. Target: the initial certificate when calling X509PathFinder::find.
  2. Store: certificate was found in the store
  3. Url: certificate was downloaded from a URL (AIA)

ValidateFailure

ValidationFailure stores any validation failures. Validation failures can occur even though a valid certificate path was eventually discovered. ValidateFailure contains the following fields:

  1. origin: the CertificateOrigin of where the validation error occurred
  2. reason: human-readable reason for the failure

API

The X509 PathValidator API can be implemented to use different backend authorities to validate certificate paths and add business logic, especially policy constraints.

Implementations

TODO