changeset 3928:8b7f0a3a0b2e

7025073: Stricter check on trust anchor makes VerifyCACerts.java test fail Summary: loosen the check for version 1 and 2 X.509 certificate Reviewed-by: mullan, weijun
author xuelei
date Tue, 15 Mar 2011 23:08:40 -0700
parents 4a7da412db38
children e3efbb250c0c
files src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
diffstat 2 files changed, 51 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java	Tue Mar 15 18:42:35 2011 -0700
+++ b/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java	Tue Mar 15 23:08:40 2011 -0700
@@ -46,10 +46,16 @@
  */
 class AdaptableX509CertSelector extends X509CertSelector {
     // The start date of a validity period.
-    private Date startDate = null;
+    private Date startDate;
 
     // The end date of a validity period.
-    private Date endDate = null;
+    private Date endDate;
+
+    // Is subject key identifier sensitive?
+    private boolean isSKIDSensitive = false;
+
+    // Is serial number sensitive?
+    private boolean isSNSensitive = false;
 
     AdaptableX509CertSelector() {
         super();
@@ -97,15 +103,24 @@
         if (akidext != null) {
             KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID);
             if (akid != null) {
-                DerOutputStream derout = new DerOutputStream();
-                derout.putOctetString(akid.getIdentifier());
-                super.setSubjectKeyIdentifier(derout.toByteArray());
+                // Do not override the previous setting
+                if (getSubjectKeyIdentifier() == null) {
+                    DerOutputStream derout = new DerOutputStream();
+                    derout.putOctetString(akid.getIdentifier());
+                    super.setSubjectKeyIdentifier(derout.toByteArray());
+
+                    isSKIDSensitive = true;
+                }
             }
 
             SerialNumber asn =
                 (SerialNumber)akidext.get(akidext.SERIAL_NUMBER);
             if (asn != null) {
-                super.setSerialNumber(asn.getNumber());
+                // Do not override the previous setting
+                if (getSerialNumber() == null) {
+                    super.setSerialNumber(asn.getNumber());
+                    isSNSensitive = true;
+                }
             }
 
             // the subject criterion should be set by the caller.
@@ -148,11 +163,25 @@
             }
         }
 
-        if (version < 3 || xcert.getExtensionValue("2.5.29.14") == null) {
-            // If no SubjectKeyIdentifier extension, don't bother to check it.
+        // If no SubjectKeyIdentifier extension, don't bother to check it.
+        if (isSKIDSensitive &&
+            (version < 3 || xcert.getExtensionValue("2.5.29.14") == null)) {
             setSubjectKeyIdentifier(null);
         }
 
+        // In practice, a CA may replace its root certificate and require that
+        // the existing certificate is still valid, even if the AKID extension
+        // does not match the replacement root certificate fields.
+        //
+        // Conservatively, we only support the replacement for version 1 and
+        // version 2 certificate. As for version 2, the certificate extension
+        // may contain sensitive information (for example, policies), the
+        // AKID need to be respected to seek the exact certificate in case
+        // of key or certificate abuse.
+        if (isSNSensitive && version < 3) {
+            setSerialNumber(null);
+        }
+
         return super.match(cert);
     }
 
--- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Tue Mar 15 18:42:35 2011 -0700
+++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Tue Mar 15 23:08:40 2011 -0700
@@ -243,12 +243,6 @@
                     caTargetSelector.setPolicy(getMatchingPolicies());
             }
 
-            /*
-             * Require CA certs with a pathLenConstraint that allows
-             * at least as many CA certs that have already been traversed
-             */
-            caTargetSelector.setBasicConstraints(currentState.traversedCACerts);
-
             sel = caTargetSelector;
         } else {
 
@@ -283,12 +277,6 @@
                 (caSelector, currentState.subjectNamesTraversed);
 
             /*
-             * Require CA certs with a pathLenConstraint that allows
-             * at least as many CA certs that have already been traversed
-             */
-            caSelector.setBasicConstraints(currentState.traversedCACerts);
-
-            /*
              * Facilitate certification path construction with authority
              * key identifier and subject key identifier.
              */
@@ -305,6 +293,14 @@
             sel = caSelector;
         }
 
+        /*
+         * For compatibility, conservatively, we don't check the path
+         * length constraint of trusted anchors.  Please don't set the
+         * basic constraints criterion unless the trusted certificate
+         * matching is completed.
+         */
+        sel.setBasicConstraints(-1);
+
         for (X509Certificate trustedCert : trustedCerts) {
             if (sel.match(trustedCert)) {
                 if (debug != null) {
@@ -324,6 +320,12 @@
         sel.setCertificateValid(date);
 
         /*
+         * Require CA certs with a pathLenConstraint that allows
+         * at least as many CA certs that have already been traversed
+         */
+        sel.setBasicConstraints(currentState.traversedCACerts);
+
+        /*
          * If we have already traversed as many CA certs as the maxPathLength
          * will allow us to, then we don't bother looking through these
          * certificate pairs. If maxPathLength has a value of -1, this