8066479: Better certificate chain validation
authorjuh
Fri, 19 Dec 2014 14:48:56 -0800
changeset 29909 388fe481deeb
parent 29908 83e2c403fefd
child 29910 6691760b847e
8066479: Better certificate chain validation Reviewed-by: mullan
jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
--- a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Thu Dec 18 10:45:45 2014 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Fri Dec 19 14:48:56 2014 -0800
@@ -716,6 +716,11 @@
 
         entry.protectedPrivKey = key.clone();
         if (chain != null) {
+            // validate cert-chain
+            if ((chain.length > 1) && (!validateChain(chain))) {
+                throw new KeyStoreException("Certificate chain is "
+                        + "not valid");
+            }
             entry.chain = chain.clone();
             certificateCount += chain.length;
 
@@ -1490,7 +1495,12 @@
             if (!(issuerDN.equals(subjectDN)))
                 return false;
         }
-        return true;
+
+        // Check for loops in the chain. If there are repeated certs,
+        // the Set of certs in the chain will contain fewer certs than
+        // the chain
+        Set<Certificate> set = new HashSet<>(Arrays.asList(certChain));
+        return set.size() == certChain.length;
     }
 
 
@@ -2070,7 +2080,24 @@
                 ArrayList<X509Certificate> chain =
                                 new ArrayList<X509Certificate>();
                 X509Certificate cert = findMatchedCertificate(entry);
+
+                mainloop:
                 while (cert != null) {
+                    // Check for loops in the certificate chain
+                    if (!chain.isEmpty()) {
+                        for (X509Certificate chainCert : chain) {
+                            if (cert.equals(chainCert)) {
+                                if (debug != null) {
+                                    debug.println("Loop detected in " +
+                                        "certificate chain. Skip adding " +
+                                        "repeated cert to chain. Subject: " +
+                                        cert.getSubjectX500Principal()
+                                            .toString());
+                                }
+                                break mainloop;
+                            }
+                        }
+                    }
                     chain.add(cert);
                     X500Principal issuerDN = cert.getIssuerX500Principal();
                     if (issuerDN.equals(cert.getSubjectX500Principal())) {