changeset 10436:b26b096d4c89

8230977: JEP 244/8051498 - TLS Application-Layer Protocol Negotiation Extension (Java SE 8) Reviewed-by: xuelei
author wetmore
date Fri, 22 Nov 2019 10:47:01 -0800
parents 8477d8164daf
children 6bada58189de
files src/share/classes/javax/net/ssl/SSLEngine.java src/share/classes/javax/net/ssl/SSLParameters.java src/share/classes/javax/net/ssl/SSLSocket.java src/share/classes/sun/security/ssl/ALPNExtension.java src/share/classes/sun/security/ssl/Alerts.java src/share/classes/sun/security/ssl/CipherSuite.java src/share/classes/sun/security/ssl/ClientHandshaker.java src/share/classes/sun/security/ssl/ExtensionType.java src/share/classes/sun/security/ssl/HandshakeMessage.java src/share/classes/sun/security/ssl/Handshaker.java src/share/classes/sun/security/ssl/HelloExtensions.java src/share/classes/sun/security/ssl/SSLEngineImpl.java src/share/classes/sun/security/ssl/SSLServerSocketImpl.java src/share/classes/sun/security/ssl/SSLSocketImpl.java src/share/classes/sun/security/ssl/ServerHandshaker.java test/Makefile test/sun/security/ssl/javax/net/ssl/ALPN/MyX509ExtendedKeyManager.java test/sun/security/ssl/javax/net/ssl/ALPN/SSLEngineAlpnTest.java test/sun/security/ssl/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java test/sun/security/ssl/javax/net/ssl/ALPN/SSLSocketAlpnTest.java test/sun/security/ssl/templates/SSLEngineTemplate.java test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java test/sun/security/ssl/templates/SSLSocketTemplate.java
diffstat 23 files changed, 3300 insertions(+), 371 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/javax/net/ssl/SSLEngine.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/javax/net/ssl/SSLEngine.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
 
 import java.nio.ByteBuffer;
 import java.nio.ReadOnlyBufferException;
+import java.util.List;
+import java.util.function.BiFunction;
 
 
 /**
@@ -1253,4 +1255,142 @@
         }
     }
 
+    /**
+     * Returns the most recent application protocol value negotiated for this
+     * connection.
+     * <p>
+     * If supported by the underlying SSL/TLS/DTLS implementation,
+     * application name negotiation mechanisms such as <a
+     * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
+     * Application-Layer Protocol Negotiation (ALPN), can negotiate
+     * application-level values between peers.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @return null if it has not yet been determined if application
+     *         protocols might be used for this connection, an empty
+     *         {@code String} if application protocols values will not
+     *         be used, or a non-empty application protocol {@code String}
+     *         if a value was successfully negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public String getApplicationProtocol() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the application protocol value negotiated on a SSL/TLS
+     * handshake currently in progress.
+     * <p>
+     * Like {@link #getHandshakeSession()},
+     * a connection may be in the middle of a handshake. The
+     * application protocol may or may not yet be available.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @return null if it has not yet been determined if application
+     *         protocols might be used for this handshake, an empty
+     *         {@code String} if application protocols values will not
+     *         be used, or a non-empty application protocol {@code String}
+     *         if a value was successfully negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public String getHandshakeApplicationProtocol() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Registers a callback function that selects an application protocol
+     * value for a SSL/TLS/DTLS handshake.
+     * The function overrides any values supplied using
+     * {@link SSLParameters#setApplicationProtocols
+     * SSLParameters.setApplicationProtocols} and it supports the following
+     * type parameters:
+     * <blockquote>
+     * <dl>
+     * <dt> {@code SSLEngine}
+     * <dd> The function's first argument allows the current {@code SSLEngine}
+     *      to be inspected, including the handshake session and configuration
+     *      settings.
+     * <dt> {@code List<String>}
+     * <dd> The function's second argument lists the application protocol names
+     *      advertised by the TLS peer.
+     * <dt> {@code String}
+     * <dd> The function's result is an application protocol name, or null to
+     *      indicate that none of the advertised names are acceptable.
+     *      If the return value is an empty {@code String} then application
+     *      protocol indications will not be used.
+     *      If the return value is null (no value chosen) or is a value that
+     *      was not advertised by the peer, the underlying protocol will
+     *      determine what action to take. (For example, ALPN will send a
+     *      "no_application_protocol" alert and terminate the connection.)
+     * </dl>
+     * </blockquote>
+     *
+     * For example, the following call registers a callback function that
+     * examines the TLS handshake parameters and selects an application protocol
+     * name:
+     * <pre>{@code
+     *     serverEngine.setHandshakeApplicationProtocolSelector(
+     *         (serverEngine, clientProtocols) -> {
+     *             SSLSession session = serverEngine.getHandshakeSession();
+     *             return chooseApplicationProtocol(
+     *                 serverEngine,
+     *                 clientProtocols,
+     *                 session.getProtocol(),
+     *                 session.getCipherSuite());
+     *         });
+     * }</pre>
+     *
+     * @apiNote
+     * This method should be called by TLS server applications before the TLS
+     * handshake begins. Also, this {@code SSLEngine} should be configured with
+     * parameters that are compatible with the application protocol selected by
+     * the callback function. For example, enabling a poor choice of cipher
+     * suites could result in no suitable application protocol.
+     * See {@link SSLParameters}.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @param selector the callback function, or null to disable the callback
+     *         functionality.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public void setHandshakeApplicationProtocolSelector(
+            BiFunction<SSLEngine, List<String>, String> selector) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Retrieves the callback function that selects an application protocol
+     * value during a SSL/TLS/DTLS handshake.
+     * See {@link #setHandshakeApplicationProtocolSelector
+     * setHandshakeApplicationProtocolSelector}
+     * for the function's type parameters.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @return the callback function, or null if none has been set.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public BiFunction<SSLEngine, List<String>, String>
+            getHandshakeApplicationProtocolSelector() {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/src/share/classes/javax/net/ssl/SSLParameters.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/javax/net/ssl/SSLParameters.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -56,6 +56,17 @@
  * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
  * {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
  * and {@link SSLEngine#setSSLParameters SSLEngine.setSSLParameters()}.
+ * <p>
+ * For example:
+ *
+ * <blockquote><pre>
+ *     SSLParameters p = sslSocket.getSSLParameters();
+ *     p.setProtocols(new String[] { "TLSv1.2" });
+ *     p.setCipherSuites(
+ *         new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", ... });
+ *     p.setApplicationProtocols(new String[] {"h2", "http/1.1"});
+ *     sslSocket.setSSLParameters(p);
+ * </pre></blockquote>*
  *
  * @see SSLSocket
  * @see SSLEngine
@@ -74,6 +85,7 @@
     private Map<Integer, SNIServerName> sniNames = null;
     private Map<Integer, SNIMatcher> sniMatchers = null;
     private boolean preferLocalCipherSuites;
+    private String[] applicationProtocols = new String[0];
 
     /**
      * Constructs SSLParameters.
@@ -464,5 +476,74 @@
     public final boolean getUseCipherSuitesOrder() {
         return preferLocalCipherSuites;
     }
+
+    /**
+     * Returns a prioritized array of application-layer protocol names that
+     * can be negotiated over the SSL/TLS/DTLS protocols.
+     * <p>
+     * The array could be empty (zero-length), in which case protocol
+     * indications will not be used.
+     * <p>
+     * This method will return a new array each time it is invoked.
+     *
+     * @return a non-null, possibly zero-length array of application protocol
+     *         {@code String}s.  The array is ordered based on protocol
+     *         preference, with {@code protocols[0]} being the most preferred.
+     * @see #setApplicationProtocols
+     * @since 8
+     */
+    public String[] getApplicationProtocols() {
+        return applicationProtocols.clone();
+    }
+
+    /**
+     * Sets the prioritized array of application-layer protocol names that
+     * can be negotiated over the SSL/TLS/DTLS protocols.
+     * <p>
+     * If application-layer protocols are supported by the underlying
+     * SSL/TLS implementation, this method configures which values can
+     * be negotiated by protocols such as <a
+     * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
+     * Application Layer Protocol Negotiation (ALPN).
+     * <p>
+     * If this end of the connection is expected to offer application protocol
+     * values, all protocols configured by this method will be sent to the
+     * peer.
+     * <p>
+     * If this end of the connection is expected to select the application
+     * protocol value, the {@code protocols} configured by this method are
+     * compared with those sent by the peer.  The first matched value becomes
+     * the negotiated value.  If none of the {@code protocols} were actually
+     * requested by the peer, the underlying protocol will determine what
+     * action to take.  (For example, ALPN will send a
+     * {@code "no_application_protocol"} alert and terminate the connection.)
+     *
+     * @implSpec
+     * This method will make a copy of the {@code protocols} array.
+     *
+     * @param protocols   an ordered array of application protocols,
+     *                    with {@code protocols[0]} being the most preferred.
+     *                    If the array is empty (zero-length), protocol
+     *                    indications will not be used.
+     * @throws IllegalArgumentException if protocols is null, or if
+     *                    any element in a non-empty array is null or an
+     *                    empty (zero-length) string
+     * @see #getApplicationProtocols
+     * @since 8
+     */
+    public void setApplicationProtocols(String[] protocols) {
+        if (protocols == null) {
+            throw new IllegalArgumentException("protocols was null");
+        }
+
+        String[] tempProtocols = protocols.clone();
+
+        for (String p : tempProtocols) {
+            if (p == null || p.equals("")) {
+                throw new IllegalArgumentException(
+                    "An element of protocols was null/empty");
+            }
+        }
+        applicationProtocols = tempProtocols;
+    }
 }
-
--- a/src/share/classes/javax/net/ssl/SSLSocket.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/javax/net/ssl/SSLSocket.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -28,6 +28,8 @@
 
 import java.io.IOException;
 import java.net.*;
+import java.util.List;
+import java.util.function.BiFunction;
 
 /**
  * This class extends <code>Socket</code>s and provides secure
@@ -662,4 +664,142 @@
         }
     }
 
+    /**
+     * Returns the most recent application protocol value negotiated for this
+     * connection.
+     * <p>
+     * If supported by the underlying SSL/TLS/DTLS implementation,
+     * application name negotiation mechanisms such as <a
+     * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
+     * Application-Layer Protocol Negotiation (ALPN), can negotiate
+     * application-level values between peers.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @return null if it has not yet been determined if application
+     *         protocols might be used for this connection, an empty
+     *         {@code String} if application protocols values will not
+     *         be used, or a non-empty application protocol {@code String}
+     *         if a value was successfully negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public String getApplicationProtocol() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the application protocol value negotiated on a SSL/TLS
+     * handshake currently in progress.
+     * <p>
+     * Like {@link #getHandshakeSession()},
+     * a connection may be in the middle of a handshake. The
+     * application protocol may or may not yet be available.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @return null if it has not yet been determined if application
+     *         protocols might be used for this handshake, an empty
+     *         {@code String} if application protocols values will not
+     *         be used, or a non-empty application protocol {@code String}
+     *         if a value was successfully negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public String getHandshakeApplicationProtocol() {
+        throw new UnsupportedOperationException();
+    }
+
+
+    /**
+     * Registers a callback function that selects an application protocol
+     * value for a SSL/TLS/DTLS handshake.
+     * The function overrides any values supplied using
+     * {@link SSLParameters#setApplicationProtocols
+     * SSLParameters.setApplicationProtocols} and it supports the following
+     * type parameters:
+     * <blockquote>
+     * <dl>
+     * <dt> {@code SSLSocket}
+     * <dd> The function's first argument allows the current {@code SSLSocket}
+     *      to be inspected, including the handshake session and configuration
+     *      settings.
+     * <dt> {@code List<String>}
+     * <dd> The function's second argument lists the application protocol names
+     *      advertised by the TLS peer.
+     * <dt> {@code String}
+     * <dd> The function's result is an application protocol name, or null to
+     *      indicate that none of the advertised names are acceptable.
+     *      If the return value is an empty {@code String} then application
+     *      protocol indications will not be used.
+     *      If the return value is null (no value chosen) or is a value that
+     *      was not advertised by the peer, the underlying protocol will
+     *      determine what action to take. (For example, ALPN will send a
+     *      "no_application_protocol" alert and terminate the connection.)
+     * </dl>
+     * </blockquote>
+     *
+     * For example, the following call registers a callback function that
+     * examines the TLS handshake parameters and selects an application protocol
+     * name:
+     * <pre>{@code
+     *     serverSocket.setHandshakeApplicationProtocolSelector(
+     *         (serverSocket, clientProtocols) -> {
+     *             SSLSession session = serverSocket.getHandshakeSession();
+     *             return chooseApplicationProtocol(
+     *                 serverSocket,
+     *                 clientProtocols,
+     *                 session.getProtocol(),
+     *                 session.getCipherSuite());
+     *         });
+     * }</pre>
+     *
+     * @apiNote
+     * This method should be called by TLS server applications before the TLS
+     * handshake begins. Also, this {@code SSLSocket} should be configured with
+     * parameters that are compatible with the application protocol selected by
+     * the callback function. For example, enabling a poor choice of cipher
+     * suites could result in no suitable application protocol.
+     * See {@link SSLParameters}.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @param selector the callback function, or null to de-register.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public void setHandshakeApplicationProtocolSelector(
+            BiFunction<SSLSocket, List<String>, String> selector) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Retrieves the callback function that selects an application protocol
+     * value during a SSL/TLS/DTLS handshake.
+     * See {@link #setHandshakeApplicationProtocolSelector
+     * setHandshakeApplicationProtocolSelector}
+     * for the function's type parameters.
+     *
+     * @implSpec
+     * The implementation in this class throws
+     * {@code UnsupportedOperationException} and performs no other action.
+     *
+     * @return the callback function, or null if none has been set.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     * @since 8
+     */
+    public BiFunction<SSLSocket, List<String>, String>
+            getHandshakeApplicationProtocolSelector() {
+        throw new UnsupportedOperationException();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ssl/ALPNExtension.java	Fri Nov 22 10:47:01 2019 -0800
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.io.IOException;
+import java.nio.charset.*;
+import java.util.*;
+
+import javax.net.ssl.*;
+
+/*
+ * [RFC 7301]
+ * This TLS extension facilitates the negotiation of application-layer protocols
+ * within the TLS handshake. Clients MAY include an extension of type
+ * "application_layer_protocol_negotiation" in the (extended) ClientHello
+ * message. The "extension_data" field of this extension SHALL contain a
+ * "ProtocolNameList" value:
+ *
+ *     enum {
+ *         application_layer_protocol_negotiation(16), (65535)
+ *     } ExtensionType;
+ *
+ *     opaque ProtocolName<1..2^8-1>;
+ *
+ *     struct {
+ *         ProtocolName protocol_name_list<2..2^16-1>
+ *     } ProtocolNameList;
+ */
+final class ALPNExtension extends HelloExtension {
+
+    final static int ALPN_HEADER_LENGTH = 1;
+    final static int MAX_APPLICATION_PROTOCOL_LENGTH = 255;
+    final static int MAX_APPLICATION_PROTOCOL_LIST_LENGTH = 65535;
+    private int listLength = 0;     // ProtocolNameList length
+    private List<String> protocolNames = null;
+
+    // constructor for ServerHello
+    ALPNExtension(String protocolName) throws SSLException {
+        this(new String[]{ protocolName });
+    }
+
+    // constructor for ClientHello
+    ALPNExtension(String[] protocolNames) throws SSLException {
+        super(ExtensionType.EXT_ALPN);
+        if (protocolNames.length == 0) { // never null, never empty
+            throw new IllegalArgumentException(
+                "The list of application protocols cannot be empty");
+        }
+        this.protocolNames = Arrays.asList(protocolNames);
+        for (String p : protocolNames) {
+            int length = p.getBytes(StandardCharsets.UTF_8).length;
+            if (length == 0) {
+                throw new SSLProtocolException(
+                    "Application protocol name is empty");
+            }
+            if (length <= MAX_APPLICATION_PROTOCOL_LENGTH) {
+                listLength += length + ALPN_HEADER_LENGTH;
+            } else {
+                throw new SSLProtocolException(
+                    "Application protocol name is too long: " + p);
+            }
+            if (listLength > MAX_APPLICATION_PROTOCOL_LIST_LENGTH) {
+                throw new SSLProtocolException(
+                    "Application protocol name list is too long");
+            }
+        }
+    }
+
+    // constructor for ServerHello for parsing ALPN extension
+    ALPNExtension(HandshakeInStream s, int len) throws IOException {
+        super(ExtensionType.EXT_ALPN);
+
+        if (len >= 2) {
+            listLength = s.getInt16(); // list length
+            if (listLength < 2 || listLength + 2 != len) {
+                throw new SSLProtocolException(
+                    "Invalid " + type + " extension: incorrect list length " +
+                    "(length=" + listLength + ")");
+            }
+        } else {
+            throw new SSLProtocolException(
+                "Invalid " + type + " extension: insufficient data " +
+                "(length=" + len + ")");
+        }
+
+        int remaining = listLength;
+        this.protocolNames = new ArrayList<>();
+        while (remaining > 0) {
+            // opaque ProtocolName<1..2^8-1>; // RFC 7301
+            byte[] bytes = s.getBytes8();
+            if (bytes.length == 0) {
+                throw new SSLProtocolException("Invalid " + type +
+                    " extension: empty application protocol name");
+            }
+            String p =
+                new String(bytes, StandardCharsets.UTF_8); // app protocol
+            protocolNames.add(p);
+            remaining -= bytes.length + ALPN_HEADER_LENGTH;
+        }
+
+        if (remaining != 0) {
+            throw new SSLProtocolException(
+                "Invalid " + type + " extension: extra data " +
+                "(length=" + remaining + ")");
+        }
+    }
+
+    List<String> getPeerAPs() {
+        return protocolNames;
+    }
+
+    /*
+     * Return the length in bytes, including extension type and length fields.
+     */
+    @Override
+    int length() {
+        return 6 + listLength;
+    }
+
+    @Override
+    void send(HandshakeOutStream s) throws IOException {
+        s.putInt16(type.id);
+        s.putInt16(listLength + 2); // length of extension_data
+        s.putInt16(listLength);     // length of ProtocolNameList
+
+        for (String p : protocolNames) {
+            s.putBytes8(p.getBytes(StandardCharsets.UTF_8));
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        if (protocolNames == null || protocolNames.isEmpty()) {
+            sb.append("<empty>");
+        } else {
+            for (String protocolName : protocolNames) {
+                sb.append("[" + protocolName + "]");
+            }
+        }
+
+        return "Extension " + type +
+            ", protocol names: " + sb;
+    }
+}
--- a/src/share/classes/sun/security/ssl/Alerts.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/Alerts.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -83,6 +83,9 @@
     static final byte           alert_bad_certificate_status_response = 113;
     static final byte           alert_bad_certificate_hash_value = 114;
 
+    // from RFC 7301 (TLS ALPN Extension)
+    static final byte           alert_no_application_protocol = 120;
+
     static String alertDescription(byte code) {
         switch (code) {
 
@@ -144,6 +147,8 @@
             return "bad_certificate_status_response";
         case alert_bad_certificate_hash_value:
             return "bad_certificate_hash_value";
+        case alert_no_application_protocol:
+            return "no_application_protocol";
 
         default:
             return "<UNKNOWN ALERT: " + (code & 0x0ff) + ">";
@@ -189,6 +194,7 @@
         case alert_unrecognized_name:
         case alert_bad_certificate_status_response:
         case alert_bad_certificate_hash_value:
+        case alert_no_application_protocol:
             e = new SSLHandshakeException(reason);
             break;
 
--- a/src/share/classes/sun/security/ssl/CipherSuite.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/CipherSuite.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -726,7 +726,7 @@
         final boolean N = (SunJSSE.isFIPS() == false);
 
         /*
-         * TLS Cipher Suite Registry, as of August 2010.
+         * TLS Cipher Suite Registry, as of November 2015.
          *
          * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
          *
@@ -735,77 +735,77 @@
          * 192-254    Specification Required    Refers to value of first byte
          * 255        Reserved for Private Use  Refers to value of first byte
          *
-         * Value      Description                               Reference
-         * 0x00,0x00  TLS_NULL_WITH_NULL_NULL                   [RFC5246]
-         * 0x00,0x01  TLS_RSA_WITH_NULL_MD5                     [RFC5246]
-         * 0x00,0x02  TLS_RSA_WITH_NULL_SHA                     [RFC5246]
-         * 0x00,0x03  TLS_RSA_EXPORT_WITH_RC4_40_MD5            [RFC4346]
-         * 0x00,0x04  TLS_RSA_WITH_RC4_128_MD5                  [RFC5246]
-         * 0x00,0x05  TLS_RSA_WITH_RC4_128_SHA                  [RFC5246]
-         * 0x00,0x06  TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5        [RFC4346]
-         * 0x00,0x07  TLS_RSA_WITH_IDEA_CBC_SHA                 [RFC5469]
-         * 0x00,0x08  TLS_RSA_EXPORT_WITH_DES40_CBC_SHA         [RFC4346]
-         * 0x00,0x09  TLS_RSA_WITH_DES_CBC_SHA                  [RFC5469]
-         * 0x00,0x0A  TLS_RSA_WITH_3DES_EDE_CBC_SHA             [RFC5246]
-         * 0x00,0x0B  TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA      [RFC4346]
-         * 0x00,0x0C  TLS_DH_DSS_WITH_DES_CBC_SHA               [RFC5469]
-         * 0x00,0x0D  TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA          [RFC5246]
-         * 0x00,0x0E  TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA      [RFC4346]
-         * 0x00,0x0F  TLS_DH_RSA_WITH_DES_CBC_SHA               [RFC5469]
-         * 0x00,0x10  TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA          [RFC5246]
-         * 0x00,0x11  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
-         * 0x00,0x12  TLS_DHE_DSS_WITH_DES_CBC_SHA              [RFC5469]
-         * 0x00,0x13  TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA         [RFC5246]
-         * 0x00,0x14  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
-         * 0x00,0x15  TLS_DHE_RSA_WITH_DES_CBC_SHA              [RFC5469]
-         * 0x00,0x16  TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA         [RFC5246]
-         * 0x00,0x17  TLS_DH_anon_EXPORT_WITH_RC4_40_MD5        [RFC4346]
-         * 0x00,0x18  TLS_DH_anon_WITH_RC4_128_MD5              [RFC5246]
-         * 0x00,0x19  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
-         * 0x00,0x1A  TLS_DH_anon_WITH_DES_CBC_SHA              [RFC5469]
-         * 0x00,0x1B  TLS_DH_anon_WITH_3DES_EDE_CBC_SHA         [RFC5246]
-         * 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3  [RFC5246]
-         * 0x00,0x1E  TLS_KRB5_WITH_DES_CBC_SHA                 [RFC2712]
-         * 0x00,0x1F  TLS_KRB5_WITH_3DES_EDE_CBC_SHA            [RFC2712]
-         * 0x00,0x20  TLS_KRB5_WITH_RC4_128_SHA                 [RFC2712]
-         * 0x00,0x21  TLS_KRB5_WITH_IDEA_CBC_SHA                [RFC2712]
-         * 0x00,0x22  TLS_KRB5_WITH_DES_CBC_MD5                 [RFC2712]
-         * 0x00,0x23  TLS_KRB5_WITH_3DES_EDE_CBC_MD5            [RFC2712]
-         * 0x00,0x24  TLS_KRB5_WITH_RC4_128_MD5                 [RFC2712]
-         * 0x00,0x25  TLS_KRB5_WITH_IDEA_CBC_MD5                [RFC2712]
-         * 0x00,0x26  TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA       [RFC2712]
-         * 0x00,0x27  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA       [RFC2712]
-         * 0x00,0x28  TLS_KRB5_EXPORT_WITH_RC4_40_SHA           [RFC2712]
-         * 0x00,0x29  TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5       [RFC2712]
-         * 0x00,0x2A  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5       [RFC2712]
-         * 0x00,0x2B  TLS_KRB5_EXPORT_WITH_RC4_40_MD5           [RFC2712]
-         * 0x00,0x2C  TLS_PSK_WITH_NULL_SHA                     [RFC4785]
-         * 0x00,0x2D  TLS_DHE_PSK_WITH_NULL_SHA                 [RFC4785]
-         * 0x00,0x2E  TLS_RSA_PSK_WITH_NULL_SHA                 [RFC4785]
-         * 0x00,0x2F  TLS_RSA_WITH_AES_128_CBC_SHA              [RFC5246]
-         * 0x00,0x30  TLS_DH_DSS_WITH_AES_128_CBC_SHA           [RFC5246]
-         * 0x00,0x31  TLS_DH_RSA_WITH_AES_128_CBC_SHA           [RFC5246]
-         * 0x00,0x32  TLS_DHE_DSS_WITH_AES_128_CBC_SHA          [RFC5246]
-         * 0x00,0x33  TLS_DHE_RSA_WITH_AES_128_CBC_SHA          [RFC5246]
-         * 0x00,0x34  TLS_DH_anon_WITH_AES_128_CBC_SHA          [RFC5246]
-         * 0x00,0x35  TLS_RSA_WITH_AES_256_CBC_SHA              [RFC5246]
-         * 0x00,0x36  TLS_DH_DSS_WITH_AES_256_CBC_SHA           [RFC5246]
-         * 0x00,0x37  TLS_DH_RSA_WITH_AES_256_CBC_SHA           [RFC5246]
-         * 0x00,0x38  TLS_DHE_DSS_WITH_AES_256_CBC_SHA          [RFC5246]
-         * 0x00,0x39  TLS_DHE_RSA_WITH_AES_256_CBC_SHA          [RFC5246]
-         * 0x00,0x3A  TLS_DH_anon_WITH_AES_256_CBC_SHA          [RFC5246]
-         * 0x00,0x3B  TLS_RSA_WITH_NULL_SHA256                  [RFC5246]
-         * 0x00,0x3C  TLS_RSA_WITH_AES_128_CBC_SHA256           [RFC5246]
-         * 0x00,0x3D  TLS_RSA_WITH_AES_256_CBC_SHA256           [RFC5246]
-         * 0x00,0x3E  TLS_DH_DSS_WITH_AES_128_CBC_SHA256        [RFC5246]
-         * 0x00,0x3F  TLS_DH_RSA_WITH_AES_128_CBC_SHA256        [RFC5246]
-         * 0x00,0x40  TLS_DHE_DSS_WITH_AES_128_CBC_SHA256       [RFC5246]
-         * 0x00,0x41  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA         [RFC5932]
-         * 0x00,0x42  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA      [RFC5932]
-         * 0x00,0x43  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA      [RFC5932]
-         * 0x00,0x44  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
-         * 0x00,0x45  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
-         * 0x00,0x46  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
+         * Value      Description                                   Reference
+         * 0x00,0x00  TLS_NULL_WITH_NULL_NULL                       [RFC5246]
+         * 0x00,0x01  TLS_RSA_WITH_NULL_MD5                         [RFC5246]
+         * 0x00,0x02  TLS_RSA_WITH_NULL_SHA                         [RFC5246]
+         * 0x00,0x03  TLS_RSA_EXPORT_WITH_RC4_40_MD5                [RFC4346]
+         * 0x00,0x04  TLS_RSA_WITH_RC4_128_MD5                      [RFC5246]
+         * 0x00,0x05  TLS_RSA_WITH_RC4_128_SHA                      [RFC5246]
+         * 0x00,0x06  TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5            [RFC4346]
+         * 0x00,0x07  TLS_RSA_WITH_IDEA_CBC_SHA                     [RFC5469]
+         * 0x00,0x08  TLS_RSA_EXPORT_WITH_DES40_CBC_SHA             [RFC4346]
+         * 0x00,0x09  TLS_RSA_WITH_DES_CBC_SHA                      [RFC5469]
+         * 0x00,0x0A  TLS_RSA_WITH_3DES_EDE_CBC_SHA                 [RFC5246]
+         * 0x00,0x0B  TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA          [RFC4346]
+         * 0x00,0x0C  TLS_DH_DSS_WITH_DES_CBC_SHA                   [RFC5469]
+         * 0x00,0x0D  TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA              [RFC5246]
+         * 0x00,0x0E  TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA          [RFC4346]
+         * 0x00,0x0F  TLS_DH_RSA_WITH_DES_CBC_SHA                   [RFC5469]
+         * 0x00,0x10  TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA              [RFC5246]
+         * 0x00,0x11  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA         [RFC4346]
+         * 0x00,0x12  TLS_DHE_DSS_WITH_DES_CBC_SHA                  [RFC5469]
+         * 0x00,0x13  TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA             [RFC5246]
+         * 0x00,0x14  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA         [RFC4346]
+         * 0x00,0x15  TLS_DHE_RSA_WITH_DES_CBC_SHA                  [RFC5469]
+         * 0x00,0x16  TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA             [RFC5246]
+         * 0x00,0x17  TLS_DH_anon_EXPORT_WITH_RC4_40_MD5            [RFC4346]
+         * 0x00,0x18  TLS_DH_anon_WITH_RC4_128_MD5                  [RFC5246]
+         * 0x00,0x19  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA         [RFC4346]
+         * 0x00,0x1A  TLS_DH_anon_WITH_DES_CBC_SHA                  [RFC5469]
+         * 0x00,0x1B  TLS_DH_anon_WITH_3DES_EDE_CBC_SHA             [RFC5246]
+         * 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3      [RFC5246]
+         * 0x00,0x1E  TLS_KRB5_WITH_DES_CBC_SHA                     [RFC2712]
+         * 0x00,0x1F  TLS_KRB5_WITH_3DES_EDE_CBC_SHA                [RFC2712]
+         * 0x00,0x20  TLS_KRB5_WITH_RC4_128_SHA                     [RFC2712]
+         * 0x00,0x21  TLS_KRB5_WITH_IDEA_CBC_SHA                    [RFC2712]
+         * 0x00,0x22  TLS_KRB5_WITH_DES_CBC_MD5                     [RFC2712]
+         * 0x00,0x23  TLS_KRB5_WITH_3DES_EDE_CBC_MD5                [RFC2712]
+         * 0x00,0x24  TLS_KRB5_WITH_RC4_128_MD5                     [RFC2712]
+         * 0x00,0x25  TLS_KRB5_WITH_IDEA_CBC_MD5                    [RFC2712]
+         * 0x00,0x26  TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA           [RFC2712]
+         * 0x00,0x27  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA           [RFC2712]
+         * 0x00,0x28  TLS_KRB5_EXPORT_WITH_RC4_40_SHA               [RFC2712]
+         * 0x00,0x29  TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5           [RFC2712]
+         * 0x00,0x2A  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5           [RFC2712]
+         * 0x00,0x2B  TLS_KRB5_EXPORT_WITH_RC4_40_MD5               [RFC2712]
+         * 0x00,0x2C  TLS_PSK_WITH_NULL_SHA                         [RFC4785]
+         * 0x00,0x2D  TLS_DHE_PSK_WITH_NULL_SHA                     [RFC4785]
+         * 0x00,0x2E  TLS_RSA_PSK_WITH_NULL_SHA                     [RFC4785]
+         * 0x00,0x2F  TLS_RSA_WITH_AES_128_CBC_SHA                  [RFC5246]
+         * 0x00,0x30  TLS_DH_DSS_WITH_AES_128_CBC_SHA               [RFC5246]
+         * 0x00,0x31  TLS_DH_RSA_WITH_AES_128_CBC_SHA               [RFC5246]
+         * 0x00,0x32  TLS_DHE_DSS_WITH_AES_128_CBC_SHA              [RFC5246]
+         * 0x00,0x33  TLS_DHE_RSA_WITH_AES_128_CBC_SHA              [RFC5246]
+         * 0x00,0x34  TLS_DH_anon_WITH_AES_128_CBC_SHA              [RFC5246]
+         * 0x00,0x35  TLS_RSA_WITH_AES_256_CBC_SHA                  [RFC5246]
+         * 0x00,0x36  TLS_DH_DSS_WITH_AES_256_CBC_SHA               [RFC5246]
+         * 0x00,0x37  TLS_DH_RSA_WITH_AES_256_CBC_SHA               [RFC5246]
+         * 0x00,0x38  TLS_DHE_DSS_WITH_AES_256_CBC_SHA              [RFC5246]
+         * 0x00,0x39  TLS_DHE_RSA_WITH_AES_256_CBC_SHA              [RFC5246]
+         * 0x00,0x3A  TLS_DH_anon_WITH_AES_256_CBC_SHA              [RFC5246]
+         * 0x00,0x3B  TLS_RSA_WITH_NULL_SHA256                      [RFC5246]
+         * 0x00,0x3C  TLS_RSA_WITH_AES_128_CBC_SHA256               [RFC5246]
+         * 0x00,0x3D  TLS_RSA_WITH_AES_256_CBC_SHA256               [RFC5246]
+         * 0x00,0x3E  TLS_DH_DSS_WITH_AES_128_CBC_SHA256            [RFC5246]
+         * 0x00,0x3F  TLS_DH_RSA_WITH_AES_128_CBC_SHA256            [RFC5246]
+         * 0x00,0x40  TLS_DHE_DSS_WITH_AES_128_CBC_SHA256           [RFC5246]
+         * 0x00,0x41  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA             [RFC5932]
+         * 0x00,0x42  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA          [RFC5932]
+         * 0x00,0x43  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA          [RFC5932]
+         * 0x00,0x44  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA         [RFC5932]
+         * 0x00,0x45  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA         [RFC5932]
+         * 0x00,0x46  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA         [RFC5932]
          * 0x00,0x47-4F Reserved to avoid conflicts with
          *            deployed implementations                  [Pasi_Eronen]
          * 0x00,0x50-58 Reserved to avoid conflicts             [Pasi Eronen]
@@ -814,143 +814,261 @@
          * 0x00,0x5D-5F Unassigned
          * 0x00,0x60-66 Reserved to avoid conflicts with widely
          *            deployed implementations                  [Pasi_Eronen]
-         * 0x00,0x67  TLS_DHE_RSA_WITH_AES_128_CBC_SHA256       [RFC5246]
-         * 0x00,0x68  TLS_DH_DSS_WITH_AES_256_CBC_SHA256        [RFC5246]
-         * 0x00,0x69  TLS_DH_RSA_WITH_AES_256_CBC_SHA256        [RFC5246]
-         * 0x00,0x6A  TLS_DHE_DSS_WITH_AES_256_CBC_SHA256       [RFC5246]
-         * 0x00,0x6B  TLS_DHE_RSA_WITH_AES_256_CBC_SHA256       [RFC5246]
-         * 0x00,0x6C  TLS_DH_anon_WITH_AES_128_CBC_SHA256       [RFC5246]
-         * 0x00,0x6D  TLS_DH_anon_WITH_AES_256_CBC_SHA256       [RFC5246]
+         * 0x00,0x67  TLS_DHE_RSA_WITH_AES_128_CBC_SHA256           [RFC5246]
+         * 0x00,0x68  TLS_DH_DSS_WITH_AES_256_CBC_SHA256            [RFC5246]
+         * 0x00,0x69  TLS_DH_RSA_WITH_AES_256_CBC_SHA256            [RFC5246]
+         * 0x00,0x6A  TLS_DHE_DSS_WITH_AES_256_CBC_SHA256           [RFC5246]
+         * 0x00,0x6B  TLS_DHE_RSA_WITH_AES_256_CBC_SHA256           [RFC5246]
+         * 0x00,0x6C  TLS_DH_anon_WITH_AES_128_CBC_SHA256           [RFC5246]
+         * 0x00,0x6D  TLS_DH_anon_WITH_AES_256_CBC_SHA256           [RFC5246]
          * 0x00,0x6E-83 Unassigned
-         * 0x00,0x84  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA         [RFC5932]
-         * 0x00,0x85  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA      [RFC5932]
-         * 0x00,0x86  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA      [RFC5932]
-         * 0x00,0x87  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
-         * 0x00,0x88  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
-         * 0x00,0x89  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
-         * 0x00,0x8A  TLS_PSK_WITH_RC4_128_SHA                  [RFC4279]
-         * 0x00,0x8B  TLS_PSK_WITH_3DES_EDE_CBC_SHA             [RFC4279]
-         * 0x00,0x8C  TLS_PSK_WITH_AES_128_CBC_SHA              [RFC4279]
-         * 0x00,0x8D  TLS_PSK_WITH_AES_256_CBC_SHA              [RFC4279]
-         * 0x00,0x8E  TLS_DHE_PSK_WITH_RC4_128_SHA              [RFC4279]
-         * 0x00,0x8F  TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA         [RFC4279]
-         * 0x00,0x90  TLS_DHE_PSK_WITH_AES_128_CBC_SHA          [RFC4279]
-         * 0x00,0x91  TLS_DHE_PSK_WITH_AES_256_CBC_SHA          [RFC4279]
-         * 0x00,0x92  TLS_RSA_PSK_WITH_RC4_128_SHA              [RFC4279]
-         * 0x00,0x93  TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA         [RFC4279]
-         * 0x00,0x94  TLS_RSA_PSK_WITH_AES_128_CBC_SHA          [RFC4279]
-         * 0x00,0x95  TLS_RSA_PSK_WITH_AES_256_CBC_SHA          [RFC4279]
-         * 0x00,0x96  TLS_RSA_WITH_SEED_CBC_SHA                 [RFC4162]
-         * 0x00,0x97  TLS_DH_DSS_WITH_SEED_CBC_SHA              [RFC4162]
-         * 0x00,0x98  TLS_DH_RSA_WITH_SEED_CBC_SHA              [RFC4162]
-         * 0x00,0x99  TLS_DHE_DSS_WITH_SEED_CBC_SHA             [RFC4162]
-         * 0x00,0x9A  TLS_DHE_RSA_WITH_SEED_CBC_SHA             [RFC4162]
-         * 0x00,0x9B  TLS_DH_anon_WITH_SEED_CBC_SHA             [RFC4162]
-         * 0x00,0x9C  TLS_RSA_WITH_AES_128_GCM_SHA256           [RFC5288]
-         * 0x00,0x9D  TLS_RSA_WITH_AES_256_GCM_SHA384           [RFC5288]
-         * 0x00,0x9E  TLS_DHE_RSA_WITH_AES_128_GCM_SHA256       [RFC5288]
-         * 0x00,0x9F  TLS_DHE_RSA_WITH_AES_256_GCM_SHA384       [RFC5288]
-         * 0x00,0xA0  TLS_DH_RSA_WITH_AES_128_GCM_SHA256        [RFC5288]
-         * 0x00,0xA1  TLS_DH_RSA_WITH_AES_256_GCM_SHA384        [RFC5288]
-         * 0x00,0xA2  TLS_DHE_DSS_WITH_AES_128_GCM_SHA256       [RFC5288]
-         * 0x00,0xA3  TLS_DHE_DSS_WITH_AES_256_GCM_SHA384       [RFC5288]
-         * 0x00,0xA4  TLS_DH_DSS_WITH_AES_128_GCM_SHA256        [RFC5288]
-         * 0x00,0xA5  TLS_DH_DSS_WITH_AES_256_GCM_SHA384        [RFC5288]
-         * 0x00,0xA6  TLS_DH_anon_WITH_AES_128_GCM_SHA256       [RFC5288]
-         * 0x00,0xA7  TLS_DH_anon_WITH_AES_256_GCM_SHA384       [RFC5288]
-         * 0x00,0xA8  TLS_PSK_WITH_AES_128_GCM_SHA256           [RFC5487]
-         * 0x00,0xA9  TLS_PSK_WITH_AES_256_GCM_SHA384           [RFC5487]
-         * 0x00,0xAA  TLS_DHE_PSK_WITH_AES_128_GCM_SHA256       [RFC5487]
-         * 0x00,0xAB  TLS_DHE_PSK_WITH_AES_256_GCM_SHA384       [RFC5487]
-         * 0x00,0xAC  TLS_RSA_PSK_WITH_AES_128_GCM_SHA256       [RFC5487]
-         * 0x00,0xAD  TLS_RSA_PSK_WITH_AES_256_GCM_SHA384       [RFC5487]
-         * 0x00,0xAE  TLS_PSK_WITH_AES_128_CBC_SHA256           [RFC5487]
-         * 0x00,0xAF  TLS_PSK_WITH_AES_256_CBC_SHA384           [RFC5487]
-         * 0x00,0xB0  TLS_PSK_WITH_NULL_SHA256                  [RFC5487]
-         * 0x00,0xB1  TLS_PSK_WITH_NULL_SHA384                  [RFC5487]
-         * 0x00,0xB2  TLS_DHE_PSK_WITH_AES_128_CBC_SHA256       [RFC5487]
-         * 0x00,0xB3  TLS_DHE_PSK_WITH_AES_256_CBC_SHA384       [RFC5487]
-         * 0x00,0xB4  TLS_DHE_PSK_WITH_NULL_SHA256              [RFC5487]
-         * 0x00,0xB5  TLS_DHE_PSK_WITH_NULL_SHA384              [RFC5487]
-         * 0x00,0xB6  TLS_RSA_PSK_WITH_AES_128_CBC_SHA256       [RFC5487]
-         * 0x00,0xB7  TLS_RSA_PSK_WITH_AES_256_CBC_SHA384       [RFC5487]
-         * 0x00,0xB8  TLS_RSA_PSK_WITH_NULL_SHA256              [RFC5487]
-         * 0x00,0xB9  TLS_RSA_PSK_WITH_NULL_SHA384              [RFC5487]
-         * 0x00,0xBA  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256      [RFC5932]
-         * 0x00,0xBB  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256   [RFC5932]
-         * 0x00,0xBC  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256   [RFC5932]
-         * 0x00,0xBD  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
-         * 0x00,0xBE  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
-         * 0x00,0xBF  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
-         * 0x00,0xC0  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256      [RFC5932]
-         * 0x00,0xC1  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256   [RFC5932]
-         * 0x00,0xC2  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256   [RFC5932]
-         * 0x00,0xC3  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
-         * 0x00,0xC4  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
-         * 0x00,0xC5  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
+         * 0x00,0x84  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA             [RFC5932]
+         * 0x00,0x85  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA          [RFC5932]
+         * 0x00,0x86  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA          [RFC5932]
+         * 0x00,0x87  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA         [RFC5932]
+         * 0x00,0x88  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA         [RFC5932]
+         * 0x00,0x89  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA         [RFC5932]
+         * 0x00,0x8A  TLS_PSK_WITH_RC4_128_SHA                      [RFC4279]
+         * 0x00,0x8B  TLS_PSK_WITH_3DES_EDE_CBC_SHA                 [RFC4279]
+         * 0x00,0x8C  TLS_PSK_WITH_AES_128_CBC_SHA                  [RFC4279]
+         * 0x00,0x8D  TLS_PSK_WITH_AES_256_CBC_SHA                  [RFC4279]
+         * 0x00,0x8E  TLS_DHE_PSK_WITH_RC4_128_SHA                  [RFC4279]
+         * 0x00,0x8F  TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA             [RFC4279]
+         * 0x00,0x90  TLS_DHE_PSK_WITH_AES_128_CBC_SHA              [RFC4279]
+         * 0x00,0x91  TLS_DHE_PSK_WITH_AES_256_CBC_SHA              [RFC4279]
+         * 0x00,0x92  TLS_RSA_PSK_WITH_RC4_128_SHA                  [RFC4279]
+         * 0x00,0x93  TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA             [RFC4279]
+         * 0x00,0x94  TLS_RSA_PSK_WITH_AES_128_CBC_SHA              [RFC4279]
+         * 0x00,0x95  TLS_RSA_PSK_WITH_AES_256_CBC_SHA              [RFC4279]
+         * 0x00,0x96  TLS_RSA_WITH_SEED_CBC_SHA                     [RFC4162]
+         * 0x00,0x97  TLS_DH_DSS_WITH_SEED_CBC_SHA                  [RFC4162]
+         * 0x00,0x98  TLS_DH_RSA_WITH_SEED_CBC_SHA                  [RFC4162]
+         * 0x00,0x99  TLS_DHE_DSS_WITH_SEED_CBC_SHA                 [RFC4162]
+         * 0x00,0x9A  TLS_DHE_RSA_WITH_SEED_CBC_SHA                 [RFC4162]
+         * 0x00,0x9B  TLS_DH_anon_WITH_SEED_CBC_SHA                 [RFC4162]
+         * 0x00,0x9C  TLS_RSA_WITH_AES_128_GCM_SHA256               [RFC5288]
+         * 0x00,0x9D  TLS_RSA_WITH_AES_256_GCM_SHA384               [RFC5288]
+         * 0x00,0x9E  TLS_DHE_RSA_WITH_AES_128_GCM_SHA256           [RFC5288]
+         * 0x00,0x9F  TLS_DHE_RSA_WITH_AES_256_GCM_SHA384           [RFC5288]
+         * 0x00,0xA0  TLS_DH_RSA_WITH_AES_128_GCM_SHA256            [RFC5288]
+         * 0x00,0xA1  TLS_DH_RSA_WITH_AES_256_GCM_SHA384            [RFC5288]
+         * 0x00,0xA2  TLS_DHE_DSS_WITH_AES_128_GCM_SHA256           [RFC5288]
+         * 0x00,0xA3  TLS_DHE_DSS_WITH_AES_256_GCM_SHA384           [RFC5288]
+         * 0x00,0xA4  TLS_DH_DSS_WITH_AES_128_GCM_SHA256            [RFC5288]
+         * 0x00,0xA5  TLS_DH_DSS_WITH_AES_256_GCM_SHA384            [RFC5288]
+         * 0x00,0xA6  TLS_DH_anon_WITH_AES_128_GCM_SHA256           [RFC5288]
+         * 0x00,0xA7  TLS_DH_anon_WITH_AES_256_GCM_SHA384           [RFC5288]
+         * 0x00,0xA8  TLS_PSK_WITH_AES_128_GCM_SHA256               [RFC5487]
+         * 0x00,0xA9  TLS_PSK_WITH_AES_256_GCM_SHA384               [RFC5487]
+         * 0x00,0xAA  TLS_DHE_PSK_WITH_AES_128_GCM_SHA256           [RFC5487]
+         * 0x00,0xAB  TLS_DHE_PSK_WITH_AES_256_GCM_SHA384           [RFC5487]
+         * 0x00,0xAC  TLS_RSA_PSK_WITH_AES_128_GCM_SHA256           [RFC5487]
+         * 0x00,0xAD  TLS_RSA_PSK_WITH_AES_256_GCM_SHA384           [RFC5487]
+         * 0x00,0xAE  TLS_PSK_WITH_AES_128_CBC_SHA256               [RFC5487]
+         * 0x00,0xAF  TLS_PSK_WITH_AES_256_CBC_SHA384               [RFC5487]
+         * 0x00,0xB0  TLS_PSK_WITH_NULL_SHA256                      [RFC5487]
+         * 0x00,0xB1  TLS_PSK_WITH_NULL_SHA384                      [RFC5487]
+         * 0x00,0xB2  TLS_DHE_PSK_WITH_AES_128_CBC_SHA256           [RFC5487]
+         * 0x00,0xB3  TLS_DHE_PSK_WITH_AES_256_CBC_SHA384           [RFC5487]
+         * 0x00,0xB4  TLS_DHE_PSK_WITH_NULL_SHA256                  [RFC5487]
+         * 0x00,0xB5  TLS_DHE_PSK_WITH_NULL_SHA384                  [RFC5487]
+         * 0x00,0xB6  TLS_RSA_PSK_WITH_AES_128_CBC_SHA256           [RFC5487]
+         * 0x00,0xB7  TLS_RSA_PSK_WITH_AES_256_CBC_SHA384           [RFC5487]
+         * 0x00,0xB8  TLS_RSA_PSK_WITH_NULL_SHA256                  [RFC5487]
+         * 0x00,0xB9  TLS_RSA_PSK_WITH_NULL_SHA384                  [RFC5487]
+         * 0x00,0xBA  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256          [RFC5932]
+         * 0x00,0xBB  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256       [RFC5932]
+         * 0x00,0xBC  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256       [RFC5932]
+         * 0x00,0xBD  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256      [RFC5932]
+         * 0x00,0xBE  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256      [RFC5932]
+         * 0x00,0xBF  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256      [RFC5932]
+         * 0x00,0xC0  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256          [RFC5932]
+         * 0x00,0xC1  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256       [RFC5932]
+         * 0x00,0xC2  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256       [RFC5932]
+         * 0x00,0xC3  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256      [RFC5932]
+         * 0x00,0xC4  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256      [RFC5932]
+         * 0x00,0xC5  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256      [RFC5932]
          * 0x00,0xC6-FE         Unassigned
-         * 0x00,0xFF  TLS_EMPTY_RENEGOTIATION_INFO_SCSV         [RFC5746]
-         * 0x01-BF,*  Unassigned
-         * 0xC0,0x01  TLS_ECDH_ECDSA_WITH_NULL_SHA              [RFC4492]
-         * 0xC0,0x02  TLS_ECDH_ECDSA_WITH_RC4_128_SHA           [RFC4492]
-         * 0xC0,0x03  TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA      [RFC4492]
-         * 0xC0,0x04  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA       [RFC4492]
-         * 0xC0,0x05  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA       [RFC4492]
-         * 0xC0,0x06  TLS_ECDHE_ECDSA_WITH_NULL_SHA             [RFC4492]
-         * 0xC0,0x07  TLS_ECDHE_ECDSA_WITH_RC4_128_SHA          [RFC4492]
-         * 0xC0,0x08  TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA     [RFC4492]
-         * 0xC0,0x09  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA      [RFC4492]
-         * 0xC0,0x0A  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA      [RFC4492]
-         * 0xC0,0x0B  TLS_ECDH_RSA_WITH_NULL_SHA                [RFC4492]
-         * 0xC0,0x0C  TLS_ECDH_RSA_WITH_RC4_128_SHA             [RFC4492]
-         * 0xC0,0x0D  TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA        [RFC4492]
-         * 0xC0,0x0E  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA         [RFC4492]
-         * 0xC0,0x0F  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA         [RFC4492]
-         * 0xC0,0x10  TLS_ECDHE_RSA_WITH_NULL_SHA               [RFC4492]
-         * 0xC0,0x11  TLS_ECDHE_RSA_WITH_RC4_128_SHA            [RFC4492]
-         * 0xC0,0x12  TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA       [RFC4492]
-         * 0xC0,0x13  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA        [RFC4492]
-         * 0xC0,0x14  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA        [RFC4492]
-         * 0xC0,0x15  TLS_ECDH_anon_WITH_NULL_SHA               [RFC4492]
-         * 0xC0,0x16  TLS_ECDH_anon_WITH_RC4_128_SHA            [RFC4492]
-         * 0xC0,0x17  TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA       [RFC4492]
-         * 0xC0,0x18  TLS_ECDH_anon_WITH_AES_128_CBC_SHA        [RFC4492]
-         * 0xC0,0x19  TLS_ECDH_anon_WITH_AES_256_CBC_SHA        [RFC4492]
-         * 0xC0,0x1A  TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA         [RFC5054]
-         * 0xC0,0x1B  TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA     [RFC5054]
-         * 0xC0,0x1C  TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA     [RFC5054]
-         * 0xC0,0x1D  TLS_SRP_SHA_WITH_AES_128_CBC_SHA          [RFC5054]
-         * 0xC0,0x1E  TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA      [RFC5054]
-         * 0xC0,0x1F  TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA      [RFC5054]
-         * 0xC0,0x20  TLS_SRP_SHA_WITH_AES_256_CBC_SHA          [RFC5054]
-         * 0xC0,0x21  TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA      [RFC5054]
-         * 0xC0,0x22  TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA      [RFC5054]
-         * 0xC0,0x23  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256   [RFC5289]
-         * 0xC0,0x24  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384   [RFC5289]
-         * 0xC0,0x25  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256    [RFC5289]
-         * 0xC0,0x26  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384    [RFC5289]
-         * 0xC0,0x27  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256     [RFC5289]
-         * 0xC0,0x28  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384     [RFC5289]
-         * 0xC0,0x29  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256      [RFC5289]
-         * 0xC0,0x2A  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384      [RFC5289]
-         * 0xC0,0x2B  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256   [RFC5289]
-         * 0xC0,0x2C  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384   [RFC5289]
-         * 0xC0,0x2D  TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256    [RFC5289]
-         * 0xC0,0x2E  TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384    [RFC5289]
-         * 0xC0,0x2F  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256     [RFC5289]
-         * 0xC0,0x30  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384     [RFC5289]
-         * 0xC0,0x31  TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256      [RFC5289]
-         * 0xC0,0x32  TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384      [RFC5289]
-         * 0xC0,0x33  TLS_ECDHE_PSK_WITH_RC4_128_SHA            [RFC5489]
-         * 0xC0,0x34  TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA       [RFC5489]
-         * 0xC0,0x35  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA        [RFC5489]
-         * 0xC0,0x36  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA        [RFC5489]
-         * 0xC0,0x37  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256     [RFC5489]
-         * 0xC0,0x38  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384     [RFC5489]
-         * 0xC0,0x39  TLS_ECDHE_PSK_WITH_NULL_SHA               [RFC5489]
-         * 0xC0,0x3A  TLS_ECDHE_PSK_WITH_NULL_SHA256            [RFC5489]
-         * 0xC0,0x3B  TLS_ECDHE_PSK_WITH_NULL_SHA384            [RFC5489]
-         * 0xC0,0x3C-FF Unassigned
+         * 0x00,0xFF  TLS_EMPTY_RENEGOTIATION_INFO_SCSV             [RFC5746]
+         * 0x01-55,*  Unassigned
+         * 0x56,0x00  TLS_FALLBACK_SCSV                             [RFC7507]
+         * 0x56,0x01-0xC0,0x00  Unassigned
+         * 0xC0,0x01  TLS_ECDH_ECDSA_WITH_NULL_SHA                  [RFC4492]
+         * 0xC0,0x02  TLS_ECDH_ECDSA_WITH_RC4_128_SHA               [RFC4492]
+         * 0xC0,0x03  TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA          [RFC4492]
+         * 0xC0,0x04  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA           [RFC4492]
+         * 0xC0,0x05  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA           [RFC4492]
+         * 0xC0,0x06  TLS_ECDHE_ECDSA_WITH_NULL_SHA                 [RFC4492]
+         * 0xC0,0x07  TLS_ECDHE_ECDSA_WITH_RC4_128_SHA              [RFC4492]
+         * 0xC0,0x08  TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA         [RFC4492]
+         * 0xC0,0x09  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA          [RFC4492]
+         * 0xC0,0x0A  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA          [RFC4492]
+         * 0xC0,0x0B  TLS_ECDH_RSA_WITH_NULL_SHA                    [RFC4492]
+         * 0xC0,0x0C  TLS_ECDH_RSA_WITH_RC4_128_SHA                 [RFC4492]
+         * 0xC0,0x0D  TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA            [RFC4492]
+         * 0xC0,0x0E  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA             [RFC4492]
+         * 0xC0,0x0F  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA             [RFC4492]
+         * 0xC0,0x10  TLS_ECDHE_RSA_WITH_NULL_SHA                   [RFC4492]
+         * 0xC0,0x11  TLS_ECDHE_RSA_WITH_RC4_128_SHA                [RFC4492]
+         * 0xC0,0x12  TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA           [RFC4492]
+         * 0xC0,0x13  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA            [RFC4492]
+         * 0xC0,0x14  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA            [RFC4492]
+         * 0xC0,0x15  TLS_ECDH_anon_WITH_NULL_SHA                   [RFC4492]
+         * 0xC0,0x16  TLS_ECDH_anon_WITH_RC4_128_SHA                [RFC4492]
+         * 0xC0,0x17  TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA           [RFC4492]
+         * 0xC0,0x18  TLS_ECDH_anon_WITH_AES_128_CBC_SHA            [RFC4492]
+         * 0xC0,0x19  TLS_ECDH_anon_WITH_AES_256_CBC_SHA            [RFC4492]
+         * 0xC0,0x1A  TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA             [RFC5054]
+         * 0xC0,0x1B  TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA         [RFC5054]
+         * 0xC0,0x1C  TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA         [RFC5054]
+         * 0xC0,0x1D  TLS_SRP_SHA_WITH_AES_128_CBC_SHA              [RFC5054]
+         * 0xC0,0x1E  TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA          [RFC5054]
+         * 0xC0,0x1F  TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA          [RFC5054]
+         * 0xC0,0x20  TLS_SRP_SHA_WITH_AES_256_CBC_SHA              [RFC5054]
+         * 0xC0,0x21  TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA          [RFC5054]
+         * 0xC0,0x22  TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA          [RFC5054]
+         * 0xC0,0x23  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256       [RFC5289]
+         * 0xC0,0x24  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384       [RFC5289]
+         * 0xC0,0x25  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256        [RFC5289]
+         * 0xC0,0x26  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384        [RFC5289]
+         * 0xC0,0x27  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256         [RFC5289]
+         * 0xC0,0x28  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384         [RFC5289]
+         * 0xC0,0x29  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256          [RFC5289]
+         * 0xC0,0x2A  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384          [RFC5289]
+         * 0xC0,0x2B  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256       [RFC5289]
+         * 0xC0,0x2C  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384       [RFC5289]
+         * 0xC0,0x2D  TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256        [RFC5289]
+         * 0xC0,0x2E  TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384        [RFC5289]
+         * 0xC0,0x2F  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256         [RFC5289]
+         * 0xC0,0x30  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384         [RFC5289]
+         * 0xC0,0x31  TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256          [RFC5289]
+         * 0xC0,0x32  TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384          [RFC5289]
+         * 0xC0,0x33  TLS_ECDHE_PSK_WITH_RC4_128_SHA                [RFC5489]
+         * 0xC0,0x34  TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA           [RFC5489]
+         * 0xC0,0x35  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA            [RFC5489]
+         * 0xC0,0x36  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA            [RFC5489]
+         * 0xC0,0x37  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256         [RFC5489]
+         * 0xC0,0x38  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384         [RFC5489]
+         * 0xC0,0x39  TLS_ECDHE_PSK_WITH_NULL_SHA                   [RFC5489]
+         * 0xC0,0x3A  TLS_ECDHE_PSK_WITH_NULL_SHA256                [RFC5489]
+         * 0xC0,0x3B  TLS_ECDHE_PSK_WITH_NULL_SHA384                [RFC5489]
+         * 0xC0,0x3C  TLS_RSA_WITH_ARIA_128_CBC_SHA256              [RFC6209]
+         * 0xC0,0x3D  TLS_RSA_WITH_ARIA_256_CBC_SHA384              [RFC6209]
+         * 0xC0,0x3E  TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256           [RFC6209]
+         * 0xC0,0x3F  TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384           [RFC6209]
+         * 0xC0,0x40  TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256           [RFC6209]
+         * 0xC0,0x41  TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384           [RFC6209]
+         * 0xC0,0x42  TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256          [RFC6209]
+         * 0xC0,0x43  TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384          [RFC6209]
+         * 0xC0,0x44  TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256          [RFC6209]
+         * 0xC0,0x45  TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384          [RFC6209]
+         * 0xC0,0x46  TLS_DH_anon_WITH_ARIA_128_CBC_SHA256          [RFC6209]
+         * 0xC0,0x47  TLS_DH_anon_WITH_ARIA_256_CBC_SHA384          [RFC6209]
+         * 0xC0,0x48  TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256      [RFC6209]
+         * 0xC0,0x49  TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384      [RFC6209]
+         * 0xC0,0x4A  TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256       [RFC6209]
+         * 0xC0,0x4B  TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384       [RFC6209]
+         * 0xC0,0x4C  TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256        [RFC6209]
+         * 0xC0,0x4D  TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384        [RFC6209]
+         * 0xC0,0x4E  TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256         [RFC6209]
+         * 0xC0,0x4F  TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384         [RFC6209]
+         * 0xC0,0x50  TLS_RSA_WITH_ARIA_128_GCM_SHA256              [RFC6209]
+         * 0xC0,0x51  TLS_RSA_WITH_ARIA_256_GCM_SHA384              [RFC6209]
+         * 0xC0,0x52  TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256          [RFC6209]
+         * 0xC0,0x53  TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384          [RFC6209]
+         * 0xC0,0x54  TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256           [RFC6209]
+         * 0xC0,0x55  TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384           [RFC6209]
+         * 0xC0,0x56  TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256          [RFC6209]
+         * 0xC0,0x57  TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384          [RFC6209]
+         * 0xC0,0x58  TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256           [RFC6209]
+         * 0xC0,0x59  TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384           [RFC6209]
+         * 0xC0,0x5A  TLS_DH_anon_WITH_ARIA_128_GCM_SHA256          [RFC6209]
+         * 0xC0,0x5B  TLS_DH_anon_WITH_ARIA_256_GCM_SHA384          [RFC6209]
+         * 0xC0,0x5C  TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256      [RFC6209]
+         * 0xC0,0x5D  TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384      [RFC6209]
+         * 0xC0,0x5E  TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256       [RFC6209]
+         * 0xC0,0x5F  TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384       [RFC6209]
+         * 0xC0,0x60  TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256        [RFC6209]
+         * 0xC0,0x61  TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384        [RFC6209]
+         * 0xC0,0x62  TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256         [RFC6209]
+         * 0xC0,0x63  TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384         [RFC6209]
+         * 0xC0,0x64  TLS_PSK_WITH_ARIA_128_CBC_SHA256              [RFC6209]
+         * 0xC0,0x65  TLS_PSK_WITH_ARIA_256_CBC_SHA384              [RFC6209]
+         * 0xC0,0x66  TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256          [RFC6209]
+         * 0xC0,0x67  TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384          [RFC6209]
+         * 0xC0,0x68  TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256          [RFC6209]
+         * 0xC0,0x69  TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384          [RFC6209]
+         * 0xC0,0x6A  TLS_PSK_WITH_ARIA_128_GCM_SHA256              [RFC6209]
+         * 0xC0,0x6B  TLS_PSK_WITH_ARIA_256_GCM_SHA384              [RFC6209]
+         * 0xC0,0x6C  TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256          [RFC6209]
+         * 0xC0,0x6D  TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384          [RFC6209]
+         * 0xC0,0x6E  TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256          [RFC6209]
+         * 0xC0,0x6F  TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384          [RFC6209]
+         * 0xC0,0x70  TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256        [RFC6209]
+         * 0xC0,0x71  TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384        [RFC6209]
+         * 0xC0,0x72  TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256  [RFC6367]
+         * 0xC0,0x73  TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384  [RFC6367]
+         * 0xC0,0x74  TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256   [RFC6367]
+         * 0xC0,0x75  TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384   [RFC6367]
+         * 0xC0,0x76  TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256    [RFC6367]
+         * 0xC0,0x77  TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384    [RFC6367]
+         * 0xC0,0x78  TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256     [RFC6367]
+         * 0xC0,0x79  TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384     [RFC6367]
+         * 0xC0,0x7A  TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256          [RFC6367]
+         * 0xC0,0x7B  TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384          [RFC6367]
+         * 0xC0,0x7C  TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256      [RFC6367]
+         * 0xC0,0x7D  TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384      [RFC6367]
+         * 0xC0,0x7E  TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256       [RFC6367]
+         * 0xC0,0x7F  TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384       [RFC6367]
+         * 0xC0,0x80  TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256      [RFC6367]
+         * 0xC0,0x81  TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384      [RFC6367]
+         * 0xC0,0x82  TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256       [RFC6367]
+         * 0xC0,0x83  TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384       [RFC6367]
+         * 0xC0,0x84  TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256      [RFC6367]
+         * 0xC0,0x85  TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384      [RFC6367]
+         * 0xC0,0x86  TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256  [RFC6367]
+         * 0xC0,0x87  TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384  [RFC6367]
+         * 0xC0,0x88  TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256   [RFC6367]
+         * 0xC0,0x89  TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384   [RFC6367]
+         * 0xC0,0x8A  TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256    [RFC6367]
+         * 0xC0,0x8B  TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384    [RFC6367]
+         * 0xC0,0x8C  TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256     [RFC6367]
+         * 0xC0,0x8D  TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384     [RFC6367]
+         * 0xC0,0x8E  TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256          [RFC6367]
+         * 0xC0,0x8F  TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384          [RFC6367]
+         * 0xC0,0x90  TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256      [RFC6367]
+         * 0xC0,0x91  TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384      [RFC6367]
+         * 0xC0,0x92  TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256      [RFC6367]
+         * 0xC0,0x93  TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384      [RFC6367]
+         * 0xC0,0x94  TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256          [RFC6367]
+         * 0xC0,0x95  TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384          [RFC6367]
+         * 0xC0,0x96  TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256      [RFC6367]
+         * 0xC0,0x97  TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384      [RFC6367]
+         * 0xC0,0x98  TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256      [RFC6367]
+         * 0xC0,0x99  TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384      [RFC6367]
+         * 0xC0,0x9A  TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256    [RFC6367]
+         * 0xC0,0x9B  TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384    [RFC6367]
+         * 0xC0,0x9C  TLS_RSA_WITH_AES_128_CCM                      [RFC6655]
+         * 0xC0,0x9D  TLS_RSA_WITH_AES_256_CCM                      [RFC6655]
+         * 0xC0,0x9E  TLS_DHE_RSA_WITH_AES_128_CCM                  [RFC6655]
+         * 0xC0,0x9F  TLS_DHE_RSA_WITH_AES_256_CCM                  [RFC6655]
+         * 0xC0,0xA0  TLS_RSA_WITH_AES_128_CCM_8                    [RFC6655]
+         * 0xC0,0xA1  TLS_RSA_WITH_AES_256_CCM_8                    [RFC6655]
+         * 0xC0,0xA2  TLS_DHE_RSA_WITH_AES_128_CCM_8                [RFC6655]
+         * 0xC0,0xA3  TLS_DHE_RSA_WITH_AES_256_CCM_8                [RFC6655]
+         * 0xC0,0xA4  TLS_PSK_WITH_AES_128_CCM                      [RFC6655]
+         * 0xC0,0xA5  TLS_PSK_WITH_AES_256_CCM                      [RFC6655]
+         * 0xC0,0xA6  TLS_DHE_PSK_WITH_AES_128_CCM                  [RFC6655]
+         * 0xC0,0xA7  TLS_DHE_PSK_WITH_AES_256_CCM                  [RFC6655]
+         * 0xC0,0xA8  TLS_PSK_WITH_AES_128_CCM_8                    [RFC6655]
+         * 0xC0,0xA9  TLS_PSK_WITH_AES_256_CCM_8                    [RFC6655]
+         * 0xC0,0xAA  TLS_PSK_DHE_WITH_AES_128_CCM_8                [RFC6655]
+         * 0xC0,0xAB  TLS_PSK_DHE_WITH_AES_256_CCM_8                [RFC6655]
+         * 0xC0,0xAC  TLS_ECDHE_ECDSA_WITH_AES_128_CCM              [RFC7251]
+         * 0xC0,0xAD  TLS_ECDHE_ECDSA_WITH_AES_256_CCM              [RFC7251]
+         * 0xC0,0xAE  TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8            [RFC7251]
+         * 0xC0,0xAF  TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8            [RFC7251]
+         * 0xC0,0xB0-FF  Unassigned
          * 0xC1-FD,*  Unassigned
          * 0xFE,0x00-FD Unassigned
          * 0xFE,0xFE-FF Reserved to avoid conflicts with widely
@@ -1263,149 +1381,276 @@
         // the debug output.
 
         // remaining unsupported ciphersuites defined in RFC2246.
-        add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",          0x0006);
-        add("SSL_RSA_WITH_IDEA_CBC_SHA",                   0x0007);
-        add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",        0x000b);
-        add("SSL_DH_DSS_WITH_DES_CBC_SHA",                 0x000c);
-        add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",            0x000d);
-        add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",        0x000e);
-        add("SSL_DH_RSA_WITH_DES_CBC_SHA",                 0x000f);
-        add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",            0x0010);
+        add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",           0x0006);
+        add("SSL_RSA_WITH_IDEA_CBC_SHA",                    0x0007);
+        add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",         0x000b);
+        add("SSL_DH_DSS_WITH_DES_CBC_SHA",                  0x000c);
+        add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",             0x000d);
+        add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",         0x000e);
+        add("SSL_DH_RSA_WITH_DES_CBC_SHA",                  0x000f);
+        add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",             0x0010);
 
         // SSL 3.0 Fortezza ciphersuites
-        add("SSL_FORTEZZA_DMS_WITH_NULL_SHA",              0x001c);
-        add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",      0x001d);
+        add("SSL_FORTEZZA_DMS_WITH_NULL_SHA",               0x001c);
+        add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",       0x001d);
 
         // 1024/56 bit exportable ciphersuites from expired internet draft
-        add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA",         0x0062);
-        add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA",     0x0063);
-        add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",          0x0064);
-        add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA",      0x0065);
-        add("SSL_DHE_DSS_WITH_RC4_128_SHA",                0x0066);
+        add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA",          0x0062);
+        add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA",      0x0063);
+        add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",           0x0064);
+        add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA",       0x0065);
+        add("SSL_DHE_DSS_WITH_RC4_128_SHA",                 0x0066);
 
         // Netscape old and new SSL 3.0 FIPS ciphersuites
         // see http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
-        add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",     0xffe0);
-        add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA",          0xffe1);
-        add("SSL_RSA_FIPS_WITH_DES_CBC_SHA",               0xfefe);
-        add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",          0xfeff);
+        add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",      0xffe0);
+        add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA",           0xffe1);
+        add("SSL_RSA_FIPS_WITH_DES_CBC_SHA",                0xfefe);
+        add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",           0xfeff);
 
         // Unsupported Kerberos cipher suites from RFC 2712
-        add("TLS_KRB5_WITH_IDEA_CBC_SHA",                  0x0021);
-        add("TLS_KRB5_WITH_IDEA_CBC_MD5",                  0x0025);
-        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",         0x0027);
-        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",         0x002a);
+        add("TLS_KRB5_WITH_IDEA_CBC_SHA",                   0x0021);
+        add("TLS_KRB5_WITH_IDEA_CBC_MD5",                   0x0025);
+        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",          0x0027);
+        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",          0x002a);
 
         // Unsupported cipher suites from RFC 4162
-        add("TLS_RSA_WITH_SEED_CBC_SHA",                   0x0096);
-        add("TLS_DH_DSS_WITH_SEED_CBC_SHA",                0x0097);
-        add("TLS_DH_RSA_WITH_SEED_CBC_SHA",                0x0098);
-        add("TLS_DHE_DSS_WITH_SEED_CBC_SHA",               0x0099);
-        add("TLS_DHE_RSA_WITH_SEED_CBC_SHA",               0x009a);
-        add("TLS_DH_anon_WITH_SEED_CBC_SHA",               0x009b);
+        add("TLS_RSA_WITH_SEED_CBC_SHA",                    0x0096);
+        add("TLS_DH_DSS_WITH_SEED_CBC_SHA",                 0x0097);
+        add("TLS_DH_RSA_WITH_SEED_CBC_SHA",                 0x0098);
+        add("TLS_DHE_DSS_WITH_SEED_CBC_SHA",                0x0099);
+        add("TLS_DHE_RSA_WITH_SEED_CBC_SHA",                0x009a);
+        add("TLS_DH_anon_WITH_SEED_CBC_SHA",                0x009b);
 
         // Unsupported cipher suites from RFC 4279
-        add("TLS_PSK_WITH_RC4_128_SHA",                    0x008a);
-        add("TLS_PSK_WITH_3DES_EDE_CBC_SHA",               0x008b);
-        add("TLS_PSK_WITH_AES_128_CBC_SHA",                0x008c);
-        add("TLS_PSK_WITH_AES_256_CBC_SHA",                0x008d);
-        add("TLS_DHE_PSK_WITH_RC4_128_SHA",                0x008e);
-        add("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",           0x008f);
-        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA",            0x0090);
-        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA",            0x0091);
-        add("TLS_RSA_PSK_WITH_RC4_128_SHA",                0x0092);
-        add("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",           0x0093);
-        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA",            0x0094);
-        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA",            0x0095);
+        add("TLS_PSK_WITH_RC4_128_SHA",                     0x008a);
+        add("TLS_PSK_WITH_3DES_EDE_CBC_SHA",                0x008b);
+        add("TLS_PSK_WITH_AES_128_CBC_SHA",                 0x008c);
+        add("TLS_PSK_WITH_AES_256_CBC_SHA",                 0x008d);
+        add("TLS_DHE_PSK_WITH_RC4_128_SHA",                 0x008e);
+        add("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",            0x008f);
+        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA",             0x0090);
+        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA",             0x0091);
+        add("TLS_RSA_PSK_WITH_RC4_128_SHA",                 0x0092);
+        add("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",            0x0093);
+        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA",             0x0094);
+        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA",             0x0095);
 
         // Unsupported cipher suites from RFC 4785
-        add("TLS_PSK_WITH_NULL_SHA",                       0x002c);
-        add("TLS_DHE_PSK_WITH_NULL_SHA",                   0x002d);
-        add("TLS_RSA_PSK_WITH_NULL_SHA",                   0x002e);
+        add("TLS_PSK_WITH_NULL_SHA",                        0x002c);
+        add("TLS_DHE_PSK_WITH_NULL_SHA",                    0x002d);
+        add("TLS_RSA_PSK_WITH_NULL_SHA",                    0x002e);
 
         // Unsupported cipher suites from RFC 5246
-        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA",             0x0030);
-        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA",             0x0031);
-        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA",             0x0036);
-        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA",             0x0037);
-        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256",          0x003e);
-        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256",          0x003f);
-        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256",          0x0068);
-        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256",          0x0069);
+        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA",              0x0030);
+        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA",              0x0031);
+        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA",              0x0036);
+        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA",              0x0037);
+        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256",           0x003e);
+        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256",           0x003f);
+        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256",           0x0068);
+        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256",           0x0069);
 
         // Unsupported cipher suites from RFC 5288
-        add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256",          0x00a0);
-        add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384",          0x00a1);
-        add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256",          0x00a4);
-        add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384",          0x00a5);
+        add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256",           0x00a0);
+        add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384",           0x00a1);
+        add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256",           0x00a4);
+        add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384",           0x00a5);
 
         // Unsupported cipher suites from RFC 5487
-        add("TLS_PSK_WITH_AES_128_GCM_SHA256",             0x00a8);
-        add("TLS_PSK_WITH_AES_256_GCM_SHA384",             0x00a9);
-        add("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",         0x00aa);
-        add("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",         0x00ab);
-        add("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",         0x00ac);
-        add("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",         0x00ad);
-        add("TLS_PSK_WITH_AES_128_CBC_SHA256",             0x00ae);
-        add("TLS_PSK_WITH_AES_256_CBC_SHA384",             0x00af);
-        add("TLS_PSK_WITH_NULL_SHA256",                    0x00b0);
-        add("TLS_PSK_WITH_NULL_SHA384",                    0x00b1);
-        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",         0x00b2);
-        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",         0x00b3);
-        add("TLS_DHE_PSK_WITH_NULL_SHA256",                0x00b4);
-        add("TLS_DHE_PSK_WITH_NULL_SHA384",                0x00b5);
-        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",         0x00b6);
-        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",         0x00b7);
-        add("TLS_RSA_PSK_WITH_NULL_SHA256",                0x00b8);
-        add("TLS_RSA_PSK_WITH_NULL_SHA384",                0x00b9);
+        add("TLS_PSK_WITH_AES_128_GCM_SHA256",              0x00a8);
+        add("TLS_PSK_WITH_AES_256_GCM_SHA384",              0x00a9);
+        add("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",          0x00aa);
+        add("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",          0x00ab);
+        add("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",          0x00ac);
+        add("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",          0x00ad);
+        add("TLS_PSK_WITH_AES_128_CBC_SHA256",              0x00ae);
+        add("TLS_PSK_WITH_AES_256_CBC_SHA384",              0x00af);
+        add("TLS_PSK_WITH_NULL_SHA256",                     0x00b0);
+        add("TLS_PSK_WITH_NULL_SHA384",                     0x00b1);
+        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",          0x00b2);
+        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",          0x00b3);
+        add("TLS_DHE_PSK_WITH_NULL_SHA256",                 0x00b4);
+        add("TLS_DHE_PSK_WITH_NULL_SHA384",                 0x00b5);
+        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",          0x00b6);
+        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",          0x00b7);
+        add("TLS_RSA_PSK_WITH_NULL_SHA256",                 0x00b8);
+        add("TLS_RSA_PSK_WITH_NULL_SHA384",                 0x00b9);
 
         // Unsupported cipher suites from RFC 5932
-        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",           0x0041);
-        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",        0x0042);
-        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",        0x0043);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",       0x0044);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",       0x0045);
-        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",       0x0046);
-        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",           0x0084);
-        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",        0x0085);
-        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",        0x0086);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",       0x0087);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",       0x0088);
-        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",       0x0089);
-        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",        0x00ba);
-        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256",     0x00bb);
-        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256",     0x00bc);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",    0x00bd);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",    0x00be);
-        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",    0x00bf);
-        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",        0x00c0);
-        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256",     0x00c1);
-        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256",     0x00c2);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",    0x00c3);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",    0x00c4);
-        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",    0x00c5);
+        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",            0x0041);
+        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",         0x0042);
+        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",         0x0043);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",        0x0044);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",        0x0045);
+        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",        0x0046);
+        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",            0x0084);
+        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",         0x0085);
+        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",         0x0086);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",        0x0087);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",        0x0088);
+        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",        0x0089);
+        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",         0x00ba);
+        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256",      0x00bb);
+        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256",      0x00bc);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",     0x00bd);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",     0x00be);
+        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",     0x00bf);
+        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",         0x00c0);
+        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256",      0x00c1);
+        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256",      0x00c2);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",     0x00c3);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",     0x00c4);
+        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",     0x00c5);
+
+        // TLS Fallback Signaling Cipher Suite Value (SCSV) RFC 7507
+        add("TLS_FALLBACK_SCSV", 0x5600);
 
         // Unsupported cipher suites from RFC 5054
-        add("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",           0xc01a);
-        add("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",       0xc01b);
-        add("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",       0xc01c);
-        add("TLS_SRP_SHA_WITH_AES_128_CBC_SHA",            0xc01d);
-        add("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",        0xc01e);
-        add("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",        0xc01f);
-        add("TLS_SRP_SHA_WITH_AES_256_CBC_SHA",            0xc020);
-        add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",        0xc021);
-        add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",        0xc022);
+        add("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",            0xc01a);
+        add("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",        0xc01b);
+        add("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",        0xc01c);
+        add("TLS_SRP_SHA_WITH_AES_128_CBC_SHA",             0xc01d);
+        add("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",         0xc01e);
+        add("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",         0xc01f);
+        add("TLS_SRP_SHA_WITH_AES_256_CBC_SHA",             0xc020);
+        add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",         0xc021);
+        add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",         0xc022);
 
         // Unsupported cipher suites from RFC 5489
-        add("TLS_ECDHE_PSK_WITH_RC4_128_SHA",              0xc033);
-        add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",         0xc034);
-        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",          0xc035);
-        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",          0xc036);
-        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",       0xc037);
-        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",       0xc038);
-        add("TLS_ECDHE_PSK_WITH_NULL_SHA",                 0xc039);
-        add("TLS_ECDHE_PSK_WITH_NULL_SHA256",              0xc03a);
-        add("TLS_ECDHE_PSK_WITH_NULL_SHA384",              0xc03b);
+        add("TLS_ECDHE_PSK_WITH_RC4_128_SHA",               0xc033);
+        add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",          0xc034);
+        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",           0xc035);
+        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",           0xc036);
+        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",        0xc037);
+        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",        0xc038);
+        add("TLS_ECDHE_PSK_WITH_NULL_SHA",                  0xc039);
+        add("TLS_ECDHE_PSK_WITH_NULL_SHA256",               0xc03a);
+        add("TLS_ECDHE_PSK_WITH_NULL_SHA384",               0xc03b);
+
+        // Unsupported cipher suites from RFC 6209
+        add("TLS_RSA_WITH_ARIA_128_CBC_SHA256",             0xc03c);
+        add("TLS_RSA_WITH_ARIA_256_CBC_SHA384",             0xc03d);
+        add("TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256",          0xc03e);
+        add("TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384",          0xc03f);
+        add("TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256",          0xc040);
+        add("TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384",          0xc041);
+        add("TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256",         0xc042);
+        add("TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384",         0xc043);
+        add("TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256",         0xc044);
+        add("TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384",         0xc045);
+        add("TLS_DH_anon_WITH_ARIA_128_CBC_SHA256",         0xc046);
+        add("TLS_DH_anon_WITH_ARIA_256_CBC_SHA384",         0xc047);
+        add("TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256",     0xc048);
+        add("TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384",     0xc049);
+        add("TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256",      0xc04a);
+        add("TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384",      0xc04b);
+        add("TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256",       0xc04c);
+        add("TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384",       0xc04d);
+        add("TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256",        0xc04e);
+        add("TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384",        0xc04f);
+        add("TLS_RSA_WITH_ARIA_128_GCM_SHA256",             0xc050);
+        add("TLS_RSA_WITH_ARIA_256_GCM_SHA384",             0xc051);
+        add("TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256",         0xc052);
+        add("TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384",         0xc053);
+        add("TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256",          0xc054);
+        add("TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384",          0xc055);
+        add("TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256",         0xc056);
+        add("TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384",         0xc057);
+        add("TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256",          0xc058);
+        add("TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384",          0xc059);
+        add("TLS_DH_anon_WITH_ARIA_128_GCM_SHA256",         0xc05a);
+        add("TLS_DH_anon_WITH_ARIA_256_GCM_SHA384",         0xc05b);
+        add("TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256",     0xc05c);
+        add("TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384",     0xc05d);
+        add("TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256",      0xc05e);
+        add("TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384",      0xc05f);
+        add("TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256",       0xc060);
+        add("TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384",       0xc061);
+        add("TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256",        0xc062);
+        add("TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384",        0xc063);
+        add("TLS_PSK_WITH_ARIA_128_CBC_SHA256",             0xc064);
+        add("TLS_PSK_WITH_ARIA_256_CBC_SHA384",             0xc065);
+        add("TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256",         0xc066);
+        add("TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384",         0xc067);
+        add("TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256",         0xc068);
+        add("TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384",         0xc069);
+        add("TLS_PSK_WITH_ARIA_128_GCM_SHA256",             0xc06a);
+        add("TLS_PSK_WITH_ARIA_256_GCM_SHA384",             0xc06b);
+        add("TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256",         0xc06c);
+        add("TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384",         0xc06d);
+        add("TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256",         0xc06e);
+        add("TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384",         0xc06f);
+        add("TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256",       0xc070);
+        add("TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384",       0xc071);
+
+        // Unsupported cipher suites from RFC 6367
+        add("TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 0xc072);
+        add("TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 0xc073);
+        add("TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",  0xc074);
+        add("TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",  0xc075);
+        add("TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",   0xc076);
+        add("TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",   0xc077);
+        add("TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256",    0xc078);
+        add("TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384",    0xc079);
+        add("TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256",         0xc07a);
+        add("TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384",         0xc07b);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",     0xc07c);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",     0xc07d);
+        add("TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256",      0xc07e);
+        add("TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384",      0xc07f);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256",     0xc080);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384",     0xc081);
+        add("TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256",      0xc082);
+        add("TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384",      0xc083);
+        add("TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256",     0xc084);
+        add("TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384",     0xc085);
+        add("TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc086);
+        add("TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc087);
+        add("TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",  0xc088);
+        add("TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",  0xc089);
+        add("TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",   0xc08a);
+        add("TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",   0xc08b);
+        add("TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256",    0xc08c);
+        add("TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384",    0xc08d);
+        add("TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256",         0xc08e);
+        add("TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384",         0xc08f);
+        add("TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256",     0xc090);
+        add("TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384",     0xc091);
+        add("TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256",     0xc092);
+        add("TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384",     0xc093);
+        add("TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256",         0xc094);
+        add("TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384",         0xc095);
+        add("TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",     0xc096);
+        add("TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",     0xc097);
+        add("TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256",     0xc098);
+        add("TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384",     0xc099);
+        add("TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",   0xc09a);
+        add("TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",   0xc09b);
+
+        // Unsupported cipher suites from RFC 6655
+        add("TLS_RSA_WITH_AES_128_CCM",                     0xc09c);
+        add("TLS_RSA_WITH_AES_256_CCM",                     0xc09d);
+        add("TLS_DHE_RSA_WITH_AES_128_CCM",                 0xc09e);
+        add("TLS_DHE_RSA_WITH_AES_256_CCM",                 0xc09f);
+        add("TLS_RSA_WITH_AES_128_CCM_8",                   0xc0A0);
+        add("TLS_RSA_WITH_AES_256_CCM_8",                   0xc0A1);
+        add("TLS_DHE_RSA_WITH_AES_128_CCM_8",               0xc0A2);
+        add("TLS_DHE_RSA_WITH_AES_256_CCM_8",               0xc0A3);
+        add("TLS_PSK_WITH_AES_128_CCM",                     0xc0A4);
+        add("TLS_PSK_WITH_AES_256_CCM",                     0xc0A5);
+        add("TLS_DHE_PSK_WITH_AES_128_CCM",                 0xc0A6);
+        add("TLS_DHE_PSK_WITH_AES_256_CCM",                 0xc0A7);
+        add("TLS_PSK_WITH_AES_128_CCM_8",                   0xc0A8);
+        add("TLS_PSK_WITH_AES_256_CCM_8",                   0xc0A9);
+        add("TLS_PSK_DHE_WITH_AES_128_CCM_8",               0xc0Aa);
+        add("TLS_PSK_DHE_WITH_AES_256_CCM_8",               0xc0Ab);
+
+        // Unsupported cipher suites from RFC 7251
+        add("TLS_ECDHE_ECDSA_WITH_AES_128_CCM",             0xc0Ac);
+        add("TLS_ECDHE_ECDSA_WITH_AES_256_CCM",             0xc0Ad);
+        add("TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",           0xc0Ae);
+        add("TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",           0xc0Af);
     }
 
     // ciphersuite SSL_NULL_WITH_NULL_NULL
--- a/src/share/classes/sun/security/ssl/ClientHandshaker.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -137,6 +137,9 @@
     private final static boolean allowUnsafeServerCertChange =
         Debug.getBooleanProperty("jdk.tls.allowUnsafeServerCertChange", false);
 
+    // Whether an ALPN extension was sent in the ClientHello
+    private boolean alpnActive = false;
+
     private List<SNIServerName> requestedServerNames =
             Collections.<SNIServerName>emptyList();
 
@@ -623,6 +626,44 @@
             }
         }
 
+        // check the ALPN extension
+        ALPNExtension serverHelloALPN =
+            (ALPNExtension) mesg.extensions.get(ExtensionType.EXT_ALPN);
+
+        if (serverHelloALPN != null) {
+            // Check whether an ALPN extension was sent in ClientHello message
+            if (!alpnActive) {
+                fatalSE(Alerts.alert_unsupported_extension,
+                    "Server sent " + ExtensionType.EXT_ALPN +
+                    " extension when not requested by client");
+            }
+
+            List<String> protocols = serverHelloALPN.getPeerAPs();
+            // Only one application protocol name should be present
+            String p;
+            if ((protocols.size() == 1) &&
+                    !((p = protocols.get(0)).isEmpty())) {
+                int i;
+                for (i = 0; i < localApl.length; i++) {
+                    if (localApl[i].equals(p)) {
+                        break;
+                    }
+                }
+                if (i == localApl.length) {
+                    fatalSE(Alerts.alert_handshake_failure,
+                        "Server has selected an application protocol name " +
+                        "which was not offered by the client: " + p);
+                }
+                applicationProtocol = p;
+            } else {
+                fatalSE(Alerts.alert_handshake_failure,
+                    "Incorrect data in ServerHello " + ExtensionType.EXT_ALPN +
+                    " message");
+            }
+        } else {
+            applicationProtocol = "";
+        }
+
         if (resumingSession && session != null) {
             setHandshakeSessionSE(session);
             // Reserve the handshake state if this is a session-resumption
@@ -642,6 +683,7 @@
             } else if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
                     && (type != ExtensionType.EXT_EC_POINT_FORMATS)
                     && (type != ExtensionType.EXT_SERVER_NAME)
+                    && (type != ExtensionType.EXT_ALPN)
                     && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
                 fatalSE(Alerts.alert_unsupported_extension,
                     "Server sent an unsupported extension: " + type);
@@ -1380,6 +1422,12 @@
             }
         }
 
+        // Add ALPN extension
+        if (localApl != null && localApl.length > 0) {
+            clientHelloMessage.addALPNExtension(localApl);
+            alpnActive = true;
+        }
+
         // reset the client random cookie
         clnt_random = clientHelloMessage.clnt_random;
 
--- a/src/share/classes/sun/security/ssl/ExtensionType.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/ExtensionType.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019, 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
@@ -43,7 +43,8 @@
         return name;
     }
 
-    static List<ExtensionType> knownExtensions = new ArrayList<ExtensionType>(9);
+    static List<ExtensionType> knownExtensions =
+            new ArrayList<ExtensionType>(14);
 
     static ExtensionType get(int id) {
         for (ExtensionType ext : knownExtensions) {
@@ -96,6 +97,11 @@
     final static ExtensionType EXT_SIGNATURE_ALGORITHMS =
             e(0x000D, "signature_algorithms");   // IANA registry value: 13
 
+    // extension defined in RFC 7301 (ALPN)
+    static final ExtensionType EXT_ALPN =
+            e(0x0010, "application_layer_protocol_negotiation");
+                                                 // IANA registry value: 16
+
     // extensions defined in RFC 5746
     final static ExtensionType EXT_RENEGOTIATION_INFO =
             e(0xff01, "renegotiation_info");     // IANA registry value: 65281
--- a/src/share/classes/sun/security/ssl/HandshakeMessage.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/HandshakeMessage.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -278,6 +278,11 @@
         extensions.add(signatureAlgorithm);
     }
 
+    // add application_layer_protocol_negotiation extension
+    void addALPNExtension(String[] applicationProtocols) throws SSLException {
+        extensions.add(new ALPNExtension(applicationProtocols));
+    }
+
     @Override
     int messageType() { return ht_client_hello; }
 
--- a/src/share/classes/sun/security/ssl/Handshaker.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/Handshaker.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -28,6 +28,7 @@
 
 import java.io.*;
 import java.util.*;
+import java.util.function.BiFunction;
 import java.security.*;
 import java.security.NoSuchAlgorithmException;
 import java.security.AccessController;
@@ -115,6 +116,20 @@
     List<SNIServerName> serverNames = Collections.<SNIServerName>emptyList();
     Collection<SNIMatcher> sniMatchers = Collections.<SNIMatcher>emptyList();
 
+    // List of local ApplicationProtocols
+    String[] localApl = null;
+
+    // Negotiated ALPN value
+    String applicationProtocol = null;
+
+    // Application protocol callback function (for SSLEngine)
+    BiFunction<SSLEngine,List<String>,String>
+        appProtocolSelectorSSLEngine = null;
+
+    // Application protocol callback function (for SSLSocket)
+    BiFunction<SSLSocket,List<String>,String>
+        appProtocolSelectorSSLSocket = null;
+
     private boolean isClient;
     private boolean needCertVerify;
 
@@ -129,6 +144,10 @@
     RandomCookie clnt_random, svr_random;
     SSLSessionImpl session;
 
+    // Since this is for a Reference Implementation, only backporting a bit of
+    // the state machine improvement JDK-8074462.
+    boolean clientHelloDelivered;
+
     // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
     CipherSuite cipherSuite;
 
@@ -254,6 +273,7 @@
         enableNewSession = true;
         invalidated = false;
         sessKeysCalculated = false;
+        clientHelloDelivered = false;
 
         setCipherSuite(CipherSuite.C_NULL);
         setEnabledProtocols(enabledProtocols);
@@ -483,6 +503,36 @@
     }
 
     /**
+     * Sets the Application Protocol list.
+     */
+    void setApplicationProtocols(String[] apl) {
+        this.localApl = apl;
+    }
+
+    /**
+     * Gets the "negotiated" ALPN value.
+     */
+    String getHandshakeApplicationProtocol() {
+        return applicationProtocol;
+    }
+
+    /**
+     * Sets the Application Protocol selector function for SSLEngine.
+     */
+    void setApplicationProtocolSelectorSSLEngine(
+        BiFunction<SSLEngine,List<String>,String> selector) {
+        this.appProtocolSelectorSSLEngine = selector;
+    }
+
+    /**
+     * Sets the Application Protocol selector function for SSLSocket.
+     */
+    void setApplicationProtocolSelectorSSLSocket(
+        BiFunction<SSLSocket,List<String>,String> selector) {
+        this.appProtocolSelectorSSLSocket = selector;
+    }
+
+    /**
      * Sets the cipher suites preference.
      */
     void setUseCipherSuitesOrder(boolean on) {
@@ -945,6 +995,11 @@
                 return;
             }
 
+            // Set the flags in the message receiving side.
+            if (messageType == HandshakeMessage.ht_client_hello) {
+                clientHelloDelivered = true;
+            }
+
             /*
              * Process the message.  We require
              * that processMessage() consumes the entire message.  In
@@ -986,7 +1041,8 @@
      * Returns true iff the handshaker has sent any messages.
      */
     boolean started() {
-        return state >= 0;  // 0: HandshakeMessage.ht_hello_request
+        return (clientHelloDelivered ||
+            (state >= 0));  // 0: HandshakeMessage.ht_hello_request
                             // 1: HandshakeMessage.ht_client_hello
     }
 
--- a/src/share/classes/sun/security/ssl/HelloExtensions.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/HelloExtensions.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019, 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
@@ -33,8 +33,8 @@
 /**
  * This file contains all the classes relevant to TLS Extensions for the
  * ClientHello and ServerHello messages. The extension mechanism and
- * several extensions are defined in RFC 3546. Additional extensions are
- * defined in the ECC RFC 4492.
+ * several extensions are defined in RFC 6066. Additional extensions are
+ * defined in the ECC RFC 4492 and the ALPN extension is defined in RFC 7301.
  *
  * Currently, only the two ECC extensions are fully supported.
  *
@@ -52,6 +52,7 @@
  *  . SupportedEllipticCurvesExtension: the ECC supported curves extension.
  *  . SupportedEllipticPointFormatsExtension: the ECC supported point formats
  *      (compressed/uncompressed) extension.
+ *  . ALPNExtension: the application_layer_protocol_negotiation extension.
  *
  * @since   1.6
  * @author  Andreas Sterbenz
@@ -85,6 +86,8 @@
                         new SupportedEllipticPointFormatsExtension(s, extlen);
             } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
                 extension = new RenegotiationInfoExtension(s, extlen);
+            } else if (extType == ExtensionType.EXT_ALPN) {
+                extension = new ALPNExtension(s, extlen);
             } else {
                 extension = new UnknownExtension(s, extlen, extType);
             }
--- a/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -29,6 +29,7 @@
 import java.nio.*;
 import java.util.*;
 import java.security.*;
+import java.util.function.BiFunction;
 
 import javax.crypto.BadPaddingException;
 
@@ -264,6 +265,19 @@
     Collection<SNIMatcher>      sniMatchers =
                                     Collections.<SNIMatcher>emptyList();
 
+    // Configured application protocol values
+    String[] applicationProtocols = new String[0];
+
+    // Negotiated application protocol value.
+    //
+    // The value under negotiation will be obtained from handshaker.
+    String applicationProtocol = null;
+
+
+    // Callback function that selects the application protocol value during
+    // the SSL/TLS handshake.
+    BiFunction<SSLEngine, List<String>, String> applicationProtocolSelector;
+
     // Have we been told whether we're client or server?
     private boolean                     serverModeSet = false;
     private boolean                     roleIsServer;
@@ -492,6 +506,9 @@
         }
         handshaker.setEnabledCipherSuites(enabledCipherSuites);
         handshaker.setEnableSessionCreation(enableSessionCreation);
+        handshaker.setApplicationProtocols(applicationProtocols);
+        handshaker.setApplicationProtocolSelectorSSLEngine(
+            applicationProtocolSelector);
     }
 
     /*
@@ -1038,6 +1055,9 @@
                                         handshaker.isSecureRenegotiation();
                         clientVerifyData = handshaker.getClientVerifyData();
                         serverVerifyData = handshaker.getServerVerifyData();
+                        // set connection ALPN value
+                        applicationProtocol =
+                            handshaker.getHandshakeApplicationProtocol();
 
                         sess = handshaker.getSession();
                         handshakeSession = null;
@@ -2102,6 +2122,7 @@
         params.setSNIMatchers(sniMatchers);
         params.setServerNames(serverNames);
         params.setUseCipherSuitesOrder(preferLocalCipherSuites);
+        params.setApplicationProtocols(applicationProtocols);
 
         return params;
     }
@@ -2127,10 +2148,12 @@
         if (matchers != null) {
             sniMatchers = matchers;
         }
+        applicationProtocols = params.getApplicationProtocols();
 
         if ((handshaker != null) && !handshaker.started()) {
             handshaker.setIdentificationProtocol(identificationProtocol);
             handshaker.setAlgorithmConstraints(algorithmConstraints);
+            applicationProtocols = params.getApplicationProtocols();
             if (roleIsServer) {
                 handshaker.setSNIMatchers(sniMatchers);
                 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
@@ -2148,6 +2171,34 @@
         return receivedCCS;
     }
 
+    @Override
+    public synchronized String getApplicationProtocol() {
+        return applicationProtocol;
+    }
+
+    @Override
+    public synchronized String getHandshakeApplicationProtocol() {
+         if ((handshaker != null) && handshaker.started()) {
+            return handshaker.getHandshakeApplicationProtocol();
+        }
+        return null;
+    }
+
+    @Override
+    public synchronized void setHandshakeApplicationProtocolSelector(
+        BiFunction<SSLEngine, List<String>, String> selector) {
+        applicationProtocolSelector = selector;
+        if ((handshaker != null) && !handshaker.activated()) {
+            handshaker.setApplicationProtocolSelectorSSLEngine(selector);
+        }
+    }
+
+    @Override
+    public synchronized BiFunction<SSLEngine, List<String>, String>
+        getHandshakeApplicationProtocolSelector() {
+        return this.applicationProtocolSelector;
+    }
+
     /**
      * Returns a printable representation of this end of the connection.
      */
--- a/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -92,6 +92,9 @@
     Collection<SNIMatcher>      sniMatchers =
                                     Collections.<SNIMatcher>emptyList();
 
+    // Configured application protocol values
+    String[] applicationProtocols = new String[0];
+
     /*
      * Whether local cipher suites preference in server side should be
      * honored during handshaking?
@@ -311,7 +314,7 @@
         params.setAlgorithmConstraints(algorithmConstraints);
         params.setSNIMatchers(sniMatchers);
         params.setUseCipherSuitesOrder(preferLocalCipherSuites);
-
+        params.setApplicationProtocols(applicationProtocols);
 
         return params;
     }
@@ -331,6 +334,7 @@
         if (matchers != null) {
             sniMatchers = params.getSNIMatchers();
         }
+        applicationProtocols = params.getApplicationProtocols();
     }
 
     /**
@@ -343,7 +347,7 @@
         SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
             enabledCipherSuites, doClientAuth, enableSessionCreation,
             enabledProtocols, identificationProtocol, algorithmConstraints,
-            sniMatchers, preferLocalCipherSuites);
+            sniMatchers, preferLocalCipherSuites, applicationProtocols);
 
         implAccept(s);
         s.doneConnect();
--- a/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -36,6 +36,7 @@
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BiFunction;
 
 import javax.crypto.BadPaddingException;
 import javax.net.ssl.*;
@@ -218,6 +219,18 @@
     Collection<SNIMatcher>      sniMatchers =
                                     Collections.<SNIMatcher>emptyList();
 
+    // Configured application protocol values
+    String[] applicationProtocols = new String[0];
+
+    // Negotiated application protocol value.
+    //
+    // The value under negotiation will be obtained from handshaker.
+    String applicationProtocol = null;
+
+    // Callback function that selects the application protocol value during
+    // the SSL/TLS handshake.
+    BiFunction<SSLSocket, List<String>, String> applicationProtocolSelector;
+
     /*
      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
      * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
@@ -495,7 +508,8 @@
             String identificationProtocol,
             AlgorithmConstraints algorithmConstraints,
             Collection<SNIMatcher> sniMatchers,
-            boolean preferLocalCipherSuites) throws IOException {
+            boolean preferLocalCipherSuites,
+            String[] applicationProtocols) throws IOException {
 
         super();
         doClientAuth = clientAuth;
@@ -504,6 +518,7 @@
         this.algorithmConstraints = algorithmConstraints;
         this.sniMatchers = sniMatchers;
         this.preferLocalCipherSuites = preferLocalCipherSuites;
+        this.applicationProtocols = applicationProtocols;
         init(context, serverMode);
 
         /*
@@ -1063,6 +1078,9 @@
                                         handshaker.isSecureRenegotiation();
                         clientVerifyData = handshaker.getClientVerifyData();
                         serverVerifyData = handshaker.getServerVerifyData();
+                        // set connection ALPN value
+                        applicationProtocol =
+                            handshaker.getHandshakeApplicationProtocol();
 
                         sess = handshaker.getSession();
                         handshakeSession = null;
@@ -1322,6 +1340,9 @@
         }
         handshaker.setEnabledCipherSuites(enabledCipherSuites);
         handshaker.setEnableSessionCreation(enableSessionCreation);
+        handshaker.setApplicationProtocols(applicationProtocols);
+        handshaker.setApplicationProtocolSelectorSSLSocket(
+            applicationProtocolSelector);
     }
 
     /**
@@ -2532,6 +2553,7 @@
         params.setSNIMatchers(sniMatchers);
         params.setServerNames(serverNames);
         params.setUseCipherSuitesOrder(preferLocalCipherSuites);
+        params.setApplicationProtocols(applicationProtocols);
 
         return params;
     }
@@ -2558,9 +2580,12 @@
             sniMatchers = matchers;
         }
 
+        applicationProtocols = params.getApplicationProtocols();
+
         if ((handshaker != null) && !handshaker.started()) {
             handshaker.setIdentificationProtocol(identificationProtocol);
             handshaker.setAlgorithmConstraints(algorithmConstraints);
+            handshaker.setApplicationProtocols(applicationProtocols);
             if (roleIsServer) {
                 handshaker.setSNIMatchers(sniMatchers);
                 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
@@ -2578,6 +2603,34 @@
         return receivedCCS;
     }
 
+    @Override
+    public synchronized String getApplicationProtocol() {
+        return applicationProtocol;
+    }
+
+    @Override
+    public synchronized String getHandshakeApplicationProtocol() {
+         if ((handshaker != null) && handshaker.started()) {
+            return handshaker.getHandshakeApplicationProtocol();
+        }
+        return null;
+    }
+
+    @Override
+    public synchronized void setHandshakeApplicationProtocolSelector(
+        BiFunction<SSLSocket, List<String>, String> selector) {
+        applicationProtocolSelector = selector;
+        if ((handshaker != null) && !handshaker.activated()) {
+            handshaker.setApplicationProtocolSelectorSSLSocket(selector);
+        }
+    }
+
+    @Override
+    public synchronized BiFunction<SSLSocket, List<String>, String>
+        getHandshakeApplicationProtocolSelector() {
+        return this.applicationProtocolSelector;
+    }
+
     //
     // We allocate a separate thread to deliver handshake completion
     // events.  This ensures that the notifications don't block the
--- a/src/share/classes/sun/security/ssl/ServerHandshaker.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 import java.security.cert.*;
 import java.security.interfaces.*;
 import java.security.spec.ECParameterSpec;
+import java.util.function.BiFunction;
 
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
@@ -480,6 +481,44 @@
             }
         }
 
+        // check the ALPN extension
+        ALPNExtension clientHelloALPN = (ALPNExtension)
+            mesg.extensions.get(ExtensionType.EXT_ALPN);
+
+        // Use the application protocol callback when provided.
+        // Otherwise use the local list of application protocols.
+        boolean hasAPCallback =
+            ((engine != null && appProtocolSelectorSSLEngine != null) ||
+                (conn != null && appProtocolSelectorSSLSocket != null));
+
+        if (!hasAPCallback) {
+            if ((clientHelloALPN != null) && (localApl.length > 0)) {
+
+                // Intersect the requested and the locally supported,
+                // and save for later.
+                String negotiatedValue = null;
+                List<String> protocols = clientHelloALPN.getPeerAPs();
+
+                // Use server preference order
+                for (String ap : localApl) {
+                    if (protocols.contains(ap)) {
+                        negotiatedValue = ap;
+                        break;
+                    }
+                }
+
+                if (negotiatedValue == null) {
+                    fatalSE(Alerts.alert_no_application_protocol,
+                        new SSLHandshakeException(
+                            "No matching ALPN values"));
+                }
+                applicationProtocol = negotiatedValue;
+
+            } else {
+                applicationProtocol = "";
+            }
+        }  // Otherwise, applicationProtocol will be set by the callback.
+
         /*
          * Always make sure this entire record has been digested before we
          * start emitting output, to ensure correct digesting order.
@@ -771,6 +810,39 @@
             }
         }
 
+        // Prepare the ALPN response
+        if (clientHelloALPN != null) {
+            List<String> peerAPs = clientHelloALPN.getPeerAPs();
+
+            // check for a callback function
+            if (hasAPCallback) {
+                if (conn != null) {
+                    applicationProtocol =
+                        appProtocolSelectorSSLSocket.apply(conn, peerAPs);
+                } else {
+                    applicationProtocol =
+                        appProtocolSelectorSSLEngine.apply(engine, peerAPs);
+                }
+            }
+
+            // check for no-match and that the selected name was also proposed
+            // by the TLS peer
+            if (applicationProtocol == null ||
+                   (!applicationProtocol.isEmpty() &&
+                        !peerAPs.contains(applicationProtocol))) {
+
+                fatalSE(Alerts.alert_no_application_protocol,
+                    new SSLHandshakeException(
+                        "No matching ALPN values"));
+
+            } else if (!applicationProtocol.isEmpty()) {
+                m1.extensions.add(new ALPNExtension(applicationProtocol));
+            }
+        } else {
+            // Nothing was negotiated, returned at end of the handshake
+            applicationProtocol = "";
+        }
+
         if (debug != null && Debug.isOn("handshake")) {
             m1.print(System.out);
             System.out.println("Cipher suite:  " + session.getSuite());
--- a/test/Makefile	Fri Nov 15 15:06:48 2019 +0000
+++ b/test/Makefile	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2019, 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
@@ -262,8 +262,8 @@
   EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY)
 endif
 
-# Default JTREG to run (win32 script works for everybody)
-JTREG = $(JT_HOME)/win32/bin/jtreg
+# Default JTREG to run
+JTREG = $(JT_HOME)/bin/jtreg
 # run in agentvm mode
 JTREG_BASIC_OPTIONS += -agentvm
 # Only run automatic tests
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/ssl/javax/net/ssl/ALPN/MyX509ExtendedKeyManager.java	Fri Nov 22 10:47:01 2019 -0800
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.X509ExtendedKeyManager;
+
+public class MyX509ExtendedKeyManager extends X509ExtendedKeyManager {
+
+    static final String ERROR = "ERROR";
+    X509ExtendedKeyManager akm;
+    String expectedAP;
+    boolean doCheck = true;
+
+    MyX509ExtendedKeyManager(X509ExtendedKeyManager akm) {
+        this.akm = akm;
+    }
+
+    public MyX509ExtendedKeyManager(
+            X509ExtendedKeyManager akm, String expectedAP, boolean doCheck) {
+        this.akm = akm;
+        this.expectedAP = expectedAP;
+        this.doCheck = doCheck;
+
+    }
+
+    @Override
+    public String[] getClientAliases(String keyType, Principal[] issuers) {
+        return akm.getClientAliases(keyType, issuers);
+    }
+
+    @Override
+    public String chooseClientAlias(String[] keyType, Principal[] issuers,
+            Socket socket) {
+        String nap = ((SSLSocket) socket).getHandshakeApplicationProtocol();
+        checkALPN(nap);
+
+        return akm.chooseClientAlias(keyType, issuers, socket);
+    }
+
+    @Override
+    public String[] getServerAliases(String keyType, Principal[] issuers) {
+        return akm.getServerAliases(keyType, issuers);
+    }
+
+    @Override
+    public String chooseServerAlias(String keyType, Principal[] issuers,
+            Socket socket) {
+        String nap = ((SSLSocket) socket).getHandshakeApplicationProtocol();
+        checkALPN(nap);
+
+        return akm.chooseServerAlias(keyType, issuers, socket);
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain(String alias) {
+        return akm.getCertificateChain(alias);
+    }
+
+    @Override
+    public PrivateKey getPrivateKey(String alias) {
+        return akm.getPrivateKey(alias);
+    }
+
+    @Override
+    public String chooseEngineClientAlias(String[] keyType, Principal[] issuers,
+            SSLEngine engine) {
+        String nap = engine.getHandshakeApplicationProtocol();
+        checkALPN(nap);
+
+        return akm.chooseEngineClientAlias(keyType, issuers, engine);
+    }
+
+    @Override
+    public String chooseEngineServerAlias(String keyType, Principal[] issuers,
+            SSLEngine engine) {
+        String nap = engine.getHandshakeApplicationProtocol();
+        checkALPN(nap);
+
+        return akm.chooseEngineServerAlias(keyType, issuers, engine);
+    }
+
+    private void checkALPN(String ap) {
+
+        if (!doCheck) {
+            System.out.println("Skipping KeyManager checks " +
+                "because a callback has been registered");
+            return;
+        }
+
+        if (ERROR.equals(expectedAP)) {
+            throw new RuntimeException("Should not reach here");
+        }
+
+        System.out.println("Expected ALPN value: " + expectedAP
+                + " Got: " + ap);
+
+        if (ap == null) {
+            throw new RuntimeException(
+                    "ALPN should be negotiated, but null was received");
+        }
+        if (expectedAP.equals("NONE")) {
+            if (!ap.isEmpty()) {
+                throw new RuntimeException("Expected no ALPN value");
+            } else {
+                System.out.println("No ALPN value negotiated, as expected");
+            }
+        } else if (!expectedAP.equals(ap)) {
+            throw new RuntimeException(expectedAP
+                    + " ALPN value not available on negotiated connection");
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/ssl/javax/net/ssl/ALPN/SSLEngineAlpnTest.java	Fri Nov 22 10:47:01 2019 -0800
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8051498 8145849 8170282
+ * @summary JEP 244: TLS Application-Layer Protocol Negotiation Extension
+ * @compile MyX509ExtendedKeyManager.java
+ *
+ * @run main/othervm SSLEngineAlpnTest h2          UNUSED   h2          h2
+ * @run main/othervm SSLEngineAlpnTest h2          UNUSED   h2,http/1.1 h2
+ * @run main/othervm SSLEngineAlpnTest h2,http/1.1 UNUSED   h2,http/1.1 h2
+ * @run main/othervm SSLEngineAlpnTest http/1.1,h2 UNUSED   h2,http/1.1 http/1.1
+ * @run main/othervm SSLEngineAlpnTest h4,h3,h2    UNUSED   h1,h2       h2
+ * @run main/othervm SSLEngineAlpnTest EMPTY       UNUSED   h2,http/1.1 NONE
+ * @run main/othervm SSLEngineAlpnTest h2          UNUSED   EMPTY       NONE
+ * @run main/othervm SSLEngineAlpnTest H2          UNUSED   h2          ERROR
+ * @run main/othervm SSLEngineAlpnTest h2          UNUSED   http/1.1    ERROR
+ *
+ * @run main/othervm SSLEngineAlpnTest UNUSED      h2       h2          h2
+ * @run main/othervm SSLEngineAlpnTest UNUSED      h2       h2,http/1.1 h2
+ * @run main/othervm SSLEngineAlpnTest UNUSED      h2       http/1.1,h2 h2
+ * @run main/othervm SSLEngineAlpnTest UNUSED      http/1.1 h2,http/1.1 http/1.1
+ * @run main/othervm SSLEngineAlpnTest UNUSED      EMPTY    h2,http/1.1 NONE
+ * @run main/othervm SSLEngineAlpnTest UNUSED      h2       EMPTY       NONE
+ * @run main/othervm SSLEngineAlpnTest UNUSED      H2       h2          ERROR
+ * @run main/othervm SSLEngineAlpnTest UNUSED      h2       http/1.1    ERROR
+ *
+ * @run main/othervm SSLEngineAlpnTest h2          h2       h2          h2
+ * @run main/othervm SSLEngineAlpnTest H2          h2       h2,http/1.1 h2
+ * @run main/othervm SSLEngineAlpnTest h2,http/1.1 http/1.1 h2,http/1.1 http/1.1
+ * @run main/othervm SSLEngineAlpnTest http/1.1,h2 h2       h2,http/1.1 h2
+ * @run main/othervm SSLEngineAlpnTest EMPTY       h2       h2          h2
+ * @run main/othervm SSLEngineAlpnTest h2,http/1.1 EMPTY    http/1.1    NONE
+ * @run main/othervm SSLEngineAlpnTest h2,http/1.1 h2       EMPTY       NONE
+ * @run main/othervm SSLEngineAlpnTest UNUSED      UNUSED   http/1.1,h2 NONE
+ * @run main/othervm SSLEngineAlpnTest h2          h2       http/1.1    ERROR
+ * @run main/othervm SSLEngineAlpnTest h2,http/1.1 H2       http/1.1    ERROR
+ */
+/**
+ * A simple SSLEngine-based client/server that demonstrates the proposed API
+ * changes for JEP 244 in support of the TLS ALPN extension (RFC 7301).
+ *
+ * Usage:
+ *     java SSLEngineAlpnTest <server-APs> <callback-AP> <client-APs> <result>
+ *
+ * where:
+ *      EMPTY  indicates that ALPN is disabled
+ *      UNUSED indicates that no ALPN values are supplied (server-side only)
+ *      ERROR  indicates that an exception is expected
+ *      NONE   indicates that no ALPN is expected
+ *
+ * This example is based on our standard SSLEngineTemplate.
+ *
+ * The immediate consumer of ALPN will be HTTP/2 (RFC 7540), aka H2. The H2 IETF
+ * Working Group wanted to use TLSv1.3+ as the secure transport mechanism, but
+ * TLSv1.3 wasn't ready. The H2 folk agreed to a compromise that only TLSv1.2+
+ * can be used, and that if TLSv1.2 was selected, non-TLSv.1.3-approved
+ * ciphersuites would be blacklisted and their use discouraged.
+ *
+ * In order to support connections that might negotiate either HTTP/1.1 and H2,
+ * the guidance from the IETF Working Group is that the H2 ciphersuites be
+ * prioritized/tried first.
+ */
+
+/*
+ * The original SSLEngineTemplate comments follow.
+ *
+ * A SSLEngine usage example which simplifies the presentation
+ * by removing the I/O and multi-threading concerns.
+ *
+ * The test creates two SSLEngines, simulating a client and server.
+ * The "transport" layer consists two byte buffers:  think of them
+ * as directly connected pipes.
+ *
+ * Note, this is a *very* simple example: real code will be much more
+ * involved.  For example, different threading and I/O models could be
+ * used, transport mechanisms could close unexpectedly, and so on.
+ *
+ * When this application runs, notice that several messages
+ * (wrap/unwrap) pass before any application data is consumed or
+ * produced.  (For more information, please see the SSL/TLS
+ * specifications.)  There may several steps for a successful handshake,
+ * so it's typical to see the following series of operations:
+ *
+ *      client          server          message
+ *      ======          ======          =======
+ *      wrap()          ...             ClientHello
+ *      ...             unwrap()        ClientHello
+ *      ...             wrap()          ServerHello/Certificate
+ *      unwrap()        ...             ServerHello/Certificate
+ *      wrap()          ...             ClientKeyExchange
+ *      wrap()          ...             ChangeCipherSpec
+ *      wrap()          ...             Finished
+ *      ...             unwrap()        ClientKeyExchange
+ *      ...             unwrap()        ChangeCipherSpec
+ *      ...             unwrap()        Finished
+ *      ...             wrap()          ChangeCipherSpec
+ *      ...             wrap()          Finished
+ *      unwrap()        ...             ChangeCipherSpec
+ *      unwrap()        ...             Finished
+ */
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.io.*;
+import java.security.*;
+import java.nio.*;
+import java.util.Arrays;
+
+public class SSLEngineAlpnTest {
+
+    /*
+     * Enables logging of the SSLEngine operations.
+     */
+    private static final boolean logging = true;
+
+    /*
+     * Enables the JSSE system debugging system property:
+     *
+     *     -Djavax.net.debug=all
+     *
+     * This gives a lot of low-level information about operations underway,
+     * including specific handshake messages, and might be best examined
+     * after gaining some familiarity with this application.
+     */
+    private static final boolean debug = false;
+
+    private static boolean hasServerAPs; // whether server APs are present
+    private static boolean hasCallback; // whether a callback is present
+
+    private final SSLContext sslc;
+
+    private SSLEngine clientEngine;     // client Engine
+    private ByteBuffer clientOut;       // write side of clientEngine
+    private ByteBuffer clientIn;        // read side of clientEngine
+
+    private SSLEngine serverEngine;     // server Engine
+    private ByteBuffer serverOut;       // write side of serverEngine
+    private ByteBuffer serverIn;        // read side of serverEngine
+
+    /*
+     * For data transport, this example uses local ByteBuffers.  This
+     * isn't really useful, but the purpose of this example is to show
+     * SSLEngine concepts, not how to do network transport.
+     */
+    private ByteBuffer cTOs;            // "reliable" transport client->server
+    private ByteBuffer sTOc;            // "reliable" transport server->client
+
+    /*
+     * The following is to set up the keystores.
+     */
+    private static final String pathToStores = "../../../../etc";
+    private static final String keyStoreFile = "keystore";
+    private static final String trustStoreFile = "truststore";
+    private static final String passwd = "passphrase";
+
+    private static final String keyFilename
+            = System.getProperty("test.src", ".") + "/" + pathToStores
+            + "/" + keyStoreFile;
+    private static final String trustFilename
+            = System.getProperty("test.src", ".") + "/" + pathToStores
+            + "/" + trustStoreFile;
+
+    /*
+     * Main entry point for this test.
+     */
+    public static void main(String args[]) throws Exception {
+        if (debug) {
+            System.setProperty("javax.net.debug", "all");
+        }
+        System.out.println("Test args: " + Arrays.toString(args));
+
+        // Validate parameters
+        if (args.length != 4) {
+            throw new Exception("Invalid number of test parameters");
+        }
+
+        hasServerAPs = !args[0].equals("UNUSED"); // are server APs being used?
+        hasCallback = !args[1].equals("UNUSED"); // is callback being used?
+
+        SSLEngineAlpnTest test = new SSLEngineAlpnTest(args[3]);
+        try {
+            test.runTest(convert(args[0]), args[1], convert(args[2]), args[3]);
+        } catch (SSLHandshakeException she) {
+            if (args[3].equals("ERROR")) {
+                System.out.println("Caught the expected exception: " + she);
+            } else {
+                throw she;
+            }
+        }
+
+        System.out.println("Test Passed.");
+    }
+
+    /*
+     * Create an initialized SSLContext to use for these tests.
+     */
+    public SSLEngineAlpnTest(String expectedAP) throws Exception {
+
+        KeyStore ks = KeyStore.getInstance("JKS");
+        KeyStore ts = KeyStore.getInstance("JKS");
+
+        char[] passphrase = "passphrase".toCharArray();
+
+        ks.load(new FileInputStream(keyFilename), passphrase);
+        ts.load(new FileInputStream(trustFilename), passphrase);
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        kmf.init(ks, passphrase);
+
+        KeyManager [] kms = kmf.getKeyManagers();
+        if (!(kms[0] instanceof X509ExtendedKeyManager)) {
+            throw new Exception("kms[0] not X509ExtendedKeyManager");
+        }
+
+        kms = new KeyManager[] { new MyX509ExtendedKeyManager(
+                (X509ExtendedKeyManager) kms[0], expectedAP,
+                !hasCallback && hasServerAPs) };
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        tmf.init(ts);
+
+        SSLContext sslCtx = SSLContext.getInstance("TLS");
+
+        sslCtx.init(kms, tmf.getTrustManagers(), null);
+
+        sslc = sslCtx;
+    }
+
+    /*
+     * Convert a comma-separated list into an array of strings.
+     */
+    private static String[] convert(String list) {
+        if (list.equals("UNUSED")) {
+            return null;
+        }
+
+        if (list.equals("EMPTY")) {
+            return new String[0];
+        }
+
+        String[] strings;
+        if (list.indexOf(',') > 0) {
+            strings = list.split(",");
+        } else {
+            strings = new String[]{ list };
+        }
+
+        return strings;
+    }
+
+    /*
+     * Run the test.
+     *
+     * Sit in a tight loop, both engines calling wrap/unwrap regardless
+     * of whether data is available or not.  We do this until both engines
+     * report back they are closed.
+     *
+     * The main loop handles all of the I/O phases of the SSLEngine's
+     * lifetime:
+     *
+     *     initial handshaking
+     *     application data transfer
+     *     engine closing
+     *
+     * One could easily separate these phases into separate
+     * sections of code.
+     */
+    private void runTest(String[] serverAPs, String callbackAP,
+            String[] clientAPs, String expectedAP) throws Exception {
+
+        boolean dataDone = false;
+
+        createSSLEngines(serverAPs, callbackAP, clientAPs);
+        createBuffers();
+
+        SSLEngineResult clientResult;   // results from client's last operation
+        SSLEngineResult serverResult;   // results from server's last operation
+
+        /*
+         * Examining the SSLEngineResults could be much more involved,
+         * and may alter the overall flow of the application.
+         *
+         * For example, if we received a BUFFER_OVERFLOW when trying
+         * to write to the output pipe, we could reallocate a larger
+         * pipe, but instead we wait for the peer to drain it.
+         */
+        while (!isEngineClosed(clientEngine)
+                || !isEngineClosed(serverEngine)) {
+
+            log("================");
+
+            clientResult = clientEngine.wrap(clientOut, cTOs);
+            log("client wrap: ", clientResult);
+            runDelegatedTasks(clientResult, clientEngine);
+            checkAPResult(clientEngine, clientResult, expectedAP);
+
+            serverResult = serverEngine.wrap(serverOut, sTOc);
+            log("server wrap: ", serverResult);
+            runDelegatedTasks(serverResult, serverEngine);
+            checkAPResult(serverEngine, serverResult, expectedAP);
+
+            cTOs.flip();
+            sTOc.flip();
+
+            log("----");
+
+            clientResult = clientEngine.unwrap(sTOc, clientIn);
+            log("client unwrap: ", clientResult);
+            runDelegatedTasks(clientResult, clientEngine);
+            checkAPResult(clientEngine, clientResult, expectedAP);
+
+            serverResult = serverEngine.unwrap(cTOs, serverIn);
+            log("server unwrap: ", serverResult);
+            runDelegatedTasks(serverResult, serverEngine);
+            checkAPResult(serverEngine, serverResult, expectedAP);
+
+            cTOs.compact();
+            sTOc.compact();
+
+            /*
+             * After we've transfered all application data between the client
+             * and server, we close the clientEngine's outbound stream.
+             * This generates a close_notify handshake message, which the
+             * server engine receives and responds by closing itself.
+             */
+            if (!dataDone && (clientOut.limit() == serverIn.position())
+                    && (serverOut.limit() == clientIn.position())) {
+
+                /*
+                 * A sanity check to ensure we got what was sent.
+                 */
+                checkTransfer(serverOut, clientIn);
+                checkTransfer(clientOut, serverIn);
+
+                log("\tClosing clientEngine's *OUTBOUND*...");
+                clientEngine.closeOutbound();
+                dataDone = true;
+            }
+        }
+    }
+
+    /*
+     * Check that the resulting connection meets our defined ALPN
+     * criteria.  If we were connecting to a non-JSSE implementation,
+     * the server might have negotiated something we shouldn't accept.
+     *
+     * If we were expecting an ALPN value from server, let's make sure
+     * the conditions match.
+     */
+    private static void checkAPResult(SSLEngine engine, SSLEngineResult result,
+            String expectedAP) throws Exception {
+
+        if (result.getHandshakeStatus() != HandshakeStatus.FINISHED) {
+            return;
+        }
+
+        if (engine.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null after the handshake is completed");
+        }
+
+        String ap = engine.getApplicationProtocol();
+        System.out.println("Application Protocol: \"" + ap + "\"");
+
+        if (ap == null) {
+            throw new Exception(
+                "Handshake was completed but null was received");
+        }
+        if (expectedAP.equals("NONE")) {
+            if (!ap.isEmpty()) {
+                throw new Exception("Expected no ALPN value");
+            } else {
+                System.out.println("No ALPN value negotiated, as expected");
+            }
+        } else if (!expectedAP.equals(ap)) {
+            throw new Exception(expectedAP +
+                " ALPN value not available on negotiated connection");
+        }
+    }
+
+    /*
+     * Using the SSLContext created during object creation,
+     * create/configure the SSLEngines we'll use for this test.
+     */
+    private void createSSLEngines(String[] serverAPs, String callbackAP,
+            String[] clientAPs) throws Exception {
+        /*
+         * Configure the serverEngine to act as a server in the SSL/TLS
+         * handshake.  Also, require SSL client authentication.
+         */
+        serverEngine = sslc.createSSLEngine();
+        serverEngine.setUseClientMode(false);
+
+        SSLParameters sslp = serverEngine.getSSLParameters();
+
+        sslp.setNeedClientAuth(true);
+
+        /*
+         * The default ciphersuite ordering from the SSLContext may not
+         * reflect "h2" ciphersuites as being preferred, additionally the
+         * client may not send them in an appropriate order. We could resort
+         * the suite list if so desired.
+         */
+        String[] suites = sslp.getCipherSuites();
+        sslp.setCipherSuites(suites);
+        if (serverAPs != null) {
+            sslp.setApplicationProtocols(serverAPs);
+        }
+        sslp.setUseCipherSuitesOrder(true);  // Set server side order
+
+        serverEngine.setSSLParameters(sslp);
+
+        // check that no callback has been registered
+        if (serverEngine.getHandshakeApplicationProtocolSelector() != null) {
+            throw new Exception("getHandshakeApplicationProtocolSelector() " +
+                "should return null");
+        }
+
+        if (hasCallback) {
+            serverEngine.setHandshakeApplicationProtocolSelector(
+                (sslEngine, clientProtocols) -> {
+                    return callbackAP.equals("EMPTY") ? "" : callbackAP;
+                });
+
+            // check that the callback can be retrieved
+            if (serverEngine.getHandshakeApplicationProtocolSelector()
+                    == null) {
+                throw new Exception("getHandshakeApplicationProtocolSelector()"
+                    + " should return non-null");
+            }
+        }
+
+        /*
+         * Similar to above, but using client mode instead.
+         */
+        clientEngine = sslc.createSSLEngine("client", 80);
+        clientEngine.setUseClientMode(true);
+        sslp = clientEngine.getSSLParameters();
+        if (clientAPs != null) {
+            sslp.setApplicationProtocols(clientAPs);
+        }
+        clientEngine.setSSLParameters(sslp);
+
+        if ((clientEngine.getHandshakeApplicationProtocol() != null) ||
+                (serverEngine.getHandshakeApplicationProtocol() != null)) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null before the handshake starts");
+        }
+    }
+
+    /*
+     * Create and size the buffers appropriately.
+     */
+    private void createBuffers() {
+
+        /*
+         * We'll assume the buffer sizes are the same
+         * between client and server.
+         */
+        SSLSession session = clientEngine.getSession();
+        int appBufferMax = session.getApplicationBufferSize();
+        int netBufferMax = session.getPacketBufferSize();
+
+        /*
+         * We'll make the input buffers a bit bigger than the max needed
+         * size, so that unwrap()s following a successful data transfer
+         * won't generate BUFFER_OVERFLOWS.
+         *
+         * We'll use a mix of direct and indirect ByteBuffers for
+         * tutorial purposes only.  In reality, only use direct
+         * ByteBuffers when they give a clear performance enhancement.
+         */
+        clientIn = ByteBuffer.allocate(appBufferMax + 50);
+        serverIn = ByteBuffer.allocate(appBufferMax + 50);
+
+        cTOs = ByteBuffer.allocateDirect(netBufferMax);
+        sTOc = ByteBuffer.allocateDirect(netBufferMax);
+
+        clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
+        serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes());
+    }
+
+    /*
+     * If the result indicates that we have outstanding tasks to do,
+     * go ahead and run them in this thread.
+     */
+    private static void runDelegatedTasks(SSLEngineResult result,
+            SSLEngine engine) throws Exception {
+
+        if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+            Runnable runnable;
+            while ((runnable = engine.getDelegatedTask()) != null) {
+                log("\trunning delegated task...");
+                runnable.run();
+            }
+            HandshakeStatus hsStatus = engine.getHandshakeStatus();
+            if (hsStatus == HandshakeStatus.NEED_TASK) {
+                throw new Exception(
+                        "handshake shouldn't need additional tasks");
+            }
+            log("\tnew HandshakeStatus: " + hsStatus);
+        }
+    }
+
+    private static boolean isEngineClosed(SSLEngine engine) {
+        return (engine.isOutboundDone() && engine.isInboundDone());
+    }
+
+    /*
+     * Simple check to make sure everything came across as expected.
+     */
+    private static void checkTransfer(ByteBuffer a, ByteBuffer b)
+            throws Exception {
+        a.flip();
+        b.flip();
+
+        if (!a.equals(b)) {
+            throw new Exception("Data didn't transfer cleanly");
+        } else {
+            log("\tData transferred cleanly");
+        }
+
+        a.position(a.limit());
+        b.position(b.limit());
+        a.limit(a.capacity());
+        b.limit(b.capacity());
+    }
+
+    /*
+     * Logging code
+     */
+    private static boolean resultOnce = true;
+
+    private static void log(String str, SSLEngineResult result) {
+        if (!logging) {
+            return;
+        }
+        if (resultOnce) {
+            resultOnce = false;
+            System.out.println("The format of the SSLEngineResult is: \n"
+                    + "\t\"getStatus() / getHandshakeStatus()\" +\n"
+                    + "\t\"bytesConsumed() / bytesProduced()\"\n");
+        }
+        HandshakeStatus hsStatus = result.getHandshakeStatus();
+        log(str
+                + result.getStatus() + "/" + hsStatus + ", "
+                + result.bytesConsumed() + "/" + result.bytesProduced()
+                + " bytes");
+        if (hsStatus == HandshakeStatus.FINISHED) {
+            log("\t...ready for application data");
+        }
+    }
+
+    private static void log(String str) {
+        if (logging) {
+            System.out.println(str);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/ssl/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java	Fri Nov 22 10:47:01 2019 -0800
@@ -0,0 +1,567 @@
+/*
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8051498 8145849 8158978 8170282
+ * @summary JEP 244: TLS Application-Layer Protocol Negotiation Extension
+ * @compile MyX509ExtendedKeyManager.java
+ *
+ * @run main/othervm SSLServerSocketAlpnTest h2          UNUSED   h2          h2
+ * @run main/othervm SSLServerSocketAlpnTest h2          UNUSED   h2,http/1.1 h2
+ * @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 UNUSED   h2,http/1.1 h2
+ * @run main/othervm SSLServerSocketAlpnTest http/1.1,h2 UNUSED   h2,http/1.1 http/1.1
+ * @run main/othervm SSLServerSocketAlpnTest h4,h3,h2    UNUSED   h1,h2       h2
+ * @run main/othervm SSLServerSocketAlpnTest EMPTY       UNUSED   h2,http/1.1 NONE
+ * @run main/othervm SSLServerSocketAlpnTest h2          UNUSED   EMPTY       NONE
+ * @run main/othervm SSLServerSocketAlpnTest H2          UNUSED   h2          ERROR
+ * @run main/othervm SSLServerSocketAlpnTest h2          UNUSED   http/1.1    ERROR
+ *
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      h2       h2          h2
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      h2       h2,http/1.1 h2
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      h2       http/1.1,h2 h2
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      http/1.1 h2,http/1.1 http/1.1
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      EMPTY    h2,http/1.1 NONE
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      h2       EMPTY       NONE
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      H2       h2          ERROR
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      h2       http/1.1    ERROR
+ *
+ * @run main/othervm SSLServerSocketAlpnTest h2          h2       h2          h2
+ * @run main/othervm SSLServerSocketAlpnTest H2          h2       h2,http/1.1 h2
+ * @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 http/1.1 h2,http/1.1 http/1.1
+ * @run main/othervm SSLServerSocketAlpnTest http/1.1,h2 h2       h2,http/1.1 h2
+ * @run main/othervm SSLServerSocketAlpnTest EMPTY       h2       h2          h2
+ * @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 EMPTY    http/1.1    NONE
+ * @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 h2       EMPTY       NONE
+ * @run main/othervm SSLServerSocketAlpnTest UNUSED      UNUSED   http/1.1,h2 NONE
+ * @run main/othervm SSLServerSocketAlpnTest h2          h2       http/1.1    ERROR
+ * @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 H2       http/1.1    ERROR
+ *
+ * @author Brad Wetmore
+ */
+/**
+ * A simple SSLSocket-based client/server that demonstrates the proposed API
+ * changes for JEP 244 in support of the TLS ALPN extension (RFC 7301).
+ *
+ * Usage:
+ *     java SSLServerSocketAlpnTest
+ *             <server-APs> <callback-AP> <client-APs> <result>
+ *
+ * where:
+ *      EMPTY  indicates that ALPN is disabled
+ *      UNUSED indicates that no ALPN values are supplied (server-side only)
+ *      ERROR  indicates that an exception is expected
+ *      NONE   indicates that no ALPN is expected
+ *
+ * This example is based on our standard SSLSocketTemplate.
+ */
+import java.io.*;
+import java.security.KeyStore;
+import java.util.Arrays;
+
+import javax.net.ssl.*;
+
+public class SSLServerSocketAlpnTest {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    static String keyFilename = System.getProperty("test.src", ".") + "/"
+            + pathToStores + "/" + keyStoreFile;
+    static String trustFilename = System.getProperty("test.src", ".") + "/"
+            + pathToStores + "/" + trustStoreFile;
+
+    private static boolean hasServerAPs; // whether server APs are present
+    private static boolean hasCallback; // whether a callback is present
+
+    /*
+     * SSLContext
+     */
+    SSLContext mySSLContext = null;
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    static String[] serverAPs;
+    static String callbackAP;
+    static String[] clientAPs;
+    static String expectedAP;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang. The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf = mySSLContext.getServerSocketFactory();
+        SSLServerSocket sslServerSocket
+                = (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        sslServerSocket.setNeedClientAuth(true);
+
+        SSLParameters sslp = sslServerSocket.getSSLParameters();
+
+        // for both client/server to call into X509KM
+        sslp.setNeedClientAuth(true);
+
+        /*
+         * The default ciphersuite ordering from the SSLContext may not
+         * reflect "h2" ciphersuites as being preferred, additionally the
+         * client may not send them in an appropriate order. We could resort
+         * the suite list if so desired.
+         */
+        String[] suites = sslp.getCipherSuites();
+        sslp.setCipherSuites(suites);
+        sslp.setUseCipherSuitesOrder(true); // Set server side order
+
+        // Set the ALPN selection.
+        if (serverAPs != null) {
+            sslp.setApplicationProtocols(serverAPs);
+        }
+        sslServerSocket.setSSLParameters(sslp);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null before the handshake starts");
+        }
+
+        // check that no callback has been registered
+        if (sslSocket.getHandshakeApplicationProtocolSelector() != null) {
+            throw new Exception("getHandshakeApplicationProtocolSelector() " +
+                "should return null");
+        }
+
+        if (hasCallback) {
+            sslSocket.setHandshakeApplicationProtocolSelector(
+                (serverSocket, clientProtocols) -> {
+                    return callbackAP.equals("EMPTY") ? "" : callbackAP;
+                });
+
+            // check that the callback can be retrieved
+            if (sslSocket.getHandshakeApplicationProtocolSelector() == null) {
+                throw new Exception("getHandshakeApplicationProtocolSelector()"
+                    + " should return non-null");
+            }
+        }
+
+        sslSocket.startHandshake();
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null after the handshake is completed");
+        }
+
+        String ap = sslSocket.getApplicationProtocol();
+        System.out.println("Application Protocol: \"" + ap + "\"");
+
+        if (ap == null) {
+            throw new Exception(
+                    "Handshake was completed but null was received");
+        }
+        if (expectedAP.equals("NONE")) {
+            if (!ap.isEmpty()) {
+                throw new Exception("Expected no ALPN value");
+            } else {
+                System.out.println("No ALPN value negotiated, as expected");
+            }
+        } else if (!expectedAP.equals(ap)) {
+            throw new Exception(expectedAP
+                    + " ALPN value not available on negotiated connection");
+        }
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf = mySSLContext.getSocketFactory();
+        SSLSocket sslSocket
+                = (SSLSocket) sslsf.createSocket("localhost", serverPort);
+
+        SSLParameters sslp = sslSocket.getSSLParameters();
+
+        /*
+         * The default ciphersuite ordering from the SSLContext may not
+         * reflect "h2" ciphersuites as being preferred, additionally the
+         * client may not send them in an appropriate order. We could resort
+         * the suite list if so desired.
+         */
+        String[] suites = sslp.getCipherSuites();
+        sslp.setCipherSuites(suites);
+        sslp.setUseCipherSuitesOrder(true); // Set server side order
+
+        // Set the ALPN selection.
+        sslp.setApplicationProtocols(clientAPs);
+        sslSocket.setSSLParameters(sslp);
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null before the handshake starts");
+        }
+
+        sslSocket.startHandshake();
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null after the handshake is completed");
+        }
+
+        /*
+         * Check that the resulting connection meets our defined ALPN
+         * criteria.  If we were connecting to a non-JSSE implementation,
+         * the server might have negotiated something we shouldn't accept.
+         */
+        String ap = sslSocket.getApplicationProtocol();
+        System.out.println("Application Protocol: \"" + ap + "\"");
+
+        if (ap == null) {
+            throw new Exception(
+                    "Handshake was completed but null was received");
+        }
+        if (expectedAP.equals("NONE")) {
+            if (!ap.isEmpty()) {
+                throw new Exception("Expected no ALPN value");
+            } else {
+                System.out.println("No ALPN value negotiated, as expected");
+            }
+        } else if (!expectedAP.equals(ap)) {
+            throw new Exception(expectedAP
+                    + " ALPN value not available on negotiated connection");
+        }
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+
+        if (debug) {
+            System.setProperty("javax.net.debug", "all");
+        }
+        System.out.println("Test args: " + Arrays.toString(args));
+
+        // Validate parameters
+        if (args.length != 4) {
+            throw new Exception("Invalid number of test parameters");
+        }
+        serverAPs = convert(args[0]);
+        callbackAP = args[1];
+        clientAPs = convert(args[2]);
+        expectedAP = args[3];
+
+        hasServerAPs = !args[0].equals("UNUSED"); // are server APs being used?
+        hasCallback = !callbackAP.equals("UNUSED"); // is callback being used?
+
+        /*
+         * Start the tests.
+         */
+        try {
+            new SSLServerSocketAlpnTest();
+        } catch (SSLHandshakeException she) {
+            if (args[3].equals("ERROR")) {
+                System.out.println("Caught the expected exception: " + she);
+            } else {
+                throw she;
+            }
+        }
+
+        System.out.println("Test Passed.");
+    }
+
+    SSLContext getSSLContext(String keyFilename, String trustFilename)
+            throws Exception {
+        SSLContext ctx = SSLContext.getInstance("TLS");
+
+        // Keystores
+        KeyStore keyKS = KeyStore.getInstance("JKS");
+        keyKS.load(new FileInputStream(keyFilename), passwd.toCharArray());
+
+        KeyStore trustKS = KeyStore.getInstance("JKS");
+        trustKS.load(new FileInputStream(trustFilename), passwd.toCharArray());
+
+        // Generate KeyManager and TrustManager
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        kmf.init(keyKS, passwd.toCharArray());
+
+        KeyManager[] kms = kmf.getKeyManagers();
+        if (!(kms[0] instanceof X509ExtendedKeyManager)) {
+            throw new Exception("kms[0] not X509ExtendedKeyManager");
+        }
+
+        kms = new KeyManager[] { new MyX509ExtendedKeyManager(
+                (X509ExtendedKeyManager) kms[0], expectedAP,
+                !hasCallback && hasServerAPs) };
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        tmf.init(trustKS);
+        TrustManager[] tms = tmf.getTrustManagers();
+
+        // initial SSLContext
+        ctx.init(kms, tms, null);
+
+        return ctx;
+    }
+
+    /*
+     * Convert a comma-separated list into an array of strings.
+     */
+    private static String[] convert(String list) {
+        if (list.equals("UNUSED")) {
+            return null;
+        }
+
+        if (list.equals("EMPTY")) {
+            return new String[0];
+        }
+
+        String[] strings;
+        if (list.indexOf(',') > 0) {
+            strings = list.split(",");
+        } else {
+            strings = new String[]{ list };
+        }
+
+        return strings;
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    SSLServerSocketAlpnTest() throws Exception {
+        Exception startException = null;
+        mySSLContext = getSSLContext(keyFilename, trustFilename);
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            startException = e;
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            if (serverThread != null) {
+                serverThread.join();
+            }
+        } else {
+            if (clientThread != null) {
+                clientThread.join();
+            }
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+        } else {
+            remote = clientException;
+            local = serverException;
+        }
+
+        Exception exception = null;
+
+        /*
+         * Check various exception conditions.
+         */
+        if ((local != null) && (remote != null)) {
+            // If both failed, return the curthread's exception.
+            local.initCause(remote);
+            exception = local;
+        } else if (local != null) {
+            exception = local;
+        } else if (remote != null) {
+            exception = remote;
+        } else if (startException != null) {
+            exception = startException;
+        }
+
+        /*
+         * If there was an exception *AND* a startException,
+         * output it.
+         */
+        if (exception != null) {
+            if (exception != startException && startException != null) {
+                exception.addSuppressed(startException);
+            }
+            throw exception;
+        }
+
+        // Fall-through: no exception to throw!
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/ssl/javax/net/ssl/ALPN/SSLSocketAlpnTest.java	Fri Nov 22 10:47:01 2019 -0800
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8051498 8145849 8170282
+ * @summary JEP 244: TLS Application-Layer Protocol Negotiation Extension
+ * @compile MyX509ExtendedKeyManager.java
+ *
+ * @run main/othervm SSLSocketAlpnTest h2          UNUSED   h2          h2
+ * @run main/othervm SSLSocketAlpnTest h2          UNUSED   h2,http/1.1 h2
+ * @run main/othervm SSLSocketAlpnTest h2,http/1.1 UNUSED   h2,http/1.1 h2
+ * @run main/othervm SSLSocketAlpnTest http/1.1,h2 UNUSED   h2,http/1.1 http/1.1
+ * @run main/othervm SSLSocketAlpnTest h4,h3,h2    UNUSED   h1,h2       h2
+ * @run main/othervm SSLSocketAlpnTest EMPTY       UNUSED   h2,http/1.1 NONE
+ * @run main/othervm SSLSocketAlpnTest h2          UNUSED   EMPTY       NONE
+ * @run main/othervm SSLSocketAlpnTest H2          UNUSED   h2          ERROR
+ * @run main/othervm SSLSocketAlpnTest h2          UNUSED   http/1.1    ERROR
+ *
+ * @run main/othervm SSLSocketAlpnTest UNUSED      h2       h2          h2
+ * @run main/othervm SSLSocketAlpnTest UNUSED      h2       h2,http/1.1 h2
+ * @run main/othervm SSLSocketAlpnTest UNUSED      h2       http/1.1,h2 h2
+ * @run main/othervm SSLSocketAlpnTest UNUSED      http/1.1 h2,http/1.1 http/1.1
+ * @run main/othervm SSLSocketAlpnTest UNUSED      EMPTY    h2,http/1.1 NONE
+ * @run main/othervm SSLSocketAlpnTest UNUSED      h2       EMPTY       NONE
+ * @run main/othervm SSLSocketAlpnTest UNUSED      H2       h2          ERROR
+ * @run main/othervm SSLSocketAlpnTest UNUSED      h2       http/1.1    ERROR
+ *
+ * @run main/othervm SSLSocketAlpnTest h2          h2       h2          h2
+ * @run main/othervm SSLSocketAlpnTest H2          h2       h2,http/1.1 h2
+ * @run main/othervm SSLSocketAlpnTest h2,http/1.1 http/1.1 h2,http/1.1 http/1.1
+ * @run main/othervm SSLSocketAlpnTest http/1.1,h2 h2       h2,http/1.1 h2
+ * @run main/othervm SSLSocketAlpnTest EMPTY       h2       h2          h2
+ * @run main/othervm SSLSocketAlpnTest h2,http/1.1 EMPTY    http/1.1    NONE
+ * @run main/othervm SSLSocketAlpnTest h2,http/1.1 h2       EMPTY       NONE
+ * @run main/othervm SSLSocketAlpnTest UNUSED      UNUSED   http/1.1,h2 NONE
+ * @run main/othervm SSLSocketAlpnTest h2          h2       http/1.1    ERROR
+ * @run main/othervm SSLSocketAlpnTest h2,http/1.1 H2       http/1.1    ERROR
+ *
+ * @author Brad Wetmore
+ */
+/**
+ * A simple SSLSocket-based client/server that demonstrates the proposed API
+ * changes for JEP 244 in support of the TLS ALPN extension (RFC 7301).
+ *
+ * Usage:
+ *     java SSLSocketAlpnTest <server-APs> <callback-AP> <client-APs> <result>
+ *
+ * where:
+ *      EMPTY  indicates that ALPN is disabled
+ *      UNUSED indicates that no ALPN values are supplied (server-side only)
+ *      ERROR  indicates that an exception is expected
+ *      NONE   indicates that no ALPN is expected
+ *
+ * This example is based on our standard SSLSocketTemplate.
+ */
+import java.io.*;
+import java.security.KeyStore;
+import java.util.Arrays;
+
+import javax.net.ssl.*;
+
+public class SSLSocketAlpnTest {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    static String keyFilename = System.getProperty("test.src", ".") + "/"
+            + pathToStores + "/" + keyStoreFile;
+    static String trustFilename = System.getProperty("test.src", ".") + "/"
+            + pathToStores + "/" + trustStoreFile;
+
+    private static boolean hasServerAPs; // whether server APs are present
+    private static boolean hasCallback; // whether a callback is present
+
+    /*
+     * SSLContext
+     */
+    SSLContext mySSLContext = null;
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    static String[] serverAPs;
+    static String callbackAP;
+    static String[] clientAPs;
+    static String expectedAP;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang. The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf = mySSLContext.getServerSocketFactory();
+        SSLServerSocket sslServerSocket
+                = (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        // for both client/server to call into X509KM
+        sslServerSocket.setNeedClientAuth(true);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+
+        SSLParameters sslp = sslSocket.getSSLParameters();
+
+        /*
+         * The default ciphersuite ordering from the SSLContext may not
+         * reflect "h2" ciphersuites as being preferred, additionally the
+         * client may not send them in an appropriate order. We could resort
+         * the suite list if so desired.
+         */
+        String[] suites = sslp.getCipherSuites();
+        sslp.setCipherSuites(suites);
+        sslp.setUseCipherSuitesOrder(true); // Set server side order
+
+        // Set the ALPN selection.
+        if (serverAPs != null) {
+            sslp.setApplicationProtocols(serverAPs);
+        }
+        sslSocket.setSSLParameters(sslp);
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null before the handshake starts");
+        }
+
+        // check that no callback has been registered
+        if (sslSocket.getHandshakeApplicationProtocolSelector() != null) {
+            throw new Exception("getHandshakeApplicationProtocolSelector() " +
+                "should return null");
+        }
+
+        if (hasCallback) {
+            sslSocket.setHandshakeApplicationProtocolSelector(
+                (serverSocket, clientProtocols) -> {
+                    return callbackAP.equals("EMPTY") ? "" : callbackAP;
+                });
+
+            // check that the callback can be retrieved
+            if (sslSocket.getHandshakeApplicationProtocolSelector() == null) {
+                throw new Exception("getHandshakeApplicationProtocolSelector()"                     + " should return non-null");
+            }
+        }
+
+        sslSocket.startHandshake();
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null after the handshake is completed");
+        }
+
+        String ap = sslSocket.getApplicationProtocol();
+        System.out.println("Application Protocol: \"" + ap + "\"");
+
+        if (ap == null) {
+            throw new Exception(
+                    "Handshake was completed but null was received");
+        }
+        if (expectedAP.equals("NONE")) {
+            if (!ap.isEmpty()) {
+                throw new Exception("Expected no ALPN value");
+            } else {
+                System.out.println("No ALPN value negotiated, as expected");
+            }
+        } else if (!expectedAP.equals(ap)) {
+            throw new Exception(expectedAP
+                    + " ALPN value not available on negotiated connection");
+        }
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf = mySSLContext.getSocketFactory();
+        SSLSocket sslSocket
+                = (SSLSocket) sslsf.createSocket("localhost", serverPort);
+
+        SSLParameters sslp = sslSocket.getSSLParameters();
+
+        /*
+         * The default ciphersuite ordering from the SSLContext may not
+         * reflect "h2" ciphersuites as being preferred, additionally the
+         * client may not send them in an appropriate order. We could resort
+         * the suite list if so desired.
+         */
+        String[] suites = sslp.getCipherSuites();
+        sslp.setCipherSuites(suites);
+        sslp.setUseCipherSuitesOrder(true); // Set server side order
+
+        // Set the ALPN selection.
+        sslp.setApplicationProtocols(clientAPs);
+        sslSocket.setSSLParameters(sslp);
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null before the handshake starts");
+        }
+
+        sslSocket.startHandshake();
+
+        if (sslSocket.getHandshakeApplicationProtocol() != null) {
+            throw new Exception ("getHandshakeApplicationProtocol() should "
+                    + "return null after the handshake is completed");
+        }
+
+        /*
+         * Check that the resulting connection meets our defined ALPN
+         * criteria.  If we were connecting to a non-JSSE implementation,
+         * the server might have negotiated something we shouldn't accept.
+         */
+        String ap = sslSocket.getApplicationProtocol();
+        System.out.println("Application Protocol: \"" + ap + "\"");
+
+        if (ap == null) {
+            throw new Exception(
+                    "Handshake was completed but null was received");
+        }
+        if (expectedAP.equals("NONE")) {
+            if (!ap.isEmpty()) {
+                throw new Exception("Expected no ALPN value");
+            } else {
+                System.out.println("No ALPN value negotiated, as expected");
+            }
+        } else if (!expectedAP.equals(ap)) {
+            throw new Exception(expectedAP
+                    + " ALPN value not available on negotiated connection");
+        }
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+
+        if (debug) {
+            System.setProperty("javax.net.debug", "all");
+        }
+        System.out.println("Test args: " + Arrays.toString(args));
+
+        // Validate parameters
+        if (args.length != 4) {
+            throw new Exception("Invalid number of test parameters");
+        }
+        serverAPs = convert(args[0]);
+        callbackAP = args[1];
+        clientAPs = convert(args[2]);
+        expectedAP = args[3];
+
+        hasServerAPs = !args[0].equals("UNUSED"); // are server APs being used?
+        hasCallback = !callbackAP.equals("UNUSED"); // is callback being used?
+
+        /*
+         * Start the tests.
+         */
+        try {
+            new SSLSocketAlpnTest();
+        } catch (SSLHandshakeException she) {
+            if (args[3].equals("ERROR")) {
+                System.out.println("Caught the expected exception: " + she);
+            } else {
+                throw she;
+            }
+        }
+
+        System.out.println("Test Passed.");
+    }
+
+    SSLContext getSSLContext(String keyFilename, String trustFilename)
+            throws Exception {
+        SSLContext ctx = SSLContext.getInstance("TLS");
+
+        // Keystores
+        KeyStore keyKS = KeyStore.getInstance("JKS");
+        keyKS.load(new FileInputStream(keyFilename), passwd.toCharArray());
+
+        KeyStore trustKS = KeyStore.getInstance("JKS");
+        trustKS.load(new FileInputStream(trustFilename), passwd.toCharArray());
+
+        // Generate KeyManager and TrustManager
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        kmf.init(keyKS, passwd.toCharArray());
+
+        KeyManager[] kms = kmf.getKeyManagers();
+        if (!(kms[0] instanceof X509ExtendedKeyManager)) {
+            throw new Exception("kms[0] not X509ExtendedKeyManager");
+        }
+
+        kms = new KeyManager[] { new MyX509ExtendedKeyManager(
+                (X509ExtendedKeyManager) kms[0], expectedAP,
+                !hasCallback && hasServerAPs) };
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        tmf.init(trustKS);
+        TrustManager[] tms = tmf.getTrustManagers();
+
+        // initial SSLContext
+        ctx.init(kms, tms, null);
+
+        return ctx;
+    }
+
+    /*
+     * Convert a comma-separated list into an array of strings.
+     */
+    private static String[] convert(String list) {
+        if (list.equals("UNUSED")) {
+            return null;
+        }
+
+        if (list.equals("EMPTY")) {
+            return new String[0];
+        }
+
+        String[] strings;
+        if (list.indexOf(',') > 0) {
+            strings = list.split(",");
+        } else {
+            strings = new String[]{ list };
+        }
+
+        return strings;
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    SSLSocketAlpnTest() throws Exception {
+        Exception startException = null;
+        mySSLContext = getSSLContext(keyFilename, trustFilename);
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            startException = e;
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            if (serverThread != null) {
+                serverThread.join();
+            }
+        } else {
+            if (clientThread != null) {
+                clientThread.join();
+            }
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+        } else {
+            remote = clientException;
+            local = serverException;
+        }
+
+        Exception exception = null;
+
+        /*
+         * Check various exception conditions.
+         */
+        if ((local != null) && (remote != null)) {
+            // If both failed, return the curthread's exception.
+            local.initCause(remote);
+            exception = local;
+        } else if (local != null) {
+            exception = local;
+        } else if (remote != null) {
+            exception = remote;
+        } else if (startException != null) {
+            exception = startException;
+        }
+
+        /*
+         * If there was an exception *AND* a startException,
+         * output it.
+         */
+        if (exception != null) {
+            if (exception != startException && startException != null) {
+                exception.addSuppressed(startException);
+            }
+            throw exception;
+        }
+
+        // Fall-through: no exception to throw!
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- a/test/sun/security/ssl/templates/SSLEngineTemplate.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/test/sun/security/ssl/templates/SSLEngineTemplate.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -78,7 +78,7 @@
     /*
      * Enables logging of the SSLEngine operations.
      */
-    private static boolean logging = true;
+    private static final boolean logging = true;
 
     /*
      * Enables the JSSE system debugging system property:
@@ -89,9 +89,9 @@
      * including specific handshake messages, and might be best examined
      * after gaining some familiarity with this application.
      */
-    private static boolean debug = false;
+    private static final boolean debug = false;
 
-    private SSLContext sslc;
+    private final SSLContext sslc;
 
     private SSLEngine clientEngine;     // client Engine
     private ByteBuffer clientOut;       // write side of clientEngine
@@ -112,15 +112,15 @@
     /*
      * The following is to set up the keystores.
      */
-    private static String pathToStores = "../etc";
-    private static String keyStoreFile = "keystore";
-    private static String trustStoreFile = "truststore";
-    private static String passwd = "passphrase";
+    private static final String pathToStores = "../etc";
+    private static final String keyStoreFile = "keystore";
+    private static final String trustStoreFile = "truststore";
+    private static final String passwd = "passphrase";
 
-    private static String keyFilename =
+    private static final String keyFilename =
             System.getProperty("test.src", ".") + "/" + pathToStores +
                 "/" + keyStoreFile;
-    private static String trustFilename =
+    private static final String trustFilename =
             System.getProperty("test.src", ".") + "/" + pathToStores +
                 "/" + trustStoreFile;
 
--- a/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -86,7 +86,7 @@
     /*
      * Enables logging of the SSL/TLS operations.
      */
-    private static boolean logging = true;
+    private static final boolean logging = true;
 
     /*
      * Enables the JSSE system debugging system property:
@@ -97,8 +97,8 @@
      * including specific handshake messages, and might be best examined
      * after gaining some familiarity with this application.
      */
-    private static boolean debug = false;
-    private SSLContext sslc;
+    private static final boolean debug = false;
+    private final SSLContext sslc;
     private SSLEngine serverEngine;     // server-side SSLEngine
     private SSLSocket sslSocket;        // client-side socket
     private ServerSocket serverSocket;  // server-side Socket, generates the...
@@ -128,10 +128,10 @@
     private static final String keyStoreFile = "keystore";
     private static final String trustStoreFile = "truststore";
     private static final String passwd = "passphrase";
-    private static String keyFilename =
+    private static final String keyFilename =
             System.getProperty("test.src", ".") + "/" + pathToStores
             + "/" + keyStoreFile;
-    private static String trustFilename =
+    private static final String trustFilename =
             System.getProperty("test.src", ".") + "/" + pathToStores
             + "/" + trustStoreFile;
 
@@ -239,7 +239,7 @@
             byte[] outbound = new byte[8192];
 
             while (!isEngineClosed(serverEngine)) {
-                int len = 0;
+                int len;
 
                 // Inbound data
                 log("================");
@@ -307,7 +307,6 @@
                     serverIn.compact();
                 }
             }
-            return;
         } catch (Exception e) {
             serverException = e;
         } finally {
@@ -361,13 +360,12 @@
                     int pos = 0;
 
                     int len;
-done:
                     while ((len = is.read(inbound, pos, 2048 - pos)) != -1) {
                         pos += len;
                         // Let the client do the closing.
                         if ((pos == serverMsg.length) && !serverClose) {
                             sslSocket.close();
-                            break done;
+                            break;
                         }
                     }
 
--- a/test/sun/security/ssl/templates/SSLSocketTemplate.java	Fri Nov 15 15:06:48 2019 +0000
+++ b/test/sun/security/ssl/templates/SSLSocketTemplate.java	Fri Nov 22 10:47:01 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -33,7 +33,6 @@
  */
 
 import java.io.*;
-import java.net.*;
 import javax.net.ssl.*;
 
 public class SSLSocketTemplate {
@@ -162,8 +161,9 @@
         System.setProperty("javax.net.ssl.trustStore", trustFilename);
         System.setProperty("javax.net.ssl.trustStorePassword", passwd);
 
-        if (debug)
+        if (debug) {
             System.setProperty("javax.net.debug", "all");
+        }
 
         /*
          * Start the tests.
@@ -255,6 +255,7 @@
     void startServer(boolean newThread) throws Exception {
         if (newThread) {
             serverThread = new Thread() {
+                @Override
                 public void run() {
                     try {
                         doServerSide();
@@ -285,6 +286,7 @@
     void startClient(boolean newThread) throws Exception {
         if (newThread) {
             clientThread = new Thread() {
+                @Override
                 public void run() {
                     try {
                         doClientSide();