src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java
changeset 50768 68fa3d4026ea
parent 47216 71c04702a3d5
child 51771 1f805481d8de
--- a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java	Mon Jun 25 21:22:16 2018 +0300
+++ b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java	Mon Jun 25 13:41:39 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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,23 +25,25 @@
 
 package sun.security.ssl;
 
+import java.io.*;
 import java.net.Socket;
-
-import java.io.*;
-import java.util.*;
 import java.security.*;
 import java.security.cert.*;
-import java.security.cert.Certificate;
-
+import java.util.*;
 import javax.net.ssl.*;
-
+import sun.security.action.GetPropertyAction;
 import sun.security.provider.certpath.AlgorithmChecker;
-import sun.security.action.GetPropertyAction;
 import sun.security.validator.Validator;
 
-public abstract class SSLContextImpl extends SSLContextSpi {
+/**
+ * Implementation of an SSLContext.
+ *
+ * Implementation note: Instances of this class and the child classes are
+ * immutable, except that the context initialization (SSLContext.init()) may
+ * reset the key, trust managers and source of secure random.
+ */
 
-    private static final Debug debug = Debug.getInstance("ssl");
+public abstract class SSLContextImpl extends SSLContextSpi {
 
     private final EphemeralKeyManager ephemeralKeyManager;
     private final SSLSessionContextImpl clientCache;
@@ -54,15 +56,15 @@
     private SecureRandom secureRandom;
 
     // DTLS cookie exchange manager
-    private volatile HelloCookieManager helloCookieManager;
+    private volatile HelloCookieManager.Builder helloCookieManagerBuilder;
 
-    private final boolean clientEnableStapling = Debug.getBooleanProperty(
+    private final boolean clientEnableStapling = Utilities.getBooleanProperty(
             "jdk.tls.client.enableStatusRequestExtension", true);
-    private final boolean serverEnableStapling = Debug.getBooleanProperty(
+    private final boolean serverEnableStapling = Utilities.getBooleanProperty(
             "jdk.tls.server.enableStatusRequestExtension", false);
-    private final static Collection<CipherSuite> clientCustomizedCipherSuites =
+    private static final Collection<CipherSuite> clientCustomizedCipherSuites =
             getCustomizedCipherSuites("jdk.tls.client.cipherSuites");
-    private final static Collection<CipherSuite> serverCustomizedCipherSuites =
+    private static final Collection<CipherSuite> serverCustomizedCipherSuites =
             getCustomizedCipherSuites("jdk.tls.server.cipherSuites");
 
     private volatile StatusResponseManager statusResponseManager;
@@ -109,12 +111,12 @@
          * first connection to timeout and fail. Make sure it is
          * primed and ready by getting some initial output from it.
          */
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println("trigger seeding of SecureRandom");
+        if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
+            SSLLogger.finest("trigger seeding of SecureRandom");
         }
         secureRandom.nextInt();
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println("done seeding SecureRandom");
+        if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
+            SSLLogger.finest("done seeding of SecureRandom");
         }
 
         isInitialized = true;
@@ -168,10 +170,10 @@
             if (km instanceof X509ExtendedKeyManager) {
                 return (X509ExtendedKeyManager)km;
             }
-            if (debug != null && Debug.isOn("sslctx")) {
-                System.out.println(
-                    "X509KeyManager passed to " +
-                    "SSLContext.init():  need an " +
+
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
+                SSLLogger.warning(
+                    "X509KeyManager passed to SSLContext.init():  need an " +
                     "X509ExtendedKeyManager for SSLEngine use");
             }
             return new AbstractKeyManagerWrapper((X509KeyManager)km);
@@ -242,36 +244,26 @@
         return ephemeralKeyManager;
     }
 
-    // Used for DTLS in server mode only, see ServerHandshaker.
-    HelloCookieManager getHelloCookieManager() {
-        if (!isInitialized) {
-            throw new IllegalStateException("SSLContext is not initialized");
-        }
-
-        if (helloCookieManager != null) {
-            return helloCookieManager;
-        }
-
-        synchronized (this) {
-            if (helloCookieManager == null) {
-                helloCookieManager = getHelloCookieManager(secureRandom);
+    // Used for DTLS in server mode only.
+    HelloCookieManager getHelloCookieManager(ProtocolVersion protocolVersion) {
+        if (helloCookieManagerBuilder == null) {
+            synchronized (this) {
+                if (helloCookieManagerBuilder == null) {
+                    helloCookieManagerBuilder =
+                            new HelloCookieManager.Builder(secureRandom);
+                }
             }
         }
 
-        return helloCookieManager;
-    }
-
-    HelloCookieManager getHelloCookieManager(SecureRandom secureRandom) {
-        throw new UnsupportedOperationException(
-                "Cookie exchange applies to DTLS only");
+        return helloCookieManagerBuilder.valueOf(protocolVersion);
     }
 
     StatusResponseManager getStatusResponseManager() {
         if (serverEnableStapling && statusResponseManager == null) {
             synchronized (this) {
                 if (statusResponseManager == null) {
-                    if (debug != null && Debug.isOn("sslctx")) {
-                        System.out.println(
+                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
+                        SSLLogger.finest(
                                 "Initializing StatusResponseManager");
                     }
                     statusResponseManager = new StatusResponseManager();
@@ -282,52 +274,55 @@
         return statusResponseManager;
     }
 
-    // Get supported ProtocolList.
-    abstract ProtocolList getSuportedProtocolList();
+    // Get supported protocols.
+    abstract List<ProtocolVersion> getSupportedProtocolVersions();
+
+    // Get default protocols for server mode.
+    abstract List<ProtocolVersion> getServerDefaultProtocolVersions();
 
-    // Get default ProtocolList for server mode.
-    abstract ProtocolList getServerDefaultProtocolList();
+    // Get default protocols for client mode.
+    abstract List<ProtocolVersion> getClientDefaultProtocolVersions();
 
-    // Get default ProtocolList for client mode.
-    abstract ProtocolList getClientDefaultProtocolList();
+    // Get supported CipherSuite list.
+    abstract List<CipherSuite> getSupportedCipherSuites();
 
-    // Get supported CipherSuiteList.
-    abstract CipherSuiteList getSupportedCipherSuiteList();
+    // Get default CipherSuite list for server mode.
+    abstract List<CipherSuite> getServerDefaultCipherSuites();
 
-    // Get default CipherSuiteList for server mode.
-    abstract CipherSuiteList getServerDefaultCipherSuiteList();
+    // Get default CipherSuite list for client mode.
+    abstract List<CipherSuite> getClientDefaultCipherSuites();
 
-    // Get default CipherSuiteList for client mode.
-    abstract CipherSuiteList getClientDefaultCipherSuiteList();
+    // Is the context for DTLS protocols?
+    abstract boolean isDTLS();
 
-    // Get default ProtocolList.
-    ProtocolList getDefaultProtocolList(boolean roleIsServer) {
-        return roleIsServer ? getServerDefaultProtocolList()
-                            : getClientDefaultProtocolList();
+    // Get default protocols.
+    List<ProtocolVersion> getDefaultProtocolVersions(boolean roleIsServer) {
+        return roleIsServer ? getServerDefaultProtocolVersions()
+                            : getClientDefaultProtocolVersions();
     }
 
-    // Get default CipherSuiteList.
-    CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
-        return roleIsServer ? getServerDefaultCipherSuiteList()
-                            : getClientDefaultCipherSuiteList();
+    // Get default CipherSuite list.
+    List<CipherSuite> getDefaultCipherSuites(boolean roleIsServer) {
+        return roleIsServer ? getServerDefaultCipherSuites()
+                            : getClientDefaultCipherSuites();
     }
 
     /**
      * Return whether a protocol list is the original default enabled
      * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
      */
-    boolean isDefaultProtocolList(ProtocolList protocols) {
-        return (protocols == getServerDefaultProtocolList()) ||
-               (protocols == getClientDefaultProtocolList());
+    boolean isDefaultProtocolVesions(List<ProtocolVersion> protocols) {
+        return (protocols == getServerDefaultProtocolVersions()) ||
+               (protocols == getClientDefaultProtocolVersions());
     }
 
     /**
      * Return whether a protocol list is the original default enabled
      * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
      */
-    boolean isDefaultCipherSuiteList(CipherSuiteList cipherSuites) {
-        return (cipherSuites == getServerDefaultCipherSuiteList()) ||
-               (cipherSuites == getClientDefaultCipherSuiteList());
+    boolean isDefaultCipherSuiteList(List<CipherSuite> cipherSuites) {
+        return (cipherSuites == getServerDefaultCipherSuites()) ||
+               (cipherSuites == getClientDefaultCipherSuites());
     }
 
     /**
@@ -342,93 +337,83 @@
         return isClient ? clientEnableStapling : serverEnableStapling;
     }
 
-
     /*
      * Return the list of all available CipherSuites that are supported
      * using currently installed providers.
      */
-    private static CipherSuiteList getApplicableSupportedCipherSuiteList(
-            ProtocolList protocols) {
+    private static List<CipherSuite> getApplicableSupportedCipherSuites(
+            List<ProtocolVersion> protocols) {
 
-        return getApplicableCipherSuiteList(
-                CipherSuite.allowedCipherSuites(),
-                protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
+        return getApplicableCipherSuites(
+                CipherSuite.allowedCipherSuites(), protocols);
     }
 
     /*
      * Return the list of all available CipherSuites that are default enabled
      * in client or server side.
      */
-    private static CipherSuiteList getApplicableEnabledCipherSuiteList(
-            ProtocolList protocols, boolean isClient) {
+    private static List<CipherSuite> getApplicableEnabledCipherSuites(
+            List<ProtocolVersion> protocols, boolean isClient) {
 
         if (isClient) {
             if (!clientCustomizedCipherSuites.isEmpty()) {
-                return getApplicableCipherSuiteList(
-                        clientCustomizedCipherSuites,
-                        protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
+                return getApplicableCipherSuites(
+                        clientCustomizedCipherSuites, protocols);
             }
         } else {
             if (!serverCustomizedCipherSuites.isEmpty()) {
-                return getApplicableCipherSuiteList(
-                        serverCustomizedCipherSuites,
-                        protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
+                return getApplicableCipherSuites(
+                        serverCustomizedCipherSuites, protocols);
             }
         }
 
-        return getApplicableCipherSuiteList(
-                CipherSuite.allowedCipherSuites(),
-                protocols, CipherSuite.DEFAULT_SUITES_PRIORITY);
+        return getApplicableCipherSuites(
+                CipherSuite.defaultCipherSuites(), protocols);
     }
 
     /*
      * Return the list of available CipherSuites which are applicable to
      * the specified protocols.
      */
-    private static CipherSuiteList getApplicableCipherSuiteList(
+    private static List<CipherSuite> getApplicableCipherSuites(
             Collection<CipherSuite> allowedCipherSuites,
-            ProtocolList protocols, int minPriority) {
-
+            List<ProtocolVersion> protocols) {
         TreeSet<CipherSuite> suites = new TreeSet<>();
-        if (!(protocols.collection().isEmpty()) &&
-                protocols.min.v != ProtocolVersion.NONE.v) {
+        if (protocols != null && (!protocols.isEmpty())) {
             for (CipherSuite suite : allowedCipherSuites) {
-                if (!suite.allowed || suite.priority < minPriority) {
+                if (!suite.isAvailable()) {
                     continue;
                 }
 
-                if (suite.isAvailable() &&
-                        !protocols.min.obsoletes(suite) &&
-                        protocols.max.supports(suite)) {
+                boolean isSupported = false;
+                for (ProtocolVersion protocol : protocols) {
+                    if (!suite.supports(protocol)) {
+                        continue;
+                    }
+
                     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")) {
-                            System.out.println(
-                                    "Ignoring disabled cipher suite: " +
-                                            suite.name);
-                        }
+                        isSupported = true;
+                    } else if (SSLLogger.isOn &&
+                            SSLLogger.isOn("ssl,sslctx,verbose")) {
+                        SSLLogger.fine(
+                                "Ignore disabled cipher suite: " + suite.name);
                     }
-                } else if (debug != null &&
-                        Debug.isOn("sslctx") && Debug.isOn("verbose")) {
-                    if (protocols.min.obsoletes(suite)) {
-                        System.out.println(
-                            "Ignoring obsoleted cipher suite: " + suite);
-                    } else if (!protocols.max.supports(suite)) {
-                        System.out.println(
-                            "Ignoring unsupported cipher suite: " + suite);
-                    } else {
-                        System.out.println(
-                            "Ignoring unavailable cipher suite: " + suite);
-                    }
+
+                    break;
+                }
+
+                if (!isSupported && SSLLogger.isOn &&
+                        SSLLogger.isOn("ssl,sslctx,verbose")) {
+                    SSLLogger.finest(
+                            "Ignore unsupported cipher suite: " + suite);
                 }
             }
         }
 
-        return new CipherSuiteList(suites);
+        return new ArrayList<>(suites);
     }
 
     /*
@@ -438,8 +423,8 @@
             String propertyName) {
 
         String property = GetPropertyAction.privilegedGetProperty(propertyName);
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println(
+        if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
+            SSLLogger.fine(
                     "System property " + propertyName + " is set to '" +
                     property + "'");
         }
@@ -463,10 +448,10 @@
 
                 CipherSuite suite;
                 try {
-                    suite = CipherSuite.valueOf(cipherSuiteNames[i]);
+                    suite = CipherSuite.nameOf(cipherSuiteNames[i]);
                 } catch (IllegalArgumentException iae) {
-                    if (debug != null && Debug.isOn("sslctx")) {
-                        System.out.println(
+                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
+                        SSLLogger.fine(
                                 "Unknown or unsupported cipher suite name: " +
                                 cipherSuiteNames[i]);
                     }
@@ -474,11 +459,11 @@
                     continue;
                 }
 
-                if (suite.isAvailable()) {
+                if (suite != null && suite.isAvailable()) {
                     cipherSuites.add(suite);
                 } else {
-                    if (debug != null && Debug.isOn("sslctx")) {
-                        System.out.println(
+                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
+                        SSLLogger.fine(
                                 "The current installed providers do not " +
                                 "support cipher suite: " + cipherSuiteNames[i]);
                     }
@@ -492,23 +477,23 @@
     }
 
 
-    private static String[] getAvailableProtocols(
+    private static List<ProtocolVersion> getAvailableProtocols(
             ProtocolVersion[] protocolCandidates) {
 
-        List<String> availableProtocols = Collections.<String>emptyList();
-        if (protocolCandidates !=  null && protocolCandidates.length != 0) {
+        List<ProtocolVersion> availableProtocols =
+                Collections.<ProtocolVersion>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);
+                if (p.isAvailable) {
+                    availableProtocols.add(p);
                 }
             }
         }
 
-        return availableProtocols.toArray(new String[0]);
+        return availableProtocols;
     }
 
-
     /*
      * The SSLContext implementation for SSL/(D)TLS algorithm
      *
@@ -548,79 +533,108 @@
      * @see SSLContext
      */
     private abstract static class AbstractTLSContext extends SSLContextImpl {
-        private static final ProtocolList supportedProtocolList;
-        private static final ProtocolList serverDefaultProtocolList;
+        private static final List<ProtocolVersion> supportedProtocols;
+        private static final List<ProtocolVersion> serverDefaultProtocols;
 
-        private static final CipherSuiteList supportedCipherSuiteList;
-        private static final CipherSuiteList serverDefaultCipherSuiteList;
+        private static final List<CipherSuite> supportedCipherSuites;
+        private static final List<CipherSuite> serverDefaultCipherSuites;
 
         static {
             if (SunJSSE.isFIPS()) {
-                supportedProtocolList = new ProtocolList(new String[] {
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
+                supportedProtocols = Arrays.asList(
+                    ProtocolVersion.TLS13,
+                    ProtocolVersion.TLS12,
+                    ProtocolVersion.TLS11,
+                    ProtocolVersion.TLS10
+                );
 
-                serverDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.TLS10,
+                serverDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS13,
+                    ProtocolVersion.TLS12,
                     ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
+                    ProtocolVersion.TLS10
+                });
             } else {
-                supportedProtocolList = new ProtocolList(new String[] {
-                    ProtocolVersion.SSL20Hello.name,
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
+                supportedProtocols = Arrays.asList(
+                    ProtocolVersion.TLS13,
+                    ProtocolVersion.TLS12,
+                    ProtocolVersion.TLS11,
+                    ProtocolVersion.TLS10,
+                    ProtocolVersion.SSL30,
+                    ProtocolVersion.SSL20Hello
+                );
 
-                serverDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL20Hello,
+                serverDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS13,
+                    ProtocolVersion.TLS12,
+                    ProtocolVersion.TLS11,
+                    ProtocolVersion.TLS10,
                     ProtocolVersion.SSL30,
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
+                    ProtocolVersion.SSL20Hello
+                });
             }
 
-            supportedCipherSuiteList = getApplicableSupportedCipherSuiteList(
-                    supportedProtocolList);
-            serverDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    serverDefaultProtocolList, false);
+            supportedCipherSuites = getApplicableSupportedCipherSuites(
+                    supportedProtocols);
+            serverDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    serverDefaultProtocols, false);
         }
 
         @Override
-        ProtocolList getSuportedProtocolList() {
-            return supportedProtocolList;
+        List<ProtocolVersion> getSupportedProtocolVersions() {
+            return supportedProtocols;
         }
 
         @Override
-        CipherSuiteList getSupportedCipherSuiteList() {
-            return supportedCipherSuiteList;
+        List<CipherSuite> getSupportedCipherSuites() {
+            return supportedCipherSuites;
         }
 
         @Override
-        ProtocolList getServerDefaultProtocolList() {
-            return serverDefaultProtocolList;
+        List<ProtocolVersion> getServerDefaultProtocolVersions() {
+            return serverDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getServerDefaultCipherSuiteList() {
-            return serverDefaultCipherSuiteList;
+        List<CipherSuite> getServerDefaultCipherSuites() {
+            return serverDefaultCipherSuites;
         }
 
         @Override
         SSLEngine createSSLEngineImpl() {
-            return new SSLEngineImpl(this, false);
+            return new SSLEngineImpl(this);
         }
 
         @Override
         SSLEngine createSSLEngineImpl(String host, int port) {
-            return new SSLEngineImpl(this, host, port, false);
+            return new SSLEngineImpl(this, host, port);
+        }
+
+        @Override
+        boolean isDTLS() {
+            return false;
+        }
+
+        static ProtocolVersion[] getSupportedProtocols() {
+            if (SunJSSE.isFIPS()) {
+                return new ProtocolVersion[] {
+                        ProtocolVersion.TLS13,
+                        ProtocolVersion.TLS12,
+                        ProtocolVersion.TLS11,
+                        ProtocolVersion.TLS10
+                };
+            } else {
+                return new ProtocolVersion[]{
+                        ProtocolVersion.TLS13,
+                        ProtocolVersion.TLS12,
+                        ProtocolVersion.TLS11,
+                        ProtocolVersion.TLS10,
+                        ProtocolVersion.SSL30,
+                        ProtocolVersion.SSL20Hello
+                };
+            }
         }
     }
 
@@ -630,35 +644,35 @@
      * @see SSLContext
      */
     public static final class TLS10Context extends AbstractTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
 
         static {
             if (SunJSSE.isFIPS()) {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
                     ProtocolVersion.TLS10
-                }));
+                });
             } else {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL30,
-                    ProtocolVersion.TLS10
-                }));
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS10,
+                    ProtocolVersion.SSL30
+                });
             }
 
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
+            clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    clientDefaultProtocols, true);
         }
 
         @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
         }
     }
 
@@ -668,38 +682,38 @@
      * @see SSLContext
      */
     public static final class TLS11Context extends AbstractTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
 
         static {
             if (SunJSSE.isFIPS()) {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11
-                }));
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS11,
+                    ProtocolVersion.TLS10
+                });
             } else {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL30,
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS11,
                     ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11
-                }));
+                    ProtocolVersion.SSL30
+                });
             }
 
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
+            clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    clientDefaultProtocols, true);
 
         }
 
         @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
         }
     }
 
@@ -709,39 +723,83 @@
      * @see SSLContext
      */
     public static final class TLS12Context extends AbstractTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
 
         static {
             if (SunJSSE.isFIPS()) {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.TLS10,
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS12,
                     ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
+                    ProtocolVersion.TLS10
+                });
             } else {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL30,
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS12,
+                    ProtocolVersion.TLS11,
                     ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
+                    ProtocolVersion.SSL30
+                });
             }
 
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
+            clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    clientDefaultProtocols, true);
+        }
+
+        @Override
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
         }
 
         @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
+        }
+    }
+
+    /*
+     * The SSLContext implementation for TLS1.3 algorithm
+     *
+     * @see SSLContext
+     */
+    public static final class TLS13Context extends AbstractTLSContext {
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
+
+        static {
+            if (SunJSSE.isFIPS()) {
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS13,
+                    ProtocolVersion.TLS12,
+                    ProtocolVersion.TLS11,
+                    ProtocolVersion.TLS10
+                });
+            } else {
+                clientDefaultProtocols = getAvailableProtocols(
+                        new ProtocolVersion[] {
+                    ProtocolVersion.TLS13,
+                    ProtocolVersion.TLS12,
+                    ProtocolVersion.TLS11,
+                    ProtocolVersion.TLS10,
+                    ProtocolVersion.SSL30
+                });
+            }
+
+            clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    clientDefaultProtocols, true);
         }
 
         @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
+        }
+
+        @Override
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
         }
     }
 
@@ -751,10 +809,15 @@
      * @see SSLContext
      */
     private static class CustomizedSSLProtocols {
-        private static final String PROPERTY_NAME = "jdk.tls.client.protocols";
+        private static final String JDK_TLS_CLIENT_PROTOCOLS =
+                "jdk.tls.client.protocols";
+        private static final String JDK_TLS_SERVER_PROTOCOLS =
+                "jdk.tls.server.protocols";
         static IllegalArgumentException reservedException = null;
-        static ArrayList<ProtocolVersion>
-                                customizedProtocols = new ArrayList<>();
+        static final ArrayList<ProtocolVersion> customizedClientProtocols =
+                new ArrayList<>();
+        static final ArrayList<ProtocolVersion> customizedServerProtocols =
+                new ArrayList<>();
 
         // Don't want a java.lang.LinkageError for illegal system property.
         //
@@ -763,9 +826,18 @@
         // the provider service. Instead, please handle the initialization
         // exception in the caller's constructor.
         static {
-            String property = GetPropertyAction
-                    .privilegedGetProperty(PROPERTY_NAME);
-            if (property != null && property.length() != 0) {
+            populate(JDK_TLS_CLIENT_PROTOCOLS, customizedClientProtocols);
+            populate(JDK_TLS_SERVER_PROTOCOLS, customizedServerProtocols);
+        }
+
+        private static void populate(String propname,
+                ArrayList<ProtocolVersion> arrayList) {
+            String property = GetPropertyAction.privilegedGetProperty(propname);
+            if (property == null) {
+                return;
+            }
+
+            if (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) == '"') {
@@ -773,33 +845,32 @@
                 }
             }
 
-            if (property != null && property.length() != 0) {
+            if (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");
+                    ProtocolVersion pv =
+                            ProtocolVersion.nameOf(protocols[i]);
+                    if (pv == null) {
+                        reservedException = new IllegalArgumentException(
+                            propname + ": " + protocols[i] +
+                            " is not a supported SSL protocol name");
+                    }
 
-                            break;
-                        }
+                    if (SunJSSE.isFIPS() &&
+                            ((pv == ProtocolVersion.SSL30) ||
+                             (pv == ProtocolVersion.SSL20Hello))) {
+                        reservedException = new IllegalArgumentException(
+                                propname + ": " + pv +
+                                " is not FIPS compliant");
 
-                        // 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);
+                        break;
+                    }
+
+                    // ignore duplicated protocols
+                    if (!arrayList.contains(pv)) {
+                        arrayList.add(pv);
                     }
                 }
             }
@@ -813,10 +884,11 @@
      */
     private static class CustomizedTLSContext extends AbstractTLSContext {
 
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
-
-        private static IllegalArgumentException reservedException = null;
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<ProtocolVersion> serverDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
+        private static final List<CipherSuite> serverDefaultCipherSuites;
+        private static final IllegalArgumentException reservedException;
 
         // Don't want a java.lang.LinkageError for illegal system property.
         //
@@ -827,49 +899,69 @@
         static {
             reservedException = CustomizedSSLProtocols.reservedException;
             if (reservedException == null) {
-                ArrayList<ProtocolVersion>
-                        customizedTLSProtocols = new ArrayList<>();
-                for (ProtocolVersion protocol :
-                        CustomizedSSLProtocols.customizedProtocols) {
-                    if (!protocol.isDTLSProtocol()) {
-                        customizedTLSProtocols.add(protocol);
-                    }
+                clientDefaultProtocols = customizedProtocols(true,
+                        CustomizedSSLProtocols.customizedClientProtocols);
+                serverDefaultProtocols = customizedProtocols(false,
+                        CustomizedSSLProtocols.customizedServerProtocols);
+
+                clientDefaultCipherSuites =
+                        getApplicableEnabledCipherSuites(
+                                clientDefaultProtocols, true);
+                serverDefaultCipherSuites =
+                        getApplicableEnabledCipherSuites(
+                                serverDefaultProtocols, false);
+
+            } else {
+                // unlikely to be used
+                clientDefaultProtocols = null;
+                serverDefaultProtocols = null;
+                clientDefaultCipherSuites = null;
+                serverDefaultCipherSuites = null;
+            }
+        }
+
+        private static List<ProtocolVersion> customizedProtocols(
+                boolean client, List<ProtocolVersion> customized) {
+            List<ProtocolVersion> refactored = new ArrayList<>();
+            for (ProtocolVersion pv : customized) {
+                if (!pv.isDTLS) {
+                    refactored.add(pv);
                 }
+            }
 
-                // 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
-                        };
-                    }
+            // Use the default enabled protocols if no customization
+            ProtocolVersion[] candidates;
+            if (refactored.isEmpty()) {
+                if (client) {
+                    candidates = getProtocols();
                 } else {
-                    // Use the customized TLS protocols.
-                    candidates =
-                            new ProtocolVersion[customizedTLSProtocols.size()];
-                    candidates = customizedTLSProtocols.toArray(candidates);
+                    candidates = getSupportedProtocols();
                 }
+            } else {
+                // Use the customized TLS protocols.
+                candidates =
+                    refactored.toArray(new ProtocolVersion[refactored.size()]);
+            }
+
+            return getAvailableProtocols(candidates);
+        }
 
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(candidates));
-                clientDefaultCipherSuiteList =
-                        getApplicableEnabledCipherSuiteList(
-                                clientDefaultProtocolList, true);
+        static ProtocolVersion[] getProtocols() {
+            if (SunJSSE.isFIPS()) {
+                return new ProtocolVersion[]{
+                        ProtocolVersion.TLS13,
+                        ProtocolVersion.TLS12,
+                        ProtocolVersion.TLS11,
+                        ProtocolVersion.TLS10
+                };
             } else {
-                clientDefaultProtocolList = null;       // unlikely to be used
-                clientDefaultCipherSuiteList = null;    // unlikely to be used
+                return new ProtocolVersion[]{
+                        ProtocolVersion.TLS13,
+                        ProtocolVersion.TLS12,
+                        ProtocolVersion.TLS11,
+                        ProtocolVersion.TLS10,
+                        ProtocolVersion.SSL30
+                };
             }
         }
 
@@ -880,14 +972,26 @@
         }
 
         @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
+        }
+
+        @Override
+        List<ProtocolVersion> getServerDefaultProtocolVersions() {
+            return serverDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
         }
+
+        @Override
+        List<CipherSuite> getServerDefaultCipherSuites() {
+            return serverDefaultCipherSuites;
+        }
+
+
     }
 
     /*
@@ -909,30 +1013,33 @@
         private static final TrustManager[] trustManagers;
         private static final KeyManager[] keyManagers;
 
-        static Exception reservedException = null;
+        private static final Exception reservedException;
 
         static {
+            Exception reserved = null;
             TrustManager[] tmMediator;
             try {
                 tmMediator = getTrustManagers();
             } catch (Exception e) {
-                reservedException = e;
+                reserved = e;
                 tmMediator = new TrustManager[0];
             }
             trustManagers = tmMediator;
 
-            if (reservedException == null) {
+            if (reserved == null) {
                 KeyManager[] kmMediator;
                 try {
                     kmMediator = getKeyManagers();
                 } catch (Exception e) {
-                    reservedException = e;
+                    reserved = e;
                     kmMediator = new KeyManager[0];
                 }
                 keyManagers = kmMediator;
             } else {
                 keyManagers = new KeyManager[0];
             }
+
+            reservedException = reserved;
         }
 
         private static TrustManager[] getTrustManagers() throws Exception {
@@ -976,11 +1083,11 @@
             final String defaultKeyStore = props.get("keyStore");
             String defaultKeyStoreType = props.get("keyStoreType");
             String defaultKeyStoreProvider = props.get("keyStoreProvider");
-            if (debug != null && Debug.isOn("defaultctx")) {
-                System.out.println("keyStore is : " + defaultKeyStore);
-                System.out.println("keyStore type is : " +
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
+                SSLLogger.fine("keyStore is : " + defaultKeyStore);
+                SSLLogger.fine("keyStore type is : " +
                                         defaultKeyStoreType);
-                System.out.println("keyStore provider is : " +
+                SSLLogger.fine("keyStore provider is : " +
                                         defaultKeyStoreProvider);
             }
 
@@ -1014,8 +1121,8 @@
                  * Try to initialize key store.
                  */
                 if ((defaultKeyStoreType.length()) != 0) {
-                    if (debug != null && Debug.isOn("defaultctx")) {
-                        System.out.println("init keystore");
+                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
+                        SSLLogger.finest("init keystore");
                     }
                     if (defaultKeyStoreProvider.length() == 0) {
                         ks = KeyStore.getInstance(defaultKeyStoreType);
@@ -1037,8 +1144,8 @@
             /*
              * Try to initialize key manager.
              */
-            if (debug != null && Debug.isOn("defaultctx")) {
-                System.out.println("init keymanager of type " +
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
+                SSLLogger.fine("init keymanager of type " +
                     KeyManagerFactory.getDefaultAlgorithm());
             }
             KeyManagerFactory kmf = KeyManagerFactory.getInstance(
@@ -1095,8 +1202,8 @@
                 super.engineInit(DefaultManagersHolder.keyManagers,
                         DefaultManagersHolder.trustManagers, null);
             } catch (Exception e) {
-                if (debug != null && Debug.isOn("defaultctx")) {
-                    System.out.println("default context init failed: " + e);
+                if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
+                    SSLLogger.fine("default context init failed: ", e);
                 }
                 throw e;
             }
@@ -1128,65 +1235,65 @@
      * @see SSLContext
      */
     private abstract static class AbstractDTLSContext extends SSLContextImpl {
-        private static final ProtocolList supportedProtocolList;
-        private static final ProtocolList serverDefaultProtocolList;
+        private static final List<ProtocolVersion> supportedProtocols;
+        private static final List<ProtocolVersion> serverDefaultProtocols;
 
-        private static final CipherSuiteList supportedCipherSuiteList;
-        private static final CipherSuiteList serverDefaultCipherSuiteList;
+        private static final List<CipherSuite> supportedCipherSuites;
+        private static final List<CipherSuite> serverDefaultCipherSuites;
 
         static {
             // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode.
-            supportedProtocolList = new ProtocolList(new String[] {
-                ProtocolVersion.DTLS10.name,
-                ProtocolVersion.DTLS12.name
-            });
+            supportedProtocols = Arrays.asList(
+                ProtocolVersion.DTLS12,
+                ProtocolVersion.DTLS10
+            );
 
             // available protocols for server mode
-            serverDefaultProtocolList = new ProtocolList(
-                    getAvailableProtocols(new ProtocolVersion[] {
-                ProtocolVersion.DTLS10,
-                ProtocolVersion.DTLS12
-            }));
+            serverDefaultProtocols = getAvailableProtocols(
+                    new ProtocolVersion[] {
+                ProtocolVersion.DTLS12,
+                ProtocolVersion.DTLS10
+            });
 
-            supportedCipherSuiteList = getApplicableSupportedCipherSuiteList(
-                    supportedProtocolList);
-            serverDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    serverDefaultProtocolList, false);
+            supportedCipherSuites = getApplicableSupportedCipherSuites(
+                    supportedProtocols);
+            serverDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    serverDefaultProtocols, false);
         }
 
         @Override
-        ProtocolList getSuportedProtocolList() {
-            return supportedProtocolList;
+        List<ProtocolVersion> getSupportedProtocolVersions() {
+            return supportedProtocols;
         }
 
         @Override
-        CipherSuiteList getSupportedCipherSuiteList() {
-            return supportedCipherSuiteList;
+        List<CipherSuite> getSupportedCipherSuites() {
+            return supportedCipherSuites;
         }
 
         @Override
-        ProtocolList getServerDefaultProtocolList() {
-            return serverDefaultProtocolList;
+        List<ProtocolVersion> getServerDefaultProtocolVersions() {
+            return serverDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getServerDefaultCipherSuiteList() {
-            return serverDefaultCipherSuiteList;
+        List<CipherSuite> getServerDefaultCipherSuites() {
+            return serverDefaultCipherSuites;
         }
 
         @Override
         SSLEngine createSSLEngineImpl() {
-            return new SSLEngineImpl(this, true);
+            return new SSLEngineImpl(this);
         }
 
         @Override
         SSLEngine createSSLEngineImpl(String host, int port) {
-            return new SSLEngineImpl(this, host, port, true);
+            return new SSLEngineImpl(this, host, port);
         }
 
         @Override
-        HelloCookieManager getHelloCookieManager(SecureRandom secureRandom) {
-            return new HelloCookieManager(secureRandom);
+        boolean isDTLS() {
+            return true;
         }
     }
 
@@ -1196,28 +1303,28 @@
      * @see SSLContext
      */
     public static final class DTLS10Context extends AbstractDTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
 
         static {
             // available protocols for client mode
-            clientDefaultProtocolList = new ProtocolList(
-                    getAvailableProtocols(new ProtocolVersion[] {
+            clientDefaultProtocols = getAvailableProtocols(
+                    new ProtocolVersion[] {
                 ProtocolVersion.DTLS10
-            }));
+            });
 
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
+            clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    clientDefaultProtocols, true);
         }
 
         @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
         }
     }
 
@@ -1227,29 +1334,29 @@
      * @see SSLContext
      */
     public static final class DTLS12Context extends AbstractDTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
 
         static {
             // available protocols for client mode
-            clientDefaultProtocolList = new ProtocolList(
-                    getAvailableProtocols(new ProtocolVersion[] {
-                ProtocolVersion.DTLS10,
-                ProtocolVersion.DTLS12
-            }));
+            clientDefaultProtocols = getAvailableProtocols(
+                    new ProtocolVersion[] {
+                ProtocolVersion.DTLS12,
+                ProtocolVersion.DTLS10
+            });
 
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
+            clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
+                    clientDefaultProtocols, true);
         }
 
         @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
         }
     }
 
@@ -1259,8 +1366,10 @@
      * @see SSLContext
      */
     private static class CustomizedDTLSContext extends AbstractDTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
+        private static final List<ProtocolVersion> clientDefaultProtocols;
+        private static final List<ProtocolVersion> serverDefaultProtocols;
+        private static final List<CipherSuite> clientDefaultCipherSuites;
+        private static final List<CipherSuite> serverDefaultCipherSuites;
 
         private static IllegalArgumentException reservedException = null;
 
@@ -1273,43 +1382,53 @@
         static {
             reservedException = CustomizedSSLProtocols.reservedException;
             if (reservedException == null) {
-                ArrayList<ProtocolVersion>
-                        customizedDTLSProtocols = new ArrayList<>();
-                for (ProtocolVersion protocol :
-                        CustomizedSSLProtocols.customizedProtocols) {
-                    if (protocol.isDTLSProtocol()) {
-                        customizedDTLSProtocols.add(protocol);
-                    }
-                }
+                clientDefaultProtocols = customizedProtocols(true,
+                        CustomizedSSLProtocols.customizedClientProtocols);
+                serverDefaultProtocols = customizedProtocols(false,
+                        CustomizedSSLProtocols.customizedServerProtocols);
+
+                clientDefaultCipherSuites =
+                        getApplicableEnabledCipherSuites(
+                                clientDefaultProtocols, true);
+                serverDefaultCipherSuites =
+                        getApplicableEnabledCipherSuites(
+                                serverDefaultProtocols, false);
+
+            } else {
+                // unlikely to be used
+                clientDefaultProtocols = null;
+                serverDefaultProtocols = null;
+                clientDefaultCipherSuites = null;
+                serverDefaultCipherSuites = null;
+            }
+        }
 
-                // 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
-                    };
+        private static List<ProtocolVersion> customizedProtocols(boolean client,
+                List<ProtocolVersion> customized) {
+            List<ProtocolVersion> refactored = new ArrayList<>();
+            for (ProtocolVersion pv : customized) {
+                if (pv.isDTLS) {
+                    refactored.add(pv);
+                }
+            }
 
-                } else {
-                    // Use the customized TLS protocols.
-                    candidates =
-                            new ProtocolVersion[customizedDTLSProtocols.size()];
-                    candidates = customizedDTLSProtocols.toArray(candidates);
-                }
+            ProtocolVersion[] candidates;
+            // Use the default enabled protocols if no customization
+            if (refactored.isEmpty()) {
+                candidates = new ProtocolVersion[]{
+                        ProtocolVersion.DTLS12,
+                        ProtocolVersion.DTLS10
+                };
+                if (!client)
+                    return Arrays.asList(candidates);
+            } else {
+                // Use the customized TLS protocols.
+                candidates =
+                        new ProtocolVersion[customized.size()];
+                candidates = customized.toArray(candidates);
+            }
 
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(candidates));
-                clientDefaultCipherSuiteList =
-                        getApplicableEnabledCipherSuiteList(
-                                clientDefaultProtocolList, true);
-            } else {
-                clientDefaultProtocolList = null;       // unlikely to be used
-                clientDefaultCipherSuiteList = null;    // unlikely to be used
-            }
+            return getAvailableProtocols(candidates);
         }
 
         protected CustomizedDTLSContext() {
@@ -1319,13 +1438,23 @@
         }
 
         @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
+        List<ProtocolVersion> getClientDefaultProtocolVersions() {
+            return clientDefaultProtocols;
         }
 
         @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
+        List<ProtocolVersion> getServerDefaultProtocolVersions() {
+            return serverDefaultProtocols;
+        }
+
+        @Override
+        List<CipherSuite> getClientDefaultCipherSuites() {
+            return clientDefaultCipherSuites;
+        }
+
+        @Override
+        List<CipherSuite> getServerDefaultCipherSuites() {
+            return serverDefaultCipherSuites;
         }
     }
 
@@ -1340,7 +1469,6 @@
 
 }
 
-
 final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
             implements X509TrustManager {
 
@@ -1417,10 +1545,8 @@
             }
 
             // try the best to check the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            AlgorithmConstraints constraints = null;
-            if (protocolVersion.useTLS12PlusSpec()) {
+            AlgorithmConstraints constraints;
+            if (ProtocolVersion.useTLS12PlusSpec(session.getProtocol())) {
                 if (session instanceof ExtendedSSLSession) {
                     ExtendedSSLSession extSession =
                                     (ExtendedSSLSession)session;
@@ -1459,10 +1585,8 @@
             }
 
             // try the best to check the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            AlgorithmConstraints constraints = null;
-            if (protocolVersion.useTLS12PlusSpec()) {
+            AlgorithmConstraints constraints;
+            if (ProtocolVersion.useTLS12PlusSpec(session.getProtocol())) {
                 if (session instanceof ExtendedSSLSession) {
                     ExtendedSSLSession extSession =
                                     (ExtendedSSLSession)session;
@@ -1484,8 +1608,8 @@
     }
 
     private void checkAlgorithmConstraints(X509Certificate[] chain,
-            AlgorithmConstraints constraints, boolean isClient) throws CertificateException {
-
+            AlgorithmConstraints constraints,
+            boolean isClient) throws CertificateException {
         try {
             // Does the certificate chain end with a trusted certificate?
             int checkedLength = chain.length - 1;
@@ -1503,11 +1627,12 @@
             // A forward checker, need to check from trust to target
             if (checkedLength >= 0) {
                 AlgorithmChecker checker =
-                        new AlgorithmChecker(constraints, null,
-                                (isClient ? Validator.VAR_TLS_CLIENT : Validator.VAR_TLS_SERVER));
+                    new AlgorithmChecker(constraints, null,
+                            (isClient ? Validator.VAR_TLS_CLIENT :
+                                        Validator.VAR_TLS_SERVER));
                 checker.init(false);
                 for (int i = checkedLength; i >= 0; i--) {
-                    Certificate cert = chain[i];
+                    X509Certificate cert = chain[i];
                     // We don't care about the unresolved critical extensions.
                     checker.check(cert, Collections.<String>emptySet());
                 }