How to Implement a Custom X.509 Path Validation Rule

23 views Asked by At

I need to implement a custom path validation rule to verify an X.509 certificate chain based on a custom Certificate Policy and set of Policy Qualifiers I'm defining for a specific application.


As a minified example:

My X.509 certificates in the chain here include a fragment like this:

extensions:
- extnID: !oid 2.5.29.32 # Certificate Policies
  critical: false
  extnValue:
  - policyIdentifier: !oid 1.3.6.1.5.5.7.13.1.1 # testPolicy
    policyQualifiers:
    - policyQualifierId: !oid 1.3.6.1.5.5.7.13.2.1 # testQualifier
      qualifier: !int 100

For testing purposes (per RFC 7229) I've assigned OIDs from the 1.3.6.1.5.5.7.13 testing arc:

  • testPolicy is a Certificate Policy with OID 1.3.6.1.5.5.7.13.1.1, defined as being qualified by testQualifier.
  • testQualifier is a Policy Qualifier with OID 1.3.6.1.5.5.7.13.2.1, defined as an integer.

A chain of certificates containing this extension is valid only if the value of the testPolicy's testQualifier decreases monotonically along the certificate chain. That is, in a valid chain you might have a root certificate with a value of 100, then some intermediate CA certificate might have 50, some lower CA certificate might specify 10. etc. But if any of those numbers were in a different order the chain must be rejected.


(Note: that the actual application I'm working on will be evaluating a more complicated partial order on a more complicated structure; and it also includes additional things like custom Extended Key Usage values and will use actual OIDs allocated from a PEN arc registered with IANA. My question is not about any of those things.)


The implementation of a rule like this doesn't feel like it should be very complicated conceptually, but there are a number of rules about how Certificate Policies are evaluated in general that also need to be respected.

I specifically want the functionality provided by other standard X.509 extensions; this is a useful feature and the primary reason for implementing this piece as a Certificate Policy rather than a separate Extension.

Just to list a few of these general behaviors:

  • Require Explicit Policy: Validation needs to reject a path if it has too many certificates in a row lacking the policy, if specified by a Policy Constraint extension's requireExplicitPolicy value.
  • Any Policy: Validation needs to accept an anyPolicy policy as another way for an upstream certificate to be considered a valid path.
  • Inhibit AnyPolicy: Validation needs to still ignore an anyPolicy if it's inhibited by the Inhibit AnyPolicy extension.
  • Policy Mapping: Validation needs to also look for OIDs considered synonyms in the appropriate Policy Mapping extensions in the chain.
  • Inhibit Mapping: Validation needs to enforce the constraint on where Policy Mappings can appear, if specified by a Policy Constraint extension's inhibitMapping value.

I could theoretically parse each certificate myself with ASN.1 and run a separate validation pass with just my own logic in addition to a separate run through an X.509-specific library. But that will mean needing to re-implement other portions of this logic that are already standard, so I would like to avoid that approach both for expediency and for correctness.


I'm not married to any particular library or any particular language for this project. I'm still prototyping the specification at this point; any tool that provides a straightforward way to implement this type of custom path validation would be useful to me.

So far, I've tried to search through the source of openSSL and pyca/cryptography, but my search skills have come up inadequate: I've not been able to find where path validation logic actually occurs, and it's unclear to me if either project necessarily has facilities to straightforwardly add this type of validation rule.

I don't expect a task nearly so esoteric to have a written how-to guide ready to go, either. What I'm looking for is specific libraries that have ways to add this, and pointers to where in the source I should be reading to figure out how.

0

There are 0 answers