6792180: Enhance to reject weak algorithms or conform to crypto recommendations
authorxuelei
Mon, 01 Nov 2010 07:57:46 -0700
changeset 7040 659824c2a550
parent 7039 6464c8e62a18
child 7041 07f4ed79094e
6792180: Enhance to reject weak algorithms or conform to crypto recommendations Reviewed-by: mullan, weijun, wetmore
jdk/src/share/classes/java/security/AlgorithmConstraints.java
jdk/src/share/classes/java/security/CryptoPrimitive.java
jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java
jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java
jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java
jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
jdk/src/share/classes/sun/security/validator/PKIXValidator.java
jdk/src/share/classes/sun/security/validator/SimpleValidator.java
jdk/src/share/classes/sun/security/validator/Validator.java
jdk/src/share/classes/sun/security/x509/X509CRLImpl.java
jdk/src/share/lib/security/java.security
jdk/src/share/lib/security/java.security-solaris
jdk/src/share/lib/security/java.security-windows
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/AlgorithmConstraints.java	Mon Nov 01 07:57:46 2010 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.Set;
+
+/**
+ * This interface specifies constraints for cryptographic algorithms,
+ * keys (key sizes), and other algorithm parameters.
+ * <p>
+ * {@code AlgorithmConstraints} objects are immutable.  An implementation
+ * of this interface should not provide methods that can change the state
+ * of an instance once it has been created.
+ * <p>
+ * Note that {@code AlgorithmConstraints} can be used to represent the
+ * restrictions described by the security properties
+ * {@code jdk.certpath.disabledAlgorithms} and
+ * {@code jdk.tls.disabledAlgorithms}, or could be used by a
+ * concrete {@code PKIXCertPathChecker} to check whether a specified
+ * certificate in the certification path contains the required algorithm
+ * constraints.
+ *
+ * @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
+ * @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+ *
+ * @since 1.7
+ */
+
+public interface AlgorithmConstraints {
+
+    /**
+     * Determines whether an algorithm is granted permission for the
+     * specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the algorithm is permitted and can be used for all
+     *     of the specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, AlgorithmParameters parameters);
+
+    /**
+     * Determines whether a key is granted permission for the specified
+     * cryptographic primitives.
+     * <p>
+     * This method is usually used to check key size and key usage.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param key the key
+     *
+     * @return true if the key can be used for all of the specified
+     *     cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives is null or empty,
+     *     or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives, Key key);
+
+    /**
+     * Determines whether an algorithm and the corresponding key are granted
+     * permission for the specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param key the key
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the key and the algorithm can be used for all of the
+     *     specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty, or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+                String algorithm, Key key, AlgorithmParameters parameters);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/CryptoPrimitive.java	Mon Nov 01 07:57:46 2010 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * An enumeration of cryptographic primitives.
+ *
+ * @since 1.7
+ */
+public enum CryptoPrimitive {
+    /**
+     * Hash function
+     */
+    MESSAGE_DIGEST,
+
+    /**
+     * Cryptographic random number generator
+     */
+    SECURE_RANDOM,
+
+    /**
+     * Symmetric primitive: block cipher
+     */
+    BLOCK_CIPHER,
+
+    /**
+     * Symmetric primitive: stream cipher
+     */
+    STREAM_CIPHER,
+
+    /**
+     * Symmetric primitive: message authentication code
+     */
+    MAC,
+
+    /**
+     * Symmetric primitive: key wrap
+     */
+    KEY_WRAP,
+
+    /**
+     * Asymmetric primitive: public key encryption
+     */
+    PUBLIC_KEY_ENCRYPTION,
+
+    /**
+     * Asymmetric primitive: signature scheme
+     */
+    SIGNATURE,
+
+    /**
+     * Asymmetric primitive: key encapsulation mechanism
+     */
+    KEY_ENCAPSULATION,
+
+    /**
+     * Asymmetric primitive: key agreement and key distribution
+     */
+    KEY_AGREEMENT
+}
--- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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
@@ -25,95 +25,336 @@
 
 package sun.security.provider.certpath;
 
-import java.util.Set;
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
 import java.util.Collection;
-import java.util.Locale;
+import java.util.Collections;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.KeyFactory;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.GeneralSecurityException;
 import java.security.cert.Certificate;
+import java.security.cert.X509CRL;
 import java.security.cert.X509Certificate;
-import java.security.cert.X509CRL;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.TrustAnchor;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
 import java.security.cert.CertPathValidatorException;
-import java.security.cert.PKIXCertPathChecker;
+import java.io.IOException;
+import java.security.interfaces.*;
+import java.security.spec.*;
 
+import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.x509.X509CertImpl;
+import sun.security.x509.X509CRLImpl;
 import sun.security.x509.AlgorithmId;
 
 /**
- * AlgorithmChecker is a <code>PKIXCertPathChecker</code> that checks that
- * the signature algorithm of the specified certificate is not disabled.
+ * A <code>PKIXCertPathChecker</code> implementation to check whether a
+ * specified certificate contains the required algorithm constraints.
+ * <p>
+ * Certificate fields such as the subject public key, the signature
+ * algorithm, key usage, extended key usage, etc. need to conform to
+ * the specified algorithm constraints.
  *
- * @author      Xuelei Fan
+ * @see PKIXCertPathChecker
+ * @see PKIXParameters
  */
 final public class AlgorithmChecker extends PKIXCertPathChecker {
 
-    // the disabled algorithms
-    private static final String[] disabledAlgorithms = new String[] {"md2"};
+    private final AlgorithmConstraints constraints;
+    private final PublicKey trustedPubKey;
+    private PublicKey prevPubKey;
 
-    // singleton instance
-    static final AlgorithmChecker INSTANCE = new AlgorithmChecker();
+    private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
+                                    EnumSet.of(CryptoPrimitive.SIGNATURE);
+
+    private final static DisabledAlgorithmConstraints
+        certPathDefaultConstraints = new DisabledAlgorithmConstraints(
+            DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
 
     /**
-     * Default Constructor
+     * Create a new <code>AlgorithmChecker</code> with the algorithm
+     * constraints specified in security property
+     * "jdk.certpath.disabledAlgorithms".
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
      */
-    private AlgorithmChecker() {
-        // do nothing
+    public AlgorithmChecker(TrustAnchor anchor) {
+        this(anchor, certPathDefaultConstraints);
+    }
+
+    /**
+     * Create a new <code>AlgorithmChecker</code> with the
+     * given {@code AlgorithmConstraints}.
+     * <p>
+     * Note that this constructor will be used to check a certification
+     * path where the trust anchor is unknown, or a certificate list which may
+     * contain the trust anchor. This constructor is used by SunJSSE.
+     *
+     * @param constraints the algorithm constraints (or null)
+     */
+    public AlgorithmChecker(AlgorithmConstraints constraints) {
+        this.prevPubKey = null;
+        this.trustedPubKey = null;
+        this.constraints = constraints;
     }
 
     /**
-     * Return a AlgorithmChecker instance.
+     * Create a new <code>AlgorithmChecker</code> with the
+     * given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     * @param constraints the algorithm constraints (or null)
+     *
+     * @throws IllegalArgumentException if the <code>anchor</code> is null
      */
-    static AlgorithmChecker getInstance() {
-        return INSTANCE;
+    public AlgorithmChecker(TrustAnchor anchor,
+            AlgorithmConstraints constraints) {
+
+        if (anchor == null) {
+            throw new IllegalArgumentException(
+                        "The trust anchor cannot be null");
+        }
+
+        if (anchor.getTrustedCert() != null) {
+            this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
+        } else {
+            this.trustedPubKey = anchor.getCAPublicKey();
+        }
+
+        this.prevPubKey = trustedPubKey;
+        this.constraints = constraints;
     }
 
-    /**
-     * Initializes the internal state of the checker from parameters
-     * specified in the constructor.
-     */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
-        // do nothing
+        //  Note that this class does not support forward mode.
+        if (!forward) {
+            if (trustedPubKey != null) {
+                prevPubKey = trustedPubKey;
+            } else {
+                prevPubKey = null;
+            }
+        } else {
+            throw new
+                CertPathValidatorException("forward checking not supported");
+        }
     }
 
+    @Override
     public boolean isForwardCheckingSupported() {
+        //  Note that as this class does not support forward mode, the method
+        //  will always returns false.
         return false;
     }
 
+    @Override
     public Set<String> getSupportedExtensions() {
         return null;
     }
 
-    /**
-     * Checks the signature algorithm of the specified certificate.
-     */
-    public void check(Certificate cert, Collection<String> unresolvedCritExts)
+    @Override
+    public void check(Certificate cert,
+            Collection<String> unresolvedCritExts)
             throws CertPathValidatorException {
-        check(cert);
-    }
+
+        if (!(cert instanceof X509Certificate) || constraints == null) {
+            // ignore the check for non-x.509 certificate or null constraints
+            return;
+        }
+
+        X509CertImpl x509Cert = null;
+        try {
+            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        PublicKey currPubKey = x509Cert.getPublicKey();
+        String currSigAlg = x509Cert.getSigAlgName();
+
+        AlgorithmId algorithmId = null;
+        try {
+            algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
+
+        // Check the current signature algorithm
+        if (!constraints.permits(
+                SIGNATURE_PRIMITIVE_SET,
+                currSigAlg, currSigAlgParams)) {
+            throw new CertPathValidatorException(
+                "Algorithm constraints check failed: " + currSigAlg);
+        }
+
+        // check the key usage and key size
+        boolean[] keyUsage = x509Cert.getKeyUsage();
+        if (keyUsage != null && keyUsage.length < 9) {
+            throw new CertPathValidatorException(
+                        "incorrect KeyUsage extension");
+        }
+
+        if (keyUsage != null) {
+            Set<CryptoPrimitive> primitives =
+                        EnumSet.noneOf(CryptoPrimitive.class);
+
+            if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) {
+                // keyUsage[0]: KeyUsage.digitalSignature
+                // keyUsage[1]: KeyUsage.nonRepudiation
+                // keyUsage[5]: KeyUsage.keyCertSign
+                // keyUsage[6]: KeyUsage.cRLSign
+                primitives.add(CryptoPrimitive.SIGNATURE);
+            }
+
+            if (keyUsage[2]) {      // KeyUsage.keyEncipherment
+                primitives.add(CryptoPrimitive.KEY_ENCAPSULATION);
+            }
+
+            if (keyUsage[3]) {      // KeyUsage.dataEncipherment
+                primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION);
+            }
 
-    public static void check(Certificate cert)
-            throws CertPathValidatorException {
-        X509Certificate xcert = (X509Certificate)cert;
-        check(xcert.getSigAlgName());
+            if (keyUsage[4]) {      // KeyUsage.keyAgreement
+                primitives.add(CryptoPrimitive.KEY_AGREEMENT);
+            }
+
+            // KeyUsage.encipherOnly and KeyUsage.decipherOnly are
+            // undefined in the absence of the keyAgreement bit.
+
+            if (!primitives.isEmpty()) {
+                if (!constraints.permits(primitives, currPubKey)) {
+                    throw new CertPathValidatorException(
+                        "algorithm constraints check failed");
+                }
+            }
+        }
+
+        // Check with previous cert for signature algorithm and public key
+        if (prevPubKey != null) {
+            if (currSigAlg != null) {
+                if (!constraints.permits(
+                        SIGNATURE_PRIMITIVE_SET,
+                        currSigAlg, prevPubKey, currSigAlgParams)) {
+                    throw new CertPathValidatorException(
+                        "Algorithm constraints check failed: " + currSigAlg);
+                }
+            }
+
+            // Inherit key parameters from previous key
+            if (currPubKey instanceof DSAPublicKey &&
+                ((DSAPublicKey)currPubKey).getParams() == null) {
+                // Inherit DSA parameters from previous key
+                if (!(prevPubKey instanceof DSAPublicKey)) {
+                    throw new CertPathValidatorException("Input key is not " +
+                         "of a appropriate type for inheriting parameters");
+                }
+
+                DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
+                if (params == null) {
+                    throw new CertPathValidatorException(
+                                    "Key parameters missing");
+                }
+
+                try {
+                    BigInteger y = ((DSAPublicKey)currPubKey).getY();
+                    KeyFactory kf = KeyFactory.getInstance("DSA");
+                    DSAPublicKeySpec ks = new DSAPublicKeySpec(y,
+                                                       params.getP(),
+                                                       params.getQ(),
+                                                       params.getG());
+                    currPubKey = kf.generatePublic(ks);
+                } catch (GeneralSecurityException e) {
+                    throw new CertPathValidatorException("Unable to generate " +
+                        "key with inherited parameters: " + e.getMessage(), e);
+                }
+            }
+        }
+
+        // reset the previous public key
+        prevPubKey = currPubKey;
+
+        // check the extended key usage, ignore the check now
+        // List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage();
+
+        // DO NOT remove any unresolved critical extensions
     }
 
-    static void check(AlgorithmId aid) throws CertPathValidatorException {
-        check(aid.getName());
-    }
-
-    static void check(X509CRL crl) throws CertPathValidatorException {
-        check(crl.getSigAlgName());
-    }
+    /**
+     * Try to set the trust anchor of the checker.
+     * <p>
+     * If there is no trust anchor specified and the checker has not started,
+     * set the trust anchor.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     */
+    void trySetTrustAnchor(TrustAnchor anchor) {
+        // Don't bother if the check has started or trust anchor has already
+        // specified.
+        if (prevPubKey == null) {
+            if (anchor == null) {
+                throw new IllegalArgumentException(
+                        "The trust anchor cannot be null");
+            }
 
-    private static void check(String algName)
-            throws CertPathValidatorException {
-
-        String lowerCaseAlgName = algName.toLowerCase(Locale.ENGLISH);
-
-        for (String disabled : disabledAlgorithms) {
-            // checking the signature algorithm name
-            if (lowerCaseAlgName.indexOf(disabled) != -1) {
-                throw new CertPathValidatorException(
-                    "algorithm check failed: " + algName + " is disabled");
+            // Don't bother to change the trustedPubKey.
+            if (anchor.getTrustedCert() != null) {
+                prevPubKey = anchor.getTrustedCert().getPublicKey();
+            } else {
+                prevPubKey = anchor.getCAPublicKey();
             }
         }
     }
 
+    /**
+     * Check the signature algorithm with the specified public key.
+     *
+     * @param key the public key to verify the CRL signature
+     * @param crl the target CRL
+     */
+    static void check(PublicKey key, X509CRL crl)
+                        throws CertPathValidatorException {
+
+        X509CRLImpl x509CRLImpl = null;
+        try {
+            x509CRLImpl = X509CRLImpl.toImpl(crl);
+        } catch (CRLException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
+        check(key, algorithmId);
+    }
+
+    /**
+     * Check the signature algorithm with the specified public key.
+     *
+     * @param key the public key to verify the CRL signature
+     * @param crl the target CRL
+     */
+    static void check(PublicKey key, AlgorithmId algorithmId)
+                        throws CertPathValidatorException {
+        String sigAlgName = algorithmId.getName();
+        AlgorithmParameters sigAlgParams = algorithmId.getParameters();
+
+        if (!certPathDefaultConstraints.permits(
+                SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
+            throw new CertPathValidatorException(
+                "algorithm check failed: " + sigAlgName + " is disabled");
+        }
+    }
+
 }
+
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -289,16 +289,6 @@
         X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
         X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
 
-        // check the crl signature algorithm
-        try {
-            AlgorithmChecker.check(crl);
-        } catch (CertPathValidatorException cpve) {
-            if (debug != null) {
-                debug.println("CRL signature algorithm check failed: " + cpve);
-            }
-            return false;
-        }
-
         // if crlIssuer is set, verify that it matches the issuer of the
         // CRL and the CRL contains an IDP extension with the indirectCRL
         // boolean asserted. Otherwise, verify that the CRL issuer matches the
@@ -637,6 +627,16 @@
             }
         }
 
+        // check the crl signature algorithm
+        try {
+            AlgorithmChecker.check(prevKey, crl);
+        } catch (CertPathValidatorException cpve) {
+            if (debug != null) {
+                debug.println("CRL signature algorithm check failed: " + cpve);
+            }
+            return false;
+        }
+
         // validate the signature on the CRL
         try {
             crl.verify(prevKey, provider);
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -719,11 +719,6 @@
         /* we don't perform any validation of the trusted cert */
         if (!isTrustedCert) {
             /*
-             * check that the signature algorithm is not disabled.
-             */
-            AlgorithmChecker.check(cert);
-
-            /*
              * Check CRITICAL private extensions for user checkers that
              * support forward checking (forwardCheckers) and remove
              * ones we know how to check.
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -327,6 +327,10 @@
                 "(set using the OCSP security properties).");
         }
 
+        // The algorithm constraints of the OCSP trusted responder certificate
+        // does not need to be checked in this code. The constraints will be
+        // checked when the responder's certificate is validated.
+
         CertId certId = null;
         OCSPResponse response = null;
         try {
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -32,6 +32,7 @@
 import java.security.cert.CertificateParsingException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CRLReason;
+import java.security.cert.TrustAnchor;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
 import java.util.Date;
@@ -371,6 +372,13 @@
                         "OCSP responses", cpe);
                 }
 
+                // Check algorithm constraints specified in security property
+                // "jdk.certpath.disabledAlgorithms".
+                AlgorithmChecker algChecker = new AlgorithmChecker(
+                                    new TrustAnchor(responderCert, null));
+                algChecker.init(false);
+                algChecker.check(cert, Collections.<String>emptySet());
+
                 // check the validity
                 try {
                     if (dateCheckedAgainst == null) {
@@ -422,6 +430,10 @@
         // Confirm that the signed response was generated using the public
         // key from the trusted responder cert
         if (responderCert != null) {
+            // Check algorithm constraints specified in security property
+            // "jdk.certpath.disabledAlgorithms".
+            AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
+
             if (!verifyResponse(responseDataDer, responderCert,
                 sigAlgId, signature)) {
                 throw new CertPathValidatorException(
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -275,7 +275,7 @@
         int certPathLen = certList.size();
 
         basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
-        AlgorithmChecker algorithmChecker= AlgorithmChecker.getInstance();
+        AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
         KeyChecker keyChecker = new KeyChecker(certPathLen,
             pkixParam.getTargetCertConstraints());
         ConstraintsChecker constraintsChecker =
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -347,9 +347,6 @@
             return;
         }
 
-        /* check that the signature algorithm is not disabled. */
-        AlgorithmChecker.check(cert);
-
         /*
          * check for looping - abort a loop if
          * ((we encounter the same certificate twice) AND
@@ -470,9 +467,16 @@
         if (unresolvedCritExts == null) {
             unresolvedCritExts = Collections.<String>emptySet();
         }
+
+        /*
+         * Check that the signature algorithm is not disabled.
+         */
+        currentState.algorithmChecker.check(cert, unresolvedCritExts);
+
         for (PKIXCertPathChecker checker : currentState.userCheckers) {
             checker.check(cert, unresolvedCritExts);
         }
+
         /*
          * Look at the remaining extensions and remove any ones we have
          * already checked. If there are any left, throw an exception!
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -96,6 +96,9 @@
     /* the checker used for revocation status */
     public CrlRevocationChecker crlChecker;
 
+    /* the algorithm checker */
+    AlgorithmChecker algorithmChecker;
+
     /* the trust anchor used to validate the path */
     TrustAnchor trustAnchor;
 
@@ -241,6 +244,14 @@
             updateState(anchor.getCAPublicKey(), caName);
         }
 
+        // The user specified AlgorithmChecker may not be
+        // able to set the trust anchor until now.
+        for (PKIXCertPathChecker checker : userCheckers) {
+            if (checker instanceof AlgorithmChecker) {
+                ((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
+            }
+        }
+
         init = false;
     }
 
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -302,6 +302,7 @@
             // init the crl checker
             currentState.crlChecker =
                 new CrlRevocationChecker(null, buildParams, null, onlyEECert);
+            currentState.algorithmChecker = new AlgorithmChecker(anchor);
             try {
                 depthFirstSearchReverse(null, currentState,
                 new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
@@ -475,29 +476,41 @@
                 userCheckers.add(mustCheck, policyChecker);
                 mustCheck++;
 
+                // add the algorithm checker
+                userCheckers.add(mustCheck,
+                        new AlgorithmChecker(builder.trustAnchor));
+                mustCheck++;
+
                 if (nextState.keyParamsNeeded()) {
                     PublicKey rootKey = cert.getPublicKey();
                     if (builder.trustAnchor.getTrustedCert() == null) {
                         rootKey = builder.trustAnchor.getCAPublicKey();
                         if (debug != null)
-                            debug.println("SunCertPathBuilder.depthFirstSearchForward" +
-                                          " using buildParams public key: " +
-                                          rootKey.toString());
+                            debug.println(
+                                "SunCertPathBuilder.depthFirstSearchForward " +
+                                "using buildParams public key: " +
+                                rootKey.toString());
                     }
                     TrustAnchor anchor = new TrustAnchor
                         (cert.getSubjectX500Principal(), rootKey, null);
+
+                    // add the basic checker
                     basicChecker = new BasicChecker(anchor,
                                            builder.date,
                                            buildParams.getSigProvider(),
                                            true);
                     userCheckers.add(mustCheck, basicChecker);
                     mustCheck++;
+
+                    // add the crl revocation checker
                     if (buildParams.isRevocationEnabled()) {
                         userCheckers.add(mustCheck, new CrlRevocationChecker
                             (anchor, buildParams, null, onlyEECert));
                         mustCheck++;
                     }
                 }
+                // Why we don't need BasicChecker and CrlRevocationChecker
+                // if nextState.keyParamsNeeded() is false?
 
                 for (int i=0; i<appendedCerts.size(); i++) {
                     X509Certificate currCert = appendedCerts.get(i);
@@ -513,10 +526,18 @@
                     for (int j=0; j<userCheckers.size(); j++) {
                         PKIXCertPathChecker currChecker = userCheckers.get(j);
                         if (j < mustCheck ||
-                            !currChecker.isForwardCheckingSupported())
-                        {
+                            !currChecker.isForwardCheckingSupported()) {
                             if (i == 0) {
                                 currChecker.init(false);
+
+                                // The user specified
+                                // AlgorithmChecker may not be
+                                // able to set the trust anchor until now.
+                                if (j >= mustCheck &&
+                                    currChecker instanceof AlgorithmChecker) {
+                                    ((AlgorithmChecker)currChecker).
+                                        trySetTrustAnchor(builder.trustAnchor);
+                                }
                             }
 
                             try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Mon Nov 01 07:57:46 2010 -0700
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2010, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AlgorithmParameters;
+
+import java.security.Key;
+import java.security.Security;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.DSAKey;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHKey;
+
+import java.util.Locale;
+import java.util.Set;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * Algorithm constraints for disabled algorithms property
+ *
+ * See the "jdk.certpath.disabledAlgorithms" specification in java.security
+ * for the syntax of the disabled algorithm string.
+ */
+public class DisabledAlgorithmConstraints implements AlgorithmConstraints {
+
+    // the known security property, jdk.certpath.disabledAlgorithms
+    public final static String PROPERTY_CERTPATH_DISABLED_ALGS =
+            "jdk.certpath.disabledAlgorithms";
+
+    // the known security property, jdk.tls.disabledAlgorithms
+    public final static String PROPERTY_TLS_DISABLED_ALGS =
+            "jdk.tls.disabledAlgorithms";
+
+    private static Map<String, String[]> disabledAlgorithmsMap =
+            Collections.synchronizedMap(new HashMap<String, String[]>());
+    private static Map<String, KeySizeConstraints> keySizeConstraintsMap =
+        Collections.synchronizedMap(new HashMap<String, KeySizeConstraints>());
+
+    private String[] disabledAlgorithms;
+    private KeySizeConstraints keySizeConstraints;
+
+    /**
+     * Initialize algorithm constraints with the specified security property.
+     *
+     * @param propertyName the security property name that define the disabled
+     *        algorithm constraints
+     */
+    public DisabledAlgorithmConstraints(String propertyName) {
+        synchronized (disabledAlgorithmsMap) {
+            if(!disabledAlgorithmsMap.containsKey(propertyName)) {
+                loadDisabledAlgorithmsMap(propertyName);
+            }
+
+            disabledAlgorithms = disabledAlgorithmsMap.get(propertyName);
+            keySizeConstraints = keySizeConstraintsMap.get(propertyName);
+        }
+    }
+
+    @Override
+    final public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, AlgorithmParameters parameters) {
+
+        if (algorithm == null || algorithm.length() == 0) {
+            throw new IllegalArgumentException("No algorithm name specified");
+        }
+
+        if (primitives == null || primitives.isEmpty()) {
+            throw new IllegalArgumentException(
+                        "No cryptographic primitive specified");
+        }
+
+        Set<String> elements = null;
+        for (String disabled : disabledAlgorithms) {
+            if (disabled == null || disabled.isEmpty()) {
+                continue;
+            }
+
+            // check the full name
+            if (disabled.equalsIgnoreCase(algorithm)) {
+                return false;
+            }
+
+            // decompose the algorithm into sub-elements
+            if (elements == null) {
+                elements = decomposes(algorithm);
+            }
+
+            // check the items of the algorithm
+            for (String element : elements) {
+                if (disabled.equalsIgnoreCase(element)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
+        return checkConstraints(primitives, "", key, null);
+    }
+
+    @Override
+    final public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, Key key, AlgorithmParameters parameters) {
+
+        if (algorithm == null || algorithm.length() == 0) {
+            throw new IllegalArgumentException("No algorithm name specified");
+        }
+
+        return checkConstraints(primitives, algorithm, key, parameters);
+    }
+
+    /**
+     * Decompose the standard algorithm name into sub-elements.
+     * <p>
+     * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
+     * so that we can check the "SHA1" and "RSA" algorithm constraints
+     * separately.
+     * <p>
+     * Please override the method if need to support more name pattern.
+     */
+    protected Set<String> decomposes(String algorithm) {
+        if (algorithm == null || algorithm.length() == 0) {
+            return new HashSet<String>();
+        }
+
+        // algorithm/mode/padding
+        Pattern transPattern = Pattern.compile("/");
+        String[] transTockens = transPattern.split(algorithm);
+
+        Set<String> elements = new HashSet<String>();
+        for (String transTocken : transTockens) {
+            if (transTocken == null || transTocken.length() == 0) {
+                continue;
+            }
+
+            // PBEWith<digest>And<encryption>
+            // PBEWith<prf>And<encryption>
+            // OAEPWith<digest>And<mgf>Padding
+            // <digest>with<encryption>
+            // <digest>with<encryption>and<mgf>
+            Pattern pattern =
+                    Pattern.compile("with|and", Pattern.CASE_INSENSITIVE);
+            String[] tokens = pattern.split(transTocken);
+
+            for (String token : tokens) {
+                if (token == null || token.length() == 0) {
+                    continue;
+                }
+
+                elements.add(token);
+            }
+        }
+
+        // In Java standard algorithm name specification, for different
+        // purpose, the SHA-1 and SHA-2 algorithm names are different. For
+        // example, for MessageDigest, the standard name is "SHA-256", while
+        // for Signature, the digest algorithm component is "SHA256" for
+        // signature algorithm "SHA256withRSA". So we need to check both
+        // "SHA-256" and "SHA256" to make the right constraint checking.
+
+        // handle special name: SHA-1 and SHA1
+        if (elements.contains("SHA1") && !elements.contains("SHA-1")) {
+            elements.add("SHA-1");
+        }
+        if (elements.contains("SHA-1") && !elements.contains("SHA1")) {
+            elements.add("SHA1");
+        }
+
+        // handle special name: SHA-224 and SHA224
+        if (elements.contains("SHA224") && !elements.contains("SHA-224")) {
+            elements.add("SHA-224");
+        }
+        if (elements.contains("SHA-224") && !elements.contains("SHA224")) {
+            elements.add("SHA224");
+        }
+
+        // handle special name: SHA-256 and SHA256
+        if (elements.contains("SHA256") && !elements.contains("SHA-256")) {
+            elements.add("SHA-256");
+        }
+        if (elements.contains("SHA-256") && !elements.contains("SHA256")) {
+            elements.add("SHA256");
+        }
+
+        // handle special name: SHA-384 and SHA384
+        if (elements.contains("SHA384") && !elements.contains("SHA-384")) {
+            elements.add("SHA-384");
+        }
+        if (elements.contains("SHA-384") && !elements.contains("SHA384")) {
+            elements.add("SHA384");
+        }
+
+        // handle special name: SHA-512 and SHA512
+        if (elements.contains("SHA512") && !elements.contains("SHA-512")) {
+            elements.add("SHA-512");
+        }
+        if (elements.contains("SHA-512") && !elements.contains("SHA512")) {
+            elements.add("SHA512");
+        }
+
+        return elements;
+    }
+
+    // Check algorithm constraints
+    private boolean checkConstraints(Set<CryptoPrimitive> primitives,
+            String algorithm, Key key, AlgorithmParameters parameters) {
+
+        // check the key parameter, it cannot be null.
+        if (key == null) {
+            throw new IllegalArgumentException("The key cannot be null");
+        }
+
+        // check the target algorithm
+        if (algorithm != null && algorithm.length() != 0) {
+            if (!permits(primitives, algorithm, parameters)) {
+                return false;
+            }
+        }
+
+        // check the key algorithm
+        if (!permits(primitives, key.getAlgorithm(), null)) {
+            return false;
+        }
+
+        // check the key constraints
+        if (keySizeConstraints.disables(key)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // Get disabled algorithm constraints from the specified security property.
+    private static void loadDisabledAlgorithmsMap(
+            final String propertyName) {
+
+        String property = AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return Security.getProperty(propertyName);
+                }
+            });
+
+        String[] algorithmsInProperty = null;
+
+        if (property != null && !property.isEmpty()) {
+
+            // remove double quote marks from beginning/end of the property
+            if (property.charAt(0) == '"' &&
+                    property.charAt(property.length() - 1) == '"') {
+                property = property.substring(1, property.length() - 1);
+            }
+
+            algorithmsInProperty = property.split(",");
+            for (int i = 0; i < algorithmsInProperty.length; i++) {
+                algorithmsInProperty[i] = algorithmsInProperty[i].trim();
+            }
+        }
+
+        // map the disabled algorithms
+        if (algorithmsInProperty == null) {
+            algorithmsInProperty = new String[0];
+        }
+        disabledAlgorithmsMap.put(propertyName, algorithmsInProperty);
+
+        // map the key constraints
+        KeySizeConstraints keySizeConstraints =
+            new KeySizeConstraints(algorithmsInProperty);
+        keySizeConstraintsMap.put(propertyName, keySizeConstraints);
+    }
+
+    /**
+     * key constraints
+     */
+    private static class KeySizeConstraints {
+        private static final Pattern pattern = Pattern.compile(
+                "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
+
+        private Map<String, Set<KeySizeConstraint>> constraintsMap =
+            Collections.synchronizedMap(
+                        new HashMap<String, Set<KeySizeConstraint>>());
+
+        public KeySizeConstraints(String[] restrictions) {
+            for (String restriction : restrictions) {
+                if (restriction == null || restriction.isEmpty()) {
+                    continue;
+                }
+
+                Matcher matcher = pattern.matcher(restriction);
+                if (matcher.matches()) {
+                    String algorithm = matcher.group(1);
+
+                    KeySizeConstraint.Operator operator =
+                             KeySizeConstraint.Operator.of(matcher.group(2));
+                    int length = Integer.parseInt(matcher.group(3));
+
+                    algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+
+                    synchronized (constraintsMap) {
+                        if (!constraintsMap.containsKey(algorithm)) {
+                            constraintsMap.put(algorithm,
+                                new HashSet<KeySizeConstraint>());
+                        }
+
+                        Set<KeySizeConstraint> constraintSet =
+                            constraintsMap.get(algorithm);
+                        KeySizeConstraint constraint =
+                            new KeySizeConstraint(operator, length);
+                        constraintSet.add(constraint);
+                    }
+                }
+            }
+        }
+
+        // Does this KeySizeConstraints disable the specified key?
+        public boolean disables(Key key) {
+            String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH);
+            synchronized (constraintsMap) {
+                if (constraintsMap.containsKey(algorithm)) {
+                    Set<KeySizeConstraint> constraintSet =
+                                        constraintsMap.get(algorithm);
+                    for (KeySizeConstraint constraint : constraintSet) {
+                        if (constraint.disables(key)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+
+    /**
+     * Key size constraint.
+     *
+     * e.g.  "keysize <= 1024"
+     */
+    private static class KeySizeConstraint {
+        // operator
+        static enum Operator {
+            EQ,         // "=="
+            NE,         // "!="
+            LT,         // "<"
+            LE,         // "<="
+            GT,         // ">"
+            GE;         // ">="
+
+            static Operator of(String s) {
+                switch (s) {
+                    case "==":
+                        return EQ;
+                    case "!=":
+                        return NE;
+                    case "<":
+                        return LT;
+                    case "<=":
+                        return LE;
+                    case ">":
+                        return GT;
+                    case ">=":
+                        return GE;
+                }
+
+                throw new IllegalArgumentException(
+                        s + " is not a legal Operator");
+            }
+        }
+
+        private int minSize;            // the minimal available key size
+        private int maxSize;            // the maximal available key size
+        private int prohibitedSize = -1;    // unavailable key sizes
+
+        public KeySizeConstraint(Operator operator, int length) {
+            switch (operator) {
+                case EQ:      // an unavailable key size
+                    this.minSize = 0;
+                    this.maxSize = Integer.MAX_VALUE;
+                    prohibitedSize = length;
+                    break;
+                case NE:
+                    this.minSize = length;
+                    this.maxSize = length;
+                    break;
+                case LT:
+                    this.minSize = length;
+                    this.maxSize = Integer.MAX_VALUE;
+                    break;
+                case LE:
+                    this.minSize = length + 1;
+                    this.maxSize = Integer.MAX_VALUE;
+                    break;
+                case GT:
+                    this.minSize = 0;
+                    this.maxSize = length;
+                    break;
+                case GE:
+                    this.minSize = 0;
+                    this.maxSize = length > 1 ? (length - 1) : 0;
+                    break;
+                default:
+                    // unlikely to happen
+                    this.minSize = Integer.MAX_VALUE;
+                    this.maxSize = -1;
+            }
+        }
+
+        // Does this key constraint disable the specified key?
+        public boolean disables(Key key) {
+            int size = -1;
+
+            // it is a SecretKey
+            if (key instanceof SecretKey) {
+                SecretKey sk = (SecretKey)key;
+                if (sk.getFormat().equals("RAW") && sk.getEncoded() != null) {
+                    size = sk.getEncoded().length * 8;
+
+                }
+            }
+
+            // it is an asymmetric key
+            if (key instanceof RSAKey) {
+                RSAKey pubk = (RSAKey)key;
+                size = pubk.getModulus().bitLength();
+            } else if (key instanceof ECKey) {
+                ECKey pubk = (ECKey)key;
+                size = pubk.getParams().getOrder().bitLength();
+            } else if (key instanceof DSAKey) {
+                DSAKey pubk = (DSAKey)key;
+                size = pubk.getParams().getP().bitLength();
+            } else if (key instanceof DHKey) {
+                DHKey pubk = (DHKey)key;
+                size = pubk.getParams().getP().bitLength();
+            } // else, it is not a key we know.
+
+            if (size == 0) {
+                return true;    // we don't allow any key of size 0.
+            }
+
+            if (size >= 0) {
+                return ((size < minSize) || (size > maxSize) ||
+                    (prohibitedSize == size));
+            }
+
+            return false;
+        }
+    }
+
+}
+
--- a/jdk/src/share/classes/sun/security/validator/PKIXValidator.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/validator/PKIXValidator.java	Mon Nov 01 07:57:46 2010 -0700
@@ -31,20 +31,35 @@
 import java.security.cert.*;
 
 import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanAction;
+import sun.security.provider.certpath.AlgorithmChecker;
 
 /**
  * Validator implementation built on the PKIX CertPath API. This
  * implementation will be emphasized going forward.<p>
- *
+ * <p>
  * Note that the validate() implementation tries to use a PKIX validator
  * if that appears possible and a PKIX builder otherwise. This increases
  * performance and currently also leads to better exception messages
  * in case of failures.
+ * <p>
+ * {@code PKIXValidator} objects are immutable once they have been created.
+ * Please DO NOT add methods that can change the state of an instance once
+ * it has been created.
  *
  * @author Andreas Sterbenz
  */
 public final class PKIXValidator extends Validator {
 
+    /**
+     * Flag indicating whether to enable revocation check for the PKIX trust
+     * manager. Typically, this will only work if the PKIX implementation
+     * supports CRL distribution points as we do not manually setup CertStores.
+     */
+    private final static boolean checkTLSRevocation =
+        AccessController.doPrivileged
+            (new GetBooleanAction("com.sun.net.ssl.checkRevocation"));
+
     // enable use of the validator if possible
     private final static boolean TRY_VALIDATOR = true;
 
@@ -53,10 +68,10 @@
     private int certPathLength = -1;
 
     // needed only for the validator
-    private Map<X500Principal, List<PublicKey>> trustedSubjects;
-    private CertificateFactory factory;
+    private final Map<X500Principal, List<PublicKey>> trustedSubjects;
+    private final CertificateFactory factory;
 
-    private boolean plugin = false;
+    private final boolean plugin;
 
     PKIXValidator(String variant, Collection<X509Certificate> trustedCerts) {
         super(TYPE_PKIX, variant);
@@ -75,7 +90,33 @@
             throw new RuntimeException("Unexpected error: " + e.toString(), e);
         }
         setDefaultParameters(variant);
-        initCommon();
+
+        // initCommon();
+        if (TRY_VALIDATOR) {
+            if (TRY_VALIDATOR == false) {
+                return;
+            }
+            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
+            for (X509Certificate cert : trustedCerts) {
+                X500Principal dn = cert.getSubjectX500Principal();
+                List<PublicKey> keys;
+                if (trustedSubjects.containsKey(dn)) {
+                    keys = trustedSubjects.get(dn);
+                } else {
+                    keys = new ArrayList<PublicKey>();
+                    trustedSubjects.put(dn, keys);
+                }
+                keys.add(cert.getPublicKey());
+            }
+            try {
+                factory = CertificateFactory.getInstance("X.509");
+            } catch (CertificateException e) {
+                throw new RuntimeException("Internal error", e);
+            }
+            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
+        } else {
+            plugin = false;
+        }
     }
 
     PKIXValidator(String variant, PKIXBuilderParameters params) {
@@ -88,31 +129,33 @@
             }
         }
         parameterTemplate = params;
-        initCommon();
-    }
 
-    private void initCommon() {
-        if (TRY_VALIDATOR == false) {
-            return;
+        // initCommon();
+        if (TRY_VALIDATOR) {
+            if (TRY_VALIDATOR == false) {
+                return;
+            }
+            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
+            for (X509Certificate cert : trustedCerts) {
+                X500Principal dn = cert.getSubjectX500Principal();
+                List<PublicKey> keys;
+                if (trustedSubjects.containsKey(dn)) {
+                    keys = trustedSubjects.get(dn);
+                } else {
+                    keys = new ArrayList<PublicKey>();
+                    trustedSubjects.put(dn, keys);
+                }
+                keys.add(cert.getPublicKey());
+            }
+            try {
+                factory = CertificateFactory.getInstance("X.509");
+            } catch (CertificateException e) {
+                throw new RuntimeException("Internal error", e);
+            }
+            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
+        } else {
+            plugin = false;
         }
-        trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
-        for (X509Certificate cert : trustedCerts) {
-            X500Principal dn = cert.getSubjectX500Principal();
-            List<PublicKey> keys;
-            if (trustedSubjects.containsKey(dn)) {
-                keys = trustedSubjects.get(dn);
-            } else {
-                keys = new ArrayList<PublicKey>();
-                trustedSubjects.put(dn, keys);
-            }
-            keys.add(cert.getPublicKey());
-        }
-        try {
-            factory = CertificateFactory.getInstance("X.509");
-        } catch (CertificateException e) {
-            throw new RuntimeException("Internal error", e);
-        }
-        plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
     }
 
     public Collection<X509Certificate> getTrustedCertificates() {
@@ -129,7 +172,7 @@
      * @return the length of the last certification path passed to
      *   CertPathValidator.validate, or -1 if it has not been invoked yet
      */
-    public int getCertPathLength() {
+    public int getCertPathLength() { // mutable, should be private
         return certPathLength;
     }
 
@@ -138,7 +181,12 @@
      * revocation checking. In the future, this should be configurable.
      */
     private void setDefaultParameters(String variant) {
-        parameterTemplate.setRevocationEnabled(false);
+        if ((variant == Validator.VAR_TLS_SERVER) ||
+                (variant == Validator.VAR_TLS_CLIENT)) {
+            parameterTemplate.setRevocationEnabled(checkTLSRevocation);
+        } else {
+            parameterTemplate.setRevocationEnabled(false);
+        }
     }
 
     /**
@@ -146,17 +194,29 @@
      * modify the parameters but must make sure not to perform any concurrent
      * validations.
      */
-    public PKIXBuilderParameters getParameters() {
+    public PKIXBuilderParameters getParameters() { // mutable, should be private
         return parameterTemplate;
     }
 
+    @Override
     X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts, Object parameter)
-            throws CertificateException {
+            Collection<X509Certificate> otherCerts,
+            AlgorithmConstraints constraints,
+            Object parameter) throws CertificateException {
         if ((chain == null) || (chain.length == 0)) {
             throw new CertificateException
                 ("null or zero-length certificate chain");
         }
+
+        // add  new algorithm constraints checker
+        PKIXBuilderParameters pkixParameters =
+                    (PKIXBuilderParameters) parameterTemplate.clone();
+        AlgorithmChecker algorithmChecker = null;
+        if (constraints != null) {
+            algorithmChecker = new AlgorithmChecker(constraints);
+            pkixParameters.addCertPathChecker(algorithmChecker);
+        }
+
         if (TRY_VALIDATOR) {
             // check that chain is in correct order and check if chain contains
             // trust anchor
@@ -167,7 +227,7 @@
                 if (i != 0 &&
                     !dn.equals(prevIssuer)) {
                     // chain is not ordered correctly, call builder instead
-                    return doBuild(chain, otherCerts);
+                    return doBuild(chain, otherCerts, pkixParameters);
                 }
 
                 // Check if chain[i] is already trusted. It may be inside
@@ -186,7 +246,7 @@
                     // Remove and call validator on partial chain [0 .. i-1]
                     X509Certificate[] newChain = new X509Certificate[i];
                     System.arraycopy(chain, 0, newChain, 0, i);
-                    return doValidate(newChain);
+                    return doValidate(newChain, pkixParameters);
                 }
                 prevIssuer = cert.getIssuerX500Principal();
             }
@@ -197,7 +257,7 @@
             X500Principal subject = last.getSubjectX500Principal();
             if (trustedSubjects.containsKey(issuer) &&
                     isSignatureValid(trustedSubjects.get(issuer), last)) {
-                return doValidate(chain);
+                return doValidate(chain, pkixParameters);
             }
 
             // don't fallback to builder if called from plugin/webstart
@@ -209,18 +269,17 @@
                     X509Certificate[] newChain =
                         new X509Certificate[chain.length-1];
                     System.arraycopy(chain, 0, newChain, 0, newChain.length);
+
                     // temporarily set last cert as sole trust anchor
-                    PKIXBuilderParameters params =
-                        (PKIXBuilderParameters) parameterTemplate.clone();
                     try {
-                        params.setTrustAnchors
+                        pkixParameters.setTrustAnchors
                             (Collections.singleton(new TrustAnchor
                                 (chain[chain.length-1], null)));
                     } catch (InvalidAlgorithmParameterException iape) {
                         // should never occur, but ...
                         throw new CertificateException(iape);
                     }
-                    doValidate(newChain, params);
+                    doValidate(newChain, pkixParameters);
                 }
                 // if the rest of the chain is valid, throw exception
                 // indicating no trust anchor was found
@@ -230,10 +289,11 @@
             // otherwise, fall back to builder
         }
 
-        return doBuild(chain, otherCerts);
+        return doBuild(chain, otherCerts, pkixParameters);
     }
 
-    private boolean isSignatureValid(List<PublicKey> keys, X509Certificate sub) {
+    private boolean isSignatureValid(List<PublicKey> keys,
+            X509Certificate sub) {
         if (plugin) {
             for (PublicKey key: keys) {
                 try {
@@ -273,13 +333,6 @@
         }
     }
 
-    private X509Certificate[] doValidate(X509Certificate[] chain)
-            throws CertificateException {
-        PKIXBuilderParameters params =
-            (PKIXBuilderParameters)parameterTemplate.clone();
-        return doValidate(chain, params);
-    }
-
     private X509Certificate[] doValidate(X509Certificate[] chain,
             PKIXBuilderParameters params) throws CertificateException {
         try {
@@ -300,11 +353,10 @@
     }
 
     private X509Certificate[] doBuild(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts) throws CertificateException {
+        Collection<X509Certificate> otherCerts,
+        PKIXBuilderParameters params) throws CertificateException {
 
         try {
-            PKIXBuilderParameters params =
-                (PKIXBuilderParameters)parameterTemplate.clone();
             setDate(params);
 
             // setup target constraints
--- a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -48,6 +48,10 @@
  * deployed certificates and previous J2SE versions. It will never support
  * more advanced features and will be deemphasized in favor of the PKIX
  * validator going forward.
+ * <p>
+ * {@code SimpleValidator} objects are immutable once they have been created.
+ * Please DO NOT add methods that can change the state of an instance once
+ * it has been created.
  *
  * @author Andreas Sterbenz
  */
@@ -80,13 +84,14 @@
      * The list is used because there may be multiple certificates
      * with an identical subject DN.
      */
-    private Map<X500Principal, List<X509Certificate>> trustedX500Principals;
+    private final Map<X500Principal, List<X509Certificate>>
+                                            trustedX500Principals;
 
     /**
      * Set of the trusted certificates. Present only for
      * getTrustedCertificates().
      */
-    private Collection<X509Certificate> trustedCerts;
+    private final Collection<X509Certificate> trustedCerts;
 
     SimpleValidator(String variant, Collection<X509Certificate> trustedCerts) {
         super(TYPE_SIMPLE, variant);
@@ -114,9 +119,11 @@
      * Perform simple validation of chain. The arguments otherCerts and
      * parameter are ignored.
      */
+    @Override
     X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts, Object parameter)
-            throws CertificateException {
+            Collection<X509Certificate> otherCerts,
+            AlgorithmConstraints constraints,
+            Object parameter) throws CertificateException {
         if ((chain == null) || (chain.length == 0)) {
             throw new CertificateException
                 ("null or zero-length certificate chain");
@@ -129,6 +136,17 @@
         if (date == null) {
             date = new Date();
         }
+
+        // create default algorithm constraints checker
+        TrustAnchor anchor = new TrustAnchor(chain[chain.length - 1], null);
+        AlgorithmChecker defaultAlgChecker = new AlgorithmChecker(anchor);
+
+        // create application level algorithm constraints checker
+        AlgorithmChecker appAlgChecker = null;
+        if (constraints != null) {
+            appAlgChecker = new AlgorithmChecker(anchor, constraints);
+        }
+
         // verify top down, starting at the certificate issued by
         // the trust anchor
         int maxPathLength = chain.length - 1;
@@ -138,7 +156,12 @@
 
             // check certificate algorithm
             try {
-                AlgorithmChecker.check(cert);
+                // Algorithm checker don't care about the unresolved critical
+                // extensions.
+                defaultAlgChecker.check(cert, Collections.<String>emptySet());
+                if (appAlgChecker != null) {
+                    appAlgChecker.check(cert, Collections.<String>emptySet());
+                }
             } catch (CertPathValidatorException cpve) {
                 throw new ValidatorException
                         (ValidatorException.T_ALGORITHM_DISABLED, cert, cpve);
--- a/jdk/src/share/classes/sun/security/validator/Validator.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/validator/Validator.java	Mon Nov 01 07:57:46 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -27,6 +27,7 @@
 
 import java.util.*;
 
+import java.security.AlgorithmConstraints;
 import java.security.KeyStore;
 import java.security.cert.*;
 
@@ -232,16 +233,44 @@
     public final X509Certificate[] validate(X509Certificate[] chain,
             Collection<X509Certificate> otherCerts, Object parameter)
             throws CertificateException {
-        chain = engineValidate(chain, otherCerts, parameter);
+        return validate(chain, otherCerts, null, parameter);
+    }
+
+    /**
+     * Validate the given certificate chain.
+     *
+     * @param chain the target certificate chain
+     * @param otherCerts a Collection of additional X509Certificates that
+     *        could be helpful for path building (or null)
+     * @param constraints algorithm constraints for certification path
+     *        processing
+     * @param parameter an additional parameter with variant specific meaning.
+     *        Currently, it is only defined for TLS_SERVER variant validators,
+     *        where it must be non null and the name of the TLS key exchange
+     *        algorithm being used (see JSSE X509TrustManager specification).
+     *        In the future, it could be used to pass in a PKCS#7 object for
+     *        code signing to check time stamps.
+     * @return a non-empty chain that was used to validate the path. The
+     *        end entity cert is at index 0, the trust anchor at index n-1.
+     */
+    public final X509Certificate[] validate(X509Certificate[] chain,
+                Collection<X509Certificate> otherCerts,
+                AlgorithmConstraints constraints,
+                Object parameter) throws CertificateException {
+        chain = engineValidate(chain, otherCerts, constraints, parameter);
+
         // omit EE extension check if EE cert is also trust anchor
         if (chain.length > 1) {
             endEntityChecker.check(chain[0], parameter);
         }
+
         return chain;
     }
 
     abstract X509Certificate[] engineValidate(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts, Object parameter) throws CertificateException;
+                Collection<X509Certificate> otherCerts,
+                AlgorithmConstraints constraints,
+                Object parameter) throws CertificateException;
 
     /**
      * Returns an immutable Collection of the X509Certificates this instance
--- a/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java	Mon Nov 01 07:57:46 2010 -0700
@@ -764,6 +764,15 @@
     }
 
     /**
+     * Gets the signature AlgorithmId from the CRL.
+     *
+     * @return the signature AlgorithmId
+     */
+    public AlgorithmId getSigAlgId() {
+        return sigAlgId;
+    }
+
+    /**
      * return the AuthorityKeyIdentifier, if any.
      *
      * @returns AuthorityKeyIdentifier or null
--- a/jdk/src/share/lib/security/java.security	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/lib/security/java.security	Mon Nov 01 07:57:46 2010 -0700
@@ -282,3 +282,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+
--- a/jdk/src/share/lib/security/java.security-solaris	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/lib/security/java.security-solaris	Mon Nov 01 07:57:46 2010 -0700
@@ -56,10 +56,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -73,7 +73,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -150,7 +150,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -165,13 +165,14 @@
 #
 # default value is forever (FOREVER). For security reasons, this
 # caching is made forever when a security manager is set. When a security
-# manager is not set, the default behavior is to cache for 30 seconds.
+# manager is not set, the default behavior in this implementation
+# is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +184,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +193,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +202,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +214,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +238,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,7 +260,7 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
 #
 # Policy for failed Kerberos KDC lookups:
 #
@@ -287,3 +288,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+
--- a/jdk/src/share/lib/security/java.security-windows	Sat Oct 30 18:39:17 2010 +0800
+++ b/jdk/src/share/lib/security/java.security-windows	Mon Nov 01 07:57:46 2010 -0700
@@ -56,10 +56,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -73,7 +73,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -150,7 +150,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -165,13 +165,14 @@
 #
 # default value is forever (FOREVER). For security reasons, this
 # caching is made forever when a security manager is set. When a security
-# manager is not set, the default behavior is to cache for 30 seconds.
+# manager is not set, the default behavior in this implementation
+# is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +184,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +193,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +202,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +214,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +238,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,7 +260,7 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
 #
 # Policy for failed Kerberos KDC lookups:
 #
@@ -287,3 +288,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+