Allow path building to return the validated path
cpu opened this issue · comments
Presently the validate_cert.rs
implementation of build_path
used for path-building only returns an indication of whether the operation failed or not:
Lines 20 to 28 in 15acd62
CRL validation also requires building a path from the issuer of the CRL to a trust anchor. Further, RFC 5280 6.3.3 says the path must be built to the same trust anchor used to validate the target end-entity certificate for which we're considering revocation status:
(f) Obtain and validate the certification path for the issuer of
the complete CRL. The trust anchor for the certification
path MUST be the same as the trust anchor used to validate
the target certificate. ....
At a minimum, the build_path
implementation should yield the final TrustAnchor
that was used to build the validated path so that we can ensure this requirement is met.
To avoid having to build a path from scratch from the issuer to that TrustAnchor
it would be best if build_path
could yield the full validated path including the intermediate certificates used. That would allow the CRL validation to proceed using the same validation path to the same root. This is the approach used by the gRPC implementation of CRL validation based on providing the implementation the verifiedChains [][]*x509.Certificate
produced by path building.
Changing the implementation to yield just a TrustAnchor
is fairly straight forward. Producing the full chain that was validated without making it require alloc
is likely to be more difficult.
Related issue: briansmith/webpki#264
Changing the implementation to yield just a TrustAnchor is fairly straight forward. Producing the full chain that was validated without making it require alloc is likely to be more difficult.
Reading the existing cert.rs
and verify_cert.rs
code more carefully I realized we already have a way to represent this to look at for inspiration. The Cert.ee_or_ca
field's Ca
variant holds a &'a Cert<'a>
ref that's used to track the child cert of the CA Cert
in-hand. The verify_cert::check_signatures
fn uses this to walk the chain built in build_chain
backwards from the selected trust anchor to the leaf end entity certificate.
I thought I'd be able to smuggle out a &Cert
from build_chain
to use to reconstruct the path through ee_or_ca
but the snag I'm hitting is that build_chain
builds a Cert
from intermediate DER internal to the second loop_while_non_fatal_error
body while processing intermediates. I can't return a value from build_chain
that references the value owned by that function:
Lines 93 to 94 in a0c2af2
I can't change build_chain
to take an owned Cert
instead of &Cert
because the consumers of build_chain
are &self
and can't move the inner Cert
out. I'm going to continue trying to figure something out and will push a broken branch for some help if I stay stuck.
Can you replace the potential_issuer
part of Cert
with a Cow
-like thing that would allow us to do either?
I experimented with that and I think the catch there was that Cert
isn't Clone
and some of its fields aren't either. I don't have the error in front of me at the moment. I might have been holding it wrong.
I also thought about having the caller transform the slice of DER references into Cert
's up-front but that can't be done easily either (I thought I'd need to map + Collect into a vec which requires alloc, and there's the catch of needing to set the ee_or_ca
field for the intermediates with pointers to the child certs). It might be doable but wasn't coming easy and front-loads parsing work we defer until later otherwise.
I had to log off for the day but my thought for a next idea is to try to return references to the DER of the built chain intermediates instead of the parsed Cert
at the cost of having to re-build Cert
from the DER elsewhere. The DER comes from the caller and has a lifetime that would encapsulate the built chain.
I think I'm going to take a different approach. I don't want to heavily refactor the existing path building just to support CRLs and haven't been able to arrive at a minimal change that's workable. I think it will be easier to consider the CRL path building and signature validation separate from the existing implementation to start.
I need to add test coverage but I think I've figured out a way forward. I was making life harder for myself trying to handle CRL validation separately from path building. Threading the CRL data into the existing validation works out better and obviates the requirement to pull the validated path out. It's also a better match to how 5280 + friends recommend this be handled.
Closing this since the approach I used in #66 doesn't require this and implementing it will require more significant changes to the core path building than I'm keen to bite off right now.