In rustls, I was looking at the API for verifying client certificates against a CRL or set of CRLs. It seems like there's a problem: say the server provides a CRL from http://example.com/1.crl, but the client certificate is not covered by that CRL. For instance, the server could be using sharded CRLs and the client certificate could be on a different shard. Or, more likely, the server is using an out-of-date config and the client certificate is now reported on an entirely different CRL, or is issued by a different issuer.
One helpful thing here is the CRL Distribution Points extension. We could modify the API such that a CertRevocationList has an accessor that provides the Issuing Distribution Point encoded in that CRL. Then, when validating a client certificate that contains a CRLDP, we could require that there is a CertRevocationList matching a CRLDP from the client certificate. This also provides resistance against substitution attacks.
That would not solve the case where the client certificate does not contain a CRLDP. I think probably we should "fail closed" in such a case, provided the the crls list is non-empty. If the server was expecting to process revocation information from CRLs, and the client certificates do not provide CRLDP, that seems too risky in terms of misconfiguration.
Another check we could perform: if the CRLs list is non-empty, then there must be at least one CRL whose issuer matches the issuer of the certificate we are verifying. Right now it looks like we fail open: https://docs.rs/rustls-webpki/0.101.1/src/webpki/verify_cert.rs.html#203-209. I think that should be inverted. If the user provided a list of CRLs, they probably expected that list of CRLs to be complete for all the issuers of certificates they might encounter during the handshake. Or another way of putting it: if the user provided a list of CRLs, they want to treat certificates of "unknown" status as invalid.
In rustls, I was looking at the API for verifying client certificates against a CRL or set of CRLs. It seems like there's a problem: say the server provides a CRL from
http://example.com/1.crl, but the client certificate is not covered by that CRL. For instance, the server could be using sharded CRLs and the client certificate could be on a different shard. Or, more likely, the server is using an out-of-date config and the client certificate is now reported on an entirely different CRL, or is issued by a different issuer.One helpful thing here is the CRL Distribution Points extension. We could modify the API such that a CertRevocationList has an accessor that provides the Issuing Distribution Point encoded in that CRL. Then, when validating a client certificate that contains a CRLDP, we could require that there is a
CertRevocationListmatching a CRLDP from the client certificate. This also provides resistance against substitution attacks.That would not solve the case where the client certificate does not contain a CRLDP. I think probably we should "fail closed" in such a case, provided the the crls list is non-empty. If the server was expecting to process revocation information from CRLs, and the client certificates do not provide CRLDP, that seems too risky in terms of misconfiguration.
Another check we could perform: if the CRLs list is non-empty, then there must be at least one CRL whose issuer matches the issuer of the certificate we are verifying. Right now it looks like we fail open: https://docs.rs/rustls-webpki/0.101.1/src/webpki/verify_cert.rs.html#203-209. I think that should be inverted. If the user provided a list of CRLs, they probably expected that list of CRLs to be complete for all the issuers of certificates they might encounter during the handshake. Or another way of putting it: if the user provided a list of CRLs, they want to treat certificates of "unknown" status as invalid.