changeset 8168:e969ecc528f5

8066479: Better certificate chain validation Reviewed-by: juh, coffeys
author robm
date Mon, 12 Jan 2015 22:27:20 +0000
parents 4f227205bfb1
children 64e16c60b6f0
files src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
diffstat 1 files changed, 32 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Fri Dec 05 12:20:51 2014 +0100
+++ b/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Mon Jan 12 22:27:20 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,7 @@
 import javax.crypto.Mac;
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.util.Debug;
 import sun.security.util.DerInputStream;
 import sun.security.util.DerOutputStream;
 import sun.security.util.DerValue;
@@ -122,6 +123,8 @@
 
     public static final int VERSION_3 = 3;
 
+    private static final Debug debug = Debug.getInstance("pkcs12");
+
     private static final int keyBag[]  = {1, 2, 840, 113549, 1, 12, 10, 1, 2};
     private static final int certBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 3};
 
@@ -490,6 +493,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();
         }
 
@@ -901,7 +909,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;
     }
 
 
@@ -1356,7 +1369,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())) {