1

I have set CertStore configured with locally stored CRLs. I want to carry out certificate validation using these locally stored CRLs only. In case if incoming connection's certificate does not match against any of these CRLs, it should not try to fetch the CRL from CDP point and just softfail. Is there any way to achieve this ?

        System.setProperty("com.sun.security.enableCRLDP", "false");
        KeyManagerFactory keyManagerFactory = null;
        KeyStore keyStore = null;
        keyManagerFactory = KeyManagerFactory.getInstance(keyAlgorithm);
        keyStore = KeyStore.getInstance(keyStoreType);
        ksFile = new FileInputStream(keyStoreFile);
        keyStore.load(ksFile,password);
        keyManagerFactory.init (keyStore,password);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
        CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
        List<CertStore> certStores =  new ArrayList<>();
        Collection<CRL> crls = new HashSet<>();
       crls.add(CertificateFactory.getInstance("X.509").generateCRL( new java.io.FileInputStream("crl path")));
       crls.add(CertificateFactory.getInstance("X.509").generateCRL( new java.io.FileInputStream("crl path2")));
       certStores.add(CertStore.getInstance("Collection", new CollectionCertStoreParameters(crls)));
      PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
        rc.setOptions(EnumSet.of(
            PKIXRevocationChecker.Option.PREFER_CRLS, // prefer CLR over OCSP 
                        // handshake should not fail when CRL is not available
            PKIXRevocationChecker.Option.NO_FALLBACK));

        CertPathParameters pkixParams = new PKIXBuilderParameters(keyStore, new X509CertSelector());
       // PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(keyStore, new X509CertSelector());
        ((PKIXParameters) pkixParams).setRevocationEnabled(true);
        ((PKIXParameters) pkixParams).setCertStores(certStores);
        ((PKIXParameters) pkixParams).addCertPathChecker(rc);

        tmf.init( new CertPathTrustManagerParameters(pkixParams) );

        SSLContext context = SSLContext.getInstance(protocol);
                    context.init (keyManagerFactory.getKeyManagers (), tmf.getTrustManagers(), null);
supraja
  • 93
  • 2
  • 11
  • Do you want to validate the SSL certificate provided by server creating your own `TrustManager`, or do you want to extract the the SSLL certificate after the SSLConnection were stablished and perform the validation using your CRL list? – pedrofb Aug 02 '17 at 11:54
  • yes using TrustManager during ssl handshake.. – supraja Aug 02 '17 at 11:56

1 Answers1

1

Reviewing PKIXRevocationChecker documentation and checkCRLs code, I can see com.sun.security.enableCRLDP is not being used except in legacy mode, and CRLs are downloaded if the provided ones are not suitable to verify the certificate

You can review/debug the criteria that are being applied in DistributionPointFetcher.verifyCRLs to see why you CRLs are not being used

Verifies a CRL for the given certificate's Distribution Point to ensure it is appropriate for checking the revocation status.

static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,X509CRL crl, boolean[] reasonsMask, boolean signFlag,PublicKey prevKey, X509Certificate prevCert, String provider,Set<TrustAnchor> trustAnchors, List<CertStore> certStores,Date validity) throws CRLException, IOException {

Alternative: Check revocation yourself

You need to disable default revocation checking to use your own CRL list. I think you can wrap the default TrustManager to include the revocation checking during the trust verification of the server certification chain

First remove ((PKIXParameters) pkixParams).setRevocationEnabled(true); and then add this code

//tmf.init(...);

TrustManager[] trustManagers = tmf.getTrustManagers();
final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0];

TrustManager[] wrappedTrustManagers = new TrustManager[]{
   new X509TrustManager() {
       public java.security.cert.X509Certificate[] getAcceptedIssuers() {
          return origTrustmanager.getAcceptedIssuers();
       }

       public void checkClientTrusted(X509Certificate[] certs, String authType) {
           origTrustmanager.checkClientTrusted(certs, authType);
       }

       public void checkServerTrusted(X509Certificate[] certs, String authType) {
           //Original trust checking
           origTrustmanager.checkServerTrusted(certs, authType);
           
           //Check revocation with each CRL
           //from docs: CertificateException - if the certificate chain is not trusted by this TrustManager.
           for (CRL crl: crls){
               if (crl.isRevoked(certs[0]){
                    throw new CertificateException (e);
               }
           }
       }
   }
};

Disclaimer: I did't test it, but it should work based on similar examples

Community
  • 1
  • 1
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • So is it not possible without creating wrapper class ? PKIXRevocation should be doing all this right? My code is taking CRL file from the local path and not downloading from the CDP point.. But when CRL is not present in the local path it is downloading from the CDP. How to **disallow** downloading CRL from CDP ? **Is it possible** ? – supraja Aug 02 '17 at 13:55
  • I've reviewed doc&code to see how it is being performed the CRL check. Seems there is a previous validation to ensure that the CRLs are suitable to do the validation. I updated the answer – pedrofb Aug 03 '17 at 06:27