# HG changeset patch # User asmotrak # Date 1437347756 -3600 # Node ID 5aec959c9177ececf374543d094398ba71244944 # Parent 7b2018284119b49c0b829d226128a90ff213dff2 8043201: Deprecate RC4 in SunJSSE provider Reviewed-by: xuelei diff -r 7b2018284119 -r 5aec959c9177 src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java --- a/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java Mon Jul 20 00:11:26 2015 +0100 +++ b/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java Mon Jul 20 00:15:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,9 @@ import java.security.Key; import java.util.Set; -import java.util.HashSet; import sun.security.util.DisabledAlgorithmConstraints; +import static sun.security.util.DisabledAlgorithmConstraints.*; import sun.security.ssl.CipherSuite.*; /** @@ -46,10 +46,15 @@ * for the syntax of the disabled algorithm string. */ final class SSLAlgorithmConstraints implements AlgorithmConstraints { + private final static AlgorithmConstraints tlsDisabledAlgConstraints = - new TLSDisabledAlgConstraints(); + new DisabledAlgorithmConstraints(PROPERTY_TLS_DISABLED_ALGS, + new SSLAlgorithmDecomposer()); + private final static AlgorithmConstraints x509DisabledAlgConstraints = - new X509DisabledAlgConstraints(); + new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS, + new SSLAlgorithmDecomposer(true)); + private AlgorithmConstraints userAlgConstraints = null; private AlgorithmConstraints peerAlgConstraints = null; @@ -261,217 +266,4 @@ } } - static private class BasicDisabledAlgConstraints - extends DisabledAlgorithmConstraints { - BasicDisabledAlgConstraints(String propertyName) { - super(propertyName); - } - - protected Set decomposes(KeyExchange keyExchange, - boolean forCertPathOnly) { - Set components = new HashSet<>(); - switch (keyExchange) { - case K_NULL: - if (!forCertPathOnly) { - components.add("NULL"); - } - break; - case K_RSA: - components.add("RSA"); - break; - case K_RSA_EXPORT: - components.add("RSA"); - components.add("RSA_EXPORT"); - break; - case K_DH_RSA: - components.add("RSA"); - components.add("DH"); - components.add("DiffieHellman"); - components.add("DH_RSA"); - break; - case K_DH_DSS: - components.add("DSA"); - components.add("DSS"); - components.add("DH"); - components.add("DiffieHellman"); - components.add("DH_DSS"); - break; - case K_DHE_DSS: - components.add("DSA"); - components.add("DSS"); - components.add("DH"); - components.add("DHE"); - components.add("DiffieHellman"); - components.add("DHE_DSS"); - break; - case K_DHE_RSA: - components.add("RSA"); - components.add("DH"); - components.add("DHE"); - components.add("DiffieHellman"); - components.add("DHE_RSA"); - break; - case K_DH_ANON: - if (!forCertPathOnly) { - components.add("ANON"); - components.add("DH"); - components.add("DiffieHellman"); - components.add("DH_ANON"); - } - break; - case K_ECDH_ECDSA: - components.add("ECDH"); - components.add("ECDSA"); - components.add("ECDH_ECDSA"); - break; - case K_ECDH_RSA: - components.add("ECDH"); - components.add("RSA"); - components.add("ECDH_RSA"); - break; - case K_ECDHE_ECDSA: - components.add("ECDHE"); - components.add("ECDSA"); - components.add("ECDHE_ECDSA"); - break; - case K_ECDHE_RSA: - components.add("ECDHE"); - components.add("RSA"); - components.add("ECDHE_RSA"); - break; - case K_ECDH_ANON: - if (!forCertPathOnly) { - components.add("ECDH"); - components.add("ANON"); - components.add("ECDH_ANON"); - } - break; - case K_KRB5: - if (!forCertPathOnly) { - components.add("KRB5"); - } - break; - case K_KRB5_EXPORT: - if (!forCertPathOnly) { - components.add("KRB5_EXPORT"); - } - break; - default: - // ignore - } - - return components; - } - - protected Set decomposes(BulkCipher bulkCipher) { - Set components = new HashSet<>(); - - if (bulkCipher.transformation != null) { - components.addAll(super.decomposes(bulkCipher.transformation)); - } - - return components; - } - - protected Set decomposes(MacAlg macAlg) { - Set components = new HashSet<>(); - - if (macAlg == CipherSuite.M_MD5) { - components.add("MD5"); - components.add("HmacMD5"); - } else if (macAlg == CipherSuite.M_SHA) { - components.add("SHA1"); - components.add("SHA-1"); - components.add("HmacSHA1"); - } else if (macAlg == CipherSuite.M_SHA256) { - components.add("SHA256"); - components.add("SHA-256"); - components.add("HmacSHA256"); - } else if (macAlg == CipherSuite.M_SHA384) { - components.add("SHA384"); - components.add("SHA-384"); - components.add("HmacSHA384"); - } - - return components; - } - } - - static private class TLSDisabledAlgConstraints - extends BasicDisabledAlgConstraints { - - TLSDisabledAlgConstraints() { - super(DisabledAlgorithmConstraints.PROPERTY_TLS_DISABLED_ALGS); - } - - @Override - protected Set decomposes(String algorithm) { - if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) { - CipherSuite cipherSuite = null; - try { - cipherSuite = CipherSuite.valueOf(algorithm); - } catch (IllegalArgumentException iae) { - // ignore: unknown or unsupported ciphersuite - } - - if (cipherSuite != null) { - Set components = new HashSet<>(); - - if(cipherSuite.keyExchange != null) { - components.addAll( - decomposes(cipherSuite.keyExchange, false)); - } - - if (cipherSuite.cipher != null) { - components.addAll(decomposes(cipherSuite.cipher)); - } - - if (cipherSuite.macAlg != null) { - components.addAll(decomposes(cipherSuite.macAlg)); - } - - return components; - } - } - - return super.decomposes(algorithm); - } - } - - static private class X509DisabledAlgConstraints - extends BasicDisabledAlgConstraints { - - X509DisabledAlgConstraints() { - super(DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); - } - - @Override - protected Set decomposes(String algorithm) { - if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) { - CipherSuite cipherSuite = null; - try { - cipherSuite = CipherSuite.valueOf(algorithm); - } catch (IllegalArgumentException iae) { - // ignore: unknown or unsupported ciphersuite - } - - if (cipherSuite != null) { - Set components = new HashSet<>(); - - if(cipherSuite.keyExchange != null) { - components.addAll( - decomposes(cipherSuite.keyExchange, true)); - } - - // Certification path algorithm constraints do not apply - // to cipherSuite.cipher and cipherSuite.macAlg. - - return components; - } - } - - return super.decomposes(algorithm); - } - } } - diff -r 7b2018284119 -r 5aec959c9177 src/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java Mon Jul 20 00:15:56 2015 +0100 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.ssl; + +import java.util.HashSet; +import java.util.Set; +import sun.security.util.AlgorithmDecomposer; +import static sun.security.ssl.CipherSuite.*; +import static sun.security.ssl.CipherSuite.KeyExchange.*; + +/** + * The class decomposes standard SSL/TLS cipher suites into sub-elements. + */ +class SSLAlgorithmDecomposer extends AlgorithmDecomposer { + + // indicates that only certification path algorithms need to be used + private final boolean onlyX509; + + SSLAlgorithmDecomposer(boolean onlyX509) { + this.onlyX509 = onlyX509; + } + + SSLAlgorithmDecomposer() { + this(false); + } + + private Set decomposes(CipherSuite.KeyExchange keyExchange) { + Set components = new HashSet<>(); + switch (keyExchange) { + case K_NULL: + if (!onlyX509) { + components.add("K_NULL"); + } + break; + case K_RSA: + components.add("RSA"); + break; + case K_RSA_EXPORT: + components.add("RSA"); + components.add("RSA_EXPORT"); + break; + case K_DH_RSA: + components.add("RSA"); + components.add("DH"); + components.add("DiffieHellman"); + components.add("DH_RSA"); + break; + case K_DH_DSS: + components.add("DSA"); + components.add("DSS"); + components.add("DH"); + components.add("DiffieHellman"); + components.add("DH_DSS"); + break; + case K_DHE_DSS: + components.add("DSA"); + components.add("DSS"); + components.add("DH"); + components.add("DHE"); + components.add("DiffieHellman"); + components.add("DHE_DSS"); + break; + case K_DHE_RSA: + components.add("RSA"); + components.add("DH"); + components.add("DHE"); + components.add("DiffieHellman"); + components.add("DHE_RSA"); + break; + case K_DH_ANON: + if (!onlyX509) { + components.add("ANON"); + components.add("DH"); + components.add("DiffieHellman"); + components.add("DH_ANON"); + } + break; + case K_ECDH_ECDSA: + components.add("ECDH"); + components.add("ECDSA"); + components.add("ECDH_ECDSA"); + break; + case K_ECDH_RSA: + components.add("ECDH"); + components.add("RSA"); + components.add("ECDH_RSA"); + break; + case K_ECDHE_ECDSA: + components.add("ECDHE"); + components.add("ECDSA"); + components.add("ECDHE_ECDSA"); + break; + case K_ECDHE_RSA: + components.add("ECDHE"); + components.add("RSA"); + components.add("ECDHE_RSA"); + break; + case K_ECDH_ANON: + if (!onlyX509) { + components.add("ECDH"); + components.add("ANON"); + components.add("ECDH_ANON"); + } + break; + case K_KRB5: + if (!onlyX509) { + components.add("KRB5"); + } + break; + case K_KRB5_EXPORT: + if (!onlyX509) { + components.add("KRB5_EXPORT"); + } + break; + default: + // ignore + } + + return components; + } + + private Set decomposes(CipherSuite.BulkCipher bulkCipher) { + Set components = new HashSet<>(); + + if (bulkCipher.transformation != null) { + components.addAll(super.decompose(bulkCipher.transformation)); + } + + if (bulkCipher == B_NULL) { + components.add("C_NULL"); + } else if (bulkCipher == B_RC2_40) { + components.add("RC2_CBC_40"); + } else if (bulkCipher == B_RC4_40) { + components.add("RC4_40"); + } else if (bulkCipher == B_RC4_128) { + components.add("RC4_128"); + } else if (bulkCipher == B_DES_40) { + components.add("DES40_CBC"); + components.add("DES_CBC_40"); + } else if (bulkCipher == B_DES) { + components.add("DES_CBC"); + } else if (bulkCipher == B_3DES) { + components.add("3DES_EDE_CBC"); + } else if (bulkCipher == B_AES_128) { + components.add("AES_128_CBC"); + } else if (bulkCipher == B_AES_256) { + components.add("AES_256_CBC"); + } + + return components; + } + + private Set decomposes(CipherSuite.MacAlg macAlg, + BulkCipher cipher) { + Set components = new HashSet<>(); + + if (macAlg == M_NULL) { + components.add("M_NULL"); + } else if (macAlg == M_MD5) { + components.add("MD5"); + components.add("HmacMD5"); + } else if (macAlg == M_SHA) { + components.add("SHA1"); + components.add("SHA-1"); + components.add("HmacSHA1"); + } else if (macAlg == M_SHA256) { + components.add("SHA256"); + components.add("SHA-256"); + components.add("HmacSHA256"); + } else if (macAlg == M_SHA384) { + components.add("SHA384"); + components.add("SHA-384"); + components.add("HmacSHA384"); + } + + return components; + } + + private Set decompose(KeyExchange keyExchange, BulkCipher cipher, + MacAlg macAlg) { + Set components = new HashSet<>(); + + if (keyExchange != null) { + components.addAll(decomposes(keyExchange)); + } + + if (onlyX509) { + // Certification path algorithm constraints do not apply + // to cipher and macAlg. + return components; + } + + if (cipher != null) { + components.addAll(decomposes(cipher)); + } + + if (macAlg != null) { + components.addAll(decomposes(macAlg, cipher)); + } + + return components; + } + + @Override + public Set decompose(String algorithm) { + if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) { + CipherSuite cipherSuite = null; + try { + cipherSuite = CipherSuite.valueOf(algorithm); + } catch (IllegalArgumentException iae) { + // ignore: unknown or unsupported ciphersuite + } + + if (cipherSuite != null) { + return decompose(cipherSuite.keyExchange, cipherSuite.cipher, + cipherSuite.macAlg); + } + } + + return super.decompose(algorithm); + } + +} diff -r 7b2018284119 -r 5aec959c9177 src/share/classes/sun/security/ssl/ServerHandshaker.java --- a/src/share/classes/sun/security/ssl/ServerHandshaker.java Mon Jul 20 00:11:26 2015 +0100 +++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java Mon Jul 20 00:15:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import javax.security.auth.Subject; import sun.security.util.KeyUtil; +import sun.security.util.LegacyAlgorithmConstraints; import sun.security.action.GetPropertyAction; import sun.security.ssl.HandshakeMessage.*; import sun.security.ssl.CipherSuite.*; @@ -140,6 +141,12 @@ } } + // legacy algorithm constraints + private static final AlgorithmConstraints legacyAlgorithmConstraints = + new LegacyAlgorithmConstraints( + LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS, + new SSLAlgorithmDecomposer()); + /* * Constructor ... use the keys found in the auth context. */ @@ -928,6 +935,7 @@ * the cipherSuite and keyExchange variables. */ private void chooseCipherSuite(ClientHello mesg) throws IOException { + List legacySuites = new ArrayList(); for (CipherSuite suite : mesg.getCipherSuites().collection()) { if (isNegotiable(suite) == false) { continue; @@ -939,11 +947,24 @@ continue; } } + + if (!legacyAlgorithmConstraints.permits(null, suite.name, null)) { + legacySuites.add(suite); + continue; + } + if (trySetCipherSuite(suite) == false) { continue; } return; } + + for (CipherSuite suite : legacySuites) { + if (trySetCipherSuite(suite)) { + return; + } + } + fatalSE(Alerts.alert_handshake_failure, "no cipher suites in common"); } diff -r 7b2018284119 -r 5aec959c9177 src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java Mon Jul 20 00:15:56 2015 +0100 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.AccessController; +import java.security.AlgorithmConstraints; +import java.security.PrivilegedAction; +import java.security.Security; +import java.util.Map; +import java.util.Set; + +/** + * The class contains common functionality for algorithm constraints classes. + */ +public abstract class AbstractAlgorithmConstraints + implements AlgorithmConstraints { + + protected final AlgorithmDecomposer decomposer; + + protected AbstractAlgorithmConstraints(AlgorithmDecomposer decomposer) { + this.decomposer = decomposer; + } + + // Get algorithm constraints from the specified security property. + private static void loadAlgorithmsMap(Map algorithmsMap, + final String propertyName) { + String property = AccessController.doPrivileged( + new PrivilegedAction() { + 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]; + } + algorithmsMap.put(propertyName, algorithmsInProperty); + } + + static String[] getAlgorithms(Map algorithmsMap, + String propertyName) { + synchronized (algorithmsMap) { + if (!algorithmsMap.containsKey(propertyName)) { + loadAlgorithmsMap(algorithmsMap, propertyName); + } + + return algorithmsMap.get(propertyName); + } + } + + static boolean checkAlgorithm(String[] algorithms, String algorithm, + AlgorithmDecomposer decomposer) { + if (algorithm == null || algorithm.length() == 0) { + throw new IllegalArgumentException("No algorithm name specified"); + } + + Set elements = null; + for (String item : algorithms) { + if (item == null || item.isEmpty()) { + continue; + } + + // check the full name + if (item.equalsIgnoreCase(algorithm)) { + return false; + } + + // decompose the algorithm into sub-elements + if (elements == null) { + elements = decomposer.decompose(algorithm); + } + + // check the items of the algorithm + for (String element : elements) { + if (item.equalsIgnoreCase(element)) { + return false; + } + } + } + + return true; + } + +} diff -r 7b2018284119 -r 5aec959c9177 src/share/classes/sun/security/util/AlgorithmDecomposer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/util/AlgorithmDecomposer.java Mon Jul 20 00:15:56 2015 +0100 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * The class decomposes standard algorithms into sub-elements. + */ +public class AlgorithmDecomposer { + + private static final Pattern transPattern = Pattern.compile("/"); + private static final Pattern pattern = + Pattern.compile("with|and", Pattern.CASE_INSENSITIVE); + + /** + * Decompose the standard algorithm name into sub-elements. + *

+ * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA" + * so that we can check the "SHA1" and "RSA" algorithm constraints + * separately. + *

+ * Please override the method if need to support more name pattern. + */ + public Set decompose(String algorithm) { + if (algorithm == null || algorithm.length() == 0) { + return new HashSet<>(); + } + + // algorithm/mode/padding + String[] transTockens = transPattern.split(algorithm); + + Set elements = new HashSet<>(); + for (String transTocken : transTockens) { + if (transTocken == null || transTocken.length() == 0) { + continue; + } + + // PBEWithAnd + // PBEWithAnd + // OAEPWithAndPadding + // with + // withand + 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; + } + +} diff -r 7b2018284119 -r 5aec959c9177 src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java --- a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Mon Jul 20 00:11:26 2015 +0100 +++ b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Mon Jul 20 00:15:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,9 @@ 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.util.Locale; import java.util.Set; import java.util.Collections; @@ -49,7 +43,7 @@ * See the "jdk.certpath.disabledAlgorithms" specification in java.security * for the syntax of the disabled algorithm string. */ -public class DisabledAlgorithmConstraints implements AlgorithmConstraints { +public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { // the known security property, jdk.certpath.disabledAlgorithms public final static String PROPERTY_CERTPATH_DISABLED_ALGS = @@ -64,8 +58,8 @@ private static Map keySizeConstraintsMap = Collections.synchronizedMap(new HashMap()); - private String[] disabledAlgorithms; - private KeySizeConstraints keySizeConstraints; + private final String[] disabledAlgorithms; + private final KeySizeConstraints keySizeConstraints; /** * Initialize algorithm constraints with the specified security property. @@ -74,54 +68,27 @@ * algorithm constraints */ public DisabledAlgorithmConstraints(String propertyName) { - synchronized (disabledAlgorithmsMap) { - if(!disabledAlgorithmsMap.containsKey(propertyName)) { - loadDisabledAlgorithmsMap(propertyName); - } + this(propertyName, new AlgorithmDecomposer()); + } - disabledAlgorithms = disabledAlgorithmsMap.get(propertyName); - keySizeConstraints = keySizeConstraintsMap.get(propertyName); - } + public DisabledAlgorithmConstraints(String propertyName, + AlgorithmDecomposer decomposer) { + super(decomposer); + disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName); + keySizeConstraints = getKeySizeConstraints(disabledAlgorithms, + propertyName); } @Override final public boolean permits(Set 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 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; + return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); } @Override @@ -140,98 +107,6 @@ return checkConstraints(primitives, algorithm, key, parameters); } - /** - * Decompose the standard algorithm name into sub-elements. - *

- * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA" - * so that we can check the "SHA1" and "RSA" algorithm constraints - * separately. - *

- * Please override the method if need to support more name pattern. - */ - protected Set decomposes(String algorithm) { - if (algorithm == null || algorithm.length() == 0) { - return new HashSet(); - } - - // algorithm/mode/padding - Pattern transPattern = Pattern.compile("/"); - String[] transTockens = transPattern.split(algorithm); - - Set elements = new HashSet(); - for (String transTocken : transTockens) { - if (transTocken == null || transTocken.length() == 0) { - continue; - } - - // PBEWithAnd - // PBEWithAnd - // OAEPWithAndPadding - // with - // withand - 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 primitives, String algorithm, Key key, AlgorithmParameters parameters) { @@ -261,43 +136,18 @@ return true; } - // Get disabled algorithm constraints from the specified security property. - private static void loadDisabledAlgorithmsMap( - final String propertyName) { - - String property = AccessController.doPrivileged( - new PrivilegedAction() { - 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); + private static KeySizeConstraints getKeySizeConstraints( + String[] disabledAlgorithms, String propertyName) { + synchronized (keySizeConstraintsMap) { + if(!keySizeConstraintsMap.containsKey(propertyName)) { + // map the key constraints + KeySizeConstraints keySizeConstraints = + new KeySizeConstraints(disabledAlgorithms); + keySizeConstraintsMap.put(propertyName, keySizeConstraints); } - algorithmsInProperty = property.split(","); - for (int i = 0; i < algorithmsInProperty.length; i++) { - algorithmsInProperty[i] = algorithmsInProperty[i].trim(); - } + return keySizeConstraintsMap.get(propertyName); } - - // 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); } /** diff -r 7b2018284119 -r 5aec959c9177 src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java Mon Jul 20 00:15:56 2015 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.AlgorithmParameters; +import java.security.CryptoPrimitive; +import java.security.Key; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms; + +/** + * Algorithm constraints for legacy algorithms. + */ +public class LegacyAlgorithmConstraints extends AbstractAlgorithmConstraints { + + // the known security property, jdk.tls.legacyAlgorithms + public final static String PROPERTY_TLS_LEGACY_ALGS = + "jdk.tls.legacyAlgorithms"; + + private final static Map legacyAlgorithmsMap = + new HashMap<>(); + + private final String[] legacyAlgorithms; + + public LegacyAlgorithmConstraints(String propertyName, + AlgorithmDecomposer decomposer) { + super(decomposer); + legacyAlgorithms = getAlgorithms(legacyAlgorithmsMap, propertyName); + } + + @Override + final public boolean permits(Set primitives, + String algorithm, AlgorithmParameters parameters) { + return checkAlgorithm(legacyAlgorithms, algorithm, decomposer); + } + + @Override + final public boolean permits(Set primitives, Key key) { + return true; + } + + @Override + final public boolean permits(Set primitives, + String algorithm, Key key, AlgorithmParameters parameters) { + return checkAlgorithm(legacyAlgorithms, algorithm, decomposer); + } + +} diff -r 7b2018284119 -r 5aec959c9177 src/share/lib/security/java.security-linux --- a/src/share/lib/security/java.security-linux Mon Jul 20 00:11:26 2015 +0100 +++ b/src/share/lib/security/java.security-linux Mon Jul 20 00:15:56 2015 +0100 @@ -438,3 +438,60 @@ # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=SSLv3 + +# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) +# processing in JSSE implementation. +# +# In some environments, a certain algorithm may be undesirable but it +# cannot be disabled because of its use in legacy applications. Legacy +# algorithms may still be supported, but applications should not use them +# as the security strength of legacy algorithms are usually not strong enough +# in practice. +# +# During SSL/TLS security parameters negotiation, legacy algorithms will +# not be negotiated unless there are no other candidates. +# +# The syntax of the disabled algorithm string is described as this Java +# BNF-style: +# LegacyAlgorithms: +# " LegacyAlgorithm { , LegacyAlgorithm } " +# +# LegacyAlgorithm: +# AlgorithmName (standard JSSE algorithm name) +# +# See the specification of security property "jdk.certpath.disabledAlgorithms" +# for the syntax and description of the "AlgorithmName" notation. +# +# Per SSL/TLS specifications, cipher suites have the form: +# SSL_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# or +# TLS_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# +# For example, the cipher suite TLS_RSA_WITH_AES_128_CBC_SHA uses RSA as the +# key exchange algorithm, AES_128_CBC (128 bits AES cipher algorithm in CBC +# mode) as the cipher (encryption) algorithm, and SHA-1 as the message digest +# algorithm for HMAC. +# +# The LegacyAlgorithm can be one of the following standard algorithm names: +# 1. JSSE cipher suite name, e.g., TLS_RSA_WITH_AES_128_CBC_SHA +# 2. JSSE key exchange algorithm name, e.g., RSA +# 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC +# 4. JSSE message digest algorithm name, e.g., SHA-1 +# +# See SSL/TLS specifications and "Java Cryptography Architecture Standard +# Algorithm Name Documentation" for information about the algorithm names. +# +# Note: This property is currently used by Oracle's JSSE implementation. +# It is not guaranteed to be examined and used by other implementations. +# There is no guarantee the property will continue to exist or be of the +# same syntax in future releases. +# +# Example: +# jdk.tls.legacyAlgorithms=DH_anon, DES_CBC, SSL_RSA_WITH_RC4_128_MD5 +# +jdk.tls.legacyAlgorithms= \ + K_NULL, C_NULL, M_NULL, \ + DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ + DH_RSA_EXPORT, RSA_EXPORT, \ + DH_anon, ECDH_anon, \ + RC4_128, RC4_40, DES_CBC, DES40_CBC diff -r 7b2018284119 -r 5aec959c9177 src/share/lib/security/java.security-macosx --- a/src/share/lib/security/java.security-macosx Mon Jul 20 00:11:26 2015 +0100 +++ b/src/share/lib/security/java.security-macosx Mon Jul 20 00:15:56 2015 +0100 @@ -443,3 +443,60 @@ # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=SSLv3 + +# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) +# processing in JSSE implementation. +# +# In some environments, a certain algorithm may be undesirable but it +# cannot be disabled because of its use in legacy applications. Legacy +# algorithms may still be supported, but applications should not use them +# as the security strength of legacy algorithms are usually not strong enough +# in practice. +# +# During SSL/TLS security parameters negotiation, legacy algorithms will +# not be negotiated unless there are no other candidates. +# +# The syntax of the disabled algorithm string is described as this Java +# BNF-style: +# LegacyAlgorithms: +# " LegacyAlgorithm { , LegacyAlgorithm } " +# +# LegacyAlgorithm: +# AlgorithmName (standard JSSE algorithm name) +# +# See the specification of security property "jdk.certpath.disabledAlgorithms" +# for the syntax and description of the "AlgorithmName" notation. +# +# Per SSL/TLS specifications, cipher suites have the form: +# SSL_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# or +# TLS_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# +# For example, the cipher suite TLS_RSA_WITH_AES_128_CBC_SHA uses RSA as the +# key exchange algorithm, AES_128_CBC (128 bits AES cipher algorithm in CBC +# mode) as the cipher (encryption) algorithm, and SHA-1 as the message digest +# algorithm for HMAC. +# +# The LegacyAlgorithm can be one of the following standard algorithm names: +# 1. JSSE cipher suite name, e.g., TLS_RSA_WITH_AES_128_CBC_SHA +# 2. JSSE key exchange algorithm name, e.g., RSA +# 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC +# 4. JSSE message digest algorithm name, e.g., SHA-1 +# +# See SSL/TLS specifications and "Java Cryptography Architecture Standard +# Algorithm Name Documentation" for information about the algorithm names. +# +# Note: This property is currently used by Oracle's JSSE implementation. +# It is not guaranteed to be examined and used by other implementations. +# There is no guarantee the property will continue to exist or be of the +# same syntax in future releases. +# +# Example: +# jdk.tls.legacyAlgorithms=DH_anon, DES_CBC, SSL_RSA_WITH_RC4_128_MD5 +# +jdk.tls.legacyAlgorithms= \ + K_NULL, C_NULL, M_NULL, \ + DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ + DH_RSA_EXPORT, RSA_EXPORT, \ + DH_anon, ECDH_anon, \ + RC4_128, RC4_40, DES_CBC, DES40_CBC diff -r 7b2018284119 -r 5aec959c9177 src/share/lib/security/java.security-solaris --- a/src/share/lib/security/java.security-solaris Mon Jul 20 00:11:26 2015 +0100 +++ b/src/share/lib/security/java.security-solaris Mon Jul 20 00:15:56 2015 +0100 @@ -442,3 +442,60 @@ # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=SSLv3 + +# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) +# processing in JSSE implementation. +# +# In some environments, a certain algorithm may be undesirable but it +# cannot be disabled because of its use in legacy applications. Legacy +# algorithms may still be supported, but applications should not use them +# as the security strength of legacy algorithms are usually not strong enough +# in practice. +# +# During SSL/TLS security parameters negotiation, legacy algorithms will +# not be negotiated unless there are no other candidates. +# +# The syntax of the disabled algorithm string is described as this Java +# BNF-style: +# LegacyAlgorithms: +# " LegacyAlgorithm { , LegacyAlgorithm } " +# +# LegacyAlgorithm: +# AlgorithmName (standard JSSE algorithm name) +# +# See the specification of security property "jdk.certpath.disabledAlgorithms" +# for the syntax and description of the "AlgorithmName" notation. +# +# Per SSL/TLS specifications, cipher suites have the form: +# SSL_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# or +# TLS_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# +# For example, the cipher suite TLS_RSA_WITH_AES_128_CBC_SHA uses RSA as the +# key exchange algorithm, AES_128_CBC (128 bits AES cipher algorithm in CBC +# mode) as the cipher (encryption) algorithm, and SHA-1 as the message digest +# algorithm for HMAC. +# +# The LegacyAlgorithm can be one of the following standard algorithm names: +# 1. JSSE cipher suite name, e.g., TLS_RSA_WITH_AES_128_CBC_SHA +# 2. JSSE key exchange algorithm name, e.g., RSA +# 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC +# 4. JSSE message digest algorithm name, e.g., SHA-1 +# +# See SSL/TLS specifications and "Java Cryptography Architecture Standard +# Algorithm Name Documentation" for information about the algorithm names. +# +# Note: This property is currently used by Oracle's JSSE implementation. +# It is not guaranteed to be examined and used by other implementations. +# There is no guarantee the property will continue to exist or be of the +# same syntax in future releases. +# +# Example: +# jdk.tls.legacyAlgorithms=DH_anon, DES_CBC, SSL_RSA_WITH_RC4_128_MD5 +# +jdk.tls.legacyAlgorithms= \ + K_NULL, C_NULL, M_NULL, \ + DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ + DH_RSA_EXPORT, RSA_EXPORT, \ + DH_anon, ECDH_anon, \ + RC4_128, RC4_40, DES_CBC, DES40_CBC diff -r 7b2018284119 -r 5aec959c9177 src/share/lib/security/java.security-windows --- a/src/share/lib/security/java.security-windows Mon Jul 20 00:11:26 2015 +0100 +++ b/src/share/lib/security/java.security-windows Mon Jul 20 00:15:56 2015 +0100 @@ -443,3 +443,60 @@ # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=SSLv3 + +# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) +# processing in JSSE implementation. +# +# In some environments, a certain algorithm may be undesirable but it +# cannot be disabled because of its use in legacy applications. Legacy +# algorithms may still be supported, but applications should not use them +# as the security strength of legacy algorithms are usually not strong enough +# in practice. +# +# During SSL/TLS security parameters negotiation, legacy algorithms will +# not be negotiated unless there are no other candidates. +# +# The syntax of the disabled algorithm string is described as this Java +# BNF-style: +# LegacyAlgorithms: +# " LegacyAlgorithm { , LegacyAlgorithm } " +# +# LegacyAlgorithm: +# AlgorithmName (standard JSSE algorithm name) +# +# See the specification of security property "jdk.certpath.disabledAlgorithms" +# for the syntax and description of the "AlgorithmName" notation. +# +# Per SSL/TLS specifications, cipher suites have the form: +# SSL_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# or +# TLS_KeyExchangeAlg_WITH_CipherAlg_MacAlg +# +# For example, the cipher suite TLS_RSA_WITH_AES_128_CBC_SHA uses RSA as the +# key exchange algorithm, AES_128_CBC (128 bits AES cipher algorithm in CBC +# mode) as the cipher (encryption) algorithm, and SHA-1 as the message digest +# algorithm for HMAC. +# +# The LegacyAlgorithm can be one of the following standard algorithm names: +# 1. JSSE cipher suite name, e.g., TLS_RSA_WITH_AES_128_CBC_SHA +# 2. JSSE key exchange algorithm name, e.g., RSA +# 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC +# 4. JSSE message digest algorithm name, e.g., SHA-1 +# +# See SSL/TLS specifications and "Java Cryptography Architecture Standard +# Algorithm Name Documentation" for information about the algorithm names. +# +# Note: This property is currently used by Oracle's JSSE implementation. +# It is not guaranteed to be examined and used by other implementations. +# There is no guarantee the property will continue to exist or be of the +# same syntax in future releases. +# +# Example: +# jdk.tls.legacyAlgorithms=DH_anon, DES_CBC, SSL_RSA_WITH_RC4_128_MD5 +# +jdk.tls.legacyAlgorithms= \ + K_NULL, C_NULL, M_NULL, \ + DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ + DH_RSA_EXPORT, RSA_EXPORT, \ + DH_anon, ECDH_anon, \ + RC4_128, RC4_40, DES_CBC, DES40_CBC