JDK-8072067 : Valid CRL is rejected for backdated enquiries
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 8,9
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • Submitted: 2015-02-02
  • Updated: 2015-02-04
  • Resolved: 2015-02-04
Related Reports
Relates :  
Description
PKIX certpath validation is normally performed using the current time. It may also be requested to be performed at a specific time in the past by calling PKIXParameters.setDate() method.

PKIX revocation checker can use CRL to check revocation status of certificate. CRLs have a specific validity interval. Revocation checker examines that validity interval to ensure that a CRL is still current. This check seems to be performed incorrectly for backdated enquiries when a date in the past was set by calling PKIXParameters.setDate() method.

Revocation checker uses X509CRLSelector to retrieve appropriate CRLs:

http://hg.openjdk.java.net/jdk9/dev/jdk/file/58ec14da9fe8/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java#l492

...
        CertPathHelper.setDateAndTime(sel, params.date(), MAX_CLOCK_SKEW);

        // First, check user-specified CertStores
        CertPathValidatorException networkFailureException = null;
        for (CertStore store : certStores) {
            try {
                for (CRL crl : store.getCRLs(sel)) {
                    possibleCRLs.add((X509CRL)crl);
                }
...

There is a check for CRL valid period in X509CRLSelector:

http://hg.openjdk.java.net/jdk9/dev/jdk/file/58ec14da9fe8/src/java.base/share/classes/java/security/cert/X509CRLSelector.java#l682

...
            if (nowMinusSkew.after(nextUpdate)
                || nowPlusSkew.before(crlThisUpdate)) {
                if (debug != null) {
                    debug.println("X509CRLSelector.match: update out of range");
                }
                return false;
            }
...

nowPlusSkew.before(crlThisUpdate) returns false for backdated enquiries if up-to-date CRL is used (for example, that was retrieved from CRLDP extension). As a result, the CRL is not used to check revocation status.

There was a similar issue for OCSP revocation checking, please see JDK-8020940.
Comments
This is not a bug. We should not make this change. We are checking if a certificate is valid at a certain point in the past. If the certificate is expired (as of now), and you validate it at a point in the past when it was unexpired, and you get a fresh CRL, and the certificate is not on the CRL, you cannot safely determine if the certificate is revoked, since the CA may no longer be maintaining status for it (it may be pruning expired certs from the CRLs). Thus, we should not consider the CRL unless its validity period includes the backdated time. The only practical way to check backdated times is to pass in a cached CRL (ex: via PKIXParameters.addCertStore) that was produced during that time period.
04-02-2015

This is not a regression in JDK 8u. The issue is reproducible on JDK 8 b132 fcs.
02-02-2015

To fix the issue, nowPlusSkew.before(crlThisUpdate) check may be omitted. But removing this check from X509CRLSelector will require spec update for X509CRLSelector.match() method. I suggest to move a check for CRL validity period to RevocationChecker: http://cr.openjdk.java.net/~asmotrak/8072067/webrev.00/ Please see a test to reproduce the issue in the webrev.
02-02-2015