diff -r 0c7d705209c6 -r ec0224270f90 jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Mon Jun 01 10:29:06 2015 -0400 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Tue Jun 02 04:01:04 2015 +0000 @@ -62,6 +62,9 @@ private CipherSuiteList defaultClientCipherSuiteList; private CipherSuiteList supportedCipherSuiteList; + // DTLS cookie exchange manager + private HelloCookieManager helloCookieManager; + SSLContextImpl() { ephemeralKeyManager = new EphemeralKeyManager(); clientCache = new SSLSessionContextImpl(); @@ -175,11 +178,29 @@ return DummyX509KeyManager.INSTANCE; } + abstract SSLEngine createSSLEngineImpl(); + abstract SSLEngine createSSLEngineImpl(String host, int port); + + @Override + protected SSLEngine engineCreateSSLEngine() { + if (!isInitialized) { + throw new IllegalStateException("SSLContext is not initialized"); + } + return createSSLEngineImpl(); + } + + @Override + protected SSLEngine engineCreateSSLEngine(String host, int port) { + if (!isInitialized) { + throw new IllegalStateException("SSLContext is not initialized"); + } + return createSSLEngineImpl(host, port); + } + @Override protected SSLSocketFactory engineGetSocketFactory() { if (!isInitialized) { - throw new IllegalStateException( - "SSLContextImpl is not initialized"); + throw new IllegalStateException("SSLContext is not initialized"); } return new SSLSocketFactoryImpl(this); } @@ -193,24 +214,6 @@ } @Override - protected SSLEngine engineCreateSSLEngine() { - if (!isInitialized) { - throw new IllegalStateException( - "SSLContextImpl is not initialized"); - } - return new SSLEngineImpl(this); - } - - @Override - protected SSLEngine engineCreateSSLEngine(String host, int port) { - if (!isInitialized) { - throw new IllegalStateException( - "SSLContextImpl is not initialized"); - } - return new SSLEngineImpl(this, host, port); - } - - @Override protected SSLSessionContext engineGetClientSessionContext() { return clientCache; } @@ -236,6 +239,23 @@ return ephemeralKeyManager; } + HelloCookieManager getHelloCookieManager() { + if (!isInitialized) { + throw new IllegalStateException("SSLContext is not initialized"); + } + + if (helloCookieManager == null) { + helloCookieManager = getHelloCookieManager(secureRandom); + } + + return helloCookieManager; + } + + HelloCookieManager getHelloCookieManager(SecureRandom secureRandom) { + throw new UnsupportedOperationException( + "Cookie exchange applies to DTLS only"); + } + abstract SSLParameters getDefaultServerSSLParams(); abstract SSLParameters getDefaultClientSSLParams(); abstract SSLParameters getSupportedSSLParams(); @@ -319,12 +339,20 @@ (protocols == defaultClientProtocolList); } + /** + * Return whether a protocol list is the original default enabled + * protocols. See: SSLSocket/SSLEngine.setEnabledProtocols() + */ + boolean isDefaultCipherSuiteList(CipherSuiteList cipherSuites) { + return (cipherSuites == defaultClientCipherSuiteList) || + (cipherSuites == defaultServerCipherSuiteList); + } /* * Return the list of all available CipherSuites with a priority of * minPriority or above. */ - private CipherSuiteList getApplicableCipherSuiteList( + private static CipherSuiteList getApplicableCipherSuiteList( ProtocolList protocols, boolean onlyEnabled) { int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY; @@ -344,8 +372,8 @@ } if (suite.isAvailable() && - suite.obsoleted > protocols.min.v && - suite.supported <= protocols.max.v) { + !protocols.min.obsoletes(suite) && + protocols.max.supports(suite)) { if (SSLAlgorithmConstraints.DEFAULT.permits( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) { @@ -353,10 +381,10 @@ } } else if (debug != null && Debug.isOn("sslctx") && Debug.isOn("verbose")) { - if (suite.obsoleted <= protocols.min.v) { + if (protocols.min.obsoletes(suite)) { System.out.println( "Ignoring obsoleted cipher suite: " + suite); - } else if (suite.supported > protocols.max.v) { + } else if (!protocols.max.supports(suite)) { System.out.println( "Ignoring unsupported cipher suite: " + suite); } else { @@ -388,8 +416,25 @@ } } + private static String[] getAvailableProtocols( + ProtocolVersion[] protocolCandidates) { + + List availableProtocols = Collections.emptyList(); + if (protocolCandidates != null && protocolCandidates.length != 0) { + availableProtocols = new ArrayList<>(protocolCandidates.length); + for (ProtocolVersion p : protocolCandidates) { + if (ProtocolVersion.availableProtocols.contains(p)) { + availableProtocols.add(p.name); + } + } + } + + return availableProtocols.toArray(new String[0]); + } + + /* - * The SSLContext implementation for TLS/SSL algorithm + * The SSLContext implementation for SSL/(D)TLS algorithm * * SSL/TLS protocols specify the forward compatibility and version * roll-back attack protections, however, a number of SSL/TLS server @@ -418,14 +463,15 @@ */ /* - * The base abstract SSLContext implementation. + * The base abstract SSLContext implementation for the Transport Layer + * Security (TLS) protocols. * * This abstract class encapsulates supported and the default server - * SSL parameters. + * SSL/TLS parameters. * * @see SSLContext */ - private abstract static class AbstractSSLContext extends SSLContextImpl { + private abstract static class AbstractTLSContext extends SSLContextImpl { // parameters private static final SSLParameters defaultServerSSLParams; private static final SSLParameters supportedSSLParams; @@ -482,20 +528,14 @@ return supportedSSLParams; } - static String[] getAvailableProtocols( - ProtocolVersion[] protocolCandidates) { + @Override + SSLEngine createSSLEngineImpl() { + return new SSLEngineImpl(this, false); + } - List availableProtocols = Collections.emptyList(); - if (protocolCandidates != null && protocolCandidates.length != 0) { - availableProtocols = new ArrayList<>(protocolCandidates.length); - for (ProtocolVersion p : protocolCandidates) { - if (ProtocolVersion.availableProtocols.contains(p)) { - availableProtocols.add(p.name); - } - } - } - - return availableProtocols.toArray(new String[0]); + @Override + SSLEngine createSSLEngineImpl(String host, int port) { + return new SSLEngineImpl(this, host, port, false); } } @@ -504,7 +544,7 @@ * * @see SSLContext */ - public static final class TLS10Context extends AbstractSSLContext { + public static final class TLS10Context extends AbstractTLSContext { private static final SSLParameters defaultClientSSLParams; static { @@ -537,7 +577,7 @@ * * @see SSLContext */ - public static final class TLS11Context extends AbstractSSLContext { + public static final class TLS11Context extends AbstractTLSContext { private static final SSLParameters defaultClientSSLParams; static { @@ -572,7 +612,7 @@ * * @see SSLContext */ - public static final class TLS12Context extends AbstractSSLContext { + public static final class TLS12Context extends AbstractTLSContext { private static final SSLParameters defaultClientSSLParams; static { @@ -605,12 +645,73 @@ } /* + * The interface for the customized SSL/(D)TLS SSLContext. + * + * @see SSLContext + */ + private static class CustomizedSSLProtocols { + private final static String PROPERTY_NAME = "jdk.tls.client.protocols"; + static IllegalArgumentException reservedException = null; + static ArrayList + customizedProtocols = new ArrayList<>(); + + // Don't want a java.lang.LinkageError for illegal system property. + // + // Please don't throw exception in this static block. Otherwise, + // java.lang.LinkageError may be thrown during the instantiation of + // the provider service. Instead, please handle the initialization + // exception in the caller's constructor. + static { + String property = AccessController.doPrivileged( + new GetPropertyAction(PROPERTY_NAME)); + if (property != null && property.length() != 0) { + // remove double quote marks from beginning/end of the property + if (property.length() > 1 && property.charAt(0) == '"' && + property.charAt(property.length() - 1) == '"') { + property = property.substring(1, property.length() - 1); + } + } + + if (property != null && property.length() != 0) { + String[] protocols = property.split(","); + for (int i = 0; i < protocols.length; i++) { + protocols[i] = protocols[i].trim(); + // Is it a supported protocol name? + try { + ProtocolVersion pro = + ProtocolVersion.valueOf(protocols[i]); + + if (SunJSSE.isFIPS() && + ((pro.v == ProtocolVersion.SSL30.v) || + (pro.v == ProtocolVersion.SSL20Hello.v))) { + reservedException = new IllegalArgumentException( + PROPERTY_NAME + ": " + pro + + " is not FIPS compliant"); + + break; + } + + // ignore duplicated protocols + if (!customizedProtocols.contains(pro)) { + customizedProtocols.add(pro); + } + } catch (IllegalArgumentException iae) { + reservedException = new IllegalArgumentException( + PROPERTY_NAME + ": " + protocols[i] + + " is not a standard SSL protocol name", iae); + } + } + } + } + } + + /* * The SSLContext implementation for customized TLS protocols * * @see SSLContext */ - private static class CustomizedSSLContext extends AbstractSSLContext { - private static final String PROPERTY_NAME = "jdk.tls.client.protocols"; + private static class CustomizedTLSContext extends AbstractTLSContext { + private static final SSLParameters defaultClientSSLParams; private static IllegalArgumentException reservedException = null; @@ -621,78 +722,52 @@ // the provider service. Instead, let's handle the initialization // exception in constructor. static { - // candidates for available protocols - ProtocolVersion[] candidates; - - String property = AccessController.doPrivileged( - new GetPropertyAction(PROPERTY_NAME)); - if (property == null || property.length() == 0) { - // the default enabled client TLS protocols - if (SunJSSE.isFIPS()) { - candidates = new ProtocolVersion[] { - ProtocolVersion.TLS10, - ProtocolVersion.TLS11, - ProtocolVersion.TLS12 - }; - } else { - candidates = new ProtocolVersion[] { - ProtocolVersion.SSL30, - ProtocolVersion.TLS10, - ProtocolVersion.TLS11, - ProtocolVersion.TLS12 - }; - } - } else { - // remove double quote marks from beginning/end of the property - if (property.length() > 1 && property.charAt(0) == '"' && - property.charAt(property.length() - 1) == '"') { - property = property.substring(1, property.length() - 1); - } - - String[] protocols = null; - if (property != null && property.length() != 0) { - protocols = property.split(","); - } else { - reservedException = new IllegalArgumentException( - "No protocol specified in " + - PROPERTY_NAME + " system property"); - protocols = new String[0]; - } - - candidates = new ProtocolVersion[protocols.length]; - for (int i = 0; i < protocols.length; i++) { - protocols[i] = protocols[i].trim(); - // Is it a supported protocol name? - try { - candidates[i] = ProtocolVersion.valueOf(protocols[i]); - } catch (IllegalArgumentException iae) { - reservedException = new IllegalArgumentException( - PROPERTY_NAME + ": " + protocols[i] + - " is not a standard SSL/TLS protocol name", iae); - break; + reservedException = CustomizedSSLProtocols.reservedException; + if (reservedException == null) { + ArrayList + customizedTLSProtocols = new ArrayList<>(); + for (ProtocolVersion protocol : + CustomizedSSLProtocols.customizedProtocols) { + if (!protocol.isDTLSProtocol()) { + customizedTLSProtocols.add(protocol); } } - if ((reservedException == null) && SunJSSE.isFIPS()) { - for (ProtocolVersion protocolVersion : candidates) { - if (ProtocolVersion.SSL20Hello.v == protocolVersion.v || - ProtocolVersion.SSL30.v == protocolVersion.v) { - reservedException = new IllegalArgumentException( - PROPERTY_NAME + ": " + protocolVersion + - " is not FIPS compliant"); - } + // candidates for available protocols + ProtocolVersion[] candidates; + if (customizedTLSProtocols.isEmpty()) { + // Use the default enabled client protocols if no + // customized TLS protocols. + if (SunJSSE.isFIPS()) { + candidates = new ProtocolVersion[] { + ProtocolVersion.TLS10, + ProtocolVersion.TLS11, + ProtocolVersion.TLS12 + }; + } else { + candidates = new ProtocolVersion[] { + ProtocolVersion.SSL30, + ProtocolVersion.TLS10, + ProtocolVersion.TLS11, + ProtocolVersion.TLS12 + }; } + } else { + // Use the customized TLS protocols. + candidates = + new ProtocolVersion[customizedTLSProtocols.size()]; + candidates = customizedTLSProtocols.toArray(candidates); } - } - defaultClientSSLParams = new SSLParameters(); - if (reservedException == null) { + defaultClientSSLParams = new SSLParameters(); defaultClientSSLParams.setProtocols( getAvailableProtocols(candidates)); + } else { + defaultClientSSLParams = null; // unlikely to be used } } - protected CustomizedSSLContext() { + protected CustomizedTLSContext() { if (reservedException != null) { throw reservedException; } @@ -709,7 +784,7 @@ * * @see SSLContext */ - public static final class TLSContext extends CustomizedSSLContext { + public static final class TLSContext extends CustomizedTLSContext { // use the default constructor and methods } @@ -718,7 +793,7 @@ * * @see SSLContext */ - public static final class DefaultSSLContext extends CustomizedSSLContext { + public static final class DefaultSSLContext extends CustomizedTLSContext { private static final String NONE = "NONE"; private static final String P11KEYSTORE = "PKCS11"; @@ -879,6 +954,193 @@ } } + /* + * The base abstract SSLContext implementation for the Datagram Transport + * Layer Security (DTLS) protocols. + * + * This abstract class encapsulates supported and the default server DTLS + * parameters. + * + * @see SSLContext + */ + private abstract static class AbstractDTLSContext extends SSLContextImpl { + // parameters + private static final SSLParameters defaultServerSSLParams; + private static final SSLParameters supportedSSLParams; + + static { + // supported SSL parameters + supportedSSLParams = new SSLParameters(); + + // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode. + supportedSSLParams.setProtocols(new String[] { + ProtocolVersion.DTLS10.name, + ProtocolVersion.DTLS12.name + }); + + // candidates for available protocols + ProtocolVersion[] candidates = new ProtocolVersion[] { + ProtocolVersion.DTLS10, + ProtocolVersion.DTLS12 + }; + + defaultServerSSLParams = new SSLParameters(); + defaultServerSSLParams.setProtocols( + getAvailableProtocols(candidates)); + } + + @Override + SSLParameters getDefaultServerSSLParams() { + return defaultServerSSLParams; + } + + @Override + SSLParameters getSupportedSSLParams() { + return supportedSSLParams; + } + + @Override + SSLEngine createSSLEngineImpl() { + return new SSLEngineImpl(this, true); + } + + @Override + SSLEngine createSSLEngineImpl(String host, int port) { + return new SSLEngineImpl(this, host, port, true); + } + + @Override + HelloCookieManager getHelloCookieManager(SecureRandom secureRandom) { + return new HelloCookieManager(secureRandom); + } + } + + /* + * The SSLContext implementation for DTLSv1.0 algorithm. + * + * @see SSLContext + */ + public static final class DTLS10Context extends AbstractDTLSContext { + private final static SSLParameters defaultClientSSLParams; + + static { + // candidates for available protocols + ProtocolVersion[] candidates = new ProtocolVersion[] { + ProtocolVersion.DTLS10 + }; + + defaultClientSSLParams = new SSLParameters(); + defaultClientSSLParams.setProtocols( + getAvailableProtocols(candidates)); + } + + @Override + SSLParameters getDefaultClientSSLParams() { + return defaultClientSSLParams; + } + } + + /* + * The SSLContext implementation for DTLSv1.2 algorithm. + * + * @see SSLContext + */ + public static final class DTLS12Context extends AbstractDTLSContext { + private final static SSLParameters defaultClientSSLParams; + + static { + // candidates for available protocols + ProtocolVersion[] candidates = new ProtocolVersion[] { + ProtocolVersion.DTLS10, + ProtocolVersion.DTLS12 + }; + + defaultClientSSLParams = new SSLParameters(); + defaultClientSSLParams.setProtocols( + getAvailableProtocols(candidates)); + } + + @Override + SSLParameters getDefaultClientSSLParams() { + return defaultClientSSLParams; + } + } + + /* + * The SSLContext implementation for customized TLS protocols + * + * @see SSLContext + */ + private static class CustomizedDTLSContext extends AbstractDTLSContext { + private final static SSLParameters defaultClientSSLParams; + private static IllegalArgumentException reservedException = null; + + // Don't want a java.lang.LinkageError for illegal system property. + // + // Please don't throw exception in this static block. Otherwise, + // java.lang.LinkageError may be thrown during the instantiation of + // the provider service. Instead, let's handle the initialization + // exception in constructor. + static { + reservedException = CustomizedSSLProtocols.reservedException; + if (reservedException == null) { + ArrayList + customizedDTLSProtocols = new ArrayList<>(); + for (ProtocolVersion protocol : + CustomizedSSLProtocols.customizedProtocols) { + if (protocol.isDTLSProtocol()) { + customizedDTLSProtocols.add(protocol); + } + } + + // candidates for available protocols + ProtocolVersion[] candidates; + if (customizedDTLSProtocols.isEmpty()) { + // Use the default enabled client protocols if no + // customized TLS protocols. + // + // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode. + candidates = new ProtocolVersion[] { + ProtocolVersion.DTLS10, + ProtocolVersion.DTLS12 + }; + + } else { + // Use the customized TLS protocols. + candidates = + new ProtocolVersion[customizedDTLSProtocols.size()]; + candidates = customizedDTLSProtocols.toArray(candidates); + } + + defaultClientSSLParams = new SSLParameters(); + defaultClientSSLParams.setProtocols( + getAvailableProtocols(candidates)); + } else { + defaultClientSSLParams = null; // unlikely to be used + } + } + + protected CustomizedDTLSContext() { + if (reservedException != null) { + throw reservedException; + } + } + + @Override + SSLParameters getDefaultClientSSLParams() { + return defaultClientSSLParams; + } + } + + /* + * The SSLContext implementation for default "DTLS" algorithm + * + * @see SSLContext + */ + public static final class DTLSContext extends CustomizedDTLSContext { + // use the default constructor and methods + } + } @@ -961,7 +1223,7 @@ ProtocolVersion protocolVersion = ProtocolVersion.valueOf(session.getProtocol()); AlgorithmConstraints constraints = null; - if (protocolVersion.v >= ProtocolVersion.TLS12.v) { + if (protocolVersion.useTLS12PlusSpec()) { if (session instanceof ExtendedSSLSession) { ExtendedSSLSession extSession = (ExtendedSSLSession)session; @@ -1003,7 +1265,7 @@ ProtocolVersion protocolVersion = ProtocolVersion.valueOf(session.getProtocol()); AlgorithmConstraints constraints = null; - if (protocolVersion.v >= ProtocolVersion.TLS12.v) { + if (protocolVersion.useTLS12PlusSpec()) { if (session instanceof ExtendedSSLSession) { ExtendedSSLSession extSession = (ExtendedSSLSession)session;