Library
Module
Module type
Parameter
Class
Class type
X.509 Certificate Chain Validation.
A chain of pairwise signed X.509 certificates is sent to the endpoint, which use these to authenticate the other endpoint. Usually a set of trust anchors is configured on the endpoint, and the chain needs to be rooted in one of the trust anchors. In reality, chains may be incomplete or reversed, and there can be multiple paths from the leaf certificate to a trust anchor.
RFC 5280 specifies a path validation algorithm for authenticating chains, but this does not handle multiple possible paths. RFC 4158 describes possible path building strategies.
This module provides path building, chain of trust verification, trust anchor (certificate authority) validation, and validation via a fingerprint list (for a trust on first use implementation).
type ca_error = [
| `CAIssuerSubjectMismatch of t
| `CAInvalidVersion of t
| `CAInvalidSelfSignature of t
| `CACertificateExpired of t * Ptime.t option
| `CAInvalidExtensions of t
]
The polymorphic variant of possible certificate authorities failures.
val ca_error_of_sexp : Sexplib.Sexp.t -> ca_error
ca_error_of_sexp sexp
is ca_error
, the unmarshalled sexp
.
val sexp_of_ca_error : ca_error -> Sexplib.Sexp.t
sexp_of_ca_error ca_error
is sexp
, the marshalled ca_error
.
val ca_error_to_string : ca_error -> string
ca_error_to_string validation_error
is string
, the string representation of the ca_error
.
valid_ca ~time certificate
is result
, which is `Ok if the given certificate is self-signed, it is valid at time
, its extensions are not present (if X.509 version 1 certificate), or are appropriate for a CA (BasicConstraints is present and true, KeyUsage extension contains keyCertSign).
valid_cas ~time certificates
is valid_certificates
, only those certificates which pass the valid_ca
check.
type leaf_validation_error = [
| `LeafCertificateExpired of t * Ptime.t option
| `LeafInvalidName of t * host option
| `LeafInvalidVersion of t
| `LeafInvalidExtensions of t
]
The polymorphic variant of a leaf certificate validation error.
type chain_validation_error = [
| `IntermediateInvalidExtensions of t
| `IntermediateCertificateExpired of t * Ptime.t option
| `IntermediateInvalidVersion of t
| `ChainIssuerSubjectMismatch of t * t
| `ChainAuthorityKeyIdSubjectKeyIdMismatch of t * t
| `ChainInvalidSignature of t * t
| `ChainInvalidPathlen of t * int
| `EmptyCertificateChain
| `NoTrustAnchor of t
| `Revoked of t
]
The polymorphic variant of a chain validation error.
build_paths server rest
is paths
, which are all possible certificate paths starting with server
. These chains (C1..Cn) fulfill the predicate that each certificate Cn is issued by the next one in the chain (C(n+1)): the issuer of Cn matches the subject of C(n+1). This is as described in RFC 4158.
The polymorphic variant of a chain validation error: either the leaf certificate is problematic, or the chain itself.
val chain_error_of_sexp : Sexplib.Sexp.t -> chain_error
chain_error_of_sexp sexp
is chain_error
, the unmarshalled sexp
.
val sexp_of_chain_error : chain_error -> Sexplib.Sexp.t
sexp_of_chain_error chain_error
is sexp
, the marshalled chain_error
.
val chain_error_to_string : chain_error -> string
chain_error_to_string validation_error
is string
, the string representation of the chain_error
.
val verify_chain :
?host:host ->
?time:Ptime.t ->
?revoked:(issuer:t -> cert:t -> bool) ->
anchors:t list ->
t list ->
[ `Ok of t | `Fail of chain_error ]
verify_chain ~host ~time ~revoked ~anchors chain
is result
, either Ok
and the trust anchor used to verify the chain, or Fail
and the chain error. RFC 5280 describes the implemented path validation algorithm: The validity period of the given certificates is checked against the time
. The X509v3 extensions of the chain
are checked, then a chain of trust from anchors
to the server certificate is validated. The path length constraints are checked. The server certificate is checked to contain the given host
, using hostnames
. The returned certificate is the root of the chain, a member of the given list of anchors
.
type fingerprint_validation_error = [
| `ServerNameNotPresent of t * string
| `NameNotInList of t
| `InvalidFingerprint of t * Cstruct.t * Cstruct.t
]
The polymorphic variant of a fingerprint validation error.
type validation_error = [
| `EmptyCertificateChain
| `InvalidChain
| `Leaf of leaf_validation_error
| `Fingerprint of fingerprint_validation_error
]
The polymorphic variant of validation errors.
val validation_error_of_sexp : Sexplib.Sexp.t -> validation_error
validation_error_of_sexp sexp
is validation_error
, the unmarshalled sexp
.
val sexp_of_validation_error : validation_error -> Sexplib.Sexp.t
sexp_of_validation_error validation_error
is sexp
, the marshalled validation_error
.
val validation_error_to_string : validation_error -> string
validation_error_to_string validation_error
is string
, the string representation of the validation_error
.
The result of a validation: either success (optionally returning the used trust anchor), or failure
val verify_chain_of_trust :
?host:host ->
?time:Ptime.t ->
?revoked:(issuer:t -> cert:t -> bool) ->
anchors:t list ->
t list ->
result
verify_chain_of_trust ~host ~time ~revoked ~anchors certificates
is result
. First, all possible paths are constructed using the build_paths
function, the first certificate of the chain is verified to be a valid leaf certificate (no BasicConstraints extension) and contains the given host
(using hostnames
); if some path is valid, using verify_chain
, the result will be Ok
and contain the actual certificate chain and the trust anchor.
val trust_key_fingerprint :
?host:host ->
?time:Ptime.t ->
hash:Nocrypto.Hash.hash ->
fingerprints:(string * Cstruct.t) list ->
t list ->
result
trust_key_fingerprint ~time ~hash ~fingerprints certificates
is result
, the first element of certificates
is verified against the given fingerprints
map (hostname to public key fingerprint) using key_fingerprint
. The certificate has to be valid in the given time
. If a host
is provided, the certificate is checked for this name. The `Wildcard hostname
of the fingerprint list must match the name in the certificate, using hostnames
.
val trust_cert_fingerprint :
?host:host ->
?time:Ptime.t ->
hash:Nocrypto.Hash.hash ->
fingerprints:(string * Cstruct.t) list ->
t list ->
result
trust_cert_fingerprint ~time ~hash ~fingerprints certificates
is result
, the first element of certificates
is verified to match the given fingerprints
map (hostname to fingerprint) using fingerprint
. The certificate has to be valid in the given time
. If a host
is provided, the certificate is checked for this name. The `Wildcard hostname
of the fingerprint list must match the name in the certificate, using hostnames
.