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 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.

Validators can be implemented with one method. To get users started, X509 Path Finder ships with an OpenSSL validator.

Usage

By default, you'll need to implement your own PathValidator.

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

Or, enable the openssl feature for access to the provided OpenSSLPathValidator validator.

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

Example

```` rust no_run

use x509pathfinder::api::CertificateStore; use x509pathfinder::provided::certificate::openssl::OpenSSLCertificateIterator; use x509pathfinder::provided::store::DefaultCertificateStore; use x509pathfinder::provided::validator::openssl::OpenSSLPathValidator; use x509pathfinder::{X509PathFinder, X509PathFinderConfiguration, X509PathFinderResult, AIA, NoAIA}; use openssl::x509::store::{X509Store, X509StoreBuilder}; use openssl::x509::verify::X509VerifyFlags; use openssl::x509::X509; use std::marker::PhantomData; use std::time::Duration;

async fn test() -> X509PathFinderResult<()> { // load certificates let (root, certificates) = load_certificates().unwrap();

// create store, load in certificates
let store = DefaultCertificateStore::from_iter(&certificates);

// build openssl store for validator
let openssl_store = build_openssl_store(root).unwrap();

// Instantiate validator with OpenSSL store
let validator = OpenSSLPathValidator::new(openssl_store);

// Instantiate finder with store and validator
let mut finder = X509PathFinder::new(X509PathFinderConfiguration {
    limit: Duration::default(),
    aia: AIA::None(NoAIA::default()),
    store,
    validator,
});

// Find a path, starting with first certificate
let report = finder.find(certificates[0].as_ref()).await?;
let path = report.path.unwrap().into_iter().collect::<Vec<X509>>();
assert_eq!(2, path.len());

// Find a path, starting with second certificate
let report = finder.find(certificates[1].as_ref()).await?;
let path = report.path.unwrap().into_iter().collect::<Vec<X509>>();
assert_eq!(1, path.len());

Ok(())

}

// load certificates with OpenSSL fn loadcertificates() -> Result<(X509, Vec), openssl::error::ErrorStack> { let root = X509::frompem(&[])?; let certificates = X509::stackfrompem(&[])?; Ok((root, certificates)) }

// create OpenSSL store fn buildopensslstore(root: X509) -> Result { let mut builder = X509StoreBuilder::new()?; builder.addcert(root)?; builder.setflags(X509VerifyFlags::X509_STRICT)?; Ok(builder.build()) }

````

Configuration

The X509PathFinderConfiguration struct has the following fields.

To enable AIA: text AIA::Client(MyX509Client::new())

To disable AIA: text AIA::None(NoAIA::default())
* store - CertificateStore implementation * validator: PathValidator implementation

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 vast amounts of data. Configuration options for managing X509 Path Finder resources:

Finding Paths

Call X509PathFinder::find to start the search.

The returning Report contains the following fields:

CertificatePath

CertificatePath is an iterator over a list of certificates.

CertificateOrigin

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

  1. Find: 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

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

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

API

X509 Path Finder can be extended with three traits:

Implementations

The following API implementations are provided with the X509 Path Finder crate:

Certificate

CertificateStore

PathValidator

TODO