src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java
Print this page
@@ -60,10 +60,13 @@
// supported and default cipher suites
private CipherSuiteList defaultServerCipherSuiteList;
private CipherSuiteList defaultClientCipherSuiteList;
private CipherSuiteList supportedCipherSuiteList;
+ // DTLS cookie exchange manager
+ private HelloCookieManager helloCookieManager;
+
SSLContextImpl() {
ephemeralKeyManager = new EphemeralKeyManager();
clientCache = new SSLSessionContextImpl();
serverCache = new SSLSessionContextImpl();
}
@@ -173,43 +176,43 @@
// nothing found, return a dummy X509ExtendedKeyManager
return DummyX509KeyManager.INSTANCE;
}
+ abstract SSLEngine createSSLEngineImpl();
+ abstract SSLEngine createSSLEngineImpl(String host, int port);
+
@Override
- protected SSLSocketFactory engineGetSocketFactory() {
+ protected SSLEngine engineCreateSSLEngine() {
if (!isInitialized) {
- throw new IllegalStateException(
- "SSLContextImpl is not initialized");
+ throw new IllegalStateException("SSLContext is not initialized");
}
- return new SSLSocketFactoryImpl(this);
+ return createSSLEngineImpl();
}
@Override
- protected SSLServerSocketFactory engineGetServerSocketFactory() {
+ protected SSLEngine engineCreateSSLEngine(String host, int port) {
if (!isInitialized) {
throw new IllegalStateException("SSLContext is not initialized");
}
- return new SSLServerSocketFactoryImpl(this);
+ return createSSLEngineImpl(host, port);
}
@Override
- protected SSLEngine engineCreateSSLEngine() {
+ protected SSLSocketFactory engineGetSocketFactory() {
if (!isInitialized) {
- throw new IllegalStateException(
- "SSLContextImpl is not initialized");
+ throw new IllegalStateException("SSLContext is not initialized");
}
- return new SSLEngineImpl(this);
+ return new SSLSocketFactoryImpl(this);
}
@Override
- protected SSLEngine engineCreateSSLEngine(String host, int port) {
+ protected SSLServerSocketFactory engineGetServerSocketFactory() {
if (!isInitialized) {
- throw new IllegalStateException(
- "SSLContextImpl is not initialized");
+ throw new IllegalStateException("SSLContext is not initialized");
}
- return new SSLEngineImpl(this, host, port);
+ return new SSLServerSocketFactoryImpl(this);
}
@Override
protected SSLSessionContext engineGetClientSessionContext() {
return clientCache;
@@ -234,10 +237,27 @@
EphemeralKeyManager getEphemeralKeyManager() {
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();
// Get supported ProtocolList.
@@ -317,16 +337,24 @@
boolean isDefaultProtocolList(ProtocolList protocols) {
return (protocols == defaultServerProtocolList) ||
(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;
if (onlyEnabled) {
minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
@@ -342,23 +370,23 @@
if (!suite.allowed || suite.priority < minPriority) {
continue;
}
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)) {
suites.add(suite);
}
} 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 {
System.out.println(
"Ignoring unavailable cipher suite: " + suite);
@@ -386,12 +414,29 @@
CipherSuite.BulkCipher.clearAvailableCache();
JsseJce.clearEcAvailable();
}
}
+ private static String[] getAvailableProtocols(
+ ProtocolVersion[] protocolCandidates) {
+
+ List<String> availableProtocols = Collections.<String>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
* vendors did not implement these aspects properly, and some current
* SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
@@ -416,18 +461,19 @@
* by default. Applications still can use it by enabling SSLv2Hello with
* the series of setEnabledProtocols APIs.
*/
/*
- * 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;
static {
@@ -480,33 +526,27 @@
@Override
SSLParameters getSupportedSSLParams() {
return supportedSSLParams;
}
- static String[] getAvailableProtocols(
- ProtocolVersion[] protocolCandidates) {
-
- List<String> availableProtocols = Collections.<String>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);
+ @Override
+ SSLEngine createSSLEngineImpl() {
+ return new SSLEngineImpl(this, false);
}
- }
- }
- return availableProtocols.toArray(new String[0]);
+ @Override
+ SSLEngine createSSLEngineImpl(String host, int port) {
+ return new SSLEngineImpl(this, host, port, false);
}
}
/*
* The SSLContext implementation for SSLv3 and TLS10 algorithm
*
* @see SSLContext
*/
- public static final class TLS10Context extends AbstractSSLContext {
+ public static final class TLS10Context extends AbstractTLSContext {
private static final SSLParameters defaultClientSSLParams;
static {
// candidates for available protocols
ProtocolVersion[] candidates;
@@ -535,11 +575,11 @@
/*
* The SSLContext implementation for TLS11 algorithm
*
* @see SSLContext
*/
- public static final class TLS11Context extends AbstractSSLContext {
+ public static final class TLS11Context extends AbstractTLSContext {
private static final SSLParameters defaultClientSSLParams;
static {
// candidates for available protocols
ProtocolVersion[] candidates;
@@ -570,11 +610,11 @@
/*
* The SSLContext implementation for TLS12 algorithm
*
* @see SSLContext
*/
- public static final class TLS12Context extends AbstractSSLContext {
+ public static final class TLS12Context extends AbstractTLSContext {
private static final SSLParameters defaultClientSSLParams;
static {
// candidates for available protocols
ProtocolVersion[] candidates;
@@ -603,16 +643,77 @@
return defaultClientSSLParams;
}
}
/*
+ * 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<ProtocolVersion>
+ 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;
// Don't want a java.lang.LinkageError for illegal system property.
//
@@ -619,17 +720,26 @@
// 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<ProtocolVersion>
+ customizedTLSProtocols = new ArrayList<>();
+ for (ProtocolVersion protocol :
+ CustomizedSSLProtocols.customizedProtocols) {
+ if (!protocol.isDTLSProtocol()) {
+ customizedTLSProtocols.add(protocol);
+ }
+ }
+
// 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 (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
@@ -641,60 +751,25 @@
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);
+ // Use the customized TLS protocols.
+ candidates =
+ new ProtocolVersion[customizedTLSProtocols.size()];
+ candidates = customizedTLSProtocols.toArray(candidates);
}
- 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;
- }
- }
-
- 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");
- }
- }
- }
- }
-
defaultClientSSLParams = new SSLParameters();
- if (reservedException == null) {
defaultClientSSLParams.setProtocols(
getAvailableProtocols(candidates));
+ } else {
+ defaultClientSSLParams = null; // unlikely to be used
}
}
- protected CustomizedSSLContext() {
+ protected CustomizedTLSContext() {
if (reservedException != null) {
throw reservedException;
}
}
@@ -707,20 +782,20 @@
/*
* The SSLContext implementation for default "TLS" algorithm
*
* @see SSLContext
*/
- public static final class TLSContext extends CustomizedSSLContext {
+ public static final class TLSContext extends CustomizedTLSContext {
// use the default constructor and methods
}
/*
* The SSLContext implementation for default "Default" algorithm
*
* @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";
private static volatile SSLContextImpl defaultImpl;
@@ -877,10 +952,197 @@
defaultKeyManagers = kmf.getKeyManagers();
return defaultKeyManagers;
}
}
+ /*
+ * 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<ProtocolVersion>
+ 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
+ }
+
}
final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
implements X509TrustManager {
@@ -959,11 +1221,11 @@
// try the best to check the algorithm constraints
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;
String[] peerSupportedSignAlgs =
extSession.getLocalSupportedSignatureAlgorithms();
@@ -1001,11 +1263,11 @@
// try the best to check the algorithm constraints
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;
String[] peerSupportedSignAlgs =
extSession.getLocalSupportedSignatureAlgorithms();