10

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

DoNuT
  • 463
  • 1
  • 7
  • 23
  • This may help you https://www.java.com/en/download/help/revocation_options.xml – Deepak Agrawal Jul 12 '16 at 14:25
  • Possible duplicate of [CRL Verification in Java](http://stackoverflow.com/questions/30903993/crl-verification-in-java) – Deepak Agrawal Jul 12 '16 at 14:28
  • @DeepakAgrawal Your first statement is incorrect, and the Java documentation you subsequently cited states clearly that you *don't* have to implement a custom validator. Please remove your initial incorrect statement. – user207421 Jun 28 '19 at 04:09

4 Answers4

13

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.

DoNuT
  • 463
  • 1
  • 7
  • 23
  • Hey, is there a similar solution for java 1.7 ? – mdavid Dec 07 '16 at 08:01
  • @mdavid: Sorry, I refused to give you that answer a couple of times but maybe you should just try Java 8 (3 years after the release?). There's been tons of improvements in the security stack: http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html As the _PKIXRevocationChecker _ is even mentioned in the change log, I assume there's no out-of-the-box solution for verifying certificates in 1.7. – DoNuT Jul 06 '17 at 07:22
  • 1
    Hi @DoNuT, does it take care of fetching CRL from remote location (provided in cert) and caching it till the next update time? And then fetching the new CRL again? Thanks in advance. – ramtech Sep 22 '17 at 15:09
  • 1
    @ramtech: I haven't checked implementation, but as far as I know from my tests using the SOFT_FAIL option (might be unavailable in my scenerio), it doesn't cache an hits the CRL location every time. – DoNuT Sep 25 '17 at 05:34
  • Does this is thread-safe? From my investigation it seems that later on Java will use PKIXRevocationChecker instance created in this snipped for all network calls. And this class in not thread safe... – smolarek999 Dec 30 '19 at 08:17
  • 2
    ok nvm it get cloned for every request, so seems like ugly but thread-safe – smolarek999 Dec 30 '19 at 09:46
  • What if you want to also use the default truststore? How would you do that? – Abbadon Aug 18 '22 at 16:26
  • Something seems to be missing, as when I use `PKIXBuilderParameters` like this every client cert gets `certificate_unknown`. – OrangeDog Aug 25 '22 at 11:58
  • 1
    Edit: turns out if you have no CRL source defined it will always fail – OrangeDog Aug 25 '22 at 14:45
  • @OrangeDog It's been a long while since I posted this so I don't have the answer but I'm pretty sure it is down to the fact that my sample only features PKIX CRL validation in place, so you might extend your trust chain/path with other (default) checkers not solely relying on CRLs - just a guess, though. – DoNuT Sep 16 '22 at 05:34
6

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?

fishautumn
  • 364
  • 3
  • 6
2

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);
Sadeq Dousti
  • 3,346
  • 6
  • 35
  • 53
  • 3
    I'm not sure you fully get what I wanted to achieve here? I indeed want revocation checking in place, you advise to totally disable it? SOFT_FAIL was acceptable for my use case with self-signed certs and an internal CRL (don't break the application if the CRL is temporarily unavailable), but I've taken it out the example to avoid people pasting it into their code. – DoNuT Dec 11 '18 at 08:27
  • 1
    @DoNuT The word `temporarily` will make sense if `SOFT_FAIL` has an upper bound time, imho! – faghani Apr 24 '19 at 07:21
  • This **isn't needed for SSL/TLS** which was the Q and selfA (now modified BTW); JSSE automatically does `setRevocationChecking(false)` unless you set a sysprop -- correctly given in fishautumn's new A. – dave_thompson_085 Nov 24 '19 at 06:32
1

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...

  • You're right, the VM option listed above didn't have an effect. As long as a _SSLContext_ respectively the underlying TrustManagers are used, you should get away with the approach of adding a _PKIXRevocationChecker_, so Java HTTP clients and Apache Frameworks. As far as I can remember it only supports CRLs and OSCP, LDAP might be a different topic, but you can always add complexity. I had certificate handling for client and server in my hands, so I went for the simplest approach, being CRLs. – DoNuT Oct 01 '18 at 10:46