Crates.io | x509-path-finder |
lib.rs | x509-path-finder |
version | 0.7.1 |
source | src |
created_at | 2023-08-24 14:52:22.834308 |
updated_at | 2023-09-20 06:06:23.211062 |
description | X509 Path Finder is a depth-first search certificate path validator for Rust. |
homepage | https://ciphx.com |
repository | https://github.com/merlincinematic/x509-path-finder |
max_upload_size | |
id | 953878 |
size | 314,555 |
X509 Path Finder is a depth-first search certificate path validator for Rust.
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:
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. If the path is rejected, the search continues.
X509 Path Finder provides two PathValidator
implementations:
openssl
feature flagImplementing PathValidator
itself is trivial, but safe X509 path validation is not. Engineers are encouraged to use a trusted X509 path validator for the foundation of their PathValidator
implementations, and stack business logic on top.
By default, the provided DefaultPathValidator validator is available.
[dependencies]
x509_path_finder = { version = "*"] }
Enable the openssl
feature for access to the provided OpenSSLPathValidator validator.
[dependencies]
x509_path_finder = { version = "*", features = ["openssl"] }
use webpki::{KeyUsage, TrustAnchor};
use std::sync::Arc;
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<Arc<x509_path_finder::Certificate>>,
ee: x509_path_finder::Certificate,
) -> Result<(), x509_path_finder::X509PathFinderError> {
// instantiate default validator
let root = TrustAnchor::try_from_cert_der(root.as_slice()).unwrap();
let algorithms = &[&webpki::ECDSA_P256_SHA256];
let validator = DefaultPathValidator::new(algorithms, vec![root], KeyUsage::client_auth(), &[]);
// instantiate the finder
let mut search = X509PathFinder::new(X509PathFinderConfiguration {
limit: Duration::default(),
aia: None,
validator,
certificates: ic,
});
// execute the search
let found = search.find(ee).await?.found.unwrap();
// path has two certificates
assert_eq!(2, found.path.len());
// Found is also an iterator over path
assert_eq!(2, found.into_iter().count());
Ok(())
}
The X509 Path Builder is configured with the X509PathFinderConfiguration
struct, which has the following fields:
limit
: limit execution time of path search. Actual limit will be N * HTTP timeout. See reqwest::ClientBuilder::timeout
for setting HTTP connection timeout.aia
: optional x509_client::X509ClientConfiguration
to enable Authority Information Access extensions.validator
: PathValidator
implementationcertificates
: additional intermediate, bridge and cross signed-certificates to use for path finding. These certificates are considered for path candidacy first, and are tried in order.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:
limit
duration to non-zero for X509PathFinderConfiguration::limit
reqwest::ClientBuilder::timeout
to a more aggressive valuex509_client::X509ClientConfiguration::limit
to a non-zero valueCall 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
: on path find success, contains Found
duration
: duration of path searchstore
: collection of cached Certificate
not used in a discovered pathfailures
: any validation failures reported by PathValidator
implementations are held in ValidationFailure
The Found
struct contains following fields:
Certificate
The path includes the target certificate. Per RFC 5246, the path is ordered starting with the target, toward the trust anchor.CertificateOrigin
Found
is also an iterator over references of members of path
.
CertificateOrigin
is an enum that describes the origin of each certificate. Can be one of:
Target
: the initial certificate when calling X509PathFinder::find
.Store
: certificate was found in the storeUrl
: certificate was downloaded from a URL (AIA)ValidationFailure
stores any validation failures. Validation failures can occur even though a valid certificate path was eventually discovered. ValidateFailure
contains the following fields:
path
- Vec path of Certificate
where the validation error occurredorigin
: the CertificateOrigin
of where the validation error occurredreason
: human-readable reason for the failureValidationFailure
is also an iterator over references of members of path
.
The X509 PathValidator
API can be implemented to use different backend authorities to validate certificate paths and add business logic, especially policy constraints.
Ordered by priority:
PathValidator
to reject the entire path candidate