X509 Path Finder

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

CI Status

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.2"] }

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

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

Example

```` rust use x509pathfinder::api::CertificateStore; use x509pathfinder::provided::certificate::openssl::OpenSSLCertificateIterator; use x509pathfinder::provided::store::DefaultCertificateStore; use x509pathfinder::provided::validator::openssl::OpenSSLPathValidator; use x509pathfinder::report::CertificateOrigin; use x509pathfinder::{X509ClientType, X509PathFinder, X509PathFinderConfiguration}; use openssl::x509::store::X509StoreBuilder; use openssl::x509::verify::X509VerifyFlags; use openssl::x509::X509; use std::marker::PhantomData; use std::time::Duration;

[tokio::test]

async fn test() { // load certificates with OpenSSL let certificates = X509::stackfrompem(loadcertificate())?; let root = X509::fromder(load_root())?;

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

// create OpenSSL store
let mut builder = X509StoreBuilder::new()?;
builder.add_cert(root)?;
builder.set_flags(X509VerifyFlags::X509_STRICT)?;

// Instantiate validator with OpenSSL store
let validator = OpenSSLPathValidator::new(builder.build());

// Instantiate finder with store and validator
let mut finder = X509PathFinder::new(X509PathFinderConfiguration {
    limit: Duration::default(),
    client: X509ClientType::None(PhantomData::<OpenSSLCertificateIterator>),
    store,
    validator,
});

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

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

}

````

Configuration

The X509PathFinderConfiguration struct has the following fields.

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