Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java SSL Certificate Revocation Checking

I'm currently writing a network TCP server using SSL. In production, we'll finally require clients to authenticate with a certificate.

In order to revoke certificates in case of a emergency, we would also like to establish a CRL.

My question is: Does Java check CRLs (if provided with the certificate) out of the box or do I need to manually implement such checks?

For testing, I prepared a certificate with a CRL set but Java does not seem to try to validate it (I dropped it into a local web server and there's no access).

I only found the com.sun.net.ssl.checkRevocation=true VM option, but apparently it doesn't query the CRL. VM debugging set to java.security.debug=certpath does not generate any output, either...

Java seems to have related classes in its subsystems (e.g. java.security.cert.X509CRLSelector), but it does not come into play, obviously.

edit: Removed outdated Dropbox link

like image 882
DoNuT Avatar asked Jul 11 '16 07:07

DoNuT


4 Answers

I figured how to enable CRL checking within a SSLContext without implementing a custom validator, as suggested in the comments.

It is mainly about properly initializing the SSLContext's TrustManagers with a revocation checker, only a few lines, no custom check logic and the CRL is now checked automatically as well as the verification path.

Here's a snippet...

KeyStore ts = KeyStore.getInstance("JKS");
FileInputStream tfis = new FileInputStream(trustStorePath);
ts.load(tfis, trustStorePass.toCharArray());

KeyManagerFactory kmf =  KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

// initialize certification path checking for the offered certificates and revocation checks against CLRs
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(
    PKIXRevocationChecker.Option.PREFER_CRLS, // prefer CLR over OCSP
    PKIXRevocationChecker.Option.ONLY_END_ENTITY, 
PKIXRevocationChecker.Option.NO_FALLBACK)); // don't fall back to OCSP checking

PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(ts, new X509CertSelector());
pkixParams.addCertPathChecker(rc);

tmf.init( new CertPathTrustManagerParameters(pkixParams) );
// init KeyManagerFactory
kmf.init(...)

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers), tmf.getTrustManagers(), null);

That essentially did what I needed in my application, checking whether a certificate issued to a client is revoked in our CRL. Only checking the end entity and allowing the CRL check to fail is accepted because its all our infrastructure.

like image 75
DoNuT Avatar answered Oct 08 '22 10:10

DoNuT


Is OCSP OK for you?

bellow code enables OCSP for me:

// for debugging:
System.setProperty("javax.net.debug", "all");
System.setProperty("java.security.debug", "all");

System.setProperty("com.sun.net.ssl.checkRevocation", "true");
Security.setProperty("ocsp.enable", "true");

failed on CRL for errors like: How to check revocation status of X509Certificate chain using JAVA?

like image 43
fishautumn Avatar answered Oct 08 '22 11:10

fishautumn


Notice that disabling revocation checking is a bad security practice. You can do it, but make sure you know the risk!

The currently accepted answer by @DoNuT works by setting PKIXRevocationChecker.Option.SOFT_FAIL, which causes the validator not to throw an exception even if revocation checking fails. The following answer disables revocation checking altogether, thus it is faster in case you don't want validation at all. This is because performing revocation checks needs contacting CRL distribution points or OCSP servers, and if you don't want that, you need not pay the price.

You can simply use setRevocationEnabled(false) on an object of type PKIXBuilderParameters.

// Initialize "anchors" to trusted certificates
// Initialize "selector" to the certificate you want to validate
PKIXBuilderParameters pbParams = new PKIXBuilderParameters(anchors, selector);

pbParams.setRevocationEnabled(false); // disable revocation check

CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
CertPathBuilderResult cpbResult = cpb.build(pbParams);

CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
CertPathValidatorResult result = cpv.validate(cpbResult.getCertPath(), pbParams);

System.out.println(result);
like image 42
M.S. Dousti Avatar answered Oct 08 '22 11:10

M.S. Dousti


First of all, the revocation checking that you can configure in jcontrol (from 1.8) applies only for applet and WebStart downloads and signer certificate checks ! For a programmed https client you can use the PKIXRevocationChecker mentioned above, but by my experience the Oracle implementation doesnt support LDAP CDP downloads at all. When I had this problem I needed to implement the full certificate chain check with CRL and immediate CA cert downloads from LDAP, behind my custom TrustManager's checkXXXX functions...

like image 45
László Báthory Avatar answered Oct 08 '22 10:10

László Báthory