changeset 14134:17ce8aaff4bd

8245467: Remove 8u TLSv1.2 implementation files Reviewed-by: mbalao
author abakhtin
date Wed, 20 May 2020 17:28:12 +0300
parents 84c5676f140b
children d0b56fcd1708
files src/share/classes/sun/security/ssl/ALPNExtension.java src/share/classes/sun/security/ssl/Alerts.java src/share/classes/sun/security/ssl/AppInputStream.java src/share/classes/sun/security/ssl/AppOutputStream.java src/share/classes/sun/security/ssl/Authenticator.java src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java src/share/classes/sun/security/ssl/ByteBufferInputStream.java src/share/classes/sun/security/ssl/CipherBox.java src/share/classes/sun/security/ssl/CipherSuite.java src/share/classes/sun/security/ssl/CipherSuiteList.java src/share/classes/sun/security/ssl/ClientHandshaker.java src/share/classes/sun/security/ssl/DHClientKeyExchange.java src/share/classes/sun/security/ssl/DHCrypt.java src/share/classes/sun/security/ssl/Debug.java src/share/classes/sun/security/ssl/ECDHClientKeyExchange.java src/share/classes/sun/security/ssl/ECDHCrypt.java src/share/classes/sun/security/ssl/EllipticCurvesExtension.java src/share/classes/sun/security/ssl/EllipticPointFormatsExtension.java src/share/classes/sun/security/ssl/EngineArgs.java src/share/classes/sun/security/ssl/EngineInputRecord.java src/share/classes/sun/security/ssl/EngineOutputRecord.java src/share/classes/sun/security/ssl/EngineWriter.java src/share/classes/sun/security/ssl/EphemeralKeyManager.java src/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java src/share/classes/sun/security/ssl/ExtensionType.java src/share/classes/sun/security/ssl/HandshakeHash.java src/share/classes/sun/security/ssl/HandshakeInStream.java src/share/classes/sun/security/ssl/HandshakeMessage.java src/share/classes/sun/security/ssl/HandshakeOutStream.java src/share/classes/sun/security/ssl/HandshakeStateManager.java src/share/classes/sun/security/ssl/Handshaker.java src/share/classes/sun/security/ssl/HelloExtension.java src/share/classes/sun/security/ssl/HelloExtensions.java src/share/classes/sun/security/ssl/InputRecord.java src/share/classes/sun/security/ssl/JsseJce.java src/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java src/share/classes/sun/security/ssl/MAC.java src/share/classes/sun/security/ssl/OutputRecord.java src/share/classes/sun/security/ssl/ProtocolList.java src/share/classes/sun/security/ssl/ProtocolVersion.java src/share/classes/sun/security/ssl/RSAClientKeyExchange.java src/share/classes/sun/security/ssl/RSASignature.java src/share/classes/sun/security/ssl/RandomCookie.java src/share/classes/sun/security/ssl/Record.java src/share/classes/sun/security/ssl/RenegotiationInfoExtension.java src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java src/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java src/share/classes/sun/security/ssl/SSLContextImpl.java src/share/classes/sun/security/ssl/SSLEngineImpl.java src/share/classes/sun/security/ssl/SSLServerSocketFactoryImpl.java src/share/classes/sun/security/ssl/SSLServerSocketImpl.java src/share/classes/sun/security/ssl/SSLSessionContextImpl.java src/share/classes/sun/security/ssl/SSLSessionImpl.java src/share/classes/sun/security/ssl/SSLSocketFactoryImpl.java src/share/classes/sun/security/ssl/SSLSocketImpl.java src/share/classes/sun/security/ssl/ServerHandshaker.java src/share/classes/sun/security/ssl/ServerNameExtension.java src/share/classes/sun/security/ssl/SessionId.java src/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java src/share/classes/sun/security/ssl/TrustStoreManager.java src/share/classes/sun/security/ssl/UnknownExtension.java src/share/classes/sun/security/ssl/Utilities.java src/share/classes/sun/security/ssl/X509KeyManagerImpl.java src/share/classes/sun/security/ssl/X509TrustManagerImpl.java
diffstat 67 files changed, 0 insertions(+), 32738 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/ssl/ALPNExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2015, 2020, 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	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2003, 2020, 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 javax.net.ssl.*;
-
-/*
- * A simple class to congregate alerts, their definitions, and common
- * support methods.
- */
-
-final class Alerts {
-
-    /*
-     * Alerts are always a fixed two byte format (level/description).
-     */
-
-    // warnings and fatal errors are package private facilities/constants
-
-    // Alert levels (enum AlertLevel)
-    static final byte           alert_warning = 1;
-    static final byte           alert_fatal = 2;
-
-    /*
-     * Alert descriptions (enum AlertDescription)
-     *
-     * We may not use them all in our processing, but if someone
-     * sends us one, we can at least convert it to a string for the
-     * user.
-     */
-    static final byte           alert_close_notify = 0;
-    static final byte           alert_unexpected_message = 10;
-    static final byte           alert_bad_record_mac = 20;
-    static final byte           alert_decryption_failed = 21;
-    static final byte           alert_record_overflow = 22;
-    static final byte           alert_decompression_failure = 30;
-    static final byte           alert_handshake_failure = 40;
-    static final byte           alert_no_certificate = 41;
-    static final byte           alert_bad_certificate = 42;
-    static final byte           alert_unsupported_certificate = 43;
-    static final byte           alert_certificate_revoked = 44;
-    static final byte           alert_certificate_expired = 45;
-    static final byte           alert_certificate_unknown = 46;
-    static final byte           alert_illegal_parameter = 47;
-    static final byte           alert_unknown_ca = 48;
-    static final byte           alert_access_denied = 49;
-    static final byte           alert_decode_error = 50;
-    static final byte           alert_decrypt_error = 51;
-    static final byte           alert_export_restriction = 60;
-    static final byte           alert_protocol_version = 70;
-    static final byte           alert_insufficient_security = 71;
-    static final byte           alert_internal_error = 80;
-    static final byte           alert_user_canceled = 90;
-    static final byte           alert_no_renegotiation = 100;
-
-    // from RFC 3546 (TLS Extensions)
-    static final byte           alert_unsupported_extension = 110;
-    static final byte           alert_certificate_unobtainable = 111;
-    static final byte           alert_unrecognized_name = 112;
-    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) {
-
-        case alert_close_notify:
-            return "close_notify";
-        case alert_unexpected_message:
-            return "unexpected_message";
-        case alert_bad_record_mac:
-            return "bad_record_mac";
-        case alert_decryption_failed:
-            return "decryption_failed";
-        case alert_record_overflow:
-            return "record_overflow";
-        case alert_decompression_failure:
-            return "decompression_failure";
-        case alert_handshake_failure:
-            return "handshake_failure";
-        case alert_no_certificate:
-            return "no_certificate";
-        case alert_bad_certificate:
-            return "bad_certificate";
-        case alert_unsupported_certificate:
-            return "unsupported_certificate";
-        case alert_certificate_revoked:
-            return "certificate_revoked";
-        case alert_certificate_expired:
-            return "certificate_expired";
-        case alert_certificate_unknown:
-            return "certificate_unknown";
-        case alert_illegal_parameter:
-            return "illegal_parameter";
-        case alert_unknown_ca:
-            return "unknown_ca";
-        case alert_access_denied:
-            return "access_denied";
-        case alert_decode_error:
-            return "decode_error";
-        case alert_decrypt_error:
-            return "decrypt_error";
-        case alert_export_restriction:
-            return "export_restriction";
-        case alert_protocol_version:
-            return "protocol_version";
-        case alert_insufficient_security:
-            return "insufficient_security";
-        case alert_internal_error:
-            return "internal_error";
-        case alert_user_canceled:
-            return "user_canceled";
-        case alert_no_renegotiation:
-            return "no_renegotiation";
-        case alert_unsupported_extension:
-            return "unsupported_extension";
-        case alert_certificate_unobtainable:
-            return "certificate_unobtainable";
-        case alert_unrecognized_name:
-            return "unrecognized_name";
-        case alert_bad_certificate_status_response:
-            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) + ">";
-        }
-    }
-
-    static SSLException getSSLException(byte description, String reason) {
-        return getSSLException(description, null, reason);
-    }
-
-    /*
-     * Try to be a little more specific in our choice of
-     * exceptions to throw.
-     */
-    static SSLException getSSLException(byte description, Throwable cause,
-            String reason) {
-
-        SSLException e;
-        // the SSLException classes do not have a no-args constructor
-        // make up a message if there is none
-        if (reason == null) {
-            if (cause != null) {
-                reason = cause.toString();
-            } else {
-                reason = "";
-            }
-        }
-        switch (description) {
-        case alert_handshake_failure:
-        case alert_no_certificate:
-        case alert_bad_certificate:
-        case alert_unsupported_certificate:
-        case alert_certificate_revoked:
-        case alert_certificate_expired:
-        case alert_certificate_unknown:
-        case alert_unknown_ca:
-        case alert_access_denied:
-        case alert_decrypt_error:
-        case alert_export_restriction:
-        case alert_insufficient_security:
-        case alert_unsupported_extension:
-        case alert_certificate_unobtainable:
-        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;
-
-        case alert_close_notify:
-        case alert_unexpected_message:
-        case alert_bad_record_mac:
-        case alert_decryption_failed:
-        case alert_record_overflow:
-        case alert_decompression_failure:
-        case alert_illegal_parameter:
-        case alert_decode_error:
-        case alert_protocol_version:
-        case alert_internal_error:
-        case alert_user_canceled:
-        case alert_no_renegotiation:
-        default:
-            e = new SSLException(reason);
-            break;
-        }
-
-        if (cause != null) {
-            e.initCause(cause);
-        }
-        return e;
-    }
-}
--- a/src/share/classes/sun/security/ssl/AppInputStream.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, 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.*;
-
-/**
- * InputStream for application data as returned by SSLSocket.getInputStream().
- * It uses an InputRecord as internal buffer that is refilled on demand
- * whenever it runs out of data.
- *
- * @author David Brownell
- */
-class AppInputStream extends InputStream {
-
-    // static dummy array we use to implement skip()
-    private final static byte[] SKIP_ARRAY = new byte[1024];
-
-    private SSLSocketImpl c;
-    InputRecord r;
-
-    // One element array used to implement the single byte read() method
-    private final byte[] oneByte = new byte[1];
-
-    AppInputStream(SSLSocketImpl conn) {
-        r = new InputRecord();
-        c = conn;
-    }
-
-    /**
-     * Return the minimum number of bytes that can be read without blocking.
-     * Currently not synchronized.
-     */
-    @Override
-    public int available() throws IOException {
-        if (c.checkEOF() || (r.isAppDataValid() == false)) {
-            return 0;
-        }
-        return r.available();
-    }
-
-    /**
-     * Read a single byte, returning -1 on non-fault EOF status.
-     */
-    @Override
-    public synchronized int read() throws IOException {
-        int n = read(oneByte, 0, 1);
-        if (n <= 0) { // EOF
-            return -1;
-        }
-        return oneByte[0] & 0xff;
-    }
-
-    /**
-     * Read up to "len" bytes into this buffer, starting at "off".
-     * If the layer above needs more data, it asks for more, so we
-     * are responsible only for blocking to fill at most one buffer,
-     * and returning "-1" on non-fault EOF status.
-     */
-    @Override
-    public synchronized int read(byte b[], int off, int len)
-            throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return 0;
-        }
-
-        if (c.checkEOF()) {
-            return -1;
-        }
-        try {
-            /*
-             * Read data if needed ... notice that the connection guarantees
-             * that handshake, alert, and change cipher spec data streams are
-             * handled as they arrive, so we never see them here.
-             */
-            while (r.available() == 0) {
-                c.readDataRecord(r);
-                if (c.checkEOF()) {
-                    return -1;
-                }
-            }
-
-            int howmany = Math.min(len, r.available());
-            howmany = r.read(b, off, howmany);
-            return howmany;
-        } catch (Exception e) {
-            // shutdown and rethrow (wrapped) exception as appropriate
-            c.handleException(e);
-            // dummy for compiler
-            return -1;
-        }
-    }
-
-
-    /**
-     * Skip n bytes. This implementation is somewhat less efficient
-     * than possible, but not badly so (redundant copy). We reuse
-     * the read() code to keep things simpler. Note that SKIP_ARRAY
-     * is static and may garbled by concurrent use, but we are not interested
-     * in the data anyway.
-     */
-    @Override
-    public synchronized long skip(long n) throws IOException {
-        long skipped = 0;
-        while (n > 0) {
-            int len = (int)Math.min(n, SKIP_ARRAY.length);
-            int r = read(SKIP_ARRAY, 0, len);
-            if (r <= 0) {
-                break;
-            }
-            n -= r;
-            skipped += r;
-        }
-        return skipped;
-    }
-
-    /*
-     * Socket close is already synchronized, no need to block here.
-     */
-    @Override
-    public void close() throws IOException {
-        c.close();
-    }
-
-    // inherit default mark/reset behavior (throw Exceptions) from InputStream
-
-}
--- a/src/share/classes/sun/security/ssl/AppOutputStream.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, 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.OutputStream;
-import java.io.IOException;
-
-/*
- * Output stream for application data. This is the kind of stream
- * that's handed out via SSLSocket.getOutputStream(). It's all the application
- * ever sees.
- *
- * Once the initial handshake has completed, application data may be
- * interleaved with handshake data. That is handled internally and remains
- * transparent to the application.
- *
- * @author  David Brownell
- */
-class AppOutputStream extends OutputStream {
-
-    private SSLSocketImpl c;
-    OutputRecord r;
-
-    // One element array used to implement the write(byte) method
-    private final byte[] oneByte = new byte[1];
-
-    AppOutputStream(SSLSocketImpl conn) {
-        r = new OutputRecord(Record.ct_application_data);
-        c = conn;
-    }
-
-    /**
-     * Write the data out, NOW.
-     */
-    @Override
-    synchronized public void write(byte b[], int off, int len)
-            throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return;
-        }
-
-        // check if the Socket is invalid (error or closed)
-        c.checkWrite();
-
-        /*
-         * By default, we counter chosen plaintext issues on CBC mode
-         * ciphersuites in SSLv3/TLS1.0 by sending one byte of application
-         * data in the first record of every payload, and the rest in
-         * subsequent record(s). Note that the issues have been solved in
-         * TLS 1.1 or later.
-         *
-         * It is not necessary to split the very first application record of
-         * a freshly negotiated TLS session, as there is no previous
-         * application data to guess.  To improve compatibility, we will not
-         * split such records.
-         *
-         * This avoids issues in the outbound direction.  For a full fix,
-         * the peer must have similar protections.
-         */
-        boolean isFirstRecordOfThePayload = true;
-
-        // Always flush at the end of each application level record.
-        // This lets application synchronize read and write streams
-        // however they like; if we buffered here, they couldn't.
-        try {
-            do {
-                boolean holdRecord = false;
-                int howmuch;
-                if (isFirstRecordOfThePayload && c.needToSplitPayload()) {
-                    howmuch = Math.min(0x01, r.availableDataBytes());
-                     /*
-                      * Nagle's algorithm (TCP_NODELAY) was coming into
-                      * play here when writing short (split) packets.
-                      * Signal to the OutputRecord code to internally
-                      * buffer this small packet until the next outbound
-                      * packet (of any type) is written.
-                      */
-                     if ((len != 1) && (howmuch == 1)) {
-                         holdRecord = true;
-                     }
-                } else {
-                    howmuch = Math.min(len, r.availableDataBytes());
-                }
-
-                if (isFirstRecordOfThePayload && howmuch != 0) {
-                    isFirstRecordOfThePayload = false;
-                }
-
-                // NOTE: *must* call c.writeRecord() even for howmuch == 0
-                if (howmuch > 0) {
-                    r.write(b, off, howmuch);
-                    off += howmuch;
-                    len -= howmuch;
-                }
-                c.writeRecord(r, holdRecord);
-                c.checkWrite();
-            } while (len > 0);
-        } catch (Exception e) {
-            // shutdown and rethrow (wrapped) exception as appropriate
-            c.handleException(e);
-        }
-    }
-
-    /**
-     * Write one byte now.
-     */
-    @Override
-    synchronized public void write(int i) throws IOException {
-        oneByte[0] = (byte)i;
-        write(oneByte, 0, 1);
-    }
-
-    /*
-     * Socket close is already synchronized, no need to block here.
-     */
-    @Override
-    public void close() throws IOException {
-        c.close();
-    }
-
-    // inherit no-op flush()
-}
--- a/src/share/classes/sun/security/ssl/Authenticator.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.Arrays;
-
-/**
- * This class represents an SSL/TLS message authentication token,
- * which encapsulates a sequence number and ensures that attempts to
- * delete or reorder messages can be detected.
- *
- * Each SSL/TLS connection state contains a sequence number, which
- * is maintained separately for read and write states.  The sequence
- * number MUST be set to zero whenever a connection state is made the
- * active state.  Sequence numbers are of type uint64 and may not
- * exceed 2^64-1.  Sequence numbers do not wrap.  If a SSL/TLS
- * implementation would need to wrap a sequence number, it must
- * renegotiate instead.  A sequence number is incremented after each
- * record: specifically, the first record transmitted under a
- * particular connection state MUST use sequence number 0.
- */
-class Authenticator {
-
-    // byte array containing the additional authentication information for
-    // each record
-    private final byte[] block;
-
-    // the block size of SSL v3.0:
-    // sequence number + record type + + record length
-    private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
-
-    // the block size of TLS v1.0 and later:
-    // sequence number + record type + protocol version + record length
-    private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
-
-    /**
-     * Default construct, no message authentication token is initialized.
-     *
-     * Note that this construct can only be called for null MAC
-     */
-    Authenticator() {
-        block = new byte[0];
-    }
-
-    /**
-     * Constructs the message authentication token for the specified
-     * SSL/TLS protocol.
-     */
-    Authenticator(ProtocolVersion protocolVersion) {
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            block = new byte[BLOCK_SIZE_TLS];
-            block[9] = protocolVersion.major;
-            block[10] = protocolVersion.minor;
-        } else {
-            block = new byte[BLOCK_SIZE_SSL];
-        }
-    }
-
-    /**
-     * Checks whether the sequence number is close to wrap.
-     *
-     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
-     * Sequence numbers do not wrap. When the sequence number is near
-     * to wrap, we need to close the connection immediately.
-     *
-     * @return true if the sequence number is close to wrap
-     */
-    final boolean seqNumOverflow() {
-        /*
-         * Conservatively, we don't allow more records to be generated
-         * when there are only 2^8 sequence numbers left.
-         */
-        return (block.length != 0 &&
-                block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
-                block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
-                block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
-                block[6] == (byte)0xFF);
-    }
-
-    /**
-     * Checks whether the sequence number close to renew.
-     *
-     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
-     * Sequence numbers do not wrap.  If a TLS
-     * implementation would need to wrap a sequence number, it must
-     * renegotiate instead.
-     *
-     * @return true if the sequence number is huge enough to renew
-     */
-    final boolean seqNumIsHuge() {
-        /*
-         * Conservatively, we should ask for renegotiation when there are
-         * only 2^48 sequence numbers left.
-         */
-        return (block.length != 0 &&
-                block[0] == (byte)0xFF && block[1] == (byte)0xFF);
-    }
-
-    /**
-     * Gets the current sequence number.
-     *
-     * @return the byte array of the current sequence number
-     */
-    final byte[] sequenceNumber() {
-        return Arrays.copyOf(block, 8);
-    }
-
-    /**
-     * Acquires the current message authentication information with the
-     * specified record type and fragment length, and then increases the
-     * sequence number.
-     *
-     * @param  type the record type
-     * @param  length the fragment of the record
-     * @return the byte array of the current message authentication information
-     */
-    final byte[] acquireAuthenticationBytes(byte type, int length) {
-        byte[] copy = block.clone();
-
-        if (block.length != 0) {
-            copy[8] = type;
-            copy[copy.length - 2] = (byte)(length >> 8);
-            copy[copy.length - 1] = (byte)(length);
-
-            /*
-             * Increase the sequence number in the block array
-             * it is a 64-bit number stored in big-endian format
-             */
-            int k = 7;
-            while ((k >= 0) && (++block[k] == 0)) {
-                k--;
-            }
-        }
-
-        return copy;
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,640 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, 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.*;
-import java.nio.channels.SocketChannel;
-import java.net.*;
-
-import javax.net.ssl.*;
-
-/**
- * Abstract base class for SSLSocketImpl. Its purpose is to house code with
- * no SSL related logic (or no logic at all). This makes SSLSocketImpl shorter
- * and easier to read. It contains a few constants and static methods plus
- * overridden java.net.Socket methods.
- *
- * Methods are defined final to ensure that they are not accidentally
- * overridden in SSLSocketImpl.
- *
- * @see javax.net.ssl.SSLSocket
- * @see SSLSocketImpl
- *
- */
-abstract class BaseSSLSocketImpl extends SSLSocket {
-
-    /*
-     * Normally "self" is "this" ... but not when this connection is
-     * layered over a preexisting socket.  If we're using an existing
-     * socket, we delegate some actions to it.  Else, we delegate
-     * instead to "super".  This is important to ensure that we don't
-     * recurse infinitely ... e.g. close() calling itself, or doing
-     * I/O in terms of our own streams.
-     */
-    final private Socket self;
-    final private InputStream consumedInput;
-
-    BaseSSLSocketImpl() {
-        super();
-        this.self = this;
-        this.consumedInput = null;
-    }
-
-    BaseSSLSocketImpl(Socket socket) {
-        super();
-        this.self = socket;
-        this.consumedInput = null;
-    }
-
-    BaseSSLSocketImpl(Socket socket, InputStream consumed) {
-        super();
-        this.self = socket;
-        this.consumedInput = consumed;
-    }
-
-    //
-    // CONSTANTS AND STATIC METHODS
-    //
-
-    /**
-     * TLS requires that a close_notify warning alert is sent before the
-     * connection is closed in order to avoid truncation attacks. Some
-     * implementations (MS IIS and others) don't do that. The property
-     * below controls whether we accept that or treat it as an error.
-     *
-     * The default is "false", i.e. tolerate the broken behavior.
-     */
-    private final static String PROP_NAME =
-                                "com.sun.net.ssl.requireCloseNotify";
-
-    final static boolean requireCloseNotify =
-                                Debug.getBooleanProperty(PROP_NAME, false);
-
-    //
-    // MISC SOCKET METHODS
-    //
-
-    /**
-     * Returns the unique {@link java.nio.SocketChannel SocketChannel} object
-     * associated with this socket, if any.
-     * @see java.net.Socket#getChannel
-     */
-    @Override
-    public final SocketChannel getChannel() {
-        if (self == this) {
-            return super.getChannel();
-        } else {
-            return self.getChannel();
-        }
-    }
-
-    /**
-     * Binds the address to the socket.
-     * @see java.net.Socket#bind
-     */
-    @Override
-    public void bind(SocketAddress bindpoint) throws IOException {
-        /*
-         * Bind to this socket
-         */
-        if (self == this) {
-            super.bind(bindpoint);
-        } else {
-            // If we're binding on a layered socket...
-            throw new IOException(
-                "Underlying socket should already be connected");
-        }
-    }
-
-    /**
-     * Returns the address of the endpoint this socket is connected to
-     * @see java.net.Socket#getLocalSocketAddress
-     */
-    @Override
-    public SocketAddress getLocalSocketAddress() {
-        if (self == this) {
-            return super.getLocalSocketAddress();
-        } else {
-            return self.getLocalSocketAddress();
-        }
-    }
-
-    /**
-     * Returns the address of the endpoint this socket is connected to
-     * @see java.net.Socket#getRemoteSocketAddress
-     */
-    @Override
-    public SocketAddress getRemoteSocketAddress() {
-        if (self == this) {
-            return super.getRemoteSocketAddress();
-        } else {
-            return self.getRemoteSocketAddress();
-        }
-    }
-
-    /**
-     * Connects this socket to the server.
-     *
-     * This method is either called on an unconnected SSLSocketImpl by the
-     * application, or it is called in the constructor of a regular
-     * SSLSocketImpl. If we are layering on top on another socket, then
-     * this method should not be called, because we assume that the
-     * underlying socket is already connected by the time it is passed to
-     * us.
-     *
-     * @param   endpoint the <code>SocketAddress</code>
-     * @throws  IOException if an error occurs during the connection
-     */
-    @Override
-    public final void connect(SocketAddress endpoint) throws IOException {
-        connect(endpoint, 0);
-    }
-
-    /**
-     * Returns the connection state of the socket.
-     * @see java.net.Socket#isConnected
-     */
-    @Override
-    public final boolean isConnected() {
-        if (self == this) {
-            return super.isConnected();
-        } else {
-            return self.isConnected();
-        }
-    }
-
-    /**
-     * Returns the binding state of the socket.
-     * @see java.net.Socket#isBound
-     */
-    @Override
-    public final boolean isBound() {
-        if (self == this) {
-            return super.isBound();
-        } else {
-            return self.isBound();
-        }
-    }
-
-    //
-    // CLOSE RELATED METHODS
-    //
-
-    /**
-     * The semantics of shutdownInput is not supported in TLS 1.0
-     * spec. Thus when the method is called on an SSL socket, an
-     * UnsupportedOperationException will be thrown.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public final void shutdownInput() throws IOException {
-        throw new UnsupportedOperationException("The method shutdownInput()" +
-                   " is not supported in SSLSocket");
-    }
-
-    /**
-     * The semantics of shutdownOutput is not supported in TLS 1.0
-     * spec. Thus when the method is called on an SSL socket, an
-     * UnsupportedOperationException will be thrown.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public final void shutdownOutput() throws IOException {
-        throw new UnsupportedOperationException("The method shutdownOutput()" +
-                   " is not supported in SSLSocket");
-
-    }
-
-    /**
-     * Returns the input state of the socket
-     * @see java.net.Socket#isInputShutdown
-     */
-    @Override
-    public final boolean isInputShutdown() {
-        if (self == this) {
-            return super.isInputShutdown();
-        } else {
-            return self.isInputShutdown();
-        }
-    }
-
-    /**
-     * Returns the output state of the socket
-     * @see java.net.Socket#isOutputShutdown
-     */
-    @Override
-    public final boolean isOutputShutdown() {
-        if (self == this) {
-            return super.isOutputShutdown();
-        } else {
-            return self.isOutputShutdown();
-        }
-    }
-
-    /**
-     * Ensures that the SSL connection is closed down as cleanly
-     * as possible, in case the application forgets to do so.
-     * This allows SSL connections to be implicitly reclaimed,
-     * rather than forcing them to be explicitly reclaimed at
-     * the penalty of prematurly killing SSL sessions.
-     */
-    @Override
-    protected final void finalize() throws Throwable {
-        try {
-            close();
-        } catch (IOException e1) {
-            try {
-                if (self == this) {
-                    super.close();
-                }
-            } catch (IOException e2) {
-                // ignore
-            }
-        } finally {
-            // We called close on the underlying socket above to
-            // make doubly sure all resources got released.  We
-            // don't finalize self in the case of overlain sockets,
-            // that's a different object which the GC will finalize
-            // separately.
-
-            super.finalize();
-        }
-    }
-
-    //
-    // GET ADDRESS METHODS
-    //
-
-    /**
-     * Returns the address of the remote peer for this connection.
-     */
-    @Override
-    public final InetAddress getInetAddress() {
-        if (self == this) {
-            return super.getInetAddress();
-        } else {
-            return self.getInetAddress();
-        }
-    }
-
-    /**
-     * Gets the local address to which the socket is bound.
-     *
-     * @return the local address to which the socket is bound.
-     * @since   JDK1.1
-     */
-    @Override
-    public final InetAddress getLocalAddress() {
-        if (self == this) {
-            return super.getLocalAddress();
-        } else {
-            return self.getLocalAddress();
-        }
-    }
-
-    /**
-     * Returns the number of the remote port that this connection uses.
-     */
-    @Override
-    public final int getPort() {
-        if (self == this) {
-            return super.getPort();
-        } else {
-            return self.getPort();
-        }
-    }
-
-    /**
-     * Returns the number of the local port that this connection uses.
-     */
-    @Override
-    public final int getLocalPort() {
-        if (self == this) {
-            return super.getLocalPort();
-        } else {
-            return self.getLocalPort();
-        }
-    }
-
-    //
-    // SOCKET OPTION METHODS
-    //
-
-    /**
-     * Enables or disables the Nagle optimization.
-     * @see java.net.Socket#setTcpNoDelay
-     */
-    @Override
-    public final void setTcpNoDelay(boolean value) throws SocketException {
-        if (self == this) {
-            super.setTcpNoDelay(value);
-        } else {
-            self.setTcpNoDelay(value);
-        }
-    }
-
-    /**
-     * Returns true if the Nagle optimization is disabled.  This
-     * relates to low-level buffering of TCP traffic, delaying the
-     * traffic to promote better throughput.
-     *
-     * @see java.net.Socket#getTcpNoDelay
-     */
-    @Override
-    public final boolean getTcpNoDelay() throws SocketException {
-        if (self == this) {
-            return super.getTcpNoDelay();
-        } else {
-            return self.getTcpNoDelay();
-        }
-    }
-
-    /**
-     * Assigns the socket's linger timeout.
-     * @see java.net.Socket#setSoLinger
-     */
-    @Override
-    public final void setSoLinger(boolean flag, int linger)
-            throws SocketException {
-        if (self == this) {
-            super.setSoLinger(flag, linger);
-        } else {
-            self.setSoLinger(flag, linger);
-        }
-    }
-
-    /**
-     * Returns the socket's linger timeout.
-     * @see java.net.Socket#getSoLinger
-     */
-    @Override
-    public final int getSoLinger() throws SocketException {
-        if (self == this) {
-            return super.getSoLinger();
-        } else {
-            return self.getSoLinger();
-        }
-    }
-
-    /**
-     * Send one byte of urgent data on the socket.
-     * @see java.net.Socket#sendUrgentData
-     * At this point, there seems to be no specific requirement to support
-     * this for an SSLSocket. An implementation can be provided if a need
-     * arises in future.
-     */
-    @Override
-    public final void sendUrgentData(int data) throws SocketException {
-        throw new SocketException("This method is not supported "
-                        + "by SSLSockets");
-    }
-
-    /**
-     * Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this
-     * option is disabled and TCP urgent data received on a socket is silently
-     * discarded.
-     * @see java.net.Socket#setOOBInline
-     * Setting OOBInline does not have any effect on SSLSocket,
-     * since currently we don't support sending urgent data.
-     */
-    @Override
-    public final void setOOBInline(boolean on) throws SocketException {
-        throw new SocketException("This method is ineffective, since"
-                + " sending urgent data is not supported by SSLSockets");
-    }
-
-    /**
-     * Tests if OOBINLINE is enabled.
-     * @see java.net.Socket#getOOBInline
-     */
-    @Override
-    public final boolean getOOBInline() throws SocketException {
-        throw new SocketException("This method is ineffective, since"
-                + " sending urgent data is not supported by SSLSockets");
-    }
-
-    /**
-     * Returns the socket timeout.
-     * @see java.net.Socket#getSoTimeout
-     */
-    @Override
-    public final int getSoTimeout() throws SocketException {
-        if (self == this) {
-            return super.getSoTimeout();
-        } else {
-            return self.getSoTimeout();
-        }
-    }
-
-    @Override
-    public final void setSendBufferSize(int size) throws SocketException {
-        if (self == this) {
-            super.setSendBufferSize(size);
-        } else {
-            self.setSendBufferSize(size);
-        }
-    }
-
-    @Override
-    public final int getSendBufferSize() throws SocketException {
-        if (self == this) {
-            return super.getSendBufferSize();
-        } else {
-            return self.getSendBufferSize();
-        }
-    }
-
-    @Override
-    public final void setReceiveBufferSize(int size) throws SocketException {
-        if (self == this) {
-            super.setReceiveBufferSize(size);
-        } else {
-            self.setReceiveBufferSize(size);
-        }
-    }
-
-    @Override
-    public final int getReceiveBufferSize() throws SocketException {
-        if (self == this) {
-            return super.getReceiveBufferSize();
-        } else {
-            return self.getReceiveBufferSize();
-        }
-    }
-
-    /**
-     * Enable/disable SO_KEEPALIVE.
-     * @see java.net.Socket#setKeepAlive
-     */
-    @Override
-    public final void setKeepAlive(boolean on) throws SocketException {
-        if (self == this) {
-            super.setKeepAlive(on);
-        } else {
-            self.setKeepAlive(on);
-        }
-    }
-
-    /**
-     * Tests if SO_KEEPALIVE is enabled.
-     * @see java.net.Socket#getKeepAlive
-     */
-    @Override
-    public final boolean getKeepAlive() throws SocketException {
-        if (self == this) {
-            return super.getKeepAlive();
-        } else {
-            return self.getKeepAlive();
-        }
-    }
-
-    /**
-     * Sets traffic class or type-of-service octet in the IP header for
-     * packets sent from this Socket.
-     * @see java.net.Socket#setTrafficClass
-     */
-    @Override
-    public final void setTrafficClass(int tc) throws SocketException {
-        if (self == this) {
-            super.setTrafficClass(tc);
-        } else {
-            self.setTrafficClass(tc);
-        }
-    }
-
-    /**
-     * Gets traffic class or type-of-service in the IP header for packets
-     * sent from this Socket.
-     * @see java.net.Socket#getTrafficClass
-     */
-    @Override
-    public final int getTrafficClass() throws SocketException {
-        if (self == this) {
-            return super.getTrafficClass();
-        } else {
-            return self.getTrafficClass();
-        }
-    }
-
-    /**
-     * Enable/disable SO_REUSEADDR.
-     * @see java.net.Socket#setReuseAddress
-     */
-    @Override
-    public final void setReuseAddress(boolean on) throws SocketException {
-        if (self == this) {
-            super.setReuseAddress(on);
-        } else {
-            self.setReuseAddress(on);
-        }
-    }
-
-    /**
-     * Tests if SO_REUSEADDR is enabled.
-     * @see java.net.Socket#getReuseAddress
-     */
-    @Override
-    public final boolean getReuseAddress() throws SocketException {
-        if (self == this) {
-            return super.getReuseAddress();
-        } else {
-            return self.getReuseAddress();
-        }
-    }
-
-    /**
-     * Sets performance preferences for this socket.
-     *
-     * @see java.net.Socket#setPerformancePreferences(int, int, int)
-     */
-    @Override
-    public void setPerformancePreferences(int connectionTime,
-            int latency, int bandwidth) {
-        if (self == this) {
-            super.setPerformancePreferences(
-                connectionTime, latency, bandwidth);
-        } else {
-            self.setPerformancePreferences(
-                connectionTime, latency, bandwidth);
-        }
-    }
-
-    @Override
-    public String toString() {
-        if (self == this) {
-            return super.toString();
-        }
-
-        return self.toString();
-    }
-
-    @Override
-    public InputStream getInputStream() throws IOException {
-        if (self == this) {
-            return super.getInputStream();
-        }
-
-        if (consumedInput != null) {
-            return new SequenceInputStream(consumedInput,
-                                                self.getInputStream());
-        }
-
-        return self.getInputStream();
-    }
-
-    @Override
-    public OutputStream getOutputStream() throws IOException {
-        if (self == this) {
-            return super.getOutputStream();
-        }
-
-        return self.getOutputStream();
-    }
-
-    @Override
-    public synchronized void close() throws IOException {
-        if (self == this) {
-            super.close();
-        } else {
-            self.close();
-        }
-    }
-
-    @Override
-    public synchronized void setSoTimeout(int timeout) throws SocketException {
-        if (self == this) {
-            super.setSoTimeout(timeout);
-        } else {
-            self.setSoTimeout(timeout);
-        }
-    }
-
-    boolean isLayered() {
-        return (self != this);
-    }
-}
--- a/src/share/classes/sun/security/ssl/ByteBufferInputStream.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2003, 2014, 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.*;
-import java.nio.*;
-
-/**
- * A simple InputStream which uses ByteBuffers as it's backing store.
- * <P>
- * The only IOException should come if the InputStream has been closed.
- * All other IOException should not occur because all the data is local.
- * Data reads on an exhausted ByteBuffer returns a -1.
- *
- * @author  Brad Wetmore
- */
-class ByteBufferInputStream extends InputStream {
-
-    ByteBuffer bb;
-
-    ByteBufferInputStream(ByteBuffer bb) {
-        this.bb = bb;
-    }
-
-    /**
-     * Returns a byte from the ByteBuffer.
-     *
-     * Increments position().
-     */
-    @Override
-    public int read() throws IOException {
-
-        if (bb == null) {
-            throw new IOException("read on a closed InputStream");
-        }
-
-        if (bb.remaining() == 0) {
-            return -1;
-        }
-
-        return (bb.get() & 0xFF);   // need to be in the range 0 to 255
-    }
-
-    /**
-     * Returns a byte array from the ByteBuffer.
-     *
-     * Increments position().
-     */
-    @Override
-    public int read(byte b[]) throws IOException {
-
-        if (bb == null) {
-            throw new IOException("read on a closed InputStream");
-        }
-
-        return read(b, 0, b.length);
-    }
-
-    /**
-     * Returns a byte array from the ByteBuffer.
-     *
-     * Increments position().
-     */
-    @Override
-    public int read(byte b[], int off, int len) throws IOException {
-
-        if (bb == null) {
-            throw new IOException("read on a closed InputStream");
-        }
-
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return 0;
-        }
-
-        int length = Math.min(bb.remaining(), len);
-        if (length == 0) {
-            return -1;
-        }
-
-        bb.get(b, off, length);
-        return length;
-    }
-
-    /**
-     * Skips over and discards <code>n</code> bytes of data from this input
-     * stream.
-     */
-    @Override
-    public long skip(long n) throws IOException {
-
-        if (bb == null) {
-            throw new IOException("skip on a closed InputStream");
-        }
-
-        if (n <= 0) {
-            return 0;
-        }
-
-        /*
-         * ByteBuffers have at most an int, so lose the upper bits.
-         * The contract allows this.
-         */
-        int nInt = (int) n;
-        int skip = Math.min(bb.remaining(), nInt);
-
-        bb.position(bb.position() + skip);
-
-        return nInt;
-    }
-
-    /**
-     * Returns the number of bytes that can be read (or skipped over)
-     * from this input stream without blocking by the next caller of a
-     * method for this input stream.
-     */
-    @Override
-    public int available() throws IOException {
-
-        if (bb == null) {
-            throw new IOException("available on a closed InputStream");
-        }
-
-        return bb.remaining();
-    }
-
-    /**
-     * Closes this input stream and releases any system resources associated
-     * with the stream.
-     *
-     * @exception  IOException  if an I/O error occurs.
-     */
-    @Override
-    public void close() throws IOException {
-        bb = null;
-    }
-
-    /**
-     * Marks the current position in this input stream.
-     */
-    @Override
-    public synchronized void mark(int readlimit) {}
-
-    /**
-     * Repositions this stream to the position at the time the
-     * <code>mark</code> method was last called on this input stream.
-     */
-    @Override
-    public synchronized void reset() throws IOException {
-        throw new IOException("mark/reset not supported");
-    }
-
-    /**
-     * Tests if this input stream supports the <code>mark</code> and
-     * <code>reset</code> methods.
-     */
-    @Override
-    public boolean markSupported() {
-        return false;
-    }
-}
--- a/src/share/classes/sun/security/ssl/CipherBox.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1089 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, 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.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Arrays;
-
-import java.security.*;
-import javax.crypto.*;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.GCMParameterSpec;
-
-import java.nio.*;
-
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.CipherType.*;
-
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * This class handles bulk data enciphering/deciphering for each SSLv3
- * message.  This provides data confidentiality.  Stream ciphers (such
- * as RC4) don't need to do padding; block ciphers (e.g. DES) need it.
- *
- * Individual instances are obtained by calling the static method
- * newCipherBox(), which should only be invoked by BulkCipher.newCipher().
- *
- * In RFC 2246, with bock ciphers in CBC mode, the Initialization
- * Vector (IV) for the first record is generated with the other keys
- * and secrets when the security parameters are set.  The IV for
- * subsequent records is the last ciphertext block from the previous
- * record.
- *
- * In RFC 4346, the implicit Initialization Vector (IV) is replaced
- * with an explicit IV to protect against CBC attacks.  RFC 4346
- * recommends two algorithms used to generated the per-record IV.
- * The implementation uses the algorithm (2)(b), as described at
- * section 6.2.3.2 of RFC 4346.
- *
- * The usage of IV in CBC block cipher can be illustrated in
- * the following diagrams.
- *
- *   (random)
- *        R         P1                    IV        C1
- *        |          |                     |         |
- *  SIV---+    |-----+    |-...            |-----    |------
- *        |    |     |    |                |    |    |     |
- *     +----+  |  +----+  |             +----+  |  +----+  |
- *     | Ek |  |  + Ek +  |             | Dk |  |  | Dk |  |
- *     +----+  |  +----+  |             +----+  |  +----+  |
- *        |    |     |    |                |    |    |     |
- *        |----|     |----|           SIV--+    |----|     |-...
- *        |          |                     |       |
- *       IV         C1                     R      P1
- *                                     (discard)
- *
- *       CBC Encryption                    CBC Decryption
- *
- * NOTE that any ciphering involved in key exchange (e.g. with RSA) is
- * handled separately.
- *
- * @author David Brownell
- * @author Andreas Sterbenz
- */
-final class CipherBox {
-
-    // A CipherBox that implements the identity operation
-    final static CipherBox NULL = new CipherBox();
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    // the protocol version this cipher conforms to
-    private final ProtocolVersion protocolVersion;
-
-    // cipher object
-    private final Cipher cipher;
-
-    /**
-     * secure random
-     */
-    private SecureRandom random;
-
-    /**
-     * fixed IV, the implicit nonce of AEAD cipher suite, only apply to
-     * AEAD cipher suites
-     */
-    private final byte[] fixedIv;
-
-    /**
-     * the key, reserved only for AEAD cipher initialization
-     */
-    private final Key key;
-
-    /**
-     * the operation mode, reserved for AEAD cipher initialization
-     */
-    private final int mode;
-
-    /**
-     * the authentication tag size, only apply to AEAD cipher suites
-     */
-    private final int tagSize;
-
-    /**
-     * the record IV length, only apply to AEAD cipher suites
-     */
-    private final int recordIvSize;
-
-    /**
-     * cipher type
-     */
-    private final CipherType cipherType;
-
-    /**
-     * Fixed masks of various block size, as the initial decryption IVs
-     * for TLS 1.1 or later.
-     *
-     * For performance, we do not use random IVs. As the initial decryption
-     * IVs will be discarded by TLS decryption processes, so the fixed masks
-     * do not hurt cryptographic strength.
-     */
-    private static Hashtable<Integer, IvParameterSpec> masks;
-
-    /**
-     * NULL cipherbox. Identity operation, no encryption.
-     */
-    private CipherBox() {
-        this.protocolVersion = ProtocolVersion.DEFAULT;
-        this.cipher = null;
-        this.cipherType = STREAM_CIPHER;
-        this.fixedIv = new byte[0];
-        this.key = null;
-        this.mode = Cipher.ENCRYPT_MODE;    // choose at random
-        this.random = null;
-        this.tagSize = 0;
-        this.recordIvSize = 0;
-    }
-
-    /**
-     * Construct a new CipherBox using the cipher transformation.
-     *
-     * @exception NoSuchAlgorithmException if no appropriate JCE Cipher
-     * implementation could be found.
-     */
-    private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
-            SecretKey key, IvParameterSpec iv, SecureRandom random,
-            boolean encrypt) throws NoSuchAlgorithmException {
-        try {
-            this.protocolVersion = protocolVersion;
-            this.cipher = JsseJce.getCipher(bulkCipher.transformation);
-            this.mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
-
-            if (random == null) {
-                random = JsseJce.getSecureRandom();
-            }
-            this.random = random;
-            this.cipherType = bulkCipher.cipherType;
-
-            /*
-             * RFC 4346 recommends two algorithms used to generated the
-             * per-record IV. The implementation uses the algorithm (2)(b),
-             * as described at section 6.2.3.2 of RFC 4346.
-             *
-             * As we don't care about the initial IV value for TLS 1.1 or
-             * later, so if the "iv" parameter is null, we use the default
-             * value generated by Cipher.init() for encryption, and a fixed
-             * mask for decryption.
-             */
-            if (iv == null && bulkCipher.ivSize != 0 &&
-                    mode == Cipher.DECRYPT_MODE &&
-                    protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                iv = getFixedMask(bulkCipher.ivSize);
-            }
-
-            if (cipherType == AEAD_CIPHER) {
-                // AEAD must completely initialize the cipher for each packet,
-                // and so we save initialization parameters for packet
-                // processing time.
-
-                // Set the tag size for AEAD cipher
-                tagSize = bulkCipher.tagSize;
-
-                // Reserve the key for AEAD cipher initialization
-                this.key = key;
-
-                fixedIv = iv.getIV();
-                if (fixedIv == null ||
-                        fixedIv.length != bulkCipher.fixedIvSize) {
-                    throw new RuntimeException("Improper fixed IV for AEAD");
-                }
-
-                // Set the record IV length for AEAD cipher
-                recordIvSize = bulkCipher.ivSize - bulkCipher.fixedIvSize;
-
-                // DON'T initialize the cipher for AEAD!
-            } else {
-                // CBC only requires one initialization during its lifetime
-                // (future packets/IVs set the proper CBC state), so we can
-                // initialize now.
-
-                // Zeroize the variables that only apply to AEAD cipher
-                this.tagSize = 0;
-                this.fixedIv = new byte[0];
-                this.recordIvSize = 0;
-                this.key = null;
-
-                // Initialize the cipher
-                cipher.init(mode, key, iv, random);
-            }
-        } catch (NoSuchAlgorithmException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new NoSuchAlgorithmException
-                    ("Could not create cipher " + bulkCipher, e);
-        } catch (ExceptionInInitializerError e) {
-            throw new NoSuchAlgorithmException
-                    ("Could not create cipher " + bulkCipher, e);
-        }
-    }
-
-    /*
-     * Factory method to obtain a new CipherBox object.
-     */
-    static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
-            SecretKey key, IvParameterSpec iv, SecureRandom random,
-            boolean encrypt) throws NoSuchAlgorithmException {
-        if (cipher.allowed == false) {
-            throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
-        }
-
-        if (cipher == B_NULL) {
-            return NULL;
-        } else {
-            return new CipherBox(version, cipher, key, iv, random, encrypt);
-        }
-    }
-
-    /*
-     * Get a fixed mask, as the initial decryption IVs for TLS 1.1 or later.
-     */
-    private static IvParameterSpec getFixedMask(int ivSize) {
-        if (masks == null) {
-            masks = new Hashtable<Integer, IvParameterSpec>(5);
-        }
-
-        IvParameterSpec iv = masks.get(ivSize);
-        if (iv == null) {
-            iv = new IvParameterSpec(new byte[ivSize]);
-            masks.put(ivSize, iv);
-        }
-
-        return iv;
-    }
-
-    /*
-     * Encrypts a block of data, returning the size of the
-     * resulting block.
-     */
-    int encrypt(byte[] buf, int offset, int len) {
-        if (cipher == null) {
-            return len;
-        }
-
-        try {
-            int blockSize = cipher.getBlockSize();
-            if (cipherType == BLOCK_CIPHER) {
-                len = addPadding(buf, offset, len, blockSize);
-            }
-
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext before ENCRYPTION:  len = "
-                        + len);
-                    hd.encodeBuffer(
-                        new ByteArrayInputStream(buf, offset, len),
-                        System.out);
-                } catch (IOException e) { }
-            }
-
-
-            if (cipherType == AEAD_CIPHER) {
-                try {
-                    return cipher.doFinal(buf, offset, len, buf, offset);
-                } catch (IllegalBlockSizeException | BadPaddingException ibe) {
-                    // unlikely to happen
-                    throw new RuntimeException(
-                        "Cipher error in AEAD mode in JCE provider " +
-                        cipher.getProvider().getName(), ibe);
-                }
-            } else {
-                int newLen = cipher.update(buf, offset, len, buf, offset);
-                if (newLen != len) {
-                    // catch BouncyCastle buffering error
-                    throw new RuntimeException("Cipher buffering error " +
-                        "in JCE provider " + cipher.getProvider().getName());
-                }
-                return newLen;
-            }
-        } catch (ShortBufferException e) {
-            // unlikely to happen, we should have enough buffer space here
-            throw new ArrayIndexOutOfBoundsException(e.toString());
-        }
-    }
-
-    /*
-     * Encrypts a ByteBuffer block of data, returning the size of the
-     * resulting block.
-     *
-     * The byte buffers position and limit initially define the amount
-     * to encrypt.  On return, the position and limit are
-     * set to last position padded/encrypted.  The limit may have changed
-     * because of the added padding bytes.
-     */
-    int encrypt(ByteBuffer bb, int outLimit) {
-
-        int len = bb.remaining();
-
-        if (cipher == null) {
-            bb.position(bb.limit());
-            return len;
-        }
-
-        int pos = bb.position();
-
-        int blockSize = cipher.getBlockSize();
-        if (cipherType == BLOCK_CIPHER) {
-            // addPadding adjusts pos/limit
-            len = addPadding(bb, blockSize);
-            bb.position(pos);
-        }
-
-        if (debug != null && Debug.isOn("plaintext")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-
-                System.out.println(
-                    "Padded plaintext before ENCRYPTION:  len = "
-                    + len);
-                hd.encodeBuffer(bb.duplicate(), System.out);
-
-            } catch (IOException e) { }
-        }
-
-        /*
-         * Encrypt "in-place".  This does not add its own padding.
-         */
-        ByteBuffer dup = bb.duplicate();
-        if (cipherType == AEAD_CIPHER) {
-            try {
-                int outputSize = cipher.getOutputSize(dup.remaining());
-                if (outputSize > bb.remaining()) {
-                    // need to expand the limit of the output buffer for
-                    // the authentication tag.
-                    //
-                    // DON'T worry about the buffer's capacity, we have
-                    // reserved space for the authentication tag.
-                    if (outLimit < pos + outputSize) {
-                        // unlikely to happen
-                        throw new ShortBufferException(
-                                    "need more space in output buffer");
-                    }
-                    bb.limit(pos + outputSize);
-                }
-                int newLen = cipher.doFinal(dup, bb);
-                if (newLen != outputSize) {
-                    throw new RuntimeException(
-                            "Cipher buffering error in JCE provider " +
-                            cipher.getProvider().getName());
-                }
-                return newLen;
-            } catch (IllegalBlockSizeException |
-                           BadPaddingException | ShortBufferException ibse) {
-                // unlikely to happen
-                throw new RuntimeException(
-                        "Cipher error in AEAD mode in JCE provider " +
-                        cipher.getProvider().getName(), ibse);
-            }
-        } else {
-            int newLen;
-            try {
-                newLen = cipher.update(dup, bb);
-            } catch (ShortBufferException sbe) {
-                // unlikely to happen
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
-            }
-
-            if (bb.position() != dup.position()) {
-                throw new RuntimeException("bytebuffer padding error");
-            }
-
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
-            }
-            return newLen;
-        }
-    }
-
-
-    /*
-     * Decrypts a block of data, returning the size of the
-     * resulting block if padding was required.
-     *
-     * For SSLv3 and TLSv1.0, with block ciphers in CBC mode the
-     * Initialization Vector (IV) for the first record is generated by
-     * the handshake protocol, the IV for subsequent records is the
-     * last ciphertext block from the previous record.
-     *
-     * From TLSv1.1, the implicit IV is replaced with an explicit IV to
-     * protect against CBC attacks.
-     *
-     * Differentiating between bad_record_mac and decryption_failed alerts
-     * may permit certain attacks against CBC mode. It is preferable to
-     * uniformly use the bad_record_mac alert to hide the specific type of
-     * the error.
-     */
-    int decrypt(byte[] buf, int offset, int len,
-            int tagLen) throws BadPaddingException {
-        if (cipher == null) {
-            return len;
-        }
-
-        try {
-            int newLen;
-            if (cipherType == AEAD_CIPHER) {
-                try {
-                    newLen = cipher.doFinal(buf, offset, len, buf, offset);
-                } catch (IllegalBlockSizeException ibse) {
-                    // unlikely to happen
-                    throw new RuntimeException(
-                        "Cipher error in AEAD mode in JCE provider " +
-                        cipher.getProvider().getName(), ibse);
-                }
-            } else {
-                newLen = cipher.update(buf, offset, len, buf, offset);
-                if (newLen != len) {
-                    // catch BouncyCastle buffering error
-                    throw new RuntimeException("Cipher buffering error " +
-                        "in JCE provider " + cipher.getProvider().getName());
-                }
-            }
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext after DECRYPTION:  len = "
-                        + newLen);
-                    hd.encodeBuffer(
-                        new ByteArrayInputStream(buf, offset, newLen),
-                        System.out);
-                } catch (IOException e) { }
-            }
-
-            if (cipherType == BLOCK_CIPHER) {
-                int blockSize = cipher.getBlockSize();
-                newLen = removePadding(
-                    buf, offset, newLen, tagLen, blockSize, protocolVersion);
-
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    if (newLen < blockSize) {
-                        throw new BadPaddingException("The length after " +
-                        "padding removal (" + newLen + ") should be larger " +
-                        "than <" + blockSize + "> since explicit IV used");
-                    }
-                }
-            }
-            return newLen;
-        } catch (ShortBufferException e) {
-            // unlikely to happen, we should have enough buffer space here
-            throw new ArrayIndexOutOfBoundsException(e.toString());
-        }
-    }
-
-    /*
-     * Decrypts a block of data, returning the size of the
-     * resulting block if padding was required.  position and limit
-     * point to the end of the decrypted/depadded data.  The initial
-     * limit and new limit may be different, given we may
-     * have stripped off some padding bytes.
-     *
-     *  @see decrypt(byte[], int, int)
-     */
-    int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException {
-
-        int len = bb.remaining();
-
-        if (cipher == null) {
-            bb.position(bb.limit());
-            return len;
-        }
-
-        try {
-            /*
-             * Decrypt "in-place".
-             */
-            int pos = bb.position();
-            ByteBuffer dup = bb.duplicate();
-            int newLen;
-            if (cipherType == AEAD_CIPHER) {
-                try {
-                    newLen = cipher.doFinal(dup, bb);
-                } catch (IllegalBlockSizeException ibse) {
-                    // unlikely to happen
-                    throw new RuntimeException(
-                        "Cipher error in AEAD mode \"" + ibse.getMessage() +
-                        " \"in JCE provider " + cipher.getProvider().getName());
-                }
-            } else {
-                newLen = cipher.update(dup, bb);
-                if (newLen != len) {
-                    // catch BouncyCastle buffering error
-                    throw new RuntimeException("Cipher buffering error " +
-                        "in JCE provider " + cipher.getProvider().getName());
-                }
-            }
-
-            // reset the limit to the end of the decryted data
-            bb.limit(pos + newLen);
-
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext after DECRYPTION:  len = "
-                        + newLen);
-
-                    hd.encodeBuffer(
-                        (ByteBuffer)bb.duplicate().position(pos), System.out);
-                } catch (IOException e) { }
-            }
-
-            /*
-             * Remove the block padding.
-             */
-            if (cipherType == BLOCK_CIPHER) {
-                int blockSize = cipher.getBlockSize();
-                bb.position(pos);
-                newLen = removePadding(bb, tagLen, blockSize, protocolVersion);
-
-                // check the explicit IV of TLS v1.1 or later
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    if (newLen < blockSize) {
-                        throw new BadPaddingException("The length after " +
-                        "padding removal (" + newLen + ") should be larger " +
-                        "than <" + blockSize + "> since explicit IV used");
-                    }
-
-                    // reset the position to the end of the decrypted data
-                    bb.position(bb.limit());
-                }
-            }
-            return newLen;
-        } catch (ShortBufferException e) {
-            // unlikely to happen, we should have enough buffer space here
-            throw new ArrayIndexOutOfBoundsException(e.toString());
-        }
-    }
-
-    private static int addPadding(byte[] buf, int offset, int len,
-            int blockSize) {
-        int     newlen = len + 1;
-        byte    pad;
-        int     i;
-
-        if ((newlen % blockSize) != 0) {
-            newlen += blockSize - 1;
-            newlen -= newlen % blockSize;
-        }
-        pad = (byte) (newlen - len);
-
-        if (buf.length < (newlen + offset)) {
-            throw new IllegalArgumentException("no space to pad buffer");
-        }
-
-        /*
-         * TLS version of the padding works for both SSLv3 and TLSv1
-         */
-        for (i = 0, offset += len; i < pad; i++) {
-            buf [offset++] = (byte) (pad - 1);
-        }
-        return newlen;
-    }
-
-    /*
-     * Apply the padding to the buffer.
-     *
-     * Limit is advanced to the new buffer length.
-     * Position is equal to limit.
-     */
-    private static int addPadding(ByteBuffer bb, int blockSize) {
-
-        int     len = bb.remaining();
-        int     offset = bb.position();
-
-        int     newlen = len + 1;
-        byte    pad;
-        int     i;
-
-        if ((newlen % blockSize) != 0) {
-            newlen += blockSize - 1;
-            newlen -= newlen % blockSize;
-        }
-        pad = (byte) (newlen - len);
-
-        /*
-         * Update the limit to what will be padded.
-         */
-        bb.limit(newlen + offset);
-
-        /*
-         * TLS version of the padding works for both SSLv3 and TLSv1
-         */
-        for (i = 0, offset += len; i < pad; i++) {
-            bb.put(offset++, (byte) (pad - 1));
-        }
-
-        bb.position(offset);
-        bb.limit(offset);
-
-        return newlen;
-    }
-
-    /*
-     * A constant-time check of the padding.
-     *
-     * NOTE that we are checking both the padding and the padLen bytes here.
-     *
-     * The caller MUST ensure that the len parameter is a positive number.
-     */
-    private static int[] checkPadding(
-            byte[] buf, int offset, int len, byte pad) {
-
-        if (len <= 0) {
-            throw new RuntimeException("padding len must be positive");
-        }
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};    // {missed #, matched #}
-        for (int i = 0; i <= 256;) {
-            for (int j = 0; j < len && i <= 256; j++, i++) {     // j <= i
-                if (buf[offset + j] != pad) {
-                    results[0]++;       // mismatched padding data
-                } else {
-                    results[1]++;       // matched padding data
-                }
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * A constant-time check of the padding.
-     *
-     * NOTE that we are checking both the padding and the padLen bytes here.
-     *
-     * The caller MUST ensure that the bb parameter has remaining.
-     */
-    private static int[] checkPadding(ByteBuffer bb, byte pad) {
-
-        if (!bb.hasRemaining()) {
-            throw new RuntimeException("hasRemaining() must be positive");
-        }
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};    // {missed #, matched #}
-        bb.mark();
-        for (int i = 0; i <= 256; bb.reset()) {
-            for (; bb.hasRemaining() && i <= 256; i++) {
-                if (bb.get() != pad) {
-                    results[0]++;       // mismatched padding data
-                } else {
-                    results[1]++;       // matched padding data
-                }
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * Typical TLS padding format for a 64 bit block cipher is as follows:
-     *   xx xx xx xx xx xx xx 00
-     *   xx xx xx xx xx xx 01 01
-     *   ...
-     *   xx 06 06 06 06 06 06 06
-     *   07 07 07 07 07 07 07 07
-     * TLS also allows any amount of padding from 1 and 256 bytes as long
-     * as it makes the data a multiple of the block size
-     */
-    private static int removePadding(byte[] buf, int offset, int len,
-            int tagLen, int blockSize,
-            ProtocolVersion protocolVersion) throws BadPaddingException {
-
-        // last byte is length byte (i.e. actual padding length - 1)
-        int padOffset = offset + len - 1;
-        int padLen = buf[padOffset] & 0xFF;
-
-        int newLen = len - (padLen + 1);
-        if ((newLen - tagLen) < 0) {
-            // If the buffer is not long enough to contain the padding plus
-            // a MAC tag, do a dummy constant-time padding check.
-            //
-            // Note that it is a dummy check, so we won't care about what is
-            // the actual padding data.
-            checkPadding(buf, offset, len, (byte)(padLen & 0xFF));
-
-            throw new BadPaddingException("Invalid Padding length: " + padLen);
-        }
-
-        // The padding data should be filled with the padding length value.
-        int[] results = checkPadding(buf, offset + newLen,
-                        padLen + 1, (byte)(padLen & 0xFF));
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            if (results[0] != 0) {          // padding data has invalid bytes
-                throw new BadPaddingException("Invalid TLS padding data");
-            }
-        } else { // SSLv3
-            // SSLv3 requires 0 <= length byte < block size
-            // some implementations do 1 <= length byte <= block size,
-            // so accept that as well
-            // v3 does not require any particular value for the other bytes
-            if (padLen > blockSize) {
-                throw new BadPaddingException("Padding length (" +
-                padLen + ") of SSLv3 message should not be bigger " +
-                "than the block size (" + blockSize + ")");
-            }
-        }
-        return newLen;
-    }
-
-    /*
-     * Position/limit is equal the removed padding.
-     */
-    private static int removePadding(ByteBuffer bb,
-            int tagLen, int blockSize,
-            ProtocolVersion protocolVersion) throws BadPaddingException {
-
-        int len = bb.remaining();
-        int offset = bb.position();
-
-        // last byte is length byte (i.e. actual padding length - 1)
-        int padOffset = offset + len - 1;
-        int padLen = bb.get(padOffset) & 0xFF;
-
-        int newLen = len - (padLen + 1);
-        if ((newLen - tagLen) < 0) {
-            // If the buffer is not long enough to contain the padding plus
-            // a MAC tag, do a dummy constant-time padding check.
-            //
-            // Note that it is a dummy check, so we won't care about what is
-            // the actual padding data.
-            checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));
-
-            throw new BadPaddingException("Invalid Padding length: " + padLen);
-        }
-
-        // The padding data should be filled with the padding length value.
-        int[] results = checkPadding(
-                (ByteBuffer)bb.duplicate().position(offset + newLen),
-                (byte)(padLen & 0xFF));
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            if (results[0] != 0) {          // padding data has invalid bytes
-                throw new BadPaddingException("Invalid TLS padding data");
-            }
-        } else { // SSLv3
-            // SSLv3 requires 0 <= length byte < block size
-            // some implementations do 1 <= length byte <= block size,
-            // so accept that as well
-            // v3 does not require any particular value for the other bytes
-            if (padLen > blockSize) {
-                throw new BadPaddingException("Padding length (" +
-                padLen + ") of SSLv3 message should not be bigger " +
-                "than the block size (" + blockSize + ")");
-            }
-        }
-
-        /*
-         * Reset buffer limit to remove padding.
-         */
-        bb.position(offset + newLen);
-        bb.limit(offset + newLen);
-
-        return newLen;
-    }
-
-    /*
-     * Dispose of any intermediate state in the underlying cipher.
-     * For PKCS11 ciphers, this will release any attached sessions, and
-     * thus make finalization faster.
-     */
-    void dispose() {
-        try {
-            if (cipher != null) {
-                // ignore return value.
-                cipher.doFinal();
-            }
-        } catch (Exception e) {
-            // swallow all types of exceptions.
-        }
-    }
-
-    /*
-     * Does the cipher use CBC mode?
-     *
-     * @return true if the cipher use CBC mode, false otherwise.
-     */
-    boolean isCBCMode() {
-        return cipherType == BLOCK_CIPHER;
-    }
-
-    /*
-     * Does the cipher use AEAD mode?
-     *
-     * @return true if the cipher use AEAD mode, false otherwise.
-     */
-    boolean isAEADMode() {
-        return cipherType == AEAD_CIPHER;
-    }
-
-    /*
-     * Is the cipher null?
-     *
-     * @return true if the cipher is null, false otherwise.
-     */
-    boolean isNullCipher() {
-        return cipher == null;
-    }
-
-    /*
-     * Gets the explicit nonce/IV size of the cipher.
-     *
-     * The returned value is the SecurityParameters.record_iv_length in
-     * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
-     * size of explicit nonce for AEAD mode.
-     *
-     * @return the explicit nonce size of the cipher.
-     */
-    int getExplicitNonceSize() {
-        switch (cipherType) {
-            case BLOCK_CIPHER:
-                // For block ciphers, the explicit IV length is of length
-                // SecurityParameters.record_iv_length, which is equal to
-                // the SecurityParameters.block_size.
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    return cipher.getBlockSize();
-                }
-                break;
-            case AEAD_CIPHER:
-                return recordIvSize;
-                        // It is also the length of sequence number, which is
-                        // used as the nonce_explicit for AEAD cipher suites.
-        }
-
-        return 0;
-    }
-
-    /*
-     * Applies the explicit nonce/IV to this cipher. This method is used to
-     * decrypt an SSL/TLS input record.
-     *
-     * The returned value is the SecurityParameters.record_iv_length in
-     * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
-     * size of explicit nonce for AEAD mode.
-     *
-     * @param  authenticator the authenticator to get the additional
-     *         authentication data
-     * @param  contentType the content type of the input record
-     * @param  bb the byte buffer to get the explicit nonce from
-     *
-     * @return the explicit nonce size of the cipher.
-     */
-    int applyExplicitNonce(Authenticator authenticator, byte contentType,
-            ByteBuffer bb) throws BadPaddingException {
-        switch (cipherType) {
-            case BLOCK_CIPHER:
-                // sanity check length of the ciphertext
-                int tagLen = (authenticator instanceof MAC) ?
-                                    ((MAC)authenticator).MAClen() : 0;
-                if (tagLen != 0) {
-                    if (!sanityCheck(tagLen, bb.remaining())) {
-                        throw new BadPaddingException(
-                                "ciphertext sanity check failed");
-                    }
-                }
-
-                // For block ciphers, the explicit IV length is of length
-                // SecurityParameters.record_iv_length, which is equal to
-                // the SecurityParameters.block_size.
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    return cipher.getBlockSize();
-                }
-                break;
-            case AEAD_CIPHER:
-                if (bb.remaining() < (recordIvSize + tagSize)) {
-                    throw new BadPaddingException(
-                        "Insufficient buffer remaining for AEAD cipher " +
-                        "fragment (" + bb.remaining() + "). Needs to be " +
-                        "more than or equal to IV size (" + recordIvSize +
-                         ") + tag size (" + tagSize + ")");
-                }
-
-                // initialize the AEAD cipher for the unique IV
-                byte[] iv = Arrays.copyOf(fixedIv,
-                                    fixedIv.length + recordIvSize);
-                bb.get(iv, fixedIv.length, recordIvSize);
-                bb.position(bb.position() - recordIvSize);
-                GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
-                try {
-                    cipher.init(mode, key, spec, random);
-                } catch (InvalidKeyException |
-                            InvalidAlgorithmParameterException ikae) {
-                    // unlikely to happen
-                    throw new RuntimeException(
-                                "invalid key or spec in GCM mode", ikae);
-                }
-
-                // update the additional authentication data
-                byte[] aad = authenticator.acquireAuthenticationBytes(
-                        contentType, bb.remaining() - recordIvSize - tagSize);
-                cipher.updateAAD(aad);
-
-                return recordIvSize;
-                        // It is also the length of sequence number, which is
-                        // used as the nonce_explicit for AEAD cipher suites.
-        }
-
-       return 0;
-    }
-
-    /*
-     * Applies the explicit nonce/IV to this cipher. This method is used to
-     * decrypt an SSL/TLS input record.
-     *
-     * The returned value is the SecurityParameters.record_iv_length in
-     * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
-     * size of explicit nonce for AEAD mode.
-     *
-     * @param  authenticator the authenticator to get the additional
-     *         authentication data
-     * @param  contentType the content type of the input record
-     * @param  buf the byte array to get the explicit nonce from
-     * @param  offset the offset of the byte buffer
-     * @param  cipheredLength the ciphered fragment length of the output
-     *         record, it is the TLSCiphertext.length in RFC 4346/5246.
-     *
-     * @return the explicit nonce size of the cipher.
-     */
-    int applyExplicitNonce(Authenticator authenticator,
-            byte contentType, byte[] buf, int offset,
-            int cipheredLength) throws BadPaddingException {
-
-        ByteBuffer bb = ByteBuffer.wrap(buf, offset, cipheredLength);
-
-        return applyExplicitNonce(authenticator, contentType, bb);
-    }
-
-    /*
-     * Creates the explicit nonce/IV to this cipher. This method is used to
-     * encrypt an SSL/TLS output record.
-     *
-     * The size of the returned array is the SecurityParameters.record_iv_length
-     * in RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
-     * size of explicit nonce for AEAD mode.
-     *
-     * @param  authenticator the authenticator to get the additional
-     *         authentication data
-     * @param  contentType the content type of the input record
-     * @param  fragmentLength the fragment length of the output record, it is
-     *         the TLSCompressed.length in RFC 4346/5246.
-     *
-     * @return the explicit nonce of the cipher.
-     */
-    byte[] createExplicitNonce(Authenticator authenticator,
-            byte contentType, int fragmentLength) {
-
-        byte[] nonce = new byte[0];
-        switch (cipherType) {
-            case BLOCK_CIPHER:
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    // For block ciphers, the explicit IV length is of length
-                    // SecurityParameters.record_iv_length, which is equal to
-                    // the SecurityParameters.block_size.
-                    //
-                    // Generate a random number as the explicit IV parameter.
-                    nonce = new byte[cipher.getBlockSize()];
-                    random.nextBytes(nonce);
-                }
-                break;
-            case AEAD_CIPHER:
-                // To be unique and aware of overflow-wrap, sequence number
-                // is used as the nonce_explicit of AEAD cipher suites.
-                nonce = authenticator.sequenceNumber();
-
-                // initialize the AEAD cipher for the unique IV
-                byte[] iv = Arrays.copyOf(fixedIv,
-                                            fixedIv.length + nonce.length);
-                System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
-                GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
-                try {
-                    cipher.init(mode, key, spec, random);
-                } catch (InvalidKeyException |
-                            InvalidAlgorithmParameterException ikae) {
-                    // unlikely to happen
-                    throw new RuntimeException(
-                                "invalid key or spec in GCM mode", ikae);
-                }
-
-                // update the additional authentication data
-                byte[] aad = authenticator.acquireAuthenticationBytes(
-                                                contentType, fragmentLength);
-                cipher.updateAAD(aad);
-                break;
-        }
-
-        return nonce;
-    }
-
-    /**
-     * Sanity check the length of a fragment before decryption.
-     *
-     * In CBC mode, check that the fragment length is one or multiple times
-     * of the block size of the cipher suite, and is at least one (one is the
-     * smallest size of padding in CBC mode) bigger than the tag size of the
-     * MAC algorithm except the explicit IV size for TLS 1.1 or later.
-     *
-     * In non-CBC mode, check that the fragment length is not less than the
-     * tag size of the MAC algorithm.
-     *
-     * @return true if the length of a fragment matches above requirements
-     */
-    private boolean sanityCheck(int tagLen, int fragmentLen) {
-        if (!isCBCMode()) {
-            return fragmentLen >= tagLen;
-        }
-
-        int blockSize = cipher.getBlockSize();
-        if ((fragmentLen % blockSize) == 0) {
-            int minimal = tagLen + 1;
-            minimal = (minimal >= blockSize) ? minimal : blockSize;
-            if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                minimal += blockSize;   // plus the size of the explicit IV
-            }
-
-            return (fragmentLen >= minimal);
-        }
-
-        return false;
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/CipherSuite.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1618 +0,0 @@
-/*
- * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.*;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.InvalidKeyException;
-import java.security.SecureRandom;
-import java.security.KeyManagementException;
-
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-import static sun.security.ssl.CipherSuite.PRF.*;
-import static sun.security.ssl.CipherSuite.CipherType.*;
-import static sun.security.ssl.JsseJce.*;
-
-/**
- * An SSL/TLS CipherSuite. Constants for the standard key exchange, cipher,
- * and mac algorithms are also defined in this class.
- *
- * The CipherSuite class and the inner classes defined in this file roughly
- * follow the type safe enum pattern described in Effective Java. This means:
- *
- *  . instances are immutable, classes are final
- *
- *  . there is a unique instance of every value, i.e. there are never two
- *    instances representing the same CipherSuite, etc. This means equality
- *    tests can be performed using == instead of equals() (although that works
- *    as well). [A minor exception are *unsupported* CipherSuites read from a
- *    handshake message, but this is usually irrelevant]
- *
- *  . instances are obtained using the static valueOf() factory methods.
- *
- *  . properties are defined as final variables and made available as
- *    package private variables without method accessors
- *
- *  . if the member variable allowed is false, the given algorithm is either
- *    unavailable or disabled at compile time
- *
- */
-final class CipherSuite implements Comparable<CipherSuite> {
-
-    // minimum priority for supported CipherSuites
-    final static int SUPPORTED_SUITES_PRIORITY = 1;
-
-    // minimum priority for default enabled CipherSuites
-    final static int DEFAULT_SUITES_PRIORITY = 300;
-
-    private final static boolean ALLOW_ECC = Debug.getBooleanProperty
-        ("com.sun.net.ssl.enableECC", true);
-
-    // Map Integer(id) -> CipherSuite
-    // contains all known CipherSuites
-    private final static Map<Integer,CipherSuite> idMap;
-
-    // Map String(name) -> CipherSuite
-    // contains only supported CipherSuites (i.e. allowed == true)
-    private final static Map<String,CipherSuite> nameMap;
-
-    // Protocol defined CipherSuite name, e.g. SSL_RSA_WITH_RC4_128_MD5
-    // we use TLS_* only for new CipherSuites, still SSL_* for old ones
-    final String name;
-
-    // id in 16 bit MSB format, i.e. 0x0004 for SSL_RSA_WITH_RC4_128_MD5
-    final int id;
-
-    // priority for the internal default preference order. the higher the
-    // better. Each supported CipherSuite *must* have a unique priority.
-    // Ciphersuites with priority >= DEFAULT_SUITES_PRIORITY are enabled
-    // by default
-    final int priority;
-
-    // key exchange, bulk cipher, mac and prf algorithms. See those
-    // classes below.
-    final KeyExchange keyExchange;
-    final BulkCipher cipher;
-    final MacAlg macAlg;
-    final PRF prfAlg;
-
-    // whether a CipherSuite qualifies as exportable under 512/40 bit rules.
-    // TLS 1.1+ (RFC 4346) must not negotiate to these suites.
-    final boolean exportable;
-
-    // true iff implemented and enabled at compile time
-    final boolean allowed;
-
-    // obsoleted since protocol version
-    final int obsoleted;
-
-    // supported since protocol version
-    final int supported;
-
-    /**
-     * Constructor for implemented CipherSuites.
-     */
-    private CipherSuite(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher,
-            boolean allowed, int obsoleted, int supported, PRF prfAlg) {
-        this.name = name;
-        this.id = id;
-        this.priority = priority;
-        this.keyExchange = keyExchange;
-        this.cipher = cipher;
-        this.exportable = cipher.exportable;
-        if (cipher.cipherType == CipherType.AEAD_CIPHER) {
-            macAlg = M_NULL;
-        } else if (name.endsWith("_MD5")) {
-            macAlg = M_MD5;
-        } else if (name.endsWith("_SHA")) {
-            macAlg = M_SHA;
-        } else if (name.endsWith("_SHA256")) {
-            macAlg = M_SHA256;
-        } else if (name.endsWith("_SHA384")) {
-            macAlg = M_SHA384;
-        } else if (name.endsWith("_NULL")) {
-            macAlg = M_NULL;
-        } else if (name.endsWith("_SCSV")) {
-            macAlg = M_NULL;
-        } else {
-            throw new IllegalArgumentException
-                    ("Unknown MAC algorithm for ciphersuite " + name);
-        }
-
-        allowed &= keyExchange.allowed;
-        allowed &= cipher.allowed;
-        this.allowed = allowed;
-        this.obsoleted = obsoleted;
-        this.supported = supported;
-        this.prfAlg = prfAlg;
-    }
-
-    /**
-     * Constructor for unimplemented CipherSuites.
-     */
-    private CipherSuite(String name, int id) {
-        this.name = name;
-        this.id = id;
-        this.allowed = false;
-
-        this.priority = 0;
-        this.keyExchange = null;
-        this.cipher = null;
-        this.macAlg = null;
-        this.exportable = false;
-        this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
-        this.supported = ProtocolVersion.LIMIT_MIN_VALUE;
-        this.prfAlg = P_NONE;
-    }
-
-    /**
-     * Return whether this CipherSuite is available for use. A
-     * CipherSuite may be unavailable even if it is supported
-     * (i.e. allowed == true) if the required JCE cipher is not installed.
-     */
-    boolean isAvailable() {
-        return allowed && keyExchange.isAvailable() && cipher.isAvailable();
-    }
-
-    boolean isNegotiable() {
-        return this != C_SCSV && isAvailable();
-    }
-
-    /**
-     * Compares CipherSuites based on their priority. Has the effect of
-     * sorting CipherSuites when put in a sorted collection, which is
-     * used by CipherSuiteList. Follows standard Comparable contract.
-     *
-     * Note that for unsupported CipherSuites parsed from a handshake
-     * message we violate the equals() contract.
-     */
-    @Override
-    public int compareTo(CipherSuite o) {
-        return o.priority - priority;
-    }
-
-    /**
-     * Returns this.name.
-     */
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    /**
-     * Return a CipherSuite for the given name. The returned CipherSuite
-     * is supported by this implementation but may not actually be
-     * currently useable. See isAvailable().
-     *
-     * @exception IllegalArgumentException if the CipherSuite is unknown or
-     * unsupported.
-     */
-    static CipherSuite valueOf(String s) {
-        if (s == null) {
-            throw new IllegalArgumentException("Name must not be null");
-        }
-
-        CipherSuite c = nameMap.get(s);
-        if ((c == null) || (c.allowed == false)) {
-            throw new IllegalArgumentException("Unsupported ciphersuite " + s);
-        }
-
-        return c;
-    }
-
-    /**
-     * Return a CipherSuite with the given ID. A temporary object is
-     * constructed if the ID is unknown. Use isAvailable() to verify that
-     * the CipherSuite can actually be used.
-     */
-    static CipherSuite valueOf(int id1, int id2) {
-        id1 &= 0xff;
-        id2 &= 0xff;
-        int id = (id1 << 8) | id2;
-        CipherSuite c = idMap.get(id);
-        if (c == null) {
-            String h1 = Integer.toString(id1, 16);
-            String h2 = Integer.toString(id2, 16);
-            c = new CipherSuite("Unknown 0x" + h1 + ":0x" + h2, id);
-        }
-        return c;
-    }
-
-    // for use by CipherSuiteList only
-    static Collection<CipherSuite> allowedCipherSuites() {
-        return nameMap.values();
-    }
-
-    /*
-     * Use this method when all of the values need to be specified.
-     * This is primarily used when defining a new ciphersuite for
-     * TLS 1.2+ that doesn't use the "default" PRF.
-     */
-    private static void add(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher,
-            boolean allowed, int obsoleted, int supported, PRF prf) {
-
-        CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
-            cipher, allowed, obsoleted, supported, prf);
-        if (idMap.put(id, c) != null) {
-            throw new RuntimeException("Duplicate ciphersuite definition: "
-                                        + id + ", " + name);
-        }
-        if (c.allowed) {
-            if (nameMap.put(name, c) != null) {
-                throw new RuntimeException("Duplicate ciphersuite definition: "
-                                            + id + ", " + name);
-            }
-        }
-    }
-
-    /*
-     * Use this method when there is no lower protocol limit where this
-     * suite can be used, and the PRF is P_SHA256.  That is, the
-     * existing ciphersuites.  From RFC 5246:
-     *
-     *     All cipher suites in this document use P_SHA256.
-     */
-    private static void add(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher,
-            boolean allowed, int obsoleted) {
-        // If this is an obsoleted suite, then don't let the TLS 1.2
-        // protocol have a valid PRF value.
-        PRF prf = P_SHA256;
-        if (obsoleted < ProtocolVersion.TLS12.v) {
-            prf = P_NONE;
-        }
-
-        add(name, id, priority, keyExchange, cipher, allowed, obsoleted,
-            ProtocolVersion.LIMIT_MIN_VALUE, prf);
-    }
-
-    /*
-     * Use this method when there is no upper protocol limit.  That is,
-     * suites which have not been obsoleted.
-     */
-    private static void add(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
-        add(name, id, priority, keyExchange,
-            cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE);
-    }
-
-    /*
-     * Use this method to define an unimplemented suite.  This provides
-     * a number<->name mapping that can be used for debugging.
-     */
-    private static void add(String name, int id) {
-        CipherSuite c = new CipherSuite(name, id);
-        if (idMap.put(id, c) != null) {
-            throw new RuntimeException("Duplicate ciphersuite definition: "
-                                        + id + ", " + name);
-        }
-    }
-
-    /**
-     * An SSL/TLS key exchange algorithm.
-     */
-    static enum KeyExchange {
-
-        // key exchange algorithms
-        K_NULL       ("NULL",       false,      false),
-        K_RSA        ("RSA",        true,       false),
-        K_RSA_EXPORT ("RSA_EXPORT", true,       false),
-        K_DH_RSA     ("DH_RSA",     false,      false),
-        K_DH_DSS     ("DH_DSS",     false,      false),
-        K_DHE_DSS    ("DHE_DSS",    true,       false),
-        K_DHE_RSA    ("DHE_RSA",    true,       false),
-        K_DH_ANON    ("DH_anon",    true,       false),
-
-        K_ECDH_ECDSA ("ECDH_ECDSA",  ALLOW_ECC, true),
-        K_ECDH_RSA   ("ECDH_RSA",    ALLOW_ECC, true),
-        K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, true),
-        K_ECDHE_RSA  ("ECDHE_RSA",   ALLOW_ECC, true),
-        K_ECDH_ANON  ("ECDH_anon",   ALLOW_ECC, true),
-
-        // Kerberos cipher suites
-        K_KRB5       ("KRB5", true,             false),
-        K_KRB5_EXPORT("KRB5_EXPORT", true,      false),
-
-        // renegotiation protection request signaling cipher suite
-        K_SCSV       ("SCSV",        true,      false);
-
-        // name of the key exchange algorithm, e.g. DHE_DSS
-        final String name;
-        final boolean allowed;
-        final boolean isEC;
-        private final boolean alwaysAvailable;
-
-        KeyExchange(String name, boolean allowed, boolean isEC) {
-            this.name = name;
-            this.allowed = allowed;
-            this.isEC = isEC;
-            this.alwaysAvailable = allowed &&
-                (!name.startsWith("EC")) && (!name.startsWith("KRB"));
-        }
-
-        boolean isAvailable() {
-            if (alwaysAvailable) {
-                return true;
-            }
-
-            if (isEC) {
-                return (allowed && JsseJce.isEcAvailable());
-            } else if (name.startsWith("KRB")) {
-                return (allowed && JsseJce.isKerberosAvailable());
-            } else {
-                return allowed;
-            }
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-
-    static enum CipherType {
-        STREAM_CIPHER,         // null or stream cipher
-        BLOCK_CIPHER,          // block cipher in CBC mode
-        AEAD_CIPHER            // AEAD cipher
-    }
-
-    /**
-     * An SSL/TLS bulk cipher algorithm. One instance per combination of
-     * cipher and key length.
-     *
-     * Also contains a factory method to obtain in initialized CipherBox
-     * for this algorithm.
-     */
-    final static class BulkCipher {
-
-        // descriptive name including key size, e.g. AES/128
-        final String description;
-
-        // JCE cipher transformation string, e.g. AES/CBC/NoPadding
-        final String transformation;
-
-        // algorithm name, e.g. AES
-        final String algorithm;
-
-        // supported and compile time enabled. Also see isAvailable()
-        final boolean allowed;
-
-        // number of bytes of entropy in the key
-        final int keySize;
-
-        // length of the actual cipher key in bytes.
-        // for non-exportable ciphers, this is the same as keySize
-        final int expandedKeySize;
-
-        // size of the IV
-        final int ivSize;
-
-        // size of fixed IV
-        //
-        // record_iv_length = ivSize - fixedIvSize
-        final int fixedIvSize;
-
-        // exportable under 512/40 bit rules
-        final boolean exportable;
-
-        // Is the cipher algorithm of Cipher Block Chaining (CBC) mode?
-        final CipherType cipherType;
-
-        // size of the authentication tag, only applicable to cipher suites in
-        // Galois Counter Mode (GCM)
-        //
-        // As far as we know, all supported GCM cipher suites use 128-bits
-        // authentication tags.
-        final int tagSize = 16;
-
-        // The secure random used to detect the cipher availability.
-        private final static SecureRandom secureRandom;
-
-        // runtime availability
-        private final boolean isAvailable;
-
-        static {
-            try {
-                secureRandom = JsseJce.getSecureRandom();
-            } catch (KeyManagementException kme) {
-                throw new RuntimeException(kme);
-            }
-        }
-
-        BulkCipher(String transformation, CipherType cipherType, int keySize,
-                int expandedKeySize, int ivSize,
-                int fixedIvSize, boolean allowed) {
-
-            this.transformation = transformation;
-            String[] splits = transformation.split("/");
-            this.algorithm = splits[0];
-            this.cipherType = cipherType;
-            this.description = this.algorithm + "/" + (keySize << 3);
-            this.keySize = keySize;
-            this.ivSize = ivSize;
-            this.fixedIvSize = fixedIvSize;
-            this.allowed = allowed;
-
-            this.expandedKeySize = expandedKeySize;
-            this.exportable = true;
-
-            // availability of this bulk cipher
-            //
-            // Currently all supported ciphers except AES are always available
-            // via the JSSE internal implementations. We also assume AES/128 of
-            // CBC mode is always available since it is shipped with the SunJCE
-            // provider.  However, AES/256 is unavailable when the default JCE
-            // policy jurisdiction files are installed because of key length
-            // restrictions.
-            this.isAvailable =
-                    allowed ? isUnlimited(keySize, transformation) : false;
-        }
-
-        BulkCipher(String transformation, CipherType cipherType, int keySize,
-                int ivSize, int fixedIvSize, boolean allowed) {
-            this.transformation = transformation;
-            String[] splits = transformation.split("/");
-            this.algorithm = splits[0];
-            this.cipherType = cipherType;
-            this.description = this.algorithm + "/" + (keySize << 3);
-            this.keySize = keySize;
-            this.ivSize = ivSize;
-            this.fixedIvSize = fixedIvSize;
-            this.allowed = allowed;
-
-            this.expandedKeySize = keySize;
-            this.exportable = false;
-
-            // availability of this bulk cipher
-            //
-            // Currently all supported ciphers except AES are always available
-            // via the JSSE internal implementations. We also assume AES/128 of
-            // CBC mode is always available since it is shipped with the SunJCE
-            // provider.  However, AES/256 is unavailable when the default JCE
-            // policy jurisdiction files are installed because of key length
-            // restrictions.
-            this.isAvailable =
-                    allowed ? isUnlimited(keySize, transformation) : false;
-        }
-
-        /**
-         * Return an initialized CipherBox for this BulkCipher.
-         * IV must be null for stream ciphers.
-         *
-         * @exception NoSuchAlgorithmException if anything goes wrong
-         */
-        CipherBox newCipher(ProtocolVersion version, SecretKey key,
-                IvParameterSpec iv, SecureRandom random,
-                boolean encrypt) throws NoSuchAlgorithmException {
-            return CipherBox.newCipherBox(version, this,
-                                            key, iv, random, encrypt);
-        }
-
-        /**
-         * Test if this bulk cipher is available. For use by CipherSuite.
-         */
-        boolean isAvailable() {
-            return this.isAvailable;
-        }
-
-        private static boolean isUnlimited(int keySize, String transformation) {
-            int keySizeInBits = keySize * 8;
-            if (keySizeInBits > 128) {    // need the JCE unlimited
-                                          // strength jurisdiction policy
-                try {
-                    if (Cipher.getMaxAllowedKeyLength(
-                            transformation) < keySizeInBits) {
-
-                        return false;
-                    }
-                } catch (Exception e) {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return description;
-        }
-    }
-
-    /**
-     * An SSL/TLS key MAC algorithm.
-     *
-     * Also contains a factory method to obtain an initialized MAC
-     * for this algorithm.
-     */
-    final static class MacAlg {
-
-        // descriptive name, e.g. MD5
-        final String name;
-
-        // size of the MAC value (and MAC key) in bytes
-        final int size;
-
-        // block size of the underlying hash algorithm
-        final int hashBlockSize;
-
-        // minimal padding size of the underlying hash algorithm
-        final int minimalPaddingSize;
-
-        MacAlg(String name, int size,
-                int hashBlockSize, int minimalPaddingSize) {
-            this.name = name;
-            this.size = size;
-            this.hashBlockSize = hashBlockSize;
-            this.minimalPaddingSize = minimalPaddingSize;
-        }
-
-        /**
-         * Return an initialized MAC for this MacAlg. ProtocolVersion
-         * must either be SSL30 (SSLv3 custom MAC) or TLS10 (std. HMAC).
-         *
-         * @exception NoSuchAlgorithmException if anything goes wrong
-         */
-        MAC newMac(ProtocolVersion protocolVersion, SecretKey secret)
-                throws NoSuchAlgorithmException, InvalidKeyException {
-            return new MAC(this, protocolVersion, secret);
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-
-    // export strength ciphers
-    final static BulkCipher B_NULL    =
-        new BulkCipher("NULL",          STREAM_CIPHER,    0,  0,  0, 0, true);
-    final static BulkCipher B_RC4_40  =
-        new BulkCipher(CIPHER_RC4,      STREAM_CIPHER,    5, 16,  0, 0, true);
-    final static BulkCipher B_RC2_40  =
-        new BulkCipher("RC2",           BLOCK_CIPHER,     5, 16,  8, 0, false);
-    final static BulkCipher B_DES_40  =
-        new BulkCipher(CIPHER_DES,      BLOCK_CIPHER,     5,  8,  8, 0, true);
-
-    // domestic strength ciphers
-    final static BulkCipher B_RC4_128 =
-        new BulkCipher(CIPHER_RC4,      STREAM_CIPHER,   16,  0,  0, true);
-    final static BulkCipher B_DES     =
-        new BulkCipher(CIPHER_DES,      BLOCK_CIPHER,     8,  8,  0, true);
-    final static BulkCipher B_3DES    =
-        new BulkCipher(CIPHER_3DES,     BLOCK_CIPHER,    24,  8,  0, true);
-    final static BulkCipher B_IDEA    =
-        new BulkCipher("IDEA",          BLOCK_CIPHER,    16,  8,  0, false);
-    final static BulkCipher B_AES_128 =
-        new BulkCipher(CIPHER_AES,      BLOCK_CIPHER,    16, 16,  0, true);
-    final static BulkCipher B_AES_256 =
-        new BulkCipher(CIPHER_AES,      BLOCK_CIPHER,    32, 16,  0, true);
-    final static BulkCipher B_AES_128_GCM =
-        new BulkCipher(CIPHER_AES_GCM,  AEAD_CIPHER,     16, 12,  4, true);
-    final static BulkCipher B_AES_256_GCM =
-        new BulkCipher(CIPHER_AES_GCM,  AEAD_CIPHER,     32, 12,  4, true);
-
-    // MACs
-    final static MacAlg M_NULL    = new MacAlg("NULL",     0,   0,   0);
-    final static MacAlg M_MD5     = new MacAlg("MD5",     16,  64,   9);
-    final static MacAlg M_SHA     = new MacAlg("SHA",     20,  64,   9);
-    final static MacAlg M_SHA256  = new MacAlg("SHA256",  32,  64,   9);
-    final static MacAlg M_SHA384  = new MacAlg("SHA384",  48, 128,  17);
-
-    /**
-     * PRFs (PseudoRandom Function) from TLS specifications.
-     *
-     * TLS 1.1- uses a single MD5/SHA1-based PRF algorithm for generating
-     * the necessary material.
-     *
-     * In TLS 1.2+, all existing/known CipherSuites use SHA256, however
-     * new Ciphersuites (e.g. RFC 5288) can define specific PRF hash
-     * algorithms.
-     */
-    static enum PRF {
-
-        // PRF algorithms
-        P_NONE(     "NONE",  0,   0),
-        P_SHA256("SHA-256", 32,  64),
-        P_SHA384("SHA-384", 48, 128),
-        P_SHA512("SHA-512", 64, 128);  // not currently used.
-
-        // PRF characteristics
-        private final String prfHashAlg;
-        private final int prfHashLength;
-        private final int prfBlockSize;
-
-        PRF(String prfHashAlg, int prfHashLength, int prfBlockSize) {
-            this.prfHashAlg = prfHashAlg;
-            this.prfHashLength = prfHashLength;
-            this.prfBlockSize = prfBlockSize;
-        }
-
-        String getPRFHashAlg() {
-            return prfHashAlg;
-        }
-
-        int getPRFHashLength() {
-            return prfHashLength;
-        }
-
-        int getPRFBlockSize() {
-            return prfBlockSize;
-        }
-    }
-
-    static {
-        idMap = new HashMap<Integer,CipherSuite>();
-        nameMap = new HashMap<String,CipherSuite>();
-
-        final boolean F = false;
-        final boolean T = true;
-        // N: ciphersuites only allowed if we are not in FIPS mode
-        final boolean N = (SunJSSE.isFIPS() == false);
-
-        /*
-         * TLS Cipher Suite Registry, as of November 2015.
-         *
-         * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
-         *
-         * Range      Registration Procedures   Notes
-         * 000-191    Standards Action          Refers to value of first byte
-         * 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]
-         * 0x00,0x47-4F Reserved to avoid conflicts with
-         *            deployed implementations                  [Pasi_Eronen]
-         * 0x00,0x50-58 Reserved to avoid conflicts             [Pasi Eronen]
-         * 0x00,0x59-5C Reserved to avoid conflicts with
-         *            deployed implementations                  [Pasi_Eronen]
-         * 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,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,0xC6-FE         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
-         *            deployed implementations                  [Pasi_Eronen]
-         * 0xFF,0x00-FF Reserved for Private Use                [RFC5246]
-         */
-
-        add("SSL_NULL_WITH_NULL_NULL",
-                              0x0000,   1, K_NULL,       B_NULL,    F);
-
-        /*
-         * Definition of the CipherSuites that are enabled by default.
-         * They are listed in preference order, most preferred first, using
-         * the following criteria:
-         * 1. Prefer Suite B compliant cipher suites, see RFC6460 (To be
-         *    changed later, see below).
-         * 2. Prefer the stronger bulk cipher, in the order of AES_256(GCM),
-         *    AES_128(GCM), AES_256, AES_128, 3DES-EDE.
-         * 3. Prefer the stronger MAC algorithm, in the order of SHA384,
-         *    SHA256, SHA, MD5.
-         * 4. Prefer the better performance of key exchange and digital
-         *    signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
-         *    RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS.
-         */
-        int p = DEFAULT_SUITES_PRIORITY * 2;
-
-        // shorten names to fit the following table cleanly.
-        int max = ProtocolVersion.LIMIT_MAX_VALUE;
-        int tls11 = ProtocolVersion.TLS11.v;
-        int tls12 = ProtocolVersion.TLS12.v;
-
-        //  ID           Key Exchange   Cipher     A  obs  suprt  PRF
-        //  ======       ============   =========  =  ===  =====  ========
-
-
-        // Placeholder for cipher suites in GCM mode.
-        //
-        // For better compatibility and interoperability, we decrease the
-        // priority of cipher suites in GCM mode for a while as GCM
-        // technologies mature in the industry.  Eventually we'll move
-        // the GCM suites here.
-
-        // AES_256(CBC)
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
-            0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
-            0xc028, --p, K_ECDHE_RSA,   B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_RSA_WITH_AES_256_CBC_SHA256",
-            0x003d, --p, K_RSA,         B_AES_256, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
-            0xc026, --p, K_ECDH_ECDSA,  B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
-            0xc02a, --p, K_ECDH_RSA,    B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
-            0x006b, --p, K_DHE_RSA,     B_AES_256, T, max, tls12, P_SHA256);
-        add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
-            0x006a, --p, K_DHE_DSS,     B_AES_256, T, max, tls12, P_SHA256);
-
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
-            0xC00A, --p, K_ECDHE_ECDSA, B_AES_256, T);
-        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
-            0xC014, --p, K_ECDHE_RSA,   B_AES_256, T);
-        add("TLS_RSA_WITH_AES_256_CBC_SHA",
-            0x0035, --p, K_RSA,         B_AES_256, T);
-        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
-            0xC005, --p, K_ECDH_ECDSA,  B_AES_256, T);
-        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
-            0xC00F, --p, K_ECDH_RSA,    B_AES_256, T);
-        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
-            0x0039, --p, K_DHE_RSA,     B_AES_256, T);
-        add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
-            0x0038, --p, K_DHE_DSS,     B_AES_256, T);
-
-        // AES_128(CBC)
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
-            0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
-            0xc027, --p, K_ECDHE_RSA,   B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_RSA_WITH_AES_128_CBC_SHA256",
-            0x003c, --p, K_RSA,         B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
-            0xc025, --p, K_ECDH_ECDSA,  B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
-            0xc029, --p, K_ECDH_RSA,    B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
-            0x0067, --p, K_DHE_RSA,     B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
-            0x0040, --p, K_DHE_DSS,     B_AES_128, T, max, tls12, P_SHA256);
-
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
-            0xC009, --p, K_ECDHE_ECDSA, B_AES_128, T);
-        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
-            0xC013, --p, K_ECDHE_RSA,   B_AES_128, T);
-        add("TLS_RSA_WITH_AES_128_CBC_SHA",
-            0x002f, --p, K_RSA,         B_AES_128, T);
-        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
-            0xC004, --p, K_ECDH_ECDSA,  B_AES_128, T);
-        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
-            0xC00E, --p, K_ECDH_RSA,    B_AES_128, T);
-        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
-            0x0033, --p, K_DHE_RSA,     B_AES_128, T);
-        add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
-            0x0032, --p, K_DHE_DSS,     B_AES_128, T);
-
-        // Cipher suites in GCM mode, see RFC 5288/5289.
-        //
-        // We may increase the priority of cipher suites in GCM mode when
-        // GCM technologies become mature in the industry.
-
-        // Suite B compliant cipher suites, see RFC 6460.
-        //
-        // Note that, at present this provider is not Suite B compliant. The
-        // preference order of the GCM cipher suites does not follow the spec
-        // of RFC 6460.
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
-            0xc02c, --p, K_ECDHE_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
-            0xc02b, --p, K_ECDHE_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
-
-        // AES_256(GCM)
-        add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
-            0xc030, --p, K_ECDHE_RSA,   B_AES_256_GCM, T, max, tls12, P_SHA384);
-        add("TLS_RSA_WITH_AES_256_GCM_SHA384",
-            0x009d, --p, K_RSA,         B_AES_256_GCM, T, max, tls12, P_SHA384);
-        add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
-            0xc02e, --p, K_ECDH_ECDSA,  B_AES_256_GCM, T, max, tls12, P_SHA384);
-        add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
-            0xc032, --p, K_ECDH_RSA,    B_AES_256_GCM, T, max, tls12, P_SHA384);
-        add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
-            0x009f, --p, K_DHE_RSA,     B_AES_256_GCM, T, max, tls12, P_SHA384);
-        add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
-            0x00a3, --p, K_DHE_DSS,     B_AES_256_GCM, T, max, tls12, P_SHA384);
-
-        // AES_128(GCM)
-        add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
-            0xc02f, --p, K_ECDHE_RSA,   B_AES_128_GCM, T, max, tls12, P_SHA256);
-        add("TLS_RSA_WITH_AES_128_GCM_SHA256",
-            0x009c, --p, K_RSA,         B_AES_128_GCM, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
-            0xc02d, --p, K_ECDH_ECDSA,  B_AES_128_GCM, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
-            0xc031, --p, K_ECDH_RSA,    B_AES_128_GCM, T, max, tls12, P_SHA256);
-        add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
-            0x009e, --p, K_DHE_RSA,     B_AES_128_GCM, T, max, tls12, P_SHA256);
-        add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
-            0x00a2, --p, K_DHE_DSS,     B_AES_128_GCM, T, max, tls12, P_SHA256);
-        // End of cipher suites in GCM mode.
-
-        // 3DES_EDE
-        add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
-            0xC008, --p, K_ECDHE_ECDSA, B_3DES,    T);
-        add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
-            0xC012, --p, K_ECDHE_RSA,   B_3DES,    T);
-        add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",
-            0x000a, --p, K_RSA,         B_3DES,    T);
-        add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
-            0xC003, --p, K_ECDH_ECDSA,  B_3DES,    T);
-        add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
-            0xC00D, --p, K_ECDH_RSA,    B_3DES,    T);
-        add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
-            0x0016, --p, K_DHE_RSA,     B_3DES,    T);
-        add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
-            0x0013, --p, K_DHE_DSS,     B_3DES,    N);
-
-        // Renegotiation protection request Signalling Cipher Suite Value (SCSV)
-        add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
-            0x00ff, --p, K_SCSV,        B_NULL,    T);
-
-        /*
-         * Definition of the CipherSuites that are supported but not enabled
-         * by default.
-         * They are listed in preference order, preferred first, using the
-         * following criteria:
-         * 1. CipherSuites for KRB5 need additional KRB5 service
-         *    configuration, and these suites are not common in practice,
-         *    so we put KRB5 based cipher suites at the end of the supported
-         *    list.
-         * 2. If a cipher suite has been obsoleted, we put it at the end of
-         *    the list.
-         * 3. Prefer the stronger bulk cipher, in the order of AES_256,
-         *    AES_128, 3DES-EDE, RC-4, DES, DES40, RC4_40, NULL.
-         * 4. Prefer the stronger MAC algorithm, in the order of SHA384,
-         *    SHA256, SHA, MD5.
-         * 5. Prefer the better performance of key exchange and digital
-         *    signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
-         *    RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS, anonymous.
-         */
-        p = DEFAULT_SUITES_PRIORITY;
-
-        add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",
-            0x00a7, --p, K_DH_ANON,     B_AES_256_GCM, N, max, tls12, P_SHA384);
-        add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",
-            0x00a6, --p, K_DH_ANON,     B_AES_128_GCM, N, max, tls12, P_SHA256);
-
-        add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
-            0x006d, --p, K_DH_ANON,     B_AES_256, N, max, tls12, P_SHA256);
-        add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
-            0xC019, --p, K_ECDH_ANON,   B_AES_256, N);
-        add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
-            0x003a, --p, K_DH_ANON,     B_AES_256, N);
-
-        add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
-            0x006c, --p, K_DH_ANON,     B_AES_128, N, max, tls12, P_SHA256);
-        add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
-            0xC018, --p, K_ECDH_ANON,   B_AES_128, N);
-        add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
-            0x0034, --p, K_DH_ANON,     B_AES_128, N);
-
-        add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
-            0xC017, --p, K_ECDH_ANON,   B_3DES,    N);
-        add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
-            0x001b, --p, K_DH_ANON,     B_3DES,    N);
-
-        // RC-4
-        add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
-            0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
-        add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
-            0xC011, --p, K_ECDHE_RSA,   B_RC4_128, N);
-        add("SSL_RSA_WITH_RC4_128_SHA",
-            0x0005, --p, K_RSA,         B_RC4_128, N);
-        add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
-            0xC002, --p, K_ECDH_ECDSA,  B_RC4_128, N);
-        add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
-            0xC00C, --p, K_ECDH_RSA,    B_RC4_128, N);
-        add("SSL_RSA_WITH_RC4_128_MD5",
-            0x0004, --p, K_RSA,         B_RC4_128, N);
-
-        add("TLS_ECDH_anon_WITH_RC4_128_SHA",
-            0xC016, --p, K_ECDH_ANON,   B_RC4_128, N);
-        add("SSL_DH_anon_WITH_RC4_128_MD5",
-            0x0018, --p, K_DH_ANON,     B_RC4_128, N);
-
-        // weak cipher suites obsoleted in TLS 1.2
-        add("SSL_RSA_WITH_DES_CBC_SHA",
-            0x0009, --p, K_RSA,         B_DES,     N, tls12);
-        add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
-            0x0015, --p, K_DHE_RSA,     B_DES,     N, tls12);
-        add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
-            0x0012, --p, K_DHE_DSS,     B_DES,     N, tls12);
-        add("SSL_DH_anon_WITH_DES_CBC_SHA",
-            0x001a, --p, K_DH_ANON,     B_DES,     N, tls12);
-
-        // weak cipher suites obsoleted in TLS 1.1
-        add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
-            0x0008, --p, K_RSA_EXPORT,  B_DES_40,  N, tls11);
-        add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
-            0x0014, --p, K_DHE_RSA,     B_DES_40,  N, tls11);
-        add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
-            0x0011, --p, K_DHE_DSS,     B_DES_40,  N, tls11);
-        add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
-            0x0019, --p, K_DH_ANON,     B_DES_40,  N, tls11);
-
-        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
-            0x0003, --p, K_RSA_EXPORT,  B_RC4_40,  N, tls11);
-        add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
-            0x0017, --p, K_DH_ANON,     B_RC4_40,  N, tls11);
-
-        add("TLS_RSA_WITH_NULL_SHA256",
-            0x003b, --p, K_RSA,         B_NULL,    N, max, tls12, P_SHA256);
-        add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
-            0xC006, --p, K_ECDHE_ECDSA, B_NULL,    N);
-        add("TLS_ECDHE_RSA_WITH_NULL_SHA",
-            0xC010, --p, K_ECDHE_RSA,   B_NULL,    N);
-        add("SSL_RSA_WITH_NULL_SHA",
-            0x0002, --p, K_RSA,         B_NULL,    N);
-        add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
-            0xC001, --p, K_ECDH_ECDSA,  B_NULL,    N);
-        add("TLS_ECDH_RSA_WITH_NULL_SHA",
-            0xC00B, --p, K_ECDH_RSA,    B_NULL,    N);
-        add("TLS_ECDH_anon_WITH_NULL_SHA",
-            0xC015, --p, K_ECDH_ANON,   B_NULL,    N);
-        add("SSL_RSA_WITH_NULL_MD5",
-            0x0001, --p, K_RSA,         B_NULL,    N);
-
-        // Supported Kerberos ciphersuites from RFC2712
-        add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
-            0x001f, --p, K_KRB5,        B_3DES,    N);
-        add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
-            0x0023, --p, K_KRB5,        B_3DES,    N);
-        add("TLS_KRB5_WITH_RC4_128_SHA",
-            0x0020, --p, K_KRB5,        B_RC4_128, N);
-        add("TLS_KRB5_WITH_RC4_128_MD5",
-            0x0024, --p, K_KRB5,        B_RC4_128, N);
-        add("TLS_KRB5_WITH_DES_CBC_SHA",
-            0x001e, --p, K_KRB5,        B_DES,     N, tls12);
-        add("TLS_KRB5_WITH_DES_CBC_MD5",
-            0x0022, --p, K_KRB5,        B_DES,     N, tls12);
-        add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
-            0x0026, --p, K_KRB5_EXPORT, B_DES_40,  N, tls11);
-        add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
-            0x0029, --p, K_KRB5_EXPORT, B_DES_40,  N, tls11);
-        add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
-            0x0028, --p, K_KRB5_EXPORT, B_RC4_40,  N, tls11);
-        add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
-            0x002b, --p, K_KRB5_EXPORT, B_RC4_40,  N, tls11);
-
-        /*
-         * Other values from the TLS Cipher Suite Registry, as of August 2010.
-         *
-         * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
-         *
-         * Range      Registration Procedures   Notes
-         * 000-191    Standards Action          Refers to value of first byte
-         * 192-254    Specification Required    Refers to value of first byte
-         * 255        Reserved for Private Use  Refers to value of first byte
-         */
-
-        // Register the names of a few additional CipherSuites.
-        // Makes them show up as names instead of numbers in
-        // 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);
-
-        // SSL 3.0 Fortezza ciphersuites
-        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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // 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
-    final static CipherSuite C_NULL = CipherSuite.valueOf(0, 0);
-
-    // ciphersuite TLS_EMPTY_RENEGOTIATION_INFO_SCSV
-    final static CipherSuite C_SCSV = CipherSuite.valueOf(0x00, 0xff);
-}
--- a/src/share/classes/sun/security/ssl/CipherSuiteList.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, 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.*;
-import java.util.*;
-
-import javax.net.ssl.SSLException;
-
-/**
- * A list of CipherSuites. Also maintains the lists of supported and
- * default ciphersuites and supports I/O from handshake streams.
- *
- * Instances of this class are immutable.
- *
- */
-final class CipherSuiteList {
-
-    private final Collection<CipherSuite> cipherSuites;
-    private String[] suiteNames;
-
-    // flag indicating whether this list contains any ECC ciphersuites.
-    // null if not yet checked.
-    private volatile Boolean containsEC;
-
-    // for use by buildAvailableCache() and
-    // Handshaker.getKickstartMessage() only
-    CipherSuiteList(Collection<CipherSuite> cipherSuites) {
-        this.cipherSuites = cipherSuites;
-    }
-
-    /**
-     * Create a CipherSuiteList with a single element.
-     */
-    CipherSuiteList(CipherSuite suite) {
-        cipherSuites = new ArrayList<CipherSuite>(1);
-        cipherSuites.add(suite);
-    }
-
-    /**
-     * Construct a CipherSuiteList from a array of names. We don't bother
-     * to eliminate duplicates.
-     *
-     * @exception IllegalArgumentException if the array or any of its elements
-     * is null or if the ciphersuite name is unrecognized or unsupported
-     * using currently installed providers.
-     */
-    CipherSuiteList(String[] names) {
-        if (names == null) {
-            throw new IllegalArgumentException("CipherSuites may not be null");
-        }
-        cipherSuites = new ArrayList<CipherSuite>(names.length);
-        for (int i = 0; i < names.length; i++) {
-            String suiteName = names[i];
-            CipherSuite suite = CipherSuite.valueOf(suiteName);
-            if (suite.isAvailable() == false) {
-                throw new IllegalArgumentException("Cannot support "
-                    + suiteName + " with currently installed providers");
-            }
-            cipherSuites.add(suite);
-        }
-    }
-
-    /**
-     * Read a CipherSuiteList from a HandshakeInStream in V3 ClientHello
-     * format. Does not check if the listed ciphersuites are known or
-     * supported.
-     */
-    CipherSuiteList(HandshakeInStream in) throws IOException {
-        byte[] bytes = in.getBytes16();
-        if ((bytes.length & 1) != 0) {
-            throw new SSLException("Invalid ClientHello message");
-        }
-        cipherSuites = new ArrayList<CipherSuite>(bytes.length >> 1);
-        for (int i = 0; i < bytes.length; i += 2) {
-            cipherSuites.add(CipherSuite.valueOf(bytes[i], bytes[i+1]));
-        }
-    }
-
-    /**
-     * Return whether this list contains the given CipherSuite.
-     */
-    boolean contains(CipherSuite suite) {
-        return cipherSuites.contains(suite);
-    }
-
-    // Return whether this list contains any ECC ciphersuites
-    boolean containsEC() {
-        if (containsEC == null) {
-            for (CipherSuite c : cipherSuites) {
-                if (c.keyExchange.isEC) {
-                    containsEC = true;
-                    return true;
-                }
-            }
-
-            containsEC = false;
-        }
-
-        return containsEC;
-    }
-
-    /**
-     * Return an Iterator for the CipherSuites in this list.
-     */
-    Iterator<CipherSuite> iterator() {
-        return cipherSuites.iterator();
-    }
-
-    /**
-     * Return a reference to the internal Collection of CipherSuites.
-     * The Collection MUST NOT be modified.
-     */
-    Collection<CipherSuite> collection() {
-        return cipherSuites;
-    }
-
-    /**
-     * Return the number of CipherSuites in this list.
-     */
-    int size() {
-        return cipherSuites.size();
-    }
-
-    /**
-     * Return an array with the names of the CipherSuites in this list.
-     */
-    synchronized String[] toStringArray() {
-        if (suiteNames == null) {
-            suiteNames = new String[cipherSuites.size()];
-            int i = 0;
-            for (CipherSuite c : cipherSuites) {
-                suiteNames[i++] = c.name;
-            }
-        }
-        return suiteNames.clone();
-    }
-
-    @Override
-    public String toString() {
-        return cipherSuites.toString();
-    }
-
-    /**
-     * Write this list to an HandshakeOutStream in V3 ClientHello format.
-     */
-    void send(HandshakeOutStream s) throws IOException {
-        byte[] suiteBytes = new byte[cipherSuites.size() * 2];
-        int i = 0;
-        for (CipherSuite c : cipherSuites) {
-            suiteBytes[i] = (byte)(c.id >> 8);
-            suiteBytes[i+1] = (byte)c.id;
-            i += 2;
-        }
-        s.putBytes16(suiteBytes);
-    }
-}
--- a/src/share/classes/sun/security/ssl/ClientHandshaker.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1812 +0,0 @@
-/*
- * Copyright (c) 1996, 2020, 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.*;
-import java.math.BigInteger;
-import java.security.*;
-import java.util.*;
-
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.ECParameterSpec;
-
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateParsingException;
-import javax.security.auth.x500.X500Principal;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import javax.net.ssl.*;
-
-import javax.security.auth.Subject;
-
-import sun.security.ssl.HandshakeMessage.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * ClientHandshaker does the protocol handshaking from the point
- * of view of a client.  It is driven asychronously by handshake messages
- * as delivered by the parent Handshaker class, and also uses
- * common functionality (e.g. key generation) that is provided there.
- *
- * @author David Brownell
- */
-final class ClientHandshaker extends Handshaker {
-
-    // constants for subject alt names of type DNS and IP
-    private final static int ALTNAME_DNS = 2;
-    private final static int ALTNAME_IP  = 7;
-
-    // the server's public key from its certificate.
-    private PublicKey serverKey;
-
-    // the server's ephemeral public key from the server key exchange message
-    // for ECDHE/ECDH_anon and RSA_EXPORT.
-    private PublicKey ephemeralServerKey;
-
-    // server's ephemeral public value for DHE/DH_anon key exchanges
-    private BigInteger          serverDH;
-
-    private DHCrypt             dh;
-
-    private ECDHCrypt ecdh;
-
-    private CertificateRequest  certRequest;
-
-    private boolean serverKeyExchangeReceived;
-
-    /*
-     * The RSA PreMasterSecret needs to know the version of
-     * ClientHello that was used on this handshake.  This represents
-     * the "max version" this client is supporting.  In the
-     * case of an initial handshake, it's the max version enabled,
-     * but in the case of a resumption attempt, it's the version
-     * of the session we're trying to resume.
-     */
-    private ProtocolVersion maxProtocolVersion;
-
-    // To switch off the SNI extension.
-    private final static boolean enableSNIExtension =
-            Debug.getBooleanProperty("jsse.enableSNIExtension", true);
-
-    /*
-     * Allow unsafe server certificate change?
-     *
-     * Server certificate change during SSL/TLS renegotiation may be considered
-     * unsafe, as described in the Triple Handshake attacks:
-     *
-     *     https://secure-resumption.com/tlsauth.pdf
-     *
-     * Endpoint identification (See
-     * SSLParameters.getEndpointIdentificationAlgorithm()) is a pretty nice
-     * guarantee that the server certificate change in renegotiation is legal.
-     * However, endpoing identification is only enabled for HTTPS and LDAP
-     * over SSL/TLS by default.  It is not enough to protect SSL/TLS
-     * connections other than HTTPS and LDAP.
-     *
-     * The renegotiation indication extension (See RFC 5764) is a pretty
-     * strong guarantee that the endpoints on both client and server sides
-     * are identical on the same connection.  However, the Triple Handshake
-     * attacks can bypass this guarantee if there is a session-resumption
-     * handshake between the initial full handshake and the renegotiation
-     * full handshake.
-     *
-     * Server certificate change may be unsafe and should be restricted if
-     * endpoint identification is not enabled and the previous handshake is
-     * a session-resumption abbreviated initial handshake, unless the
-     * identities represented by both certificates can be regraded as the
-     * same (See isIdentityEquivalent()).
-     *
-     * Considering the compatibility impact and the actual requirements to
-     * support server certificate change in practice, the system property,
-     * jdk.tls.allowUnsafeServerCertChange, is used to define whether unsafe
-     * server certificate change in renegotiation is allowed or not.  The
-     * default value of the system property is "false".  To mitigate the
-     * compactibility impact, applications may want to set the system
-     * property to "true" at their own risk.
-     *
-     * If the value of the system property is "false", server certificate
-     * change in renegotiation after a session-resumption abbreviated initial
-     * handshake is restricted (See isIdentityEquivalent()).
-     *
-     * If the system property is set to "true" explicitly, the restriction on
-     * server certificate change in renegotiation is disabled.
-     */
-    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();
-
-    private boolean serverNamesAccepted = false;
-
-    /*
-     * the reserved server certificate chain in previous handshaking
-     *
-     * The server certificate chain is only reserved if the previous
-     * handshake is a session-resumption abbreviated initial handshake.
-     */
-    private X509Certificate[] reservedServerCerts = null;
-
-    /*
-     * Constructors
-     */
-    ClientHandshaker(SSLSocketImpl socket, SSLContextImpl context,
-            ProtocolList enabledProtocols,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(socket, context, enabledProtocols, true, true,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-    }
-
-    ClientHandshaker(SSLEngineImpl engine, SSLContextImpl context,
-            ProtocolList enabledProtocols,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(engine, context, enabledProtocols, true, true,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-    }
-
-    /*
-     * This routine handles all the client side handshake messages, one at
-     * a time.  Given the message type (and in some cases the pending cipher
-     * spec) it parses the type-specific message.  Then it calls a function
-     * that handles that specific message.
-     *
-     * It updates the state machine (need to verify it) as each message
-     * is processed, and writes responses as needed using the connection
-     * in the constructor.
-     */
-    @Override
-    void processMessage(byte type, int messageLen) throws IOException {
-
-        // check the handshake state
-        List<Byte> ignoredOptStates = handshakeState.check(type);
-
-        switch (type) {
-        case HandshakeMessage.ht_hello_request:
-            HelloRequest helloRequest = new HelloRequest(input);
-            handshakeState.update(helloRequest, resumingSession);
-            this.serverHelloRequest(helloRequest);
-            break;
-
-        case HandshakeMessage.ht_server_hello:
-            ServerHello serverHello = new ServerHello(input, messageLen);
-            this.serverHello(serverHello);
-
-            // This handshake state update needs the resumingSession value
-            // set by serverHello().
-            handshakeState.update(serverHello, resumingSession);
-            break;
-
-        case HandshakeMessage.ht_certificate:
-            if (keyExchange == K_DH_ANON || keyExchange == K_ECDH_ANON
-                    || keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-                fatalSE(Alerts.alert_unexpected_message,
-                    "unexpected server cert chain");
-                // NOTREACHED
-            }
-            CertificateMsg certificateMsg = new CertificateMsg(input);
-            handshakeState.update(certificateMsg, resumingSession);
-            this.serverCertificate(certificateMsg);
-            serverKey =
-                session.getPeerCertificates()[0].getPublicKey();
-            break;
-
-        case HandshakeMessage.ht_server_key_exchange:
-            serverKeyExchangeReceived = true;
-            switch (keyExchange) {
-            case K_RSA_EXPORT:
-                /**
-                 * The server key exchange message is sent by the server only
-                 * when the server certificate message does not contain the
-                 * proper amount of data to allow the client to exchange a
-                 * premaster secret, such as when RSA_EXPORT is used and the
-                 * public key in the server certificate is longer than 512 bits.
-                 */
-                if (serverKey == null) {
-                    throw new SSLProtocolException
-                        ("Server did not send certificate message");
-                }
-
-                if (!(serverKey instanceof RSAPublicKey)) {
-                    throw new SSLProtocolException("Protocol violation:" +
-                        " the certificate type must be appropriate for the" +
-                        " selected cipher suite's key exchange algorithm");
-                }
-
-                if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
-                    throw new SSLProtocolException("Protocol violation:" +
-                        " server sent a server key exchange message for" +
-                        " key exchange " + keyExchange +
-                        " when the public key in the server certificate" +
-                        " is less than or equal to 512 bits in length");
-                }
-
-                try {
-                    RSA_ServerKeyExchange rsaSrvKeyExchange =
-                                    new RSA_ServerKeyExchange(input);
-                    handshakeState.update(rsaSrvKeyExchange, resumingSession);
-                    this.serverKeyExchange(rsaSrvKeyExchange);
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_DH_ANON:
-                try {
-                    DH_ServerKeyExchange dhSrvKeyExchange =
-                            new DH_ServerKeyExchange(input, protocolVersion);
-                    handshakeState.update(dhSrvKeyExchange, resumingSession);
-                    this.serverKeyExchange(dhSrvKeyExchange);
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_DHE_DSS:
-            case K_DHE_RSA:
-                try {
-                    DH_ServerKeyExchange dhSrvKeyExchange =
-                        new DH_ServerKeyExchange(
-                        input, serverKey,
-                        clnt_random.random_bytes, svr_random.random_bytes,
-                        messageLen,
-                            getLocalSupportedSignAlgs(), protocolVersion);
-                    handshakeState.update(dhSrvKeyExchange, resumingSession);
-                    this.serverKeyExchange(dhSrvKeyExchange);
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_ECDHE_ECDSA:
-            case K_ECDHE_RSA:
-            case K_ECDH_ANON:
-                try {
-                    ECDH_ServerKeyExchange ecdhSrvKeyExchange =
-                        new ECDH_ServerKeyExchange
-                        (input, serverKey, clnt_random.random_bytes,
-                        svr_random.random_bytes,
-                            getLocalSupportedSignAlgs(), protocolVersion);
-                    handshakeState.update(ecdhSrvKeyExchange, resumingSession);
-                    this.serverKeyExchange(ecdhSrvKeyExchange);
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_RSA:
-            case K_DH_RSA:
-            case K_DH_DSS:
-            case K_ECDH_ECDSA:
-            case K_ECDH_RSA:
-                throw new SSLProtocolException(
-                    "Protocol violation: server sent a server key exchange"
-                    + " message for key exchange " + keyExchange);
-            case K_KRB5:
-            case K_KRB5_EXPORT:
-                throw new SSLProtocolException(
-                    "unexpected receipt of server key exchange algorithm");
-            default:
-                throw new SSLProtocolException(
-                    "unsupported key exchange algorithm = "
-                    + keyExchange);
-            }
-            break;
-
-        case HandshakeMessage.ht_certificate_request:
-            // save for later, it's handled by serverHelloDone
-            if ((keyExchange == K_DH_ANON) || (keyExchange == K_ECDH_ANON)) {
-                throw new SSLHandshakeException(
-                    "Client authentication requested for "+
-                    "anonymous cipher suite.");
-            } else if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-                throw new SSLHandshakeException(
-                    "Client certificate requested for "+
-                    "kerberos cipher suite.");
-            }
-            certRequest = new CertificateRequest(input, protocolVersion);
-            if (debug != null && Debug.isOn("handshake")) {
-                certRequest.print(System.out);
-            }
-            handshakeState.update(certRequest, resumingSession);
-
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                Collection<SignatureAndHashAlgorithm> peerSignAlgs =
-                                        certRequest.getSignAlgorithms();
-                if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                        "No peer supported signature algorithms");
-                }
-
-                Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs =
-                    SignatureAndHashAlgorithm.getSupportedAlgorithms(
-                            algorithmConstraints, peerSignAlgs);
-                if (supportedPeerSignAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                        "No supported signature and hash algorithm in common");
-                }
-
-                setPeerSupportedSignAlgs(supportedPeerSignAlgs);
-                session.setPeerSupportedSignatureAlgorithms(
-                                                supportedPeerSignAlgs);
-            }
-
-            break;
-
-        case HandshakeMessage.ht_server_hello_done:
-            ServerHelloDone serverHelloDone = new ServerHelloDone(input);
-            handshakeState.update(serverHelloDone, resumingSession);
-            this.serverHelloDone(serverHelloDone);
-            break;
-
-        case HandshakeMessage.ht_finished:
-            Finished serverFinished =
-                    new Finished(protocolVersion, input, cipherSuite);
-            handshakeState.update(serverFinished, resumingSession);
-            this.serverFinished(serverFinished);
-
-            break;
-
-        default:
-            throw new SSLProtocolException(
-                "Illegal client handshake msg, " + type);
-        }
-    }
-
-    /*
-     * Used by the server to kickstart negotiations -- this requests a
-     * "client hello" to renegotiate current cipher specs (e.g. maybe lots
-     * of data has been encrypted with the same keys, or the server needs
-     * the client to present a certificate).
-     */
-    private void serverHelloRequest(HelloRequest mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        //
-        // Could be (e.g. at connection setup) that we already
-        // sent the "client hello" but the server's not seen it.
-        //
-        if (!clientHelloDelivered) {
-            if (!secureRenegotiation && !allowUnsafeRenegotiation) {
-                // renegotiation is not allowed.
-                if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
-                    // response with a no_renegotiation warning,
-                    warningSE(Alerts.alert_no_renegotiation);
-
-                    // invalidate the handshake so that the caller can
-                    // dispose this object.
-                    invalidated = true;
-
-                    // If there is still unread block in the handshake
-                    // input stream, it would be truncated with the disposal
-                    // and the next handshake message will become incomplete.
-                    //
-                    // However, according to SSL/TLS specifications, no more
-                    // handshake message should immediately follow ClientHello
-                    // or HelloRequest. So just let it be.
-                } else {
-                    // For SSLv3, send the handshake_failure fatal error.
-                    // Note that SSLv3 does not define a no_renegotiation
-                    // alert like TLSv1. However we cannot ignore the message
-                    // simply, otherwise the other side was waiting for a
-                    // response that would never come.
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Renegotiation is not allowed");
-                }
-            } else {
-                if (!secureRenegotiation) {
-                    if (debug != null && Debug.isOn("handshake")) {
-                        System.out.println(
-                            "Warning: continue with insecure renegotiation");
-                    }
-                }
-                kickstart();
-            }
-        }
-    }
-
-
-    /*
-     * Server chooses session parameters given options created by the
-     * client -- basically, cipher options, session id, and someday a
-     * set of compression options.
-     *
-     * There are two branches of the state machine, decided by the
-     * details of this message.  One is the "fast" handshake, where we
-     * can resume the pre-existing session we asked resume.  The other
-     * is a more expensive "full" handshake, with key exchange and
-     * probably authentication getting done.
-     */
-    private void serverHello(ServerHello mesg) throws IOException {
-        serverKeyExchangeReceived = false;
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        // check if the server selected protocol version is OK for us
-        ProtocolVersion mesgVersion = mesg.protocolVersion;
-        if (!isNegotiable(mesgVersion)) {
-            throw new SSLHandshakeException(
-                "Server chose " + mesgVersion +
-                ", but that protocol version is not enabled or not supported " +
-                "by the client.");
-        }
-
-        handshakeHash.protocolDetermined(mesgVersion);
-
-        // Set protocolVersion and propagate to SSLSocket and the
-        // Handshake streams
-        setVersion(mesgVersion);
-
-        // check the "renegotiation_info" extension
-        RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension)
-                    mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
-        if (serverHelloRI != null) {
-            if (isInitialHandshake) {
-                // verify the length of the "renegotiated_connection" field
-                if (!serverHelloRI.isEmpty()) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The renegotiation_info field is not empty");
-                }
-
-                secureRenegotiation = true;
-            } else {
-                // For a legacy renegotiation, the client MUST verify that
-                // it does not contain the "renegotiation_info" extension.
-                if (!secureRenegotiation) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Unexpected renegotiation indication extension");
-                }
-
-                // verify the client_verify_data and server_verify_data values
-                byte[] verifyData =
-                    new byte[clientVerifyData.length + serverVerifyData.length];
-                System.arraycopy(clientVerifyData, 0, verifyData,
-                        0, clientVerifyData.length);
-                System.arraycopy(serverVerifyData, 0, verifyData,
-                        clientVerifyData.length, serverVerifyData.length);
-                if (!MessageDigest.isEqual(verifyData,
-                                serverHelloRI.getRenegotiatedConnection())) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Incorrect verify data in ServerHello " +
-                        "renegotiation_info message");
-                }
-            }
-        } else {
-            // no renegotiation indication extension
-            if (isInitialHandshake) {
-                if (!allowLegacyHelloMessages) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Failed to negotiate the use of secure renegotiation");
-                }
-
-                secureRenegotiation = false;
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("Warning: No renegotiation " +
-                                    "indication extension in ServerHello");
-                }
-            } else {
-                // For a secure renegotiation, the client must abort the
-                // handshake if no "renegotiation_info" extension is present.
-                if (secureRenegotiation) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "No renegotiation indication extension");
-                }
-
-                // we have already allowed unsafe renegotation before request
-                // the renegotiation.
-            }
-        }
-
-        //
-        // Save server nonce, we always use it to compute connection
-        // keys and it's also used to create the master secret if we're
-        // creating a new session (i.e. in the full handshake).
-        //
-        svr_random = mesg.svr_random;
-
-        if (isNegotiable(mesg.cipherSuite) == false) {
-            fatalSE(Alerts.alert_illegal_parameter,
-                "Server selected improper ciphersuite " + mesg.cipherSuite);
-        }
-
-        setCipherSuite(mesg.cipherSuite);
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
-        }
-
-        if (mesg.compression_method != 0) {
-            fatalSE(Alerts.alert_illegal_parameter,
-                "compression type not supported, "
-                + mesg.compression_method);
-            // NOTREACHED
-        }
-
-        // so far so good, let's look at the session
-        if (session != null) {
-            // we tried to resume, let's see what the server decided
-            if (session.getSessionId().equals(mesg.sessionId)) {
-                // server resumed the session, let's make sure everything
-                // checks out
-
-                // Verify that the session ciphers are unchanged.
-                CipherSuite sessionSuite = session.getSuite();
-                if (cipherSuite != sessionSuite) {
-                    throw new SSLProtocolException
-                        ("Server returned wrong cipher suite for session");
-                }
-
-                // verify protocol version match
-                ProtocolVersion sessionVersion = session.getProtocolVersion();
-                if (protocolVersion != sessionVersion) {
-                    throw new SSLProtocolException
-                        ("Server resumed session with wrong protocol version");
-                }
-
-                // validate subject identity
-                if (sessionSuite.keyExchange == K_KRB5 ||
-                    sessionSuite.keyExchange == K_KRB5_EXPORT) {
-                    Principal localPrincipal = session.getLocalPrincipal();
-
-                    Subject subject = null;
-                    try {
-                        subject = AccessController.doPrivileged(
-                            new PrivilegedExceptionAction<Subject>() {
-                            @Override
-                            public Subject run() throws Exception {
-                                return Krb5Helper.getClientSubject(getAccSE());
-                            }});
-                    } catch (PrivilegedActionException e) {
-                        subject = null;
-                        if (debug != null && Debug.isOn("session")) {
-                            System.out.println("Attempt to obtain" +
-                                        " subject failed!");
-                        }
-                    }
-
-                    if (subject != null) {
-                        // Eliminate dependency on KerberosPrincipal
-                        Set<Principal> principals =
-                            subject.getPrincipals(Principal.class);
-                        if (!principals.contains(localPrincipal)) {
-                            throw new SSLProtocolException("Server resumed" +
-                                " session with wrong subject identity");
-                        } else {
-                            if (debug != null && Debug.isOn("session"))
-                                System.out.println("Subject identity is same");
-                        }
-                    } else {
-                        if (debug != null && Debug.isOn("session"))
-                            System.out.println("Kerberos credentials are not" +
-                                " present in the current Subject; check if " +
-                                " javax.security.auth.useSubjectAsCreds" +
-                                " system property has been set to false");
-                        throw new SSLProtocolException
-                            ("Server resumed session with no subject");
-                    }
-                }
-
-                // looks fine; resume it, and update the state machine.
-                resumingSession = true;
-                calculateConnectionKeys(session.getMasterSecret());
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% Server resumed " + session);
-                }
-            } else {
-                // we wanted to resume, but the server refused
-                //
-                // Invalidate the session for initial handshake in case
-                // of reusing next time.
-                if (isInitialHandshake) {
-                    session.invalidate();
-                }
-                session = null;
-                if (!enableNewSession) {
-                    throw new SSLException("New session creation is disabled");
-                }
-            }
-        }
-
-        // check the "extended_master_secret" extension
-        ExtendedMasterSecretExtension extendedMasterSecretExt =
-                (ExtendedMasterSecretExtension)mesg.extensions.get(
-                        ExtensionType.EXT_EXTENDED_MASTER_SECRET);
-        if (extendedMasterSecretExt != null) {
-            // Is it the expected server extension?
-            if (!useExtendedMasterSecret ||
-                    !(mesgVersion.v >= ProtocolVersion.TLS10.v) || !requestedToUseEMS) {
-                fatalSE(Alerts.alert_unsupported_extension,
-                        "Server sent the extended_master_secret " +
-                        "extension improperly");
-            }
-
-            // For abbreviated handshake, if the original session did not use
-            // the "extended_master_secret" extension but the new ServerHello
-            // contains the extension, the client MUST abort the handshake.
-            if (resumingSession && (session != null) &&
-                    !session.getUseExtendedMasterSecret()) {
-                fatalSE(Alerts.alert_unsupported_extension,
-                        "Server sent an unexpected extended_master_secret " +
-                        "extension on session resumption");
-            }
-        } else {
-            if (useExtendedMasterSecret && !allowLegacyMasterSecret) {
-                // For full handshake, if a client receives a ServerHello
-                // without the extension, it SHOULD abort the handshake if
-                // it does not wish to interoperate with legacy servers.
-                fatalSE(Alerts.alert_handshake_failure,
-                    "Extended Master Secret extension is required");
-            }
-
-            if (resumingSession && (session != null)) {
-                if (session.getUseExtendedMasterSecret()) {
-                    // For abbreviated handshake, if the original session used
-                    // the "extended_master_secret" extension but the new
-                    // ServerHello does not contain the extension, the client
-                    // MUST abort the handshake.
-                    fatalSE(Alerts.alert_handshake_failure,
-                            "Missing Extended Master Secret extension " +
-                            "on session resumption");
-                } else if (useExtendedMasterSecret && !allowLegacyResumption) {
-                    // Unlikely, abbreviated handshake should be discarded.
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Extended Master Secret extension is required");
-                }
-            }
-        }
-
-        // 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
-            // abbreviated initial handshake.
-            if (isInitialHandshake) {
-                session.setAsSessionResumption(true);
-            }
-
-            return;
-        }
-
-        // check extensions
-        for (HelloExtension ext : mesg.extensions.list()) {
-            ExtensionType type = ext.type;
-            if (type == ExtensionType.EXT_SERVER_NAME) {
-                serverNamesAccepted = true;
-            } 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)
-                    && (type != ExtensionType.EXT_EXTENDED_MASTER_SECRET)){
-                fatalSE(Alerts.alert_unsupported_extension,
-                    "Server sent an unsupported extension: " + type);
-            }
-        }
-
-        // Create a new session, we need to do the full handshake
-        session = new SSLSessionImpl(protocolVersion, cipherSuite,
-                            getLocalSupportedSignAlgs(),
-                            mesg.sessionId, getHostSE(), getPortSE(),
-                            (extendedMasterSecretExt != null),
-                            getEndpointIdentificationAlgorithmSE());
-        session.setRequestedServerNames(requestedServerNames);
-        setHandshakeSessionSE(session);
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("** " + cipherSuite);
-        }
-    }
-
-    /*
-     * Server's own key was either a signing-only key, or was too
-     * large for export rules ... this message holds an ephemeral
-     * RSA key to use for key exchange.
-     */
-    private void serverKeyExchange(RSA_ServerKeyExchange mesg)
-            throws IOException, GeneralSecurityException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        if (!mesg.verify(serverKey, clnt_random, svr_random)) {
-            fatalSE(Alerts.alert_handshake_failure,
-                "server key exchange invalid");
-            // NOTREACHED
-        }
-        ephemeralServerKey = mesg.getPublicKey();
-
-        // check constraints of RSA PublicKey
-        if (!algorithmConstraints.permits(
-            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), ephemeralServerKey)) {
-
-            throw new SSLHandshakeException("RSA ServerKeyExchange " +
-                    "does not comply to algorithm constraints");
-        }
-    }
-
-
-    /*
-     * Diffie-Hellman key exchange.  We save the server public key and
-     * our own D-H algorithm object so we can defer key calculations
-     * until after we've sent the client key exchange message (which
-     * gives client and server some useful parallelism).
-     */
-    private void serverKeyExchange(DH_ServerKeyExchange mesg)
-            throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
-                                            sslContext.getSecureRandom());
-        serverDH = mesg.getServerPublicKey();
-
-        // check algorithm constraints
-        dh.checkConstraints(algorithmConstraints, serverDH);
-    }
-
-    private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
-            throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        ECPublicKey key = mesg.getPublicKey();
-        ecdh = new ECDHCrypt(key.getParams(), sslContext.getSecureRandom());
-        ephemeralServerKey = key;
-
-        // check constraints of EC PublicKey
-        if (!algorithmConstraints.permits(
-            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), ephemeralServerKey)) {
-
-            throw new SSLHandshakeException("ECDH ServerKeyExchange " +
-                    "does not comply to algorithm constraints");
-        }
-    }
-
-    /*
-     * The server's "Hello Done" message is the client's sign that
-     * it's time to do all the hard work.
-     */
-    private void serverHelloDone(ServerHelloDone mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        /*
-         * Always make sure the input has been digested before we
-         * start emitting data, to ensure the hashes are correctly
-         * computed for the Finished and CertificateVerify messages
-         * which we send (here).
-         */
-        input.digestNow();
-
-        /*
-         * FIRST ... if requested, send an appropriate Certificate chain
-         * to authenticate the client, and remember the associated private
-         * key to sign the CertificateVerify message.
-         */
-        PrivateKey signingKey = null;
-
-        if (certRequest != null) {
-            X509ExtendedKeyManager km = sslContext.getX509KeyManager();
-
-            ArrayList<String> keytypesTmp = new ArrayList<>(4);
-
-            for (int i = 0; i < certRequest.types.length; i++) {
-                String typeName;
-
-                switch (certRequest.types[i]) {
-                    case CertificateRequest.cct_rsa_sign:
-                        typeName = "RSA";
-                        break;
-
-                    case CertificateRequest.cct_dss_sign:
-                        typeName = "DSA";
-                            break;
-
-                    case CertificateRequest.cct_ecdsa_sign:
-                        // ignore if we do not have EC crypto available
-                        typeName = JsseJce.isEcAvailable() ? "EC" : null;
-                        break;
-
-                    // Fixed DH/ECDH client authentication not supported
-                    //
-                    // case CertificateRequest.cct_rsa_fixed_dh:
-                    // case CertificateRequest.cct_dss_fixed_dh:
-                    // case CertificateRequest.cct_rsa_fixed_ecdh:
-                    // case CertificateRequest.cct_ecdsa_fixed_ecdh:
-                    //
-                    // Any other values (currently not used in TLS)
-                    //
-                    // case CertificateRequest.cct_rsa_ephemeral_dh:
-                    // case CertificateRequest.cct_dss_ephemeral_dh:
-                    default:
-                        typeName = null;
-                        break;
-                }
-
-                if ((typeName != null) && (!keytypesTmp.contains(typeName))) {
-                    keytypesTmp.add(typeName);
-                }
-            }
-
-            String alias = null;
-            int keytypesTmpSize = keytypesTmp.size();
-            if (keytypesTmpSize != 0) {
-                String keytypes[] =
-                        keytypesTmp.toArray(new String[keytypesTmpSize]);
-
-                if (conn != null) {
-                    alias = km.chooseClientAlias(keytypes,
-                        certRequest.getAuthorities(), conn);
-                } else {
-                    alias = km.chooseEngineClientAlias(keytypes,
-                        certRequest.getAuthorities(), engine);
-                }
-            }
-
-            CertificateMsg m1 = null;
-            if (alias != null) {
-                X509Certificate[] certs = km.getCertificateChain(alias);
-                if ((certs != null) && (certs.length != 0)) {
-                    PublicKey publicKey = certs[0].getPublicKey();
-                    if (publicKey != null) {
-                        m1 = new CertificateMsg(certs);
-                        signingKey = km.getPrivateKey(alias);
-                        session.setLocalPrivateKey(signingKey);
-                        session.setLocalCertificates(certs);
-                    }
-                }
-            }
-            if (m1 == null) {
-                //
-                // No appropriate cert was found ... report this to the
-                // server.  For SSLv3, send the no_certificate alert;
-                // TLS uses an empty cert chain instead.
-                //
-                if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-                    m1 = new CertificateMsg(new X509Certificate [0]);
-                } else {
-                    warningSE(Alerts.alert_no_certificate);
-                }
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "Warning: no suitable certificate found - " +
-                        "continuing without client authentication");
-                }
-            }
-
-            //
-            // At last ... send any client certificate chain.
-            //
-            if (m1 != null) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    m1.print(System.out);
-                }
-                m1.write(output);
-                handshakeState.update(m1, resumingSession);
-            }
-        }
-
-        /*
-         * SECOND ... send the client key exchange message.  The
-         * procedure used is a function of the cipher suite selected;
-         * one is always needed.
-         */
-        HandshakeMessage m2;
-
-        switch (keyExchange) {
-
-        case K_RSA:
-        case K_RSA_EXPORT:
-            if (serverKey == null) {
-                throw new SSLProtocolException
-                        ("Server did not send certificate message");
-            }
-
-            if (!(serverKey instanceof RSAPublicKey)) {
-                throw new SSLProtocolException
-                        ("Server certificate does not include an RSA key");
-            }
-
-            /*
-             * For RSA key exchange, we randomly generate a new
-             * pre-master secret and encrypt it with the server's
-             * public key.  Then we save that pre-master secret
-             * so that we can calculate the keying data later;
-             * it's a performance speedup not to do that until
-             * the client's waiting for the server response, but
-             * more of a speedup for the D-H case.
-             *
-             * If the RSA_EXPORT scheme is active, when the public
-             * key in the server certificate is less than or equal
-             * to 512 bits in length, use the cert's public key,
-             * otherwise, the ephemeral one.
-             */
-            PublicKey key;
-            if (keyExchange == K_RSA) {
-                key = serverKey;
-            } else {    // K_RSA_EXPORT
-                if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
-                    // extraneous ephemeralServerKey check done
-                    // above in processMessage()
-                    key = serverKey;
-                } else {
-                    if (ephemeralServerKey == null) {
-                        throw new SSLProtocolException("Server did not send" +
-                            " a RSA_EXPORT Server Key Exchange message");
-                    }
-                    key = ephemeralServerKey;
-                }
-            }
-
-            m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion,
-                                sslContext.getSecureRandom(), key);
-            break;
-        case K_DH_RSA:
-        case K_DH_DSS:
-            /*
-             * For DH Key exchange, we only need to make sure the server
-             * knows our public key, so we calculate the same pre-master
-             * secret.
-             *
-             * For certs that had DH keys in them, we send an empty
-             * handshake message (no key) ... we flag this case by
-             * passing a null "dhPublic" value.
-             *
-             * Otherwise we send ephemeral DH keys, unsigned.
-             */
-            // if (useDH_RSA || useDH_DSS)
-            m2 = new DHClientKeyExchange();
-            break;
-        case K_DHE_RSA:
-        case K_DHE_DSS:
-        case K_DH_ANON:
-            if (dh == null) {
-                throw new SSLProtocolException
-                    ("Server did not send a DH Server Key Exchange message");
-            }
-            m2 = new DHClientKeyExchange(dh.getPublicKey());
-            break;
-        case K_ECDHE_RSA:
-        case K_ECDHE_ECDSA:
-        case K_ECDH_ANON:
-            if (ecdh == null) {
-                throw new SSLProtocolException
-                    ("Server did not send a ECDH Server Key Exchange message");
-            }
-            m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
-            break;
-        case K_ECDH_RSA:
-        case K_ECDH_ECDSA:
-            if (serverKey == null) {
-                throw new SSLProtocolException
-                        ("Server did not send certificate message");
-            }
-            if (serverKey instanceof ECPublicKey == false) {
-                throw new SSLProtocolException
-                        ("Server certificate does not include an EC key");
-            }
-            ECParameterSpec params = ((ECPublicKey)serverKey).getParams();
-            ecdh = new ECDHCrypt(params, sslContext.getSecureRandom());
-            m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
-            break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            String sniHostname = null;
-            for (SNIServerName serverName : requestedServerNames) {
-                if (serverName instanceof SNIHostName) {
-                    sniHostname = ((SNIHostName) serverName).getAsciiName();
-                    break;
-                }
-            }
-
-            KerberosClientKeyExchange kerberosMsg = null;
-            if (sniHostname != null) {
-                // use first requested SNI hostname
-                try {
-                    kerberosMsg = new KerberosClientKeyExchange(
-                        sniHostname, getAccSE(), protocolVersion,
-                        sslContext.getSecureRandom());
-                } catch(IOException e) {
-                    if (serverNamesAccepted) {
-                        // server accepted requested SNI hostname,
-                        // so it must be used
-                        throw e;
-                    }
-                    // fallback to using hostname
-                    if (debug != null && Debug.isOn("handshake")) {
-                        System.out.println(
-                            "Warning, cannot use Server Name Indication: "
-                                + e.getMessage());
-                    }
-                }
-            }
-
-            if (kerberosMsg == null) {
-                String hostname = getHostSE();
-                if (hostname == null) {
-                    throw new IOException("Hostname is required" +
-                        " to use Kerberos cipher suites");
-                }
-                kerberosMsg = new KerberosClientKeyExchange(
-                     hostname, getAccSE(), protocolVersion,
-                     sslContext.getSecureRandom());
-            }
-
-            // Record the principals involved in exchange
-            session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
-            session.setLocalPrincipal(kerberosMsg.getLocalPrincipal());
-            m2 = kerberosMsg;
-            break;
-        default:
-            // somethings very wrong
-            throw new RuntimeException
-                                ("Unsupported key exchange: " + keyExchange);
-        }
-        if (debug != null && Debug.isOn("handshake")) {
-            m2.print(System.out);
-        }
-        m2.write(output);
-
-        handshakeState.update(m2, resumingSession);
-
-        /*
-         * THIRD, send a "change_cipher_spec" record followed by the
-         * "Finished" message.  We flush the messages we've queued up, to
-         * get concurrency between client and server.  The concurrency is
-         * useful as we calculate the master secret, which is needed both
-         * to compute the "Finished" message, and to compute the keys used
-         * to protect all records following the change_cipher_spec.
-         */
-
-        output.doHashes();
-        output.flush();
-
-        /*
-         * We deferred calculating the master secret and this connection's
-         * keying data; we do it now.  Deferring this calculation is good
-         * from a performance point of view, since it lets us do it during
-         * some time that network delays and the server's own calculations
-         * would otherwise cause to be "dead" in the critical path.
-         */
-        SecretKey preMasterSecret;
-        switch (keyExchange) {
-        case K_RSA:
-        case K_RSA_EXPORT:
-            preMasterSecret = ((RSAClientKeyExchange)m2).preMaster;
-            break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            byte[] secretBytes =
-                ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
-            preMasterSecret = new SecretKeySpec(secretBytes,
-                "TlsPremasterSecret");
-            break;
-        case K_DHE_RSA:
-        case K_DHE_DSS:
-        case K_DH_ANON:
-            preMasterSecret = dh.getAgreedSecret(serverDH, true);
-            break;
-        case K_ECDHE_RSA:
-        case K_ECDHE_ECDSA:
-        case K_ECDH_ANON:
-            preMasterSecret = ecdh.getAgreedSecret(ephemeralServerKey);
-            break;
-        case K_ECDH_RSA:
-        case K_ECDH_ECDSA:
-            preMasterSecret = ecdh.getAgreedSecret(serverKey);
-            break;
-        default:
-            throw new IOException("Internal error: unknown key exchange "
-                + keyExchange);
-        }
-
-        calculateKeys(preMasterSecret, null);
-
-        /*
-         * FOURTH, if we sent a Certificate, we need to send a signed
-         * CertificateVerify (unless the key in the client's certificate
-         * was a Diffie-Hellman key).).
-         *
-         * This uses a hash of the previous handshake messages ... either
-         * a nonfinal one (if the particular implementation supports it)
-         * or else using the third element in the arrays of hashes being
-         * computed.
-         */
-        if (signingKey != null) {
-            CertificateVerify m3;
-            try {
-                SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    preferableSignatureAlgorithm =
-                        SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                            getPeerSupportedSignAlgs(),
-                            signingKey.getAlgorithm(), signingKey);
-
-                    if (preferableSignatureAlgorithm == null) {
-                        throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-                    }
-
-                    String hashAlg =
-                        SignatureAndHashAlgorithm.getHashAlgorithmName(
-                                preferableSignatureAlgorithm);
-                    if (hashAlg == null || hashAlg.length() == 0) {
-                        throw new SSLHandshakeException(
-                                "No supported hash algorithm");
-                    }
-                }
-
-                m3 = new CertificateVerify(protocolVersion, handshakeHash,
-                    signingKey, session.getMasterSecret(),
-                    sslContext.getSecureRandom(),
-                    preferableSignatureAlgorithm);
-            } catch (GeneralSecurityException e) {
-                fatalSE(Alerts.alert_handshake_failure,
-                    "Error signing certificate verify", e);
-                // NOTREACHED, make compiler happy
-                m3 = null;
-            }
-            if (debug != null && Debug.isOn("handshake")) {
-                m3.print(System.out);
-            }
-            m3.write(output);
-            handshakeState.update(m3, resumingSession);
-            output.doHashes();
-        }
-
-        /*
-         * OK, that's that!
-         */
-        sendChangeCipherAndFinish(false);
-    }
-
-
-    /*
-     * "Finished" is the last handshake message sent.  If we got this
-     * far, the MAC has been validated post-decryption.  We validate
-     * the two hashes here as an additional sanity check, protecting
-     * the handshake against various active attacks.
-     */
-    private void serverFinished(Finished mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
-            session.getMasterSecret());
-
-        if (!verified) {
-            fatalSE(Alerts.alert_illegal_parameter,
-                       "server 'finished' message doesn't verify");
-            // NOTREACHED
-        }
-
-        /*
-         * save server verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            serverVerifyData = mesg.getVerifyData();
-        }
-
-        /*
-         * Reset the handshake state if this is not an initial handshake.
-         */
-        if (!isInitialHandshake) {
-            session.setAsSessionResumption(false);
-        }
-
-        /*
-         * OK, it verified.  If we're doing the fast handshake, add that
-         * "Finished" message to the hash of handshake messages, then send
-         * our own change_cipher_spec and Finished message for the server
-         * to verify in turn.  These are the last handshake messages.
-         *
-         * In any case, update the session cache.  We're done handshaking,
-         * so there are no threats any more associated with partially
-         * completed handshakes.
-         */
-        if (resumingSession) {
-            input.digestNow();
-            sendChangeCipherAndFinish(true);
-        } else {
-            handshakeFinished = true;
-        }
-        session.setLastAccessedTime(System.currentTimeMillis());
-
-        if (!resumingSession) {
-            if (session.isRejoinable()) {
-                ((SSLSessionContextImpl) sslContext
-                        .engineGetClientSessionContext())
-                        .put(session);
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% Cached client session: " + session);
-                }
-            } else if (debug != null && Debug.isOn("session")) {
-                System.out.println(
-                    "%% Didn't cache non-resumable client session: "
-                    + session);
-            }
-        }
-    }
-
-
-    /*
-     * Send my change-cipher-spec and Finished message ... done as the
-     * last handshake act in either the short or long sequences.  In
-     * the short one, we've already seen the server's Finished; in the
-     * long one, we wait for it now.
-     */
-    private void sendChangeCipherAndFinish(boolean finishedTag)
-            throws IOException {
-        Finished mesg = new Finished(protocolVersion, handshakeHash,
-            Finished.CLIENT, session.getMasterSecret(), cipherSuite);
-
-        /*
-         * Send the change_cipher_spec message, then the Finished message
-         * which we just calculated (and protected using the keys we just
-         * calculated).  Server responds with its Finished message, except
-         * in the "fast handshake" (resume session) case.
-         */
-        sendChangeCipherSpec(mesg, finishedTag);
-
-        /*
-         * save client verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            clientVerifyData = mesg.getVerifyData();
-        }
-    }
-
-
-    /*
-     * Returns a ClientHello message to kickstart renegotiations
-     */
-    @Override
-    HandshakeMessage getKickstartMessage() throws SSLException {
-        // session ID of the ClientHello message
-        SessionId sessionId = new SessionId(new byte[0]);
-
-        // a list of cipher suites sent by the client
-        CipherSuiteList cipherSuites = getActiveCipherSuites();
-
-        // set the max protocol version this client is supporting.
-        maxProtocolVersion = protocolVersion;
-
-        //
-        // Try to resume an existing session.  This might be mandatory,
-        // given certain API options.
-        //
-        session = ((SSLSessionContextImpl)sslContext
-                        .engineGetClientSessionContext())
-                        .get(getHostSE(), getPortSE());
-        if (debug != null && Debug.isOn("session")) {
-            if (session != null) {
-                System.out.println("%% Client cached "
-                    + session
-                    + (session.isRejoinable() ? "" : " (not rejoinable)"));
-            } else {
-                System.out.println("%% No cached client session");
-            }
-        }
-        if (session != null) {
-            // If unsafe server certificate change is not allowed, reserve
-            // current server certificates if the previous handshake is a
-            // session-resumption abbreviated initial handshake.
-            if (!allowUnsafeServerCertChange && session.isSessionResumption()) {
-                try {
-                    // If existing, peer certificate chain cannot be null.
-                    reservedServerCerts =
-                        (X509Certificate[])session.getPeerCertificates();
-                } catch (SSLPeerUnverifiedException puve) {
-                    // Maybe not certificate-based, ignore the exception.
-                }
-            }
-
-            if (!session.isRejoinable()) {
-                session = null;
-            }
-        }
-
-        if (session != null) {
-            CipherSuite sessionSuite = session.getSuite();
-            ProtocolVersion sessionVersion = session.getProtocolVersion();
-            if (isNegotiable(sessionSuite) == false) {
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% can't resume, unavailable cipher");
-                }
-                session = null;
-            }
-
-            if ((session != null) && !isNegotiable(sessionVersion)) {
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% can't resume, protocol disabled");
-                }
-                session = null;
-            }
-
-            if ((session != null) && useExtendedMasterSecret) {
-                boolean isTLS10Plus = sessionVersion.v >= ProtocolVersion.TLS10.v;
-                if (isTLS10Plus && !session.getUseExtendedMasterSecret()) {
-                    if (!allowLegacyResumption) {
-                        // perform full handshake instead
-                        //
-                        // The client SHOULD NOT offer an abbreviated handshake
-                        // to resume a session that does not use an extended
-                        // master secret.  Instead, it SHOULD offer a full
-                        // handshake.
-                        session = null;
-                    }
-                }
-
-                if ((session != null) && !allowUnsafeServerCertChange) {
-                    // It is fine to move on with abbreviate handshake if
-                    // endpoint identification is enabled.
-                    String identityAlg = getEndpointIdentificationAlgorithmSE();
-                    if ((identityAlg == null || identityAlg.length() == 0)) {
-                        if (isTLS10Plus) {
-                            if (!session.getUseExtendedMasterSecret()) {
-                                // perform full handshake instead
-                                session = null;
-                            }   // Otherwise, use extended master secret.
-                        } else {
-                            // The extended master secret extension does not
-                            // apply to SSL 3.0.  Perform a full handshake
-                            // instead.
-                            //
-                            // Note that the useExtendedMasterSecret is
-                            // extended to protect SSL 3.0 connections,
-                            // by discarding abbreviate handshake.
-                            session = null;
-                        }
-                    }
-                }
-            }
-
-            // ensure that the endpoint identification algorithm matches the
-            // one in the session
-            String identityAlg = getEndpointIdentificationAlgorithmSE();
-            if (session != null && identityAlg != null) {
-
-                String sessionIdentityAlg =
-                    session.getEndpointIdentificationAlgorithm();
-                if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
-
-                    if (debug != null && Debug.isOn("session")) {
-                        System.out.println("%% can't resume, endpoint id" +
-                            " algorithm does not match, requested: " +
-                            identityAlg + ", cached: " + sessionIdentityAlg);
-                    }
-                    session = null;
-                }
-            }
-
-            if (session != null) {
-                if (debug != null) {
-                    if (Debug.isOn("handshake") || Debug.isOn("session")) {
-                        System.out.println("%% Try resuming " + session
-                            + " from port " + getLocalPortSE());
-                    }
-                }
-
-                sessionId = session.getSessionId();
-                maxProtocolVersion = sessionVersion;
-
-                // Update SSL version number in underlying SSL socket and
-                // handshake output stream, so that the output records (at the
-                // record layer) have the correct version
-                setVersion(sessionVersion);
-            }
-
-            /*
-             * Force use of the previous session ciphersuite, and
-             * add the SCSV if enabled.
-             */
-            if (!enableNewSession) {
-                if (session == null) {
-                    throw new SSLHandshakeException(
-                        "Can't reuse existing SSL client session");
-                }
-
-                Collection<CipherSuite> cipherList = new ArrayList<>(2);
-                cipherList.add(sessionSuite);
-                if (!secureRenegotiation &&
-                        cipherSuites.contains(CipherSuite.C_SCSV)) {
-                    cipherList.add(CipherSuite.C_SCSV);
-                }   // otherwise, renegotiation_info extension will be used
-
-                cipherSuites = new CipherSuiteList(cipherList);
-            }
-        }
-
-        if (session == null && !enableNewSession) {
-            throw new SSLHandshakeException("No existing session to resume");
-        }
-
-        // exclude SCSV for secure renegotiation
-        if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) {
-            Collection<CipherSuite> cipherList =
-                        new ArrayList<>(cipherSuites.size() - 1);
-            for (CipherSuite suite : cipherSuites.collection()) {
-                if (suite != CipherSuite.C_SCSV) {
-                    cipherList.add(suite);
-                }
-            }
-
-            cipherSuites = new CipherSuiteList(cipherList);
-        }
-
-        // make sure there is a negotiable cipher suite.
-        boolean negotiable = false;
-        for (CipherSuite suite : cipherSuites.collection()) {
-            if (isNegotiable(suite)) {
-                negotiable = true;
-                break;
-            }
-        }
-
-        if (!negotiable) {
-            throw new SSLHandshakeException("No negotiable cipher suite");
-        }
-
-        // Not a TLS1.2+ handshake
-        // For SSLv2Hello, HandshakeHash.reset() will be called, so we
-        // cannot call HandshakeHash.protocolDetermined() here. As it does
-        // not follow the spec that HandshakeHash.reset() can be only be
-        // called before protocolDetermined.
-        // if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) {
-        //     handshakeHash.protocolDetermined(maxProtocolVersion);
-        // }
-
-        // create the ClientHello message
-        ClientHello clientHelloMessage = new ClientHello(
-                sslContext.getSecureRandom(), maxProtocolVersion,
-                sessionId, cipherSuites);
-
-        // add elliptic curves and point format extensions
-        if (cipherSuites.containsEC()) {
-            EllipticCurvesExtension ece =
-                EllipticCurvesExtension.createExtension(algorithmConstraints);
-            if (ece != null) {
-                clientHelloMessage.extensions.add(ece);
-                clientHelloMessage.extensions.add(
-                   EllipticPointFormatsExtension.DEFAULT);
-            }
-        }
-
-        // add signature_algorithm extension
-        if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
-            // we will always send the signature_algorithm extension
-            Collection<SignatureAndHashAlgorithm> localSignAlgs =
-                                                getLocalSupportedSignAlgs();
-            if (localSignAlgs.isEmpty()) {
-                throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-            }
-
-            clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
-        }
-
-        // add Extended Master Secret extension
-        if (useExtendedMasterSecret && (maxProtocolVersion.v >= ProtocolVersion.TLS10.v)) {
-            if ((session == null) || session.getUseExtendedMasterSecret()) {
-                clientHelloMessage.addExtendedMasterSecretExtension();
-                requestedToUseEMS = true;
-            }
-        }
-
-        // add server_name extension
-        if (enableSNIExtension) {
-            if (session != null) {
-                requestedServerNames = session.getRequestedServerNames();
-            } else {
-                requestedServerNames = serverNames;
-            }
-
-            if (!requestedServerNames.isEmpty()) {
-                clientHelloMessage.addSNIExtension(requestedServerNames);
-            }
-        }
-
-        // Add ALPN extension
-        if (localApl != null && localApl.length > 0) {
-            clientHelloMessage.addALPNExtension(localApl);
-            alpnActive = true;
-        }
-
-        // reset the client random cookie
-        clnt_random = clientHelloMessage.clnt_random;
-
-        /*
-         * need to set the renegotiation_info extension for:
-         * 1: secure renegotiation
-         * 2: initial handshake and no SCSV in the ClientHello
-         * 3: insecure renegotiation and no SCSV in the ClientHello
-         */
-        if (secureRenegotiation ||
-                !cipherSuites.contains(CipherSuite.C_SCSV)) {
-            clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData);
-        }
-
-        return clientHelloMessage;
-    }
-
-    /*
-     * Fault detected during handshake.
-     */
-    @Override
-    void handshakeAlert(byte description) throws SSLProtocolException {
-        String message = Alerts.alertDescription(description);
-
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("SSL - handshake alert: " + message);
-        }
-        throw new SSLProtocolException("handshake alert:  " + message);
-    }
-
-    /*
-     * Unless we are using an anonymous ciphersuite, the server always
-     * sends a certificate message (for the CipherSuites we currently
-     * support). The trust manager verifies the chain for us.
-     */
-    private void serverCertificate(CertificateMsg mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        X509Certificate[] peerCerts = mesg.getCertificateChain();
-        if (peerCerts.length == 0) {
-            fatalSE(Alerts.alert_bad_certificate, "empty certificate chain");
-        }
-
-        // Allow server certificate change in client side during renegotiation
-        // after a session-resumption abbreviated initial handshake?
-        //
-        // DO NOT need to check allowUnsafeServerCertChange here.  We only
-        // reserve server certificates when allowUnsafeServerCertChange is
-        // flase.
-        //
-        // Allow server certificate change if it is negotiated to use the
-        // extended master secret.
-        if ((reservedServerCerts != null) &&
-                !session.getUseExtendedMasterSecret()) {
-            // It is not necessary to check the certificate update if endpoint
-            // identification is enabled.
-            String identityAlg = getEndpointIdentificationAlgorithmSE();
-            if ((identityAlg == null || identityAlg.length() == 0) &&
-                !isIdentityEquivalent(peerCerts[0], reservedServerCerts[0])) {
-
-                fatalSE(Alerts.alert_bad_certificate,
-                        "server certificate change is restricted " +
-                        "during renegotiation");
-            }
-        }
-
-        // ask the trust manager to verify the chain
-        X509TrustManager tm = sslContext.getX509TrustManager();
-        try {
-            // find out the key exchange algorithm used
-            // use "RSA" for non-ephemeral "RSA_EXPORT"
-            String keyExchangeString;
-            if (keyExchange == K_RSA_EXPORT && !serverKeyExchangeReceived) {
-                keyExchangeString = K_RSA.name;
-            } else {
-                keyExchangeString = keyExchange.name;
-            }
-
-            if (tm instanceof X509ExtendedTrustManager) {
-                if (conn != null) {
-                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
-                        peerCerts.clone(),
-                        keyExchangeString,
-                        conn);
-                } else {
-                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
-                        peerCerts.clone(),
-                        keyExchangeString,
-                        engine);
-                }
-            } else {
-                // Unlikely to happen, because we have wrapped the old
-                // X509TrustManager with the new X509ExtendedTrustManager.
-                throw new CertificateException(
-                    "Improper X509TrustManager implementation");
-            }
-        } catch (CertificateException e) {
-            // This will throw an exception, so include the original error.
-            fatalSE(Alerts.alert_certificate_unknown, e);
-        }
-        session.setPeerCertificates(peerCerts);
-    }
-
-    /*
-     * Whether the certificates can represent the same identity?
-     *
-     * The certificates can be used to represent the same identity:
-     *     1. If the subject alternative names of IP address are present in
-     *        both certificates, they should be identical; otherwise,
-     *     2. if the subject alternative names of DNS name are present in
-     *        both certificates, they should be identical; otherwise,
-     *     3. if the subject fields are present in both certificates, the
-     *        certificate subjects and issuers should be identical.
-     */
-    private static boolean isIdentityEquivalent(X509Certificate thisCert,
-            X509Certificate prevCert) {
-        if (thisCert.equals(prevCert)) {
-            return true;
-        }
-
-        // check subject alternative names
-        Collection<List<?>> thisSubjectAltNames = null;
-        try {
-            thisSubjectAltNames = thisCert.getSubjectAlternativeNames();
-        } catch (CertificateParsingException cpe) {
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println(
-                        "Attempt to obtain subjectAltNames extension failed!");
-            }
-        }
-
-        Collection<List<?>> prevSubjectAltNames = null;
-        try {
-            prevSubjectAltNames = prevCert.getSubjectAlternativeNames();
-        } catch (CertificateParsingException cpe) {
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println(
-                        "Attempt to obtain subjectAltNames extension failed!");
-            }
-        }
-
-        if ((thisSubjectAltNames != null) && (prevSubjectAltNames != null)) {
-            // check the iPAddress field in subjectAltName extension
-            Collection<String> thisSubAltIPAddrs =
-                        getSubjectAltNames(thisSubjectAltNames, ALTNAME_IP);
-            Collection<String> prevSubAltIPAddrs =
-                        getSubjectAltNames(prevSubjectAltNames, ALTNAME_IP);
-            if ((thisSubAltIPAddrs != null) && (prevSubAltIPAddrs != null) &&
-                (isEquivalent(thisSubAltIPAddrs, prevSubAltIPAddrs))) {
-
-                return true;
-            }
-
-            // check the dNSName field in subjectAltName extension
-            Collection<String> thisSubAltDnsNames =
-                        getSubjectAltNames(thisSubjectAltNames, ALTNAME_DNS);
-            Collection<String> prevSubAltDnsNames =
-                        getSubjectAltNames(prevSubjectAltNames, ALTNAME_DNS);
-            if ((thisSubAltDnsNames != null) && (prevSubAltDnsNames != null) &&
-                (isEquivalent(thisSubAltDnsNames, prevSubAltDnsNames))) {
-
-                return true;
-            }
-        }
-
-        // check the certificate subject and issuer
-        X500Principal thisSubject = thisCert.getSubjectX500Principal();
-        X500Principal prevSubject = prevCert.getSubjectX500Principal();
-        X500Principal thisIssuer = thisCert.getIssuerX500Principal();
-        X500Principal prevIssuer = prevCert.getIssuerX500Principal();
-        if (!thisSubject.getName().isEmpty() &&
-                !prevSubject.getName().isEmpty() &&
-                thisSubject.equals(prevSubject) &&
-                thisIssuer.equals(prevIssuer)) {
-            return true;
-        }
-
-        return false;
-    }
-
-    /*
-     * Returns the subject alternative name of the specified type in the
-     * subjectAltNames extension of a certificate.
-     *
-     * Note that only those subjectAltName types that use String data
-     * should be passed into this function.
-     */
-    private static Collection<String> getSubjectAltNames(
-            Collection<List<?>> subjectAltNames, int type) {
-
-        HashSet<String> subAltDnsNames = null;
-        for (List<?> subjectAltName : subjectAltNames) {
-            int subjectAltNameType = (Integer)subjectAltName.get(0);
-            if (subjectAltNameType == type) {
-                String subAltDnsName = (String)subjectAltName.get(1);
-                if ((subAltDnsName != null) && !subAltDnsName.isEmpty()) {
-                    if (subAltDnsNames == null) {
-                        subAltDnsNames =
-                                new HashSet<>(subjectAltNames.size());
-                    }
-                    subAltDnsNames.add(subAltDnsName);
-                }
-            }
-        }
-
-        return subAltDnsNames;
-    }
-
-    private static boolean isEquivalent(Collection<String> thisSubAltNames,
-            Collection<String> prevSubAltNames) {
-
-        for (String thisSubAltName : thisSubAltNames) {
-            for (String prevSubAltName : prevSubAltNames) {
-                // Only allow the exactly match.  Check no wildcard character.
-                if (thisSubAltName.equalsIgnoreCase(prevSubAltName)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-}
--- a/src/share/classes/sun/security/ssl/DHClientKeyExchange.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.io.PrintStream;
-import java.math.BigInteger;
-import javax.net.ssl.SSLHandshakeException;
-
-/*
- * Message used by clients to send their Diffie-Hellman public
- * keys to servers.
- *
- * @author David Brownell
- */
-final class DHClientKeyExchange extends HandshakeMessage {
-
-    @Override
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
-    /*
-     * This value may be empty if it was included in the
-     * client's certificate ...
-     */
-    private byte dh_Yc[];               // 1 to 2^16 -1 bytes
-
-    BigInteger getClientPublicKey() {
-        return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
-    }
-
-    /*
-     * Either pass the client's public key explicitly (because it's
-     * using DHE or DH_anon), or implicitly (the public key was in the
-     * certificate).
-     */
-    DHClientKeyExchange(BigInteger publicKey) {
-        dh_Yc = toByteArray(publicKey);
-    }
-
-    DHClientKeyExchange() {
-        dh_Yc = null;
-    }
-
-    /*
-     * Get the client's public key either explicitly or implicitly.
-     * (It's ugly to have an empty record be sent in the latter case,
-     * but that's what the protocol spec requires.)
-     */
-    DHClientKeyExchange(HandshakeInStream input) throws IOException {
-        if (input.available() >= 2) {
-            dh_Yc = input.getBytes16();
-        } else {
-            // currently, we don't support cipher suites that requires
-            // implicit public key of client.
-            throw new SSLHandshakeException(
-                    "Unsupported implicit client DiffieHellman public key");
-        }
-    }
-
-    @Override
-    int messageLength() {
-        if (dh_Yc == null) {
-            return 0;
-        } else {
-            return dh_Yc.length + 2;
-        }
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        if (dh_Yc != null && dh_Yc.length != 0) {
-            s.putBytes16(dh_Yc);
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** ClientKeyExchange, DH");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "DH Public key", dh_Yc);
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/DHCrypt.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,538 +0,0 @@
-/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Collections;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-import java.math.BigInteger;
-import java.security.*;
-import java.io.IOException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.crypto.SecretKey;
-import javax.crypto.KeyAgreement;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.*;
-import java.util.EnumSet;
-
-import sun.security.util.KeyUtil;
-
-/**
- * This class implements the Diffie-Hellman key exchange algorithm.
- * D-H means combining your private key with your partners public key to
- * generate a number. The peer does the same with its private key and our
- * public key. Through the magic of Diffie-Hellman we both come up with the
- * same number. This number is secret (discounting MITM attacks) and hence
- * called the shared secret. It has the same length as the modulus, e.g. 512
- * or 1024 bit. Man-in-the-middle attacks are typically countered by an
- * independent authentication step using certificates (RSA, DSA, etc.).
- *
- * The thing to note is that the shared secret is constant for two partners
- * with constant private keys. This is often not what we want, which is why
- * it is generally a good idea to create a new private key for each session.
- * Generating a private key involves one modular exponentiation assuming
- * suitable D-H parameters are available.
- *
- * General usage of this class (TLS DHE case):
- *  . if we are server, call DHCrypt(keyLength,random). This generates
- *    an ephemeral keypair of the request length.
- *  . if we are client, call DHCrypt(modulus, base, random). This
- *    generates an ephemeral keypair using the parameters specified by
- *    the server.
- *  . send parameters and public value to remote peer
- *  . receive peers ephemeral public key
- *  . call getAgreedSecret() to calculate the shared secret
- *
- * In TLS the server chooses the parameter values itself, the client must use
- * those sent to it by the server.
- *
- * The use of ephemeral keys as described above also achieves what is called
- * "forward secrecy". This means that even if the authentication keys are
- * broken at a later date, the shared secret remains secure. The session is
- * compromised only if the authentication keys are already broken at the
- * time the key exchange takes place and an active MITM attack is used.
- * This is in contrast to straightforward encrypting RSA key exchanges.
- *
- * @author David Brownell
- */
-final class DHCrypt {
-
-    // group parameters (prime modulus and generator)
-    private BigInteger modulus;                 // P (aka N)
-    private BigInteger base;                    // G (aka alpha)
-
-    // our private key (including private component x)
-    private PrivateKey privateKey;
-
-    // public component of our key, X = (g ^ x) mod p
-    private BigInteger publicValue;             // X (aka y)
-
-    // the times to recove from failure if public key validation
-    private static int MAX_FAILOVER_TIMES = 2;
-
-    /**
-     * Generate a Diffie-Hellman keypair of the specified size.
-     */
-    DHCrypt(int keyLength, SecureRandom random) {
-        this(keyLength,
-                ParametersHolder.definedParams.get(keyLength), random);
-    }
-
-    /**
-     * Generate a Diffie-Hellman keypair using the specified parameters.
-     *
-     * @param modulus the Diffie-Hellman modulus P
-     * @param base the Diffie-Hellman base G
-     */
-    DHCrypt(BigInteger modulus, BigInteger base, SecureRandom random) {
-        this(modulus.bitLength(),
-                new DHParameterSpec(modulus, base), random);
-    }
-
-    /**
-     * Generate a Diffie-Hellman keypair using the specified size and
-     * parameters.
-     */
-    private DHCrypt(int keyLength,
-            DHParameterSpec params, SecureRandom random) {
-
-        try {
-            KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
-            if (params != null) {
-                kpg.initialize(params, random);
-            } else {
-                kpg.initialize(keyLength, random);
-            }
-
-            DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
-            if (spec == null) {
-                throw new RuntimeException("Could not generate DH keypair");
-            }
-
-            publicValue = spec.getY();
-            modulus = spec.getP();
-            base = spec.getG();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
-        }
-    }
-
-    static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) {
-        if (key instanceof DHPublicKey) {
-            DHPublicKey dhKey = (DHPublicKey)key;
-            DHParameterSpec params = dhKey.getParams();
-            return new DHPublicKeySpec(dhKey.getY(),
-                                    params.getP(), params.getG());
-        }
-        try {
-            KeyFactory factory = JsseJce.getKeyFactory("DiffieHellman");
-            return factory.getKeySpec(key, DHPublicKeySpec.class);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-    /** Returns the Diffie-Hellman modulus. */
-    BigInteger getModulus() {
-        return modulus;
-    }
-
-    /** Returns the Diffie-Hellman base (generator).  */
-    BigInteger getBase() {
-        return base;
-    }
-
-    /**
-     * Gets the public key of this end of the key exchange.
-     */
-    BigInteger getPublicKey() {
-        return publicValue;
-    }
-
-    /**
-     * Get the secret data that has been agreed on through Diffie-Hellman
-     * key agreement protocol.  Note that in the two party protocol, if
-     * the peer keys are already known, no other data needs to be sent in
-     * order to agree on a secret.  That is, a secured message may be
-     * sent without any mandatory round-trip overheads.
-     *
-     * <P>It is illegal to call this member function if the private key
-     * has not been set (or generated).
-     *
-     * @param  peerPublicKey the peer's public key.
-     * @param  keyIsValidated whether the {@code peerPublicKey} has beed
-     *         validated
-     * @return the secret, which is an unsigned big-endian integer
-     *         the same size as the Diffie-Hellman modulus.
-     */
-    SecretKey getAgreedSecret(BigInteger peerPublicValue,
-            boolean keyIsValidated) throws SSLHandshakeException {
-        try {
-            KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
-            DHPublicKeySpec spec =
-                        new DHPublicKeySpec(peerPublicValue, modulus, base);
-            PublicKey publicKey = kf.generatePublic(spec);
-            KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
-
-            // validate the Diffie-Hellman public key
-            if (!keyIsValidated &&
-                    !KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) {
-                try {
-                    KeyUtil.validate(spec);
-                } catch (InvalidKeyException ike) {
-                    // prefer handshake_failure alert to internal_error alert
-                    throw new SSLHandshakeException(ike.getMessage());
-                }
-            }
-
-            ka.init(privateKey);
-            ka.doPhase(publicKey, true);
-            return ka.generateSecret("TlsPremasterSecret");
-        } catch (GeneralSecurityException e) {
-            throw (SSLHandshakeException) new SSLHandshakeException(
-                "Could not generate secret").initCause(e);
-        }
-    }
-
-    // Check constraints of the specified DH public key.
-    void checkConstraints(AlgorithmConstraints constraints,
-            BigInteger peerPublicValue) throws SSLHandshakeException {
-
-        try {
-            KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
-            DHPublicKeySpec spec =
-                        new DHPublicKeySpec(peerPublicValue, modulus, base);
-            DHPublicKey publicKey = (DHPublicKey)kf.generatePublic(spec);
-
-            // check constraints of DHPublicKey
-            if (!constraints.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
-                throw new SSLHandshakeException(
-                    "DHPublicKey does not comply to algorithm constraints");
-            }
-        } catch (GeneralSecurityException gse) {
-            throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate DHPublicKey").initCause(gse);
-        }
-    }
-
-    // Generate and validate DHPublicKeySpec
-    private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg)
-            throws GeneralSecurityException {
-
-        boolean doExtraValiadtion =
-                    (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
-        for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) {
-            KeyPair kp = kpg.generateKeyPair();
-            privateKey = kp.getPrivate();
-            DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
-
-            // validate the Diffie-Hellman public key
-            if (doExtraValiadtion) {
-                try {
-                    KeyUtil.validate(spec);
-                } catch (InvalidKeyException ivke) {
-                    if (i == MAX_FAILOVER_TIMES) {
-                        throw ivke;
-                    }
-                    // otherwise, ignore the exception and try the next one
-                    continue;
-                }
-            }
-
-            return spec;
-        }
-
-        return null;
-    }
-
-    // lazy initialization holder class idiom for static default parameters
-    //
-    // See Effective Java Second Edition: Item 71.
-    private static class ParametersHolder {
-        private final static boolean debugIsOn =
-                (Debug.getInstance("ssl") != null) && Debug.isOn("sslctx");
-
-        //
-        // Default DH ephemeral parameters
-        //
-        private static final BigInteger g2 = BigInteger.valueOf(2);
-
-        private static final BigInteger p512 = new BigInteger(   // generated
-                "D87780E15FF50B4ABBE89870188B049406B5BEA98AB23A02" +
-                "41D88EA75B7755E669C08093D3F0CA7FC3A5A25CF067DCB9" +
-                "A43DD89D1D90921C6328884461E0B6D3", 16);
-        private static final BigInteger p768 = new BigInteger(   // RFC 2409
-                "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
-                "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
-                "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
-                "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 16);
-
-        private static final BigInteger p1024 = new BigInteger(  // RFC 2409
-                "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
-                "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
-                "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
-                "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
-                "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" +
-                "FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p1536 = new BigInteger(  // RFC 3526
-                "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
-                "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
-                "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
-                "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
-                "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
-                "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
-                "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
-                "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p2048 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B423861285C97FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p3072 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p4096 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
-                "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
-                "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
-                "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
-                "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
-                "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6A" +
-                "FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p6144 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
-                "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
-                "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
-                "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
-                "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
-                "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
-                "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
-                "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
-                "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
-                "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
-                "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
-                "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
-                "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
-                "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
-                "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
-                "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
-                "A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF", 16);
-        private static final BigInteger p8192 = new BigInteger(  // TLS FFDHE
-                "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
-                "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
-                "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
-                "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
-                "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
-                "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
-                "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
-                "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
-                "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
-                "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
-                "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
-                "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
-                "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
-                "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
-                "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
-                "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
-                "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
-                "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
-                "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
-                "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
-                "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
-                "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
-                "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
-                "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
-                "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
-                "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
-                "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
-                "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
-                "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
-                "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
-                "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
-                "A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C838" +
-                "1E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E" +
-                "0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665" +
-                "CB2C0F1CC01BD70229388839D2AF05E454504AC78B758282" +
-                "2846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022" +
-                "BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C" +
-                "51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9" +
-                "D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA457" +
-                "1EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30" +
-                "FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D" +
-                "97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88C" +
-                "D68C8BB7C5C6424CFFFFFFFFFFFFFFFF", 16);
-
-        private static final BigInteger[] supportedPrimes = {
-                p512, p768, p1024, p1536, p2048, p3072, p4096, p6144, p8192};
-
-        // a measure of the uncertainty that prime modulus p is not a prime
-        //
-        // see BigInteger.isProbablePrime(int certainty)
-        private final static int PRIME_CERTAINTY = 120;
-
-        // the known security property, jdk.tls.server.defaultDHEParameters
-        private final static String PROPERTY_NAME =
-                "jdk.tls.server.defaultDHEParameters";
-
-        private static final Pattern spacesPattern = Pattern.compile("\\s+");
-
-        private final static Pattern syntaxPattern = Pattern.compile(
-                "(\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})" +
-                "(,\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})*");
-
-        private static final Pattern paramsPattern = Pattern.compile(
-                "\\{([0-9A-Fa-f]+),([0-9A-Fa-f]+)\\}");
-
-        // cache of predefined default DH ephemeral parameters
-        private final static Map<Integer,DHParameterSpec> definedParams;
-
-        static {
-            String property = AccessController.doPrivileged(
-                new PrivilegedAction<String>() {
-                    public String run() {
-                        return Security.getProperty(PROPERTY_NAME);
-                    }
-                });
-
-            if (property != null && !property.isEmpty()) {
-                // remove double quote marks from beginning/end of the property
-                if (property.length() >= 2 && property.charAt(0) == '"' &&
-                        property.charAt(property.length() - 1) == '"') {
-                    property = property.substring(1, property.length() - 1);
-                }
-
-                property = property.trim();
-            }
-
-            if (property != null && !property.isEmpty()) {
-                Matcher spacesMatcher = spacesPattern.matcher(property);
-                property = spacesMatcher.replaceAll("");
-
-                if (debugIsOn) {
-                    System.out.println("The Security Property " +
-                            PROPERTY_NAME + ": " + property);
-                }
-            }
-
-            Map<Integer,DHParameterSpec> defaultParams = new HashMap<>();
-            if (property != null && !property.isEmpty()) {
-                Matcher syntaxMatcher = syntaxPattern.matcher(property);
-                if (syntaxMatcher.matches()) {
-                    Matcher paramsFinder = paramsPattern.matcher(property);
-                    while(paramsFinder.find()) {
-                        String primeModulus = paramsFinder.group(1);
-                        BigInteger p = new BigInteger(primeModulus, 16);
-                        if (!p.isProbablePrime(PRIME_CERTAINTY)) {
-                            if (debugIsOn) {
-                                System.out.println(
-                                    "Prime modulus p in Security Property, " +
-                                    PROPERTY_NAME + ", is not a prime: " +
-                                    primeModulus);
-                            }
-
-                            continue;
-                        }
-
-                        String baseGenerator = paramsFinder.group(2);
-                        BigInteger g = new BigInteger(baseGenerator, 16);
-
-                        DHParameterSpec spec = new DHParameterSpec(p, g);
-                        int primeLen = p.bitLength();
-                        defaultParams.put(primeLen, spec);
-                    }
-                } else if (debugIsOn) {
-                    System.out.println("Invalid Security Property, " +
-                            PROPERTY_NAME + ", definition");
-                }
-            }
-
-            for (BigInteger p : supportedPrimes) {
-                int primeLen = p.bitLength();
-                defaultParams.putIfAbsent(primeLen, new DHParameterSpec(p, g2));
-            }
-
-            definedParams =
-                    Collections.<Integer,DHParameterSpec>unmodifiableMap(
-                                                                defaultParams);
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/Debug.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, 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.PrintStream;
-import java.security.AccessController;
-import java.util.Locale;
-
-import sun.security.action.GetPropertyAction;
-
-/**
- * This class has be shamefully lifted from sun.security.util.Debug
- *
- * @author Gary Ellison
- */
-public class Debug {
-
-    private String prefix;
-
-    private static String args;
-
-    static {
-        args = java.security.AccessController.doPrivileged(
-            new GetPropertyAction("javax.net.debug", ""));
-        args = args.toLowerCase(Locale.ENGLISH);
-        if (args.equals("help")) {
-            Help();
-        }
-    }
-
-    public static void Help()
-    {
-        System.err.println();
-        System.err.println("all            turn on all debugging");
-        System.err.println("ssl            turn on ssl debugging");
-        System.err.println();
-        System.err.println("The following can be used with ssl:");
-        System.err.println("\trecord       enable per-record tracing");
-        System.err.println("\thandshake    print each handshake message");
-        System.err.println("\tkeygen       print key generation data");
-        System.err.println("\tsession      print session activity");
-        System.err.println("\tdefaultctx   print default SSL initialization");
-        System.err.println("\tsslctx       print SSLContext tracing");
-        System.err.println("\tsessioncache print session cache tracing");
-        System.err.println("\tkeymanager   print key manager tracing");
-        System.err.println("\ttrustmanager print trust manager tracing");
-        System.err.println("\tpluggability print pluggability tracing");
-        System.err.println();
-        System.err.println("\thandshake debugging can be widened with:");
-        System.err.println("\tdata         hex dump of each handshake message");
-        System.err.println("\tverbose      verbose handshake message printing");
-        System.err.println();
-        System.err.println("\trecord debugging can be widened with:");
-        System.err.println("\tplaintext    hex dump of record plaintext");
-        System.err.println("\tpacket       print raw SSL/TLS packets");
-        System.err.println();
-        System.exit(0);
-    }
-
-    /**
-     * Get a Debug object corresponding to whether or not the given
-     * option is set. Set the prefix to be the same as option.
-     */
-
-    public static Debug getInstance(String option)
-    {
-        return getInstance(option, option);
-    }
-
-    /**
-     * Get a Debug object corresponding to whether or not the given
-     * option is set. Set the prefix to be prefix.
-     */
-    public static Debug getInstance(String option, String prefix)
-    {
-        if (isOn(option)) {
-            Debug d = new Debug();
-            d.prefix = prefix;
-            return d;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * True if the property "javax.net.debug" contains the
-     * string "option".
-     */
-    public static boolean isOn(String option)
-    {
-        if (args == null) {
-            return false;
-        } else {
-            int n = 0;
-            option = option.toLowerCase(Locale.ENGLISH);
-
-            if (args.indexOf("all") != -1) {
-                return true;
-            } else if ((n = args.indexOf("ssl")) != -1) {
-                if (args.indexOf("sslctx", n) == -1) {
-                    // don't enable data and plaintext options by default
-                    if (!(option.equals("data")
-                        || option.equals("packet")
-                        || option.equals("plaintext"))) {
-                        return true;
-                    }
-                }
-            }
-            return (args.indexOf(option) != -1);
-        }
-    }
-
-    /**
-     * print a message to stderr that is prefixed with the prefix
-     * created from the call to getInstance.
-     */
-
-    public void println(String message)
-    {
-        System.err.println(prefix + ": "+message);
-    }
-
-    /**
-     * print a blank line to stderr that is prefixed with the prefix.
-     */
-
-    public void println()
-    {
-        System.err.println(prefix + ":");
-    }
-
-    /**
-     * print a message to stderr that is prefixed with the prefix.
-     */
-
-    public static void println(String prefix, String message)
-    {
-        System.err.println(prefix + ": "+message);
-    }
-
-    public static void println(PrintStream s, String name, byte[] data) {
-        s.print(name + ":  { ");
-        if (data == null) {
-            s.print("null");
-        } else {
-            for (int i = 0; i < data.length; i++) {
-                if (i != 0) s.print(", ");
-                s.print(data[i] & 0x0ff);
-            }
-        }
-        s.println(" }");
-    }
-
-    /**
-     * Return the value of the boolean System property propName.
-     *
-     * Note use of doPrivileged(). Do make accessible to applications.
-     */
-    static boolean getBooleanProperty(String propName, boolean defaultValue) {
-        // if set, require value of either true or false
-        String b = AccessController.doPrivileged(
-                new GetPropertyAction(propName));
-        if (b == null) {
-            return defaultValue;
-        } else if (b.equalsIgnoreCase("false")) {
-            return false;
-        } else if (b.equalsIgnoreCase("true")) {
-            return true;
-        } else {
-            throw new RuntimeException("Value of " + propName
-                + " must either be 'true' or 'false'");
-        }
-    }
-
-    static String toString(byte[] b) {
-        return sun.security.util.Debug.toString(b);
-    }
-}
--- a/src/share/classes/sun/security/ssl/ECDHClientKeyExchange.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2006, 2012, 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.io.PrintStream;
-
-import java.security.PublicKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.*;
-
-/**
- * ClientKeyExchange message for all ECDH based key exchange methods. It
- * contains the client's ephemeral public value.
- *
- * @since   1.6
- * @author  Andreas Sterbenz
- */
-final class ECDHClientKeyExchange extends HandshakeMessage {
-
-    @Override
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
-    private byte[] encodedPoint;
-
-    byte[] getEncodedPoint() {
-        return encodedPoint;
-    }
-
-    // Called by the client with its ephemeral public key.
-    ECDHClientKeyExchange(PublicKey publicKey) {
-        ECPublicKey ecKey = (ECPublicKey)publicKey;
-        ECPoint point = ecKey.getW();
-        ECParameterSpec params = ecKey.getParams();
-        encodedPoint = JsseJce.encodePoint(point, params.getCurve());
-    }
-
-    ECDHClientKeyExchange(HandshakeInStream input) throws IOException {
-        encodedPoint = input.getBytes8();
-    }
-
-    @Override
-    int messageLength() {
-        return encodedPoint.length + 1;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putBytes8(encodedPoint);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** ECDHClientKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "ECDH Public value", encodedPoint);
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/ECDHCrypt.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2006, 2016, 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.security.*;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.*;
-
-import java.util.EnumSet;
-import javax.crypto.SecretKey;
-import javax.crypto.KeyAgreement;
-import javax.net.ssl.SSLHandshakeException;
-
-/**
- * Helper class for the ECDH key exchange. It generates the appropriate
- * ephemeral keys as necessary and performs the actual shared secret derivation.
- *
- * @since   1.6
- * @author  Andreas Sterbenz
- */
-final class ECDHCrypt {
-
-    // our private key
-    private PrivateKey privateKey;
-
-    // our public key
-    private ECPublicKey publicKey;
-
-    // Called by ServerHandshaker for static ECDH
-    ECDHCrypt(PrivateKey privateKey, PublicKey publicKey) {
-        this.privateKey = privateKey;
-        this.publicKey = (ECPublicKey)publicKey;
-    }
-
-    // Called by ServerHandshaker for ephemeral ECDH
-    ECDHCrypt(int curveId, SecureRandom random) {
-        try {
-            KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
-            ECGenParameterSpec params =
-                    EllipticCurvesExtension.getECGenParamSpec(curveId);
-            kpg.initialize(params, random);
-            KeyPair kp = kpg.generateKeyPair();
-            privateKey = kp.getPrivate();
-            publicKey = (ECPublicKey)kp.getPublic();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
-        }
-    }
-
-    // Called by ClientHandshaker with params it received from the server
-    ECDHCrypt(ECParameterSpec params, SecureRandom random) {
-        try {
-            KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
-            kpg.initialize(params, random);
-            KeyPair kp = kpg.generateKeyPair();
-            privateKey = kp.getPrivate();
-            publicKey = (ECPublicKey)kp.getPublic();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
-        }
-    }
-
-    /**
-     * Gets the public key of this end of the key exchange.
-     */
-    PublicKey getPublicKey() {
-        return publicKey;
-    }
-
-    // called by ClientHandshaker with either the server's static or
-    // ephemeral public key
-    SecretKey getAgreedSecret(
-            PublicKey peerPublicKey) throws SSLHandshakeException {
-
-        try {
-            KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
-            ka.init(privateKey);
-            ka.doPhase(peerPublicKey, true);
-            return ka.generateSecret("TlsPremasterSecret");
-        } catch (GeneralSecurityException e) {
-            throw (SSLHandshakeException) new SSLHandshakeException(
-                "Could not generate secret").initCause(e);
-        }
-    }
-
-    // called by ServerHandshaker
-    SecretKey getAgreedSecret(
-            byte[] encodedPoint) throws SSLHandshakeException {
-
-        try {
-            ECParameterSpec params = publicKey.getParams();
-            ECPoint point =
-                    JsseJce.decodePoint(encodedPoint, params.getCurve());
-            KeyFactory kf = JsseJce.getKeyFactory("EC");
-            ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
-            PublicKey peerPublicKey = kf.generatePublic(spec);
-            return getAgreedSecret(peerPublicKey);
-        } catch (GeneralSecurityException | java.io.IOException e) {
-            throw (SSLHandshakeException) new SSLHandshakeException(
-                "Could not generate secret").initCause(e);
-        }
-    }
-
-    // Check constraints of the specified EC public key.
-    void checkConstraints(AlgorithmConstraints constraints,
-            byte[] encodedPoint) throws SSLHandshakeException {
-
-        try {
-
-            ECParameterSpec params = publicKey.getParams();
-            ECPoint point =
-                    JsseJce.decodePoint(encodedPoint, params.getCurve());
-            ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
-
-            KeyFactory kf = JsseJce.getKeyFactory("EC");
-            ECPublicKey publicKey = (ECPublicKey)kf.generatePublic(spec);
-
-            // check constraints of ECPublicKey
-            if (!constraints.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
-                throw new SSLHandshakeException(
-                    "ECPublicKey does not comply to algorithm constraints");
-            }
-        } catch (GeneralSecurityException | java.io.IOException e) {
-            throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate ECPublicKey").initCause(e);
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/EllipticCurvesExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,388 +0,0 @@
-/*
- * Copyright (c) 2006, 2017, 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.security.spec.ECParameterSpec;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.security.AlgorithmParameters;
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.AccessController;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.ArrayList;
-import javax.net.ssl.SSLProtocolException;
-
-import sun.security.action.GetPropertyAction;
-
-final class EllipticCurvesExtension extends HelloExtension {
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private static final int ARBITRARY_PRIME = 0xff01;
-    private static final int ARBITRARY_CHAR2 = 0xff02;
-
-    // speed up the searching
-    private static final Map<String, Integer> oidToIdMap = new HashMap<>();
-    private static final Map<Integer, String> idToOidMap = new HashMap<>();
-
-    // speed up the parameters construction
-    private static final Map<Integer,
-                AlgorithmParameters> idToParams = new HashMap<>();
-
-    // the supported elliptic curves
-    private static final int[] supportedCurveIds;
-
-    // the curves of the extension
-    private final int[] curveIds;
-
-    // See sun.security.util.CurveDB for the OIDs
-    private static enum NamedEllipticCurve {
-        T163_K1(1,  "sect163k1",    "1.3.132.0.1",      true),  // NIST K-163
-        T163_R1(2,  "sect163r1",    "1.3.132.0.2",      false),
-        T163_R2(3,  "sect163r2",    "1.3.132.0.15",     true),  // NIST B-163
-        T193_R1(4,  "sect193r1",    "1.3.132.0.24",     false),
-        T193_R2(5,  "sect193r2",    "1.3.132.0.25",     false),
-        T233_K1(6,  "sect233k1",    "1.3.132.0.26",     true),  // NIST K-233
-        T233_R1(7,  "sect233r1",    "1.3.132.0.27",     true),  // NIST B-233
-        T239_K1(8,  "sect239k1",    "1.3.132.0.3",      false),
-        T283_K1(9,  "sect283k1",    "1.3.132.0.16",     true),  // NIST K-283
-        T283_R1(10, "sect283r1",    "1.3.132.0.17",     true),  // NIST B-283
-        T409_K1(11, "sect409k1",    "1.3.132.0.36",     true),  // NIST K-409
-        T409_R1(12, "sect409r1",    "1.3.132.0.37",     true),  // NIST B-409
-        T571_K1(13, "sect571k1",    "1.3.132.0.38",     true),  // NIST K-571
-        T571_R1(14, "sect571r1",    "1.3.132.0.39",     true),  // NIST B-571
-
-        P160_K1(15, "secp160k1",    "1.3.132.0.9",      false),
-        P160_R1(16, "secp160r1",    "1.3.132.0.8",      false),
-        P160_R2(17, "secp160r2",    "1.3.132.0.30",     false),
-        P192_K1(18, "secp192k1",    "1.3.132.0.31",     false),
-        P192_R1(19, "secp192r1",    "1.2.840.10045.3.1.1", true), // NIST P-192
-        P224_K1(20, "secp224k1",    "1.3.132.0.32",     false),
-        P224_R1(21, "secp224r1",    "1.3.132.0.33",     true),  // NIST P-224
-        P256_K1(22, "secp256k1",    "1.3.132.0.10",     false),
-        P256_R1(23, "secp256r1",    "1.2.840.10045.3.1.7", true), // NIST P-256
-        P384_R1(24, "secp384r1",    "1.3.132.0.34",     true),  // NIST P-384
-        P521_R1(25, "secp521r1",    "1.3.132.0.35",     true);  // NIST P-521
-
-        int          id;
-        String       name;
-        String       oid;
-        boolean      isFips;
-
-        NamedEllipticCurve(int id, String name, String oid, boolean isFips) {
-            this.id = id;
-            this.name = name;
-            this.oid = oid;
-            this.isFips = isFips;
-
-            if (oidToIdMap.put(oid, id) != null ||
-                idToOidMap.put(id, oid) != null) {
-
-                throw new RuntimeException(
-                        "Duplicate named elliptic curve definition: " + name);
-            }
-        }
-
-        static NamedEllipticCurve getCurve(String name, boolean requireFips) {
-            for (NamedEllipticCurve curve : NamedEllipticCurve.values()) {
-                if (curve.name.equals(name) && (!requireFips || curve.isFips)) {
-                    return curve;
-                }
-            }
-
-            return null;
-        }
-    }
-
-    static {
-        boolean requireFips = SunJSSE.isFIPS();
-
-        // hack code to initialize NamedEllipticCurve
-        NamedEllipticCurve nec =
-                NamedEllipticCurve.getCurve("secp256r1", false);
-
-        // The value of the System Property defines a list of enabled named
-        // curves in preference order, separated with comma.  For example:
-        //
-        //      jdk.tls.namedGroups="secp521r1, secp256r1, secp384r1"
-        //
-        // If the System Property is not defined or the value is empty, the
-        // default curves and preferences will be used.
-        String property = AccessController.doPrivileged(
-                    new GetPropertyAction("jdk.tls.namedGroups"));
-        if (property != null && property.length() != 0) {
-            // remove double quote marks from beginning/end of the property
-            if (property.length() > 1 && property.charAt(0) == '"' &&
-                    property.charAt(property.length() - 1) == '"') {
-                property = property.substring(1, property.length() - 1);
-            }
-        }
-
-        ArrayList<Integer> idList;
-        if (property != null && property.length() != 0) {   // customized curves
-            String[] curves = property.split(",");
-            idList = new ArrayList<>(curves.length);
-            for (String curve : curves) {
-                curve = curve.trim();
-                if (!curve.isEmpty()) {
-                    NamedEllipticCurve namedCurve =
-                            NamedEllipticCurve.getCurve(curve, requireFips);
-                    if (namedCurve != null) {
-                        if (isAvailableCurve(namedCurve.id)) {
-                            idList.add(namedCurve.id);
-                        }
-                    }   // ignore unknown curves
-                }
-            }
-            if (idList.isEmpty() && JsseJce.isEcAvailable()) {
-                throw new IllegalArgumentException(
-                    "System property jdk.tls.namedGroups(" + property + ") " +
-                    "contains no supported elliptic curves");
-            }
-        } else {        // default curves
-            int[] ids = new int[] {
-                // The three widely-used NIST curves:
-                // secp256r1, secp384r1 & secp521r1
-                23, 24, 25
-            };
-
-            idList = new ArrayList<>(ids.length);
-            for (int curveId : ids) {
-                if (isAvailableCurve(curveId)) {
-                    idList.add(curveId);
-                }
-            }
-        }
-
-        if (debug != null && idList.isEmpty()) {
-            debug.println(
-                "Initialized [jdk.tls.namedGroups|default] list contains " +
-                "no available elliptic curves. " +
-                (property != null ? "(" + property + ")" : "[Default]"));
-        }
-
-            supportedCurveIds = new int[idList.size()];
-            int i = 0;
-            for (Integer id : idList) {
-                supportedCurveIds[i++] = id;
-            }
-        }
-
-    // check whether the curve is supported by the underlying providers
-    private static boolean isAvailableCurve(int curveId) {
-        String oid = idToOidMap.get(curveId);
-        if (oid != null) {
-            AlgorithmParameters params = null;
-            try {
-                params = JsseJce.getAlgorithmParameters("EC");
-                params.init(new ECGenParameterSpec(oid));
-            } catch (Exception e) {
-                return false;
-            }
-
-            // cache the parameters
-            idToParams.put(curveId, params);
-
-            return true;
-        }
-
-        return false;
-    }
-
-    private EllipticCurvesExtension(int[] curveIds) {
-        super(ExtensionType.EXT_ELLIPTIC_CURVES);
-        this.curveIds = curveIds;
-    }
-
-    EllipticCurvesExtension(HandshakeInStream s, int len)
-            throws IOException {
-        super(ExtensionType.EXT_ELLIPTIC_CURVES);
-        int k = s.getInt16();
-        if (((len & 1) != 0) || (k + 2 != len)) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        // Note: unknown curves will be ignored later.
-        curveIds = new int[k >> 1];
-        for (int i = 0; i < curveIds.length; i++) {
-            curveIds[i] = s.getInt16();
-        }
-    }
-
-    // get the preferred active curve
-    static int getActiveCurves(AlgorithmConstraints constraints) {
-        return getPreferredCurve(supportedCurveIds, constraints);
-    }
-
-    static boolean hasActiveCurves(AlgorithmConstraints constraints) {
-        return getActiveCurves(constraints) >= 0;
-    }
-
-    static EllipticCurvesExtension createExtension(
-                AlgorithmConstraints constraints) {
-
-        ArrayList<Integer> idList = new ArrayList<>(supportedCurveIds.length);
-        for (int curveId : supportedCurveIds) {
-            if (constraints.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                "EC", idToParams.get(curveId))) {
-                idList.add(curveId);
-            }
-        }
-
-        if (!idList.isEmpty()) {
-            int[] ids = new int[idList.size()];
-            int i = 0;
-            for (Integer id : idList) {
-                ids[i++] = id;
-            }
-
-            return new EllipticCurvesExtension(ids);
-        }
-
-        return null;
-    }
-
-    // get the preferred activated curve
-    int getPreferredCurve(AlgorithmConstraints constraints) {
-        return getPreferredCurve(curveIds, constraints);
-    }
-
-    // get a preferred activated curve
-    private static int getPreferredCurve(int[] curves,
-                AlgorithmConstraints constraints) {
-        for (int curveId : curves) {
-            if (isSupported(curveId) && constraints.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                "EC", idToParams.get(curveId))) {
-                return curveId;
-            }
-        }
-
-        return -1;
-    }
-
-    boolean contains(int index) {
-        for (int curveId : curveIds) {
-            if (index == curveId) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    int length() {
-        return 6 + (curveIds.length << 1);
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        int k = curveIds.length << 1;
-        s.putInt16(k + 2);
-        s.putInt16(k);
-        for (int curveId : curveIds) {
-            s.putInt16(curveId);
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Extension " + type + ", curve names: {");
-        boolean first = true;
-        for (int curveId : curveIds) {
-            if (first) {
-                first = false;
-            } else {
-                sb.append(", ");
-            }
-            String curveName = getCurveName(curveId);
-            if (curveName != null) {
-                sb.append(curveName);
-            } else if (curveId == ARBITRARY_PRIME) {
-                sb.append("arbitrary_explicit_prime_curves");
-            } else if (curveId == ARBITRARY_CHAR2) {
-                sb.append("arbitrary_explicit_char2_curves");
-            } else {
-                sb.append("unknown curve " + curveId);
-            }
-        }
-        sb.append("}");
-        return sb.toString();
-    }
-
-    // Test whether the given curve is supported.
-    static boolean isSupported(int index) {
-        for (int curveId : supportedCurveIds) {
-            if (index == curveId) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    static int getCurveIndex(ECParameterSpec params) {
-        String oid = JsseJce.getNamedCurveOid(params);
-        if (oid == null) {
-            return -1;
-        }
-        Integer n = oidToIdMap.get(oid);
-        return (n == null) ? -1 : n;
-    }
-
-    static String getCurveOid(int index) {
-        return idToOidMap.get(index);
-    }
-
-    static ECGenParameterSpec getECGenParamSpec(int index) {
-        AlgorithmParameters params = idToParams.get(index);
-        try {
-            return params.getParameterSpec(ECGenParameterSpec.class);
-        } catch (InvalidParameterSpecException ipse) {
-            // should be unlikely
-            String curveOid = getCurveOid(index);
-            return new ECGenParameterSpec(curveOid);
-        }
-    }
-
-    private static String getCurveName(int index) {
-        for (NamedEllipticCurve namedCurve : NamedEllipticCurve.values()) {
-            if (namedCurve.id == index) {
-                return namedCurve.name;
-            }
-        }
-
-        return null;
-    }
-}
--- a/src/share/classes/sun/security/ssl/EllipticPointFormatsExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2006, 2016, 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.util.ArrayList;
-import java.util.List;
-
-import javax.net.ssl.SSLProtocolException;
-
-final class EllipticPointFormatsExtension extends HelloExtension {
-
-    final static int FMT_UNCOMPRESSED = 0;
-    final static int FMT_ANSIX962_COMPRESSED_PRIME = 1;
-    final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2;
-
-    static final HelloExtension DEFAULT =
-        new EllipticPointFormatsExtension(
-            new byte[] {FMT_UNCOMPRESSED});
-
-    private final byte[] formats;
-
-    private EllipticPointFormatsExtension(byte[] formats) {
-        super(ExtensionType.EXT_EC_POINT_FORMATS);
-        this.formats = formats;
-    }
-
-    EllipticPointFormatsExtension(HandshakeInStream s, int len)
-            throws IOException {
-        super(ExtensionType.EXT_EC_POINT_FORMATS);
-        formats = s.getBytes8();
-        // RFC 4492 says uncompressed points must always be supported.
-        // Check just to make sure.
-        boolean uncompressed = false;
-        for (int format : formats) {
-            if (format == FMT_UNCOMPRESSED) {
-                uncompressed = true;
-                break;
-            }
-        }
-        if (uncompressed == false) {
-            throw new SSLProtocolException
-                ("Peer does not support uncompressed points");
-        }
-    }
-
-    @Override
-    int length() {
-        return 5 + formats.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putInt16(formats.length + 1);
-        s.putBytes8(formats);
-    }
-
-    private static String toString(byte format) {
-        int f = format & 0xff;
-        switch (f) {
-        case FMT_UNCOMPRESSED:
-            return "uncompressed";
-        case FMT_ANSIX962_COMPRESSED_PRIME:
-            return "ansiX962_compressed_prime";
-        case FMT_ANSIX962_COMPRESSED_CHAR2:
-            return "ansiX962_compressed_char2";
-        default:
-            return "unknown-" + f;
-        }
-    }
-
-    @Override
-    public String toString() {
-        List<String> list = new ArrayList<String>();
-        for (byte format : formats) {
-            list.add(toString(format));
-        }
-        return "Extension " + type + ", formats: " + list;
-    }
-}
--- a/src/share/classes/sun/security/ssl/EngineArgs.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2004, 2012, 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.nio.*;
-
-/*
- * A multi-purpose class which handles all of the SSLEngine arguments.
- * It validates arguments, checks for RO conditions, does space
- * calculations, performs scatter/gather, etc.
- *
- * @author Brad R. Wetmore
- */
-class EngineArgs {
-
-    /*
-     * Keep track of the input parameters.
-     */
-    ByteBuffer netData;
-    ByteBuffer [] appData;
-
-    private int offset;         // offset/len for the appData array.
-    private int len;
-
-    /*
-     * The initial pos/limit conditions.  This is useful because we can
-     * quickly calculate the amount consumed/produced in successful
-     * operations, or easily return the buffers to their pre-error
-     * conditions.
-     */
-    private int netPos;
-    private int netLim;
-
-    private int [] appPoss;
-    private int [] appLims;
-
-    /*
-     * Sum total of the space remaining in all of the appData buffers
-     */
-    private int appRemaining = 0;
-
-    private boolean wrapMethod;
-
-    /*
-     * Called by the SSLEngine.wrap() method.
-     */
-    EngineArgs(ByteBuffer [] appData, int offset, int len,
-            ByteBuffer netData) {
-        this.wrapMethod = true;
-        init(netData, appData, offset, len);
-    }
-
-    /*
-     * Called by the SSLEngine.unwrap() method.
-     */
-    EngineArgs(ByteBuffer netData, ByteBuffer [] appData, int offset,
-            int len) {
-        this.wrapMethod = false;
-        init(netData, appData, offset, len);
-    }
-
-    /*
-     * The main initialization method for the arguments.  Most
-     * of them are pretty obvious as to what they do.
-     *
-     * Since we're already iterating over appData array for validity
-     * checking, we also keep track of how much remainging space is
-     * available.  Info is used in both unwrap (to see if there is
-     * enough space available in the destination), and in wrap (to
-     * determine how much more we can copy into the outgoing data
-     * buffer.
-     */
-    private void init(ByteBuffer netData, ByteBuffer [] appData,
-            int offset, int len) {
-
-        if ((netData == null) || (appData == null)) {
-            throw new IllegalArgumentException("src/dst is null");
-        }
-
-        if ((offset < 0) || (len < 0) || (offset > appData.length - len)) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (wrapMethod && netData.isReadOnly()) {
-            throw new ReadOnlyBufferException();
-        }
-
-        netPos = netData.position();
-        netLim = netData.limit();
-
-        appPoss = new int [appData.length];
-        appLims = new int [appData.length];
-
-        for (int i = offset; i < offset + len; i++) {
-            if (appData[i] == null) {
-                throw new IllegalArgumentException(
-                    "appData[" + i + "] == null");
-            }
-
-            /*
-             * If we're unwrapping, then check to make sure our
-             * destination bufffers are writable.
-             */
-            if (!wrapMethod && appData[i].isReadOnly()) {
-                throw new ReadOnlyBufferException();
-            }
-
-            appRemaining += appData[i].remaining();
-
-            appPoss[i] = appData[i].position();
-            appLims[i] = appData[i].limit();
-        }
-
-        /*
-         * Ok, looks like we have a good set of args, let's
-         * store the rest of this stuff.
-         */
-        this.netData = netData;
-        this.appData = appData;
-        this.offset = offset;
-        this.len = len;
-    }
-
-    /*
-     * Given spaceLeft bytes to transfer, gather up that much data
-     * from the appData buffers (starting at offset in the array),
-     * and transfer it into the netData buffer.
-     *
-     * The user has already ensured there is enough room.
-     */
-    void gather(int spaceLeft) {
-        for (int i = offset; (i < (offset + len)) && (spaceLeft > 0); i++) {
-            int amount = Math.min(appData[i].remaining(), spaceLeft);
-            appData[i].limit(appData[i].position() + amount);
-            netData.put(appData[i]);
-            appRemaining -= amount;
-            spaceLeft -= amount;
-        }
-    }
-
-    /*
-     * Using the supplied buffer, scatter the data into the appData buffers
-     * (starting at offset in the array).
-     *
-     * The user has already ensured there is enough room.
-     */
-    void scatter(ByteBuffer readyData) {
-        int amountLeft = readyData.remaining();
-
-        for (int i = offset; (i < (offset + len)) && (amountLeft > 0);
-                i++) {
-            int amount = Math.min(appData[i].remaining(), amountLeft);
-            readyData.limit(readyData.position() + amount);
-            appData[i].put(readyData);
-            amountLeft -= amount;
-        }
-        assert(readyData.remaining() == 0);
-    }
-
-    int getAppRemaining() {
-        return appRemaining;
-    }
-
-    /*
-     * Calculate the bytesConsumed/byteProduced.  Aren't you glad
-     * we saved this off earlier?
-     */
-    int deltaNet() {
-        return (netData.position() - netPos);
-    }
-
-    /*
-     * Calculate the bytesConsumed/byteProduced.  Aren't you glad
-     * we saved this off earlier?
-     */
-    int deltaApp() {
-        int sum = 0;    // Only calculating 2^14 here, don't need a long.
-
-        for (int i = offset; i < offset + len; i++) {
-            sum += appData[i].position() - appPoss[i];
-        }
-
-        return sum;
-    }
-
-    /*
-     * In the case of Exception, we want to reset the positions
-     * to appear as though no data has been consumed or produced.
-     *
-     * Currently, this method is only called as we are preparing to
-     * fail out, and thus we don't need to actually recalculate
-     * appRemaining.  If that assumption changes, that variable should
-     * be updated here.
-     */
-    void resetPos() {
-        netData.position(netPos);
-        for (int i = offset; i < offset + len; i++) {
-            // See comment above about recalculating appRemaining.
-            appData[i].position(appPoss[i]);
-        }
-    }
-
-    /*
-     * We are doing lots of ByteBuffer manipulations, in which case
-     * we need to make sure that the limits get set back correctly.
-     * This is one of the last things to get done before returning to
-     * the user.
-     */
-    void resetLim() {
-        netData.limit(netLim);
-        for (int i = offset; i < offset + len; i++) {
-            appData[i].limit(appLims[i]);
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/EngineInputRecord.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,428 +0,0 @@
-/*
- * Copyright (c) 2003, 2014, 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.*;
-import java.nio.*;
-import javax.net.ssl.*;
-import javax.crypto.BadPaddingException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * Wrapper class around InputRecord.
- *
- * Application data is kept external to the InputRecord,
- * but handshake data (alert/change_cipher_spec/handshake) will
- * be kept internally in the ByteArrayInputStream.
- *
- * @author Brad Wetmore
- */
-final class EngineInputRecord extends InputRecord {
-
-    private SSLEngineImpl engine;
-
-    /*
-     * A dummy ByteBuffer we'll pass back even when the data
-     * is stored internally.  It'll never actually be used.
-     */
-    static private ByteBuffer tmpBB = ByteBuffer.allocate(0);
-
-    /*
-     * Flag to tell whether the last read/parsed data resides
-     * internal in the ByteArrayInputStream, or in the external
-     * buffers.
-     */
-    private boolean internalData;
-
-    EngineInputRecord(SSLEngineImpl engine) {
-        super();
-        this.engine = engine;
-    }
-
-    @Override
-    byte contentType() {
-        if (internalData) {
-            return super.contentType();
-        } else {
-            return ct_application_data;
-        }
-    }
-
-    /*
-     * Check if there is enough inbound data in the ByteBuffer
-     * to make a inbound packet.  Look for both SSLv2 and SSLv3.
-     *
-     * @return -1 if there are not enough bytes to tell (small header),
-     */
-    int bytesInCompletePacket(ByteBuffer buf) throws SSLException {
-
-        /*
-         * SSLv2 length field is in bytes 0/1
-         * SSLv3/TLS length field is in bytes 3/4
-         */
-        if (buf.remaining() < 5) {
-            return -1;
-        }
-
-        int pos = buf.position();
-        byte byteZero = buf.get(pos);
-
-        int len = 0;
-
-        /*
-         * If we have already verified previous packets, we can
-         * ignore the verifications steps, and jump right to the
-         * determination.  Otherwise, try one last hueristic to
-         * see if it's SSL/TLS.
-         */
-        if (formatVerified ||
-                (byteZero == ct_handshake) ||
-                (byteZero == ct_alert)) {
-            /*
-             * Last sanity check that it's not a wild record
-             */
-            ProtocolVersion recordVersion =
-                ProtocolVersion.valueOf(buf.get(pos + 1), buf.get(pos + 2));
-
-            // check the record version
-            checkRecordVersion(recordVersion, false);
-
-            /*
-             * Reasonably sure this is a V3, disable further checks.
-             * We can't do the same in the v2 check below, because
-             * read still needs to parse/handle the v2 clientHello.
-             */
-            formatVerified = true;
-
-            /*
-             * One of the SSLv3/TLS message types.
-             */
-            len = ((buf.get(pos + 3) & 0xff) << 8) +
-                (buf.get(pos + 4) & 0xff) + headerSize;
-
-        } else {
-            /*
-             * Must be SSLv2 or something unknown.
-             * Check if it's short (2 bytes) or
-             * long (3) header.
-             *
-             * Internals can warn about unsupported SSLv2
-             */
-            boolean isShort = ((byteZero & 0x80) != 0);
-
-            if (isShort &&
-                    ((buf.get(pos + 2) == 1) || buf.get(pos + 2) == 4)) {
-
-                ProtocolVersion recordVersion =
-                    ProtocolVersion.valueOf(buf.get(pos + 3), buf.get(pos + 4));
-
-                // check the record version
-                checkRecordVersion(recordVersion, true);
-
-                /*
-                 * Client or Server Hello
-                 */
-                int mask = (isShort ? 0x7f : 0x3f);
-                len = ((byteZero & mask) << 8) + (buf.get(pos + 1) & 0xff) +
-                    (isShort ? 2 : 3);
-
-            } else {
-                // Gobblygook!
-                throw new SSLException(
-                    "Unrecognized SSL message, plaintext connection?");
-            }
-        }
-
-        return len;
-    }
-
-    /*
-     * Pass the data down if it's internally cached, otherwise
-     * do it here.
-     *
-     * If internal data, data is decrypted internally.
-     *
-     * If external data(app), return a new ByteBuffer with data to
-     * process.
-     */
-    ByteBuffer decrypt(Authenticator authenticator,
-            CipherBox box, ByteBuffer bb) throws BadPaddingException {
-
-        if (internalData) {
-            decrypt(authenticator, box);   // MAC is checked during decryption
-            return tmpBB;
-        }
-
-        BadPaddingException reservedBPE = null;
-        int tagLen =
-            (authenticator instanceof MAC) ? ((MAC)authenticator).MAClen() : 0;
-        int cipheredLength = bb.remaining();
-
-        if (!box.isNullCipher()) {
-            try {
-                // apply explicit nonce for AEAD/CBC cipher suites if needed
-                int nonceSize =
-                    box.applyExplicitNonce(authenticator, contentType(), bb);
-
-                // decrypt the content
-                if (box.isAEADMode()) {
-                    // DON'T encrypt the nonce_explicit for AEAD mode
-                    bb.position(bb.position() + nonceSize);
-                }   // The explicit IV for CBC mode can be decrypted.
-
-                // Note that the CipherBox.decrypt() does not change
-                // the capacity of the buffer.
-                box.decrypt(bb, tagLen);
-                bb.position(nonceSize); // We don't actually remove the nonce.
-            } catch (BadPaddingException bpe) {
-                // RFC 2246 states that decryption_failed should be used
-                // for this purpose. However, that allows certain attacks,
-                // so we just send bad record MAC. We also need to make
-                // sure to always check the MAC to avoid a timing attack
-                // for the same issue. See paper by Vaudenay et al and the
-                // update in RFC 4346/5246.
-                //
-                // Failover to message authentication code checking.
-                reservedBPE = bpe;
-            }
-        }
-
-        // Requires message authentication code for null, stream and block
-        // cipher suites.
-        if ((authenticator instanceof MAC) && (tagLen != 0)) {
-            MAC signer = (MAC)authenticator;
-            int macOffset = bb.limit() - tagLen;
-
-            // Note that although it is not necessary, we run the same MAC
-            // computation and comparison on the payload for both stream
-            // cipher and CBC block cipher.
-            if (bb.remaining() < tagLen) {
-                // negative data length, something is wrong
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record");
-                }
-
-                // set offset of the dummy MAC
-                macOffset = cipheredLength - tagLen;
-                bb.limit(cipheredLength);
-            }
-
-            // Run MAC computation and comparison on the payload.
-            if (checkMacTags(contentType(), bb, signer, false)) {
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record MAC");
-                }
-            }
-
-            // Run MAC computation and comparison on the remainder.
-            //
-            // It is only necessary for CBC block cipher.  It is used to get a
-            // constant time of MAC computation and comparison on each record.
-            if (box.isCBCMode()) {
-                int remainingLen = calculateRemainingLen(
-                                        signer, cipheredLength, macOffset);
-
-                // NOTE: here we use the InputRecord.buf because I did not find
-                // an effective way to work on ByteBuffer when its capacity is
-                // less than remainingLen.
-
-                // NOTE: remainingLen may be bigger (less than 1 block of the
-                // hash algorithm of the MAC) than the cipheredLength. However,
-                // We won't need to worry about it because we always use a
-                // maximum buffer for every record.  We need a change here if
-                // we use small buffer size in the future.
-                if (remainingLen > buf.length) {
-                    // unlikely to happen, just a placehold
-                    throw new RuntimeException(
-                        "Internal buffer capacity error");
-                }
-
-                // Won't need to worry about the result on the remainder. And
-                // then we won't need to worry about what's actual data to
-                // check MAC tag on.  We start the check from the header of the
-                // buffer so that we don't need to construct a new byte buffer.
-                checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
-            }
-
-            bb.limit(macOffset);
-        }
-
-        // Is it a failover?
-        if (reservedBPE != null) {
-            throw reservedBPE;
-        }
-
-        return bb.slice();
-    }
-
-    /*
-     * Run MAC computation and comparison
-     *
-     * Please DON'T change the content of the ByteBuffer parameter!
-     */
-    private static boolean checkMacTags(byte contentType, ByteBuffer bb,
-            MAC signer, boolean isSimulated) {
-
-        int position = bb.position();
-        int tagLen = signer.MAClen();
-        int lim = bb.limit();
-        int macData = lim - tagLen;
-
-        bb.limit(macData);
-        byte[] hash = signer.compute(contentType, bb, isSimulated);
-        if (hash == null || tagLen != hash.length) {
-            // Something is wrong with MAC implementation.
-            throw new RuntimeException("Internal MAC error");
-        }
-
-        bb.position(macData);
-        bb.limit(lim);
-        try {
-            int[] results = compareMacTags(bb, hash);
-            return (results[0] != 0);
-        } finally {
-            // reset to the data
-            bb.position(position);
-            bb.limit(macData);
-        }
-    }
-
-    /*
-     * A constant-time comparison of the MAC tags.
-     *
-     * Please DON'T change the content of the ByteBuffer parameter!
-     */
-    private static int[] compareMacTags(ByteBuffer bb, byte[] tag) {
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};     // {missed #, matched #}
-
-        // The caller ensures there are enough bytes available in the buffer.
-        // So we won't need to check the remaining of the buffer.
-        for (int i = 0; i < tag.length; i++) {
-            if (bb.get() != tag[i]) {
-                results[0]++;       // mismatched bytes
-            } else {
-                results[1]++;       // matched bytes
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * Override the actual write below.  We do things this way to be
-     * consistent with InputRecord.  InputRecord may try to write out
-     * data to the peer, and *then* throw an Exception.  This forces
-     * data to be generated/output before the exception is ever
-     * generated.
-     */
-    @Override
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len)
-            throws IOException {
-        /*
-         * Copy data out of buffer, it's ready to go.
-         */
-        ByteBuffer netBB = (ByteBuffer)
-            (ByteBuffer.allocate(len).put(buf, 0, len).flip());
-        engine.writer.putOutboundDataSync(netBB);
-    }
-
-    /*
-     * Delineate or read a complete packet from src.
-     *
-     * If internal data (hs, alert, ccs), the data is read and
-     * stored internally.
-     *
-     * If external data (app), return a new ByteBuffer which points
-     * to the data to process.
-     */
-    ByteBuffer read(ByteBuffer srcBB) throws IOException {
-        /*
-         * Could have a src == null/dst == null check here,
-         * but that was already checked by SSLEngine.unwrap before
-         * ever attempting to read.
-         */
-
-        /*
-         * If we have anything besides application data,
-         * or if we haven't even done the initial v2 verification,
-         * we send this down to be processed by the underlying
-         * internal cache.
-         */
-        if (!formatVerified ||
-                (srcBB.get(srcBB.position()) != ct_application_data)) {
-            internalData = true;
-            read(new ByteBufferInputStream(srcBB), (OutputStream) null);
-            return tmpBB;
-        }
-
-        internalData = false;
-
-        int srcPos = srcBB.position();
-        int srcLim = srcBB.limit();
-
-        ProtocolVersion recordVersion = ProtocolVersion.valueOf(
-                srcBB.get(srcPos + 1), srcBB.get(srcPos + 2));
-
-        // check the record version
-        checkRecordVersion(recordVersion, false);
-
-        /*
-         * It's really application data.  How much to consume?
-         * Jump over the header.
-         */
-        int len = bytesInCompletePacket(srcBB);
-        assert(len > 0);
-
-        if (debug != null && Debug.isOn("packet")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-                ByteBuffer bb = srcBB.duplicate();  // Use copy of BB
-                bb.limit(srcPos + len);
-
-                System.out.println("[Raw read (bb)]: length = " + len);
-                hd.encodeBuffer(bb, System.out);
-            } catch (IOException e) { }
-        }
-
-        // Demarcate past header to end of packet.
-        srcBB.position(srcPos + headerSize);
-        srcBB.limit(srcPos + len);
-
-        // Protect remainder of buffer, create slice to actually
-        // operate on.
-        ByteBuffer bb = srcBB.slice();
-
-        srcBB.position(srcBB.limit());
-        srcBB.limit(srcLim);
-
-        return bb;
-    }
-}
--- a/src/share/classes/sun/security/ssl/EngineOutputRecord.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, 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.*;
-import java.nio.*;
-
-/**
- * A OutputRecord class extension which uses external ByteBuffers
- * or the internal ByteArrayOutputStream for data manipulations.
- * <P>
- * Instead of rewriting this entire class
- * to use ByteBuffers, we leave things intact, so handshake, CCS,
- * and alerts will continue to use the internal buffers, but application
- * data will use external buffers.
- *
- * @author Brad Wetmore
- */
-final class EngineOutputRecord extends OutputRecord {
-
-    private SSLEngineImpl engine;
-    private EngineWriter writer;
-
-    private boolean finishedMsg = false;
-
-    /*
-     * All handshake hashing is done by the superclass
-     */
-
-    /*
-     * Default constructor makes a record supporting the maximum
-     * SSL record size.  It allocates the header bytes directly.
-     *
-     * @param type the content type for the record
-     */
-    EngineOutputRecord(byte type, SSLEngineImpl engine) {
-        super(type, recordSize(type));
-        this.engine = engine;
-        writer = engine.writer;
-    }
-
-    /**
-     * Get the size of the buffer we need for records of the specified
-     * type.
-     * <P>
-     * Application data buffers will provide their own byte buffers,
-     * and will not use the internal byte caching.
-     */
-    private static int recordSize(byte type) {
-        switch (type) {
-
-        case ct_change_cipher_spec:
-        case ct_alert:
-            return maxAlertRecordSize;
-
-        case ct_handshake:
-            return maxRecordSize;
-
-        case ct_application_data:
-            return 0;
-        }
-
-        throw new RuntimeException("Unknown record type: " + type);
-    }
-
-    void setFinishedMsg() {
-        finishedMsg = true;
-    }
-
-    @Override
-    public void flush() throws IOException {
-        finishedMsg = false;
-    }
-
-    boolean isFinishedMsg() {
-        return finishedMsg;
-    }
-
-    /*
-     * Override the actual write below.  We do things this way to be
-     * consistent with InputRecord.  InputRecord may try to write out
-     * data to the peer, and *then* throw an Exception.  This forces
-     * data to be generated/output before the exception is ever
-     * generated.
-     */
-    @Override
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len,
-            int debugOffset) throws IOException {
-        /*
-         * Copy data out of buffer, it's ready to go.
-         */
-        ByteBuffer netBB = (ByteBuffer)
-            ByteBuffer.allocate(len).put(buf, off, len).flip();
-
-        writer.putOutboundData(netBB);
-    }
-
-    /*
-     * Main method for writing non-application data.
-     * We MAC/encrypt, then send down for processing.
-     */
-    void write(Authenticator authenticator, CipherBox writeCipher)
-            throws IOException {
-
-        /*
-         * Sanity check.
-         */
-        switch (contentType()) {
-            case ct_change_cipher_spec:
-            case ct_alert:
-            case ct_handshake:
-                break;
-            default:
-                throw new RuntimeException("unexpected byte buffers");
-        }
-
-        /*
-         * Don't bother to really write empty records.  We went this
-         * far to drive the handshake machinery, for correctness; not
-         * writing empty records improves performance by cutting CPU
-         * time and network resource usage.  Also, some protocol
-         * implementations are fragile and don't like to see empty
-         * records, so this increases robustness.
-         *
-         * (Even change cipher spec messages have a byte of data!)
-         */
-        if (!isEmpty()) {
-            // compress();              // eventually
-            encrypt(authenticator, writeCipher);
-
-            // send down for processing
-            write((OutputStream)null, false, (ByteArrayOutputStream)null);
-        }
-        return;
-    }
-
-    /**
-     * Main wrap/write driver.
-     */
-    void write(EngineArgs ea, Authenticator authenticator,
-            CipherBox writeCipher) throws IOException {
-        /*
-         * sanity check to make sure someone didn't inadvertantly
-         * send us an impossible combination we don't know how
-         * to process.
-         */
-        assert(contentType() == ct_application_data);
-
-        /*
-         * Have we set the MAC's yet?  If not, we're not ready
-         * to process application data yet.
-         */
-        if (authenticator == MAC.NULL) {
-            return;
-        }
-
-        /*
-         * Don't bother to really write empty records.  We went this
-         * far to drive the handshake machinery, for correctness; not
-         * writing empty records improves performance by cutting CPU
-         * time and network resource usage.  Also, some protocol
-         * implementations are fragile and don't like to see empty
-         * records, so this increases robustness.
-         */
-        if (ea.getAppRemaining() == 0) {
-            return;
-        }
-
-        /*
-         * By default, we counter chosen plaintext issues on CBC mode
-         * ciphersuites in SSLv3/TLS1.0 by sending one byte of application
-         * data in the first record of every payload, and the rest in
-         * subsequent record(s). Note that the issues have been solved in
-         * TLS 1.1 or later.
-         *
-         * It is not necessary to split the very first application record of
-         * a freshly negotiated TLS session, as there is no previous
-         * application data to guess.  To improve compatibility, we will not
-         * split such records.
-         *
-         * Because of the compatibility, we'd better produce no more than
-         * SSLSession.getPacketBufferSize() net data for each wrap. As we
-         * need a one-byte record at first, the 2nd record size should be
-         * equal to or less than Record.maxDataSizeMinusOneByteRecord.
-         *
-         * This avoids issues in the outbound direction.  For a full fix,
-         * the peer must have similar protections.
-         */
-        int length;
-        if (engine.needToSplitPayload(writeCipher, protocolVersion)) {
-            write(ea, authenticator, writeCipher, 0x01);
-            ea.resetLim();      // reset application data buffer limit
-            length = Math.min(ea.getAppRemaining(),
-                        maxDataSizeMinusOneByteRecord);
-        } else {
-            length = Math.min(ea.getAppRemaining(), maxDataSize);
-        }
-
-        // Don't bother to really write empty records.
-        if (length > 0) {
-            write(ea, authenticator, writeCipher, length);
-        }
-
-        return;
-    }
-
-    void write(EngineArgs ea, Authenticator authenticator,
-            CipherBox writeCipher, int length) throws IOException {
-        /*
-         * Copy out existing buffer values.
-         */
-        ByteBuffer dstBB = ea.netData;
-        int dstPos = dstBB.position();
-        int dstLim = dstBB.limit();
-
-        /*
-         * Where to put the data.  Jump over the header.
-         *
-         * Don't need to worry about SSLv2 rewrites, if we're here,
-         * that's long since done.
-         */
-        int dstData = dstPos + headerSize + writeCipher.getExplicitNonceSize();
-        dstBB.position(dstData);
-
-        /*
-         * transfer application data into the network data buffer
-         */
-        ea.gather(length);
-        dstBB.limit(dstBB.position());
-        dstBB.position(dstData);
-
-        /*
-         * "flip" but skip over header again, add MAC & encrypt
-         */
-        if (authenticator instanceof MAC) {
-            MAC signer = (MAC)authenticator;
-            if (signer.MAClen() != 0) {
-                byte[] hash = signer.compute(contentType(), dstBB, false);
-
-                /*
-                 * position was advanced to limit in compute above.
-                 *
-                 * Mark next area as writable (above layers should have
-                 * established that we have plenty of room), then write
-                 * out the hash.
-                 */
-                dstBB.limit(dstBB.limit() + hash.length);
-                dstBB.put(hash);
-
-                // reset the position and limit
-                dstBB.limit(dstBB.position());
-                dstBB.position(dstData);
-            }
-        }
-
-        if (!writeCipher.isNullCipher()) {
-            /*
-             * Requires explicit IV/nonce for CBC/AEAD cipher suites for TLS 1.1
-             * or later.
-             */
-            if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
-                    (writeCipher.isCBCMode() || writeCipher.isAEADMode())) {
-                byte[] nonce = writeCipher.createExplicitNonce(
-                        authenticator, contentType(), dstBB.remaining());
-                dstBB.position(dstPos + headerSize);
-                dstBB.put(nonce);
-                if (!writeCipher.isAEADMode()) {
-                    // The explicit IV in TLS 1.1 and later can be encrypted.
-                    dstBB.position(dstPos + headerSize);
-                }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
-            }
-
-            /*
-             * Encrypt may pad, so again the limit may have changed.
-             */
-            writeCipher.encrypt(dstBB, dstLim);
-
-            if ((debug != null) && (Debug.isOn("record") ||
-                    (Debug.isOn("handshake") &&
-                        (contentType() == ct_change_cipher_spec)))) {
-                System.out.println(Thread.currentThread().getName()
-                    // v3.0/v3.1 ...
-                    + ", WRITE: " + protocolVersion
-                    + " " + InputRecord.contentName(contentType())
-                    + ", length = " + length);
-            }
-        } else {
-            dstBB.position(dstBB.limit());
-        }
-
-        int packetLength = dstBB.limit() - dstPos - headerSize;
-
-        /*
-         * Finish out the record header.
-         */
-        dstBB.put(dstPos, contentType());
-        dstBB.put(dstPos + 1, protocolVersion.major);
-        dstBB.put(dstPos + 2, protocolVersion.minor);
-        dstBB.put(dstPos + 3, (byte)(packetLength >> 8));
-        dstBB.put(dstPos + 4, (byte)packetLength);
-
-        /*
-         * Position was already set by encrypt() above.
-         */
-        dstBB.limit(dstLim);
-    }
-}
--- a/src/share/classes/sun/security/ssl/EngineWriter.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, 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.ByteBuffer;
-import java.util.LinkedList;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import sun.misc.HexDumpEncoder;
-
-/**
- * A class to help abstract away SSLEngine writing synchronization.
- */
-final class EngineWriter {
-
-    /*
-     * Outgoing handshake Data waiting for a ride is stored here.
-     * Normal application data is written directly into the outbound
-     * buffer, but handshake data can be written out at any time,
-     * so we have buffer it somewhere.
-     *
-     * When wrap is called, we first check to see if there is
-     * any data waiting, then if we're in a data transfer state,
-     * we try to write app data.
-     *
-     * This will contain either ByteBuffers, or the marker
-     * HandshakeStatus.FINISHED to signify that a handshake just completed.
-     */
-    private LinkedList<Object> outboundList;
-
-    private boolean outboundClosed = false;
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    EngineWriter() {
-        outboundList = new LinkedList<Object>();
-    }
-
-    /*
-     * Upper levels assured us we had room for at least one packet of data.
-     * As per the SSLEngine spec, we only return one SSL packets worth of
-     * data.
-     */
-    private HandshakeStatus getOutboundData(ByteBuffer dstBB) {
-
-        Object msg = outboundList.removeFirst();
-        assert(msg instanceof ByteBuffer);
-
-        ByteBuffer bbIn = (ByteBuffer) msg;
-        assert(dstBB.remaining() >= bbIn.remaining());
-
-        dstBB.put(bbIn);
-
-        /*
-         * If we have more data in the queue, it's either
-         * a finished message, or an indication that we need
-         * to call wrap again.
-         */
-        if (hasOutboundDataInternal()) {
-            msg = outboundList.getFirst();
-            if (msg == HandshakeStatus.FINISHED) {
-                outboundList.removeFirst();     // consume the message
-                return HandshakeStatus.FINISHED;
-            } else {
-                return HandshakeStatus.NEED_WRAP;
-            }
-        } else {
-            return null;
-        }
-    }
-
-    /*
-     * Properly orders the output of the data written to the wrap call.
-     * This is only handshake data, application data goes through the
-     * other writeRecord.
-     */
-    synchronized void writeRecord(EngineOutputRecord outputRecord,
-            Authenticator authenticator,
-            CipherBox writeCipher) throws IOException {
-
-        /*
-         * Only output if we're still open.
-         */
-        if (outboundClosed) {
-            throw new IOException("writer side was already closed.");
-        }
-
-        outputRecord.write(authenticator, writeCipher);
-
-        /*
-         * Did our handshakers notify that we just sent the
-         * Finished message?
-         *
-         * Add an "I'm finished" message to the queue.
-         */
-        if (outputRecord.isFinishedMsg()) {
-            outboundList.addLast(HandshakeStatus.FINISHED);
-        }
-    }
-
-    /*
-     * Output the packet info.
-     */
-    private void dumpPacket(EngineArgs ea, boolean hsData) {
-        try {
-            HexDumpEncoder hd = new HexDumpEncoder();
-
-            ByteBuffer bb = ea.netData.duplicate();
-
-            int pos = bb.position();
-            bb.position(pos - ea.deltaNet());
-            bb.limit(pos);
-
-            System.out.println("[Raw write" +
-                (hsData ? "" : " (bb)") + "]: length = " +
-                bb.remaining());
-            hd.encodeBuffer(bb, System.out);
-        } catch (IOException e) { }
-    }
-
-    /*
-     * Properly orders the output of the data written to the wrap call.
-     * Only app data goes through here, handshake data goes through
-     * the other writeRecord.
-     *
-     * Shouldn't expect to have an IOException here.
-     *
-     * Return any determined status.
-     */
-    synchronized HandshakeStatus writeRecord(
-            EngineOutputRecord outputRecord, EngineArgs ea,
-            Authenticator authenticator,
-            CipherBox writeCipher) throws IOException {
-
-        /*
-         * If we have data ready to go, output this first before
-         * trying to consume app data.
-         */
-        if (hasOutboundDataInternal()) {
-            HandshakeStatus hss = getOutboundData(ea.netData);
-
-            if (debug != null && Debug.isOn("packet")) {
-                /*
-                 * We could have put the dump in
-                 * OutputRecord.write(OutputStream), but let's actually
-                 * output when it's actually output by the SSLEngine.
-                 */
-                dumpPacket(ea, true);
-            }
-
-            return hss;
-        }
-
-        /*
-         * If we are closed, no more app data can be output.
-         * Only existing handshake data (above) can be obtained.
-         */
-        if (outboundClosed) {
-            throw new IOException("The write side was already closed");
-        }
-
-        outputRecord.write(ea, authenticator, writeCipher);
-
-        if (debug != null && Debug.isOn("packet")) {
-            dumpPacket(ea, false);
-        }
-
-        /*
-         * No way new outbound handshake data got here if we're
-         * locked properly.
-         *
-         * We don't have any status we can return.
-         */
-        return null;
-    }
-
-    /*
-     * We already hold "this" lock, this is the callback from the
-     * outputRecord.write() above.  We already know this
-     * writer can accept more data (outboundClosed == false),
-     * and the closure is sync'd.
-     */
-    void putOutboundData(ByteBuffer bytes) {
-        outboundList.addLast(bytes);
-    }
-
-    /*
-     * This is for the really rare case that someone is writing from
-     * the *InputRecord* before we know what to do with it.
-     */
-    synchronized void putOutboundDataSync(ByteBuffer bytes)
-            throws IOException {
-
-        if (outboundClosed) {
-            throw new IOException("Write side already closed");
-        }
-
-        outboundList.addLast(bytes);
-    }
-
-    /*
-     * Non-synch'd version of this method, called by internals
-     */
-    private boolean hasOutboundDataInternal() {
-        return (outboundList.size() != 0);
-    }
-
-    synchronized boolean hasOutboundData() {
-        return hasOutboundDataInternal();
-    }
-
-    synchronized boolean isOutboundDone() {
-        return outboundClosed && !hasOutboundDataInternal();
-    }
-
-    synchronized void closeOutbound() {
-        outboundClosed = true;
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/EphemeralKeyManager.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2002, 2007, 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.security.*;
-
-/**
- * The "KeyManager" for ephemeral RSA keys. Ephemeral DH and ECDH keys
- * are handled by the DHCrypt and ECDHCrypt classes, respectively.
- *
- * @author  Andreas Sterbenz
- */
-final class EphemeralKeyManager {
-
-    // indices for the keys array below
-    private final static int INDEX_RSA512 = 0;
-    private final static int INDEX_RSA1024 = 1;
-
-    /*
-     * Current cached RSA KeyPairs. Elements are never null.
-     * Indexed via the the constants above.
-     */
-    private final EphemeralKeyPair[] keys = new EphemeralKeyPair[] {
-        new EphemeralKeyPair(null),
-        new EphemeralKeyPair(null),
-    };
-
-    EphemeralKeyManager() {
-        // empty
-    }
-
-    /*
-     * Get a temporary RSA KeyPair.
-     */
-    KeyPair getRSAKeyPair(boolean export, SecureRandom random) {
-        int length, index;
-        if (export) {
-            length = 512;
-            index = INDEX_RSA512;
-        } else {
-            length = 1024;
-            index = INDEX_RSA1024;
-        }
-
-        synchronized (keys) {
-            KeyPair kp = keys[index].getKeyPair();
-            if (kp == null) {
-                try {
-                    KeyPairGenerator kgen = JsseJce.getKeyPairGenerator("RSA");
-                    kgen.initialize(length, random);
-                    keys[index] = new EphemeralKeyPair(kgen.genKeyPair());
-                    kp = keys[index].getKeyPair();
-                } catch (Exception e) {
-                    // ignore
-                }
-            }
-            return kp;
-        }
-    }
-
-    /**
-     * Inner class to handle storage of ephemeral KeyPairs.
-     */
-    private static class EphemeralKeyPair {
-
-        // maximum number of times a KeyPair is used
-        private final static int MAX_USE = 200;
-
-        // maximum time interval in which the keypair is used (1 hour in ms)
-        private final static long USE_INTERVAL = 3600*1000;
-
-        private KeyPair keyPair;
-        private int uses;
-        private long expirationTime;
-
-        private EphemeralKeyPair(KeyPair keyPair) {
-            this.keyPair = keyPair;
-            expirationTime = System.currentTimeMillis() + USE_INTERVAL;
-        }
-
-        /*
-         * Check if the KeyPair can still be used.
-         */
-        private boolean isValid() {
-            return (keyPair != null) && (uses < MAX_USE)
-                   && (System.currentTimeMillis() < expirationTime);
-        }
-
-        /*
-         * Return the KeyPair or null if it is invalid.
-         */
-        private KeyPair getKeyPair() {
-            if (isValid() == false) {
-                keyPair = null;
-                return null;
-            }
-            uses++;
-            return keyPair;
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2017, Red Hat, Inc.
- * 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 javax.net.ssl.SSLProtocolException;
-
-/**
- * Extended Master Secret TLS extension (TLS 1.0+). This extension
- * defines how to calculate the TLS connection master secret and
- * mitigates some types of man-in-the-middle attacks.
- *
- * See further information in
- * <a href="https://tools.ietf.org/html/rfc7627">RFC 7627</a>.
- *
- * @author Martin Balao (mbalao@redhat.com)
- */
-final class ExtendedMasterSecretExtension extends HelloExtension {
-    ExtendedMasterSecretExtension() {
-        super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
-    }
-
-    ExtendedMasterSecretExtension(HandshakeInStream s,
-            int len) throws IOException {
-        super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
-
-        if (len != 0) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-    }
-
-    @Override
-    int length() {
-        return 4;       // 4: extension type and length fields
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);    // ExtensionType extension_type;
-        s.putInt16(0);          // extension_data length
-    }
-
-    @Override
-    public String toString() {
-        return "Extension " + type;
-    }
-}
-
--- a/src/share/classes/sun/security/ssl/ExtensionType.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.ArrayList;
-import java.util.List;
-
-final class ExtensionType {
-
-    final int id;
-    final String name;
-
-    private ExtensionType(int id, String name) {
-        this.id = id;
-        this.name = name;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    static List<ExtensionType> knownExtensions =
-            new ArrayList<ExtensionType>(15);
-
-    static ExtensionType get(int id) {
-        for (ExtensionType ext : knownExtensions) {
-            if (ext.id == id) {
-                return ext;
-            }
-        }
-        return new ExtensionType(id, "type_" + id);
-    }
-
-    private static ExtensionType e(int id, String name) {
-        ExtensionType ext = new ExtensionType(id, name);
-        knownExtensions.add(ext);
-        return ext;
-    }
-
-    // extensions defined in RFC 3546
-    final static ExtensionType EXT_SERVER_NAME =
-            e(0x0000, "server_name");            // IANA registry value: 0
-    final static ExtensionType EXT_MAX_FRAGMENT_LENGTH =
-            e(0x0001, "max_fragment_length");    // IANA registry value: 1
-    final static ExtensionType EXT_CLIENT_CERTIFICATE_URL =
-            e(0x0002, "client_certificate_url"); // IANA registry value: 2
-    final static ExtensionType EXT_TRUSTED_CA_KEYS =
-            e(0x0003, "trusted_ca_keys");        // IANA registry value: 3
-    final static ExtensionType EXT_TRUNCATED_HMAC =
-            e(0x0004, "truncated_hmac");         // IANA registry value: 4
-    final static ExtensionType EXT_STATUS_REQUEST =
-            e(0x0005, "status_request");         // IANA registry value: 5
-
-    // extensions defined in RFC 4681
-    final static ExtensionType EXT_USER_MAPPING =
-            e(0x0006, "user_mapping");           // IANA registry value: 6
-
-    // extensions defined in RFC 5081
-    final static ExtensionType EXT_CERT_TYPE =
-            e(0x0009, "cert_type");              // IANA registry value: 9
-
-    // extensions defined in RFC 4492 (ECC)
-    final static ExtensionType EXT_ELLIPTIC_CURVES =
-            e(0x000A, "elliptic_curves");        // IANA registry value: 10
-    final static ExtensionType EXT_EC_POINT_FORMATS =
-            e(0x000B, "ec_point_formats");       // IANA registry value: 11
-
-    // extensions defined in RFC 5054
-    final static ExtensionType EXT_SRP =
-            e(0x000C, "srp");                    // IANA registry value: 12
-
-    // extensions defined in RFC 5246
-    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 7627
-    static final ExtensionType EXT_EXTENDED_MASTER_SECRET =
-            e(0x0017, "extended_master_secret"); // IANA registry value: 23
-
-    // 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/HandshakeHash.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,427 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, 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.ByteArrayOutputStream;
-import java.security.*;
-import java.util.Locale;
-
-/**
- * Abstraction for the SSL/TLS hash of all handshake messages that is
- * maintained to verify the integrity of the negotiation. Internally,
- * it consists of an MD5 and an SHA1 digest. They are used in the client
- * and server finished messages and in certificate verify messages (if sent).
- *
- * This class transparently deals with cloneable and non-cloneable digests.
- *
- * This class now supports TLS 1.2 also. The key difference for TLS 1.2
- * is that you cannot determine the hash algorithms for CertificateVerify
- * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier)
- * that there is no messy MD5+SHA1 digests.
- *
- * You need to obey these conventions when using this class:
- *
- * 1. protocolDetermined(version) should be called when the negotiated
- * protocol version is determined.
- *
- * 2. Before protocolDetermined() is called, only update(), and reset()
- * and setFinishedAlg() can be called.
- *
- * 3. After protocolDetermined() is called, reset() cannot be called.
- *
- * 4. After protocolDetermined() is called, if the version is pre-TLS 1.2,
- * getFinishedHash() cannot be called. Otherwise,
- * getMD5Clone() and getSHAClone() cannot be called.
- *
- * 5. getMD5Clone() and getSHAClone() can only be called after
- * protocolDetermined() is called and version is pre-TLS 1.2.
- *
- * 6. getFinishedHash() can only be called after protocolDetermined()
- * and setFinishedAlg() have been called and the version is TLS 1.2.
- *
- * Suggestion: Call protocolDetermined() and setFinishedAlg()
- * as early as possible.
- *
- * Example:
- * <pre>
- * HandshakeHash hh = new HandshakeHash(...)
- * hh.protocolDetermined(ProtocolVersion.TLS12);
- * hh.update(clientHelloBytes);
- * hh.setFinishedAlg("SHA-256");
- * hh.update(serverHelloBytes);
- * ...
- * hh.update(CertificateVerifyBytes);
- * ...
- * hh.update(finished1);
- * byte[] finDigest1 = hh.getFinishedHash();
- * hh.update(finished2);
- * byte[] finDigest2 = hh.getFinishedHash();
- * </pre>
- */
-final class HandshakeHash {
-
-    // Common
-
-    // -1:  unknown
-    //  1:  <=TLS 1.1
-    //  2:  TLS 1.2
-    private int version = -1;
-    private ByteArrayOutputStream data = new ByteArrayOutputStream();
-
-    // For TLS 1.1
-    private MessageDigest md5, sha;
-    private final int clonesNeeded;    // needs to be saved for later use
-
-    // For TLS 1.2
-    private MessageDigest finMD;
-
-    /**
-     * Create a new HandshakeHash. needCertificateVerify indicates whether
-     * a hash for the certificate verify message is required.
-     */
-    HandshakeHash(boolean needCertificateVerify) {
-        // We may rework the code later, but for now we use hard-coded number
-        // of clones if the underlying MessageDigests are not cloneable.
-        //
-        // The number used here is based on the current handshake protocols and
-        // implementation.  It may be changed if the handshake processe gets
-        // changed in the future, for example adding a new extension that
-        // requires handshake hash.  Please be careful about the number of
-        // clones if additional handshak hash is required in the future.
-        //
-        // For the current implementation, the handshake hash is required for
-        // the following items:
-        //     . CertificateVerify handshake message (optional)
-        //     . client Finished handshake message
-        //     . server Finished Handshake message
-        //     . the extended Master Secret extension [RFC 7627]
-        //
-        // Note that a late call to server setNeedClientAuth dose not update
-        // the number of clones.  We may address the issue later.
-        //
-        // Note for safe, we allocate one more clone for the current
-        // implementation.  We may consider it more carefully in the future
-        // for the exactly number or rework the code in a different way.
-        clonesNeeded = needCertificateVerify ? 5 : 4;
-    }
-
-    void update(byte[] b, int offset, int len) {
-        switch (version) {
-            case 1:
-                md5.update(b, offset, len);
-                sha.update(b, offset, len);
-                break;
-            default:
-                if (finMD != null) {
-                    finMD.update(b, offset, len);
-                }
-                data.write(b, offset, len);
-                break;
-        }
-    }
-
-    /**
-     * Reset the remaining digests. Note this does *not* reset the number of
-     * digest clones that can be obtained. Digests that have already been
-     * cloned and are gone remain gone.
-     */
-    void reset() {
-        if (version != -1) {
-            throw new RuntimeException(
-                    "reset() can be only be called before protocolDetermined");
-        }
-        data.reset();
-    }
-
-
-    void protocolDetermined(ProtocolVersion pv) {
-
-        // Do not set again, will ignore
-        if (version != -1) return;
-
-        version = pv.compareTo(ProtocolVersion.TLS12) >= 0 ? 2 : 1;
-        switch (version) {
-            case 1:
-                // initiate md5, sha and call update on saved array
-                try {
-                    md5 = CloneableDigest.getDigest("MD5", clonesNeeded);
-                    sha = CloneableDigest.getDigest("SHA", clonesNeeded);
-                } catch (NoSuchAlgorithmException e) {
-                    throw new RuntimeException
-                                ("Algorithm MD5 or SHA not available", e);
-                }
-                byte[] bytes = data.toByteArray();
-                update(bytes, 0, bytes.length);
-                break;
-            case 2:
-                break;
-        }
-    }
-
-    /////////////////////////////////////////////////////////////
-    // Below are old methods for pre-TLS 1.1
-    /////////////////////////////////////////////////////////////
-
-    /**
-     * Return a new MD5 digest updated with all data hashed so far.
-     */
-    MessageDigest getMD5Clone() {
-        if (version != 1) {
-            throw new RuntimeException(
-                    "getMD5Clone() can be only be called for TLS 1.1");
-        }
-        return cloneDigest(md5);
-    }
-
-    /**
-     * Return a new SHA digest updated with all data hashed so far.
-     */
-    MessageDigest getSHAClone() {
-        if (version != 1) {
-            throw new RuntimeException(
-                    "getSHAClone() can be only be called for TLS 1.1");
-        }
-        return cloneDigest(sha);
-    }
-
-    private static MessageDigest cloneDigest(MessageDigest digest) {
-        try {
-            return (MessageDigest)digest.clone();
-        } catch (CloneNotSupportedException e) {
-            // cannot occur for digests generated via CloneableDigest
-            throw new RuntimeException("Could not clone digest", e);
-        }
-    }
-
-    /////////////////////////////////////////////////////////////
-    // Below are new methods for TLS 1.2
-    /////////////////////////////////////////////////////////////
-
-    private static String normalizeAlgName(String alg) {
-        alg = alg.toUpperCase(Locale.US);
-        if (alg.startsWith("SHA")) {
-            if (alg.length() == 3) {
-                return "SHA-1";
-            }
-            if (alg.charAt(3) != '-') {
-                return "SHA-" + alg.substring(3);
-            }
-        }
-        return alg;
-    }
-    /**
-     * Specifies the hash algorithm used in Finished. This should be called
-     * based in info in ServerHello.
-     * Can be called multiple times.
-     */
-    void setFinishedAlg(String s) {
-        if (s == null) {
-            throw new RuntimeException(
-                    "setFinishedAlg's argument cannot be null");
-        }
-
-        // Can be called multiple times, but only set once
-        if (finMD != null) return;
-
-        try {
-            // See comment in the contructor.
-            finMD = CloneableDigest.getDigest(normalizeAlgName(s), 4);
-        } catch (NoSuchAlgorithmException e) {
-            throw new Error(e);
-        }
-        finMD.update(data.toByteArray());
-    }
-
-    byte[] getAllHandshakeMessages() {
-        return data.toByteArray();
-    }
-
-    /**
-     * Calculates the hash in Finished. Must be called after setFinishedAlg().
-     * This method can be called twice, for Finished messages of the server
-     * side and client side respectively.
-     */
-    byte[] getFinishedHash() {
-        try {
-            return cloneDigest(finMD).digest();
-        } catch (Exception e) {
-            throw new Error("Error during hash calculation", e);
-        }
-    }
-}
-
-/**
- * A wrapper for MessageDigests that simulates cloning of non-cloneable
- * digests. It uses the standard MessageDigest API and therefore can be used
- * transparently in place of a regular digest.
- *
- * Note that we extend the MessageDigest class directly rather than
- * MessageDigestSpi. This works because MessageDigest was originally designed
- * this way in the JDK 1.1 days which allows us to avoid creating an internal
- * provider.
- *
- * It can be "cloned" a limited number of times, which is specified at
- * construction time. This is achieved by internally maintaining n digests
- * in parallel. Consequently, it is only 1/n-th times as fast as the original
- * digest.
- *
- * Example:
- *   MessageDigest md = CloneableDigest.getDigest("SHA", 2);
- *   md.update(data1);
- *   MessageDigest md2 = (MessageDigest)md.clone();
- *   md2.update(data2);
- *   byte[] d1 = md2.digest(); // digest of data1 || data2
- *   md.update(data3);
- *   byte[] d2 = md.digest();  // digest of data1 || data3
- *
- * This class is not thread safe.
- *
- */
-final class CloneableDigest extends MessageDigest implements Cloneable {
-
-    /**
-     * The individual MessageDigests. Initially, all elements are non-null.
-     * When clone() is called, the non-null element with the maximum index is
-     * returned and the array element set to null.
-     *
-     * All non-null element are always in the same state.
-     */
-    private final MessageDigest[] digests;
-
-    private CloneableDigest(MessageDigest digest, int n, String algorithm)
-            throws NoSuchAlgorithmException {
-        super(algorithm);
-        digests = new MessageDigest[n];
-        digests[0] = digest;
-        for (int i = 1; i < n; i++) {
-            digests[i] = JsseJce.getMessageDigest(algorithm);
-        }
-    }
-
-    /**
-     * Return a MessageDigest for the given algorithm that can be cloned the
-     * specified number of times. If the default implementation supports
-     * cloning, it is returned. Otherwise, an instance of this class is
-     * returned.
-     */
-    static MessageDigest getDigest(String algorithm, int n)
-            throws NoSuchAlgorithmException {
-        MessageDigest digest = JsseJce.getMessageDigest(algorithm);
-        try {
-            digest.clone();
-            // already cloneable, use it
-            return digest;
-        } catch (CloneNotSupportedException e) {
-            return new CloneableDigest(digest, n, algorithm);
-        }
-    }
-
-    /**
-     * Check if this object is still usable. If it has already been cloned the
-     * maximum number of times, there are no digests left and this object can no
-     * longer be used.
-     */
-    private void checkState() {
-        // XXX handshaking currently doesn't stop updating hashes...
-        // if (digests[0] == null) {
-        //     throw new IllegalStateException("no digests left");
-        // }
-    }
-
-    @Override
-    protected int engineGetDigestLength() {
-        checkState();
-        return digests[0].getDigestLength();
-    }
-
-    @Override
-    protected void engineUpdate(byte b) {
-        checkState();
-        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].update(b);
-        }
-    }
-
-    @Override
-    protected void engineUpdate(byte[] b, int offset, int len) {
-        checkState();
-        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].update(b, offset, len);
-        }
-    }
-
-    @Override
-    protected byte[] engineDigest() {
-        checkState();
-        byte[] digest = digests[0].digest();
-        digestReset();
-        return digest;
-    }
-
-    @Override
-    protected int engineDigest(byte[] buf, int offset, int len)
-            throws DigestException {
-        checkState();
-        int n = digests[0].digest(buf, offset, len);
-        digestReset();
-        return n;
-    }
-
-    /**
-     * Reset all digests after a digest() call. digests[0] has already been
-     * implicitly reset by the digest() call and does not need to be reset
-     * again.
-     */
-    private void digestReset() {
-        for (int i = 1; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].reset();
-        }
-    }
-
-    @Override
-    protected void engineReset() {
-        checkState();
-        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].reset();
-        }
-    }
-
-    @Override
-    public Object clone() {
-        checkState();
-        for (int i = digests.length - 1; i >= 0; i--) {
-            if (digests[i] != null) {
-                MessageDigest digest = digests[i];
-                digests[i] = null;
-                return digest;
-            }
-        }
-        // cannot occur
-        throw new InternalError();
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/HandshakeInStream.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, 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.InputStream;
-import java.io.IOException;
-
-import javax.net.ssl.SSLException;
-
-/**
- * InputStream for handshake data, used internally only. Contains the
- * handshake message buffer and methods to parse them.
- *
- * Once a new handshake record arrives, it is buffered in this class until
- * processed by the Handshaker. The buffer may also contain incomplete
- * handshake messages in case the message is split across multiple records.
- * Handshaker.process_record deals with all that. It may also contain
- * handshake messages larger than the default buffer size (e.g. large
- * certificate messages). The buffer is grown dynamically to handle that
- * (see InputRecord.queueHandshake()).
- *
- * Note that the InputRecord used as a buffer here is separate from the
- * AppInStream.r, which is where data from the socket is initially read
- * into. This is because once the initial handshake has been completed,
- * handshake and application data messages may be interleaved arbitrarily
- * and must be processed independently.
- *
- * @author David Brownell
- */
-public class HandshakeInStream extends InputStream {
-
-    InputRecord r;
-
-    /*
-     * Construct the stream; we'll be accumulating hashes of the
-     * input records using two sets of digests.
-     */
-    HandshakeInStream(HandshakeHash handshakeHash) {
-        r = new InputRecord();
-        r.setHandshakeHash(handshakeHash);
-    }
-
-
-    // overridden InputStream methods
-
-    /*
-     * Return the number of bytes available for read().
-     *
-     * Note that this returns the bytes remaining in the buffer, not
-     * the bytes remaining in the current handshake message.
-     */
-    @Override
-    public int available() {
-        return r.available();
-    }
-
-    /*
-     * Get a byte of handshake data.
-     */
-    @Override
-    public int read() throws IOException {
-        int n = r.read();
-        if (n == -1) {
-            throw new SSLException("Unexpected end of handshake data");
-        }
-        return n;
-    }
-
-    /*
-     * Get a bunch of bytes of handshake data.
-     */
-    @Override
-    public int read(byte b [], int off, int len) throws IOException {
-        // we read from a ByteArrayInputStream, it always returns the
-        // data in a single read if enough is available
-        int n = r.read(b, off, len);
-        if (n != len) {
-            throw new SSLException("Unexpected end of handshake data");
-        }
-        return n;
-    }
-
-    /*
-     * Skip some handshake data.
-     */
-    @Override
-    public long skip(long n) throws IOException {
-        return r.skip(n);
-    }
-
-    /*
-     * Mark/ reset code, implemented using InputRecord mark/ reset.
-     *
-     * Note that it currently provides only a limited mark functionality
-     * and should be used with care (once a new handshake record has been
-     * read, data that has already been consumed is lost even if marked).
-     */
-
-    @Override
-    public void mark(int readlimit) {
-        r.mark(readlimit);
-    }
-
-    @Override
-    public void reset() throws IOException {
-        r.reset();
-    }
-
-    @Override
-    public boolean markSupported() {
-        return true;
-    }
-
-
-    // handshake management functions
-
-    /*
-     * Here's an incoming record with handshake data.  Queue the contents;
-     * it might be one or more entire messages, complete a message that's
-     * partly queued, or both.
-     */
-    void incomingRecord(InputRecord in) throws IOException {
-        r.queueHandshake(in);
-    }
-
-    /*
-     * Hash any data we've consumed but not yet hashed.  Useful mostly
-     * for processing client certificate messages (so we can check the
-     * immediately following cert verify message) and finished messages
-     * (so we can compute our own finished message).
-     */
-    void digestNow() {
-        r.doHashes();
-    }
-
-    /*
-     * Do more than skip that handshake data ... totally ignore it.
-     * The difference is that the data does not get hashed.
-     */
-    void ignore(int n) {
-        r.ignore(n);
-    }
-
-
-    // Message parsing methods
-
-    /*
-     * Read 8, 16, 24, and 32 bit SSL integer data types, encoded
-     * in standard big-endian form.
-     */
-
-    int getInt8() throws IOException {
-        return read();
-    }
-
-    int getInt16() throws IOException {
-        return (getInt8() << 8) | getInt8();
-    }
-
-    int getInt24() throws IOException {
-        return (getInt8() << 16) | (getInt8() << 8) | getInt8();
-    }
-
-    int getInt32() throws IOException {
-        return (getInt8() << 24) | (getInt8() << 16)
-             | (getInt8() << 8) | getInt8();
-    }
-
-    /*
-     * Read byte vectors with 8, 16, and 24 bit length encodings.
-     */
-
-    byte[] getBytes8() throws IOException {
-        int len = getInt8();
-        verifyLength(len);
-        byte b[] = new byte[len];
-
-        read(b, 0, len);
-        return b;
-    }
-
-    public byte[] getBytes16() throws IOException {
-        int len = getInt16();
-        verifyLength(len);
-        byte b[] = new byte[len];
-
-        read(b, 0, len);
-        return b;
-    }
-
-    byte[] getBytes24() throws IOException {
-        int len = getInt24();
-        verifyLength(len);
-        byte b[] = new byte[len];
-
-        read(b, 0, len);
-        return b;
-    }
-
-    // Is a length greater than available bytes in the record?
-    private void verifyLength(int len) throws SSLException {
-        if (len > available()) {
-            throw new SSLException(
-                        "Not enough data to fill declared vector size");
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/HandshakeMessage.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2061 +0,0 @@
-/*
- * Copyright (c) 1996, 2020, 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.*;
-import java.math.BigInteger;
-import java.security.*;
-import java.security.interfaces.*;
-import java.security.spec.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-import java.lang.reflect.*;
-
-import javax.security.auth.x500.X500Principal;
-
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.DHPublicKeySpec;
-
-import javax.net.ssl.*;
-
-import sun.security.internal.spec.TlsPrfParameterSpec;
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.PRF.*;
-import sun.security.util.KeyUtil;
-
-/**
- * Many data structures are involved in the handshake messages.  These
- * classes are used as structures, with public data members.  They are
- * not visible outside the SSL package.
- *
- * Handshake messages all have a common header format, and they are all
- * encoded in a "handshake data" SSL record substream.  The base class
- * here (HandshakeMessage) provides a common framework and records the
- * SSL record type of the particular handshake message.
- *
- * This file contains subclasses for all the basic handshake messages.
- * All handshake messages know how to encode and decode themselves on
- * SSL streams; this facilitates using the same code on SSL client and
- * server sides, although they don't send and receive the same messages.
- *
- * Messages also know how to print themselves, which is quite handy
- * for debugging.  They always identify their type, and can optionally
- * dump all of their content.
- *
- * @author David Brownell
- */
-public abstract class HandshakeMessage {
-
-    HandshakeMessage() { }
-
-    // enum HandshakeType:
-    static final byte   ht_hello_request = 0;
-    static final byte   ht_client_hello = 1;
-    static final byte   ht_server_hello = 2;
-
-    static final byte   ht_certificate = 11;
-    static final byte   ht_server_key_exchange = 12;
-    static final byte   ht_certificate_request = 13;
-    static final byte   ht_server_hello_done = 14;
-    static final byte   ht_certificate_verify = 15;
-    static final byte   ht_client_key_exchange = 16;
-
-    static final byte   ht_finished = 20;
-
-    static final byte   ht_not_applicable         = -1;     // N/A
-
-    /* Class and subclass dynamic debugging support */
-    public static final Debug debug = Debug.getInstance("ssl");
-
-    /**
-     * Utility method to convert a BigInteger to a byte array in unsigned
-     * format as needed in the handshake messages. BigInteger uses
-     * 2's complement format, i.e. it prepends an extra zero if the MSB
-     * is set. We remove that.
-     */
-    static byte[] toByteArray(BigInteger bi) {
-        byte[] b = bi.toByteArray();
-        if ((b.length > 1) && (b[0] == 0)) {
-            int n = b.length - 1;
-            byte[] newarray = new byte[n];
-            System.arraycopy(b, 1, newarray, 0, n);
-            b = newarray;
-        }
-        return b;
-    }
-
-    /*
-     * SSL 3.0 MAC padding constants.
-     * Also used by CertificateVerify and Finished during the handshake.
-     */
-    static final byte[] MD5_pad1 = genPad(0x36, 48);
-    static final byte[] MD5_pad2 = genPad(0x5c, 48);
-
-    static final byte[] SHA_pad1 = genPad(0x36, 40);
-    static final byte[] SHA_pad2 = genPad(0x5c, 40);
-
-    private static byte[] genPad(int b, int count) {
-        byte[] padding = new byte[count];
-        Arrays.fill(padding, (byte)b);
-        return padding;
-    }
-
-    /*
-     * Write a handshake message on the (handshake) output stream.
-     * This is just a four byte header followed by the data.
-     *
-     * NOTE that huge messages -- notably, ones with huge cert
-     * chains -- are handled correctly.
-     */
-    final void write(HandshakeOutStream s) throws IOException {
-        int len = messageLength();
-        if (len >= Record.OVERFLOW_OF_INT24) {
-            throw new SSLException("Handshake message too big"
-                + ", type = " + messageType() + ", len = " + len);
-        }
-        s.write(messageType());
-        s.putInt24(len);
-        send(s);
-    }
-
-    /*
-     * Subclasses implement these methods so those kinds of
-     * messages can be emitted.  Base class delegates to subclass.
-     */
-    abstract int  messageType();
-    abstract int  messageLength();
-    abstract void send(HandshakeOutStream s) throws IOException;
-
-    /*
-     * Write a descriptive message on the output stream; for debugging.
-     */
-    abstract void print(PrintStream p) throws IOException;
-
-//
-// NOTE:  the rest of these classes are nested within this one, and are
-// imported by other classes in this package.  There are a few other
-// handshake message classes, not neatly nested here because of current
-// licensing requirement for native (RSA) methods.  They belong here,
-// but those native methods complicate things a lot!
-//
-
-
-/*
- * HelloRequest ... SERVER --> CLIENT
- *
- * Server can ask the client to initiate a new handshake, e.g. to change
- * session parameters after a connection has been (re)established.
- */
-static final class HelloRequest extends HandshakeMessage {
-    @Override
-    int messageType() { return ht_hello_request; }
-
-    HelloRequest() { }
-
-    HelloRequest(HandshakeInStream in) throws IOException
-    {
-        // nothing in this message
-    }
-
-    @Override
-    int messageLength() { return 0; }
-
-    @Override
-    void send(HandshakeOutStream out) throws IOException
-    {
-        // nothing in this messaage
-    }
-
-    @Override
-    void print(PrintStream out) throws IOException
-    {
-        out.println("*** HelloRequest (empty)");
-    }
-
-}
-
-
-/*
- * ClientHello ... CLIENT --> SERVER
- *
- * Client initiates handshake by telling server what it wants, and what it
- * can support (prioritized by what's first in the ciphe suite list).
- *
- * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
- * will have more data added at the end ... e.g. what CAs the client trusts.
- * Until we know how to parse it, we will just read what we know
- * about, and let our caller handle the jumps over unknown data.
- */
-static final class ClientHello extends HandshakeMessage {
-
-    ProtocolVersion     protocolVersion;
-    RandomCookie        clnt_random;
-    SessionId           sessionId;
-    private CipherSuiteList    cipherSuites;
-    byte[]              compression_methods;
-
-    HelloExtensions extensions = new HelloExtensions();
-
-    private final static byte[]  NULL_COMPRESSION = new byte[] {0};
-
-    ClientHello(SecureRandom generator, ProtocolVersion protocolVersion,
-            SessionId sessionId, CipherSuiteList cipherSuites) {
-
-        this.protocolVersion = protocolVersion;
-        this.sessionId = sessionId;
-        this.cipherSuites = cipherSuites;
-
-        clnt_random = new RandomCookie(generator);
-        compression_methods = NULL_COMPRESSION;
-    }
-
-    ClientHello(HandshakeInStream s, int messageLength) throws IOException {
-        protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
-        clnt_random = new RandomCookie(s);
-        sessionId = new SessionId(s.getBytes8());
-        sessionId.checkLength(protocolVersion);
-        cipherSuites = new CipherSuiteList(s);
-        compression_methods = s.getBytes8();
-        if (messageLength() != messageLength) {
-            extensions = new HelloExtensions(s);
-        }
-    }
-
-    CipherSuiteList getCipherSuites() {
-        return cipherSuites;
-    }
-
-    // add renegotiation_info extension
-    void addRenegotiationInfoExtension(byte[] clientVerifyData) {
-        HelloExtension renegotiationInfo = new RenegotiationInfoExtension(
-                    clientVerifyData, new byte[0]);
-        extensions.add(renegotiationInfo);
-    }
-
-    // add server_name extension
-    void addSNIExtension(List<SNIServerName> serverNames) {
-        try {
-            extensions.add(new ServerNameExtension(serverNames));
-        } catch (IOException ioe) {
-            // ignore the exception and return
-        }
-    }
-
-    // add signature_algorithm extension
-    void addSignatureAlgorithmsExtension(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        HelloExtension signatureAlgorithm =
-                new SignatureAlgorithmsExtension(algorithms);
-        extensions.add(signatureAlgorithm);
-    }
-
-    void addExtendedMasterSecretExtension() {
-        extensions.add(new ExtendedMasterSecretExtension());
-    }
-
-    // add application_layer_protocol_negotiation extension
-    void addALPNExtension(String[] applicationProtocols) throws SSLException {
-        extensions.add(new ALPNExtension(applicationProtocols));
-    }
-
-    @Override
-    int messageType() { return ht_client_hello; }
-
-    @Override
-    int messageLength() {
-        /*
-         * Add fixed size parts of each field...
-         * version + random + session + cipher + compress
-         */
-        return (2 + 32 + 1 + 2 + 1
-            + sessionId.length()                /* ... + variable parts */
-            + (cipherSuites.size() * 2)
-            + compression_methods.length)
-            + extensions.length();
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt8(protocolVersion.major);
-        s.putInt8(protocolVersion.minor);
-        clnt_random.send(s);
-        s.putBytes8(sessionId.getId());
-        cipherSuites.send(s);
-        s.putBytes8(compression_methods);
-        extensions.send(s);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** ClientHello, " + protocolVersion);
-
-        if (debug != null && Debug.isOn("verbose")) {
-            s.print("RandomCookie:  ");
-            clnt_random.print(s);
-
-            s.print("Session ID:  ");
-            s.println(sessionId);
-
-            s.println("Cipher Suites: " + cipherSuites);
-
-            Debug.println(s, "Compression Methods", compression_methods);
-            extensions.print(s);
-            s.println("***");
-        }
-    }
-}
-
-/*
- * ServerHello ... SERVER --> CLIENT
- *
- * Server chooses protocol options from among those it supports and the
- * client supports.  Then it sends the basic session descriptive parameters
- * back to the client.
- */
-static final
-class ServerHello extends HandshakeMessage
-{
-    @Override
-    int messageType() { return ht_server_hello; }
-
-    ProtocolVersion     protocolVersion;
-    RandomCookie        svr_random;
-    SessionId           sessionId;
-    CipherSuite         cipherSuite;
-    byte                compression_method;
-    HelloExtensions extensions = new HelloExtensions();
-
-    ServerHello() {
-        // empty
-    }
-
-    ServerHello(HandshakeInStream input, int messageLength)
-            throws IOException {
-        protocolVersion = ProtocolVersion.valueOf(input.getInt8(),
-                                                  input.getInt8());
-        svr_random = new RandomCookie(input);
-        sessionId = new SessionId(input.getBytes8());
-        sessionId.checkLength(protocolVersion);
-        cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8());
-        compression_method = (byte)input.getInt8();
-        if (messageLength() != messageLength) {
-            extensions = new HelloExtensions(input);
-        }
-    }
-
-    @Override
-    int messageLength()
-    {
-        // almost fixed size, except session ID and extensions:
-        //      major + minor = 2
-        //      random = 32
-        //      session ID len field = 1
-        //      cipher suite + compression = 3
-        //      extensions: if present, 2 + length of extensions
-        return 38 + sessionId.length() + extensions.length();
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException
-    {
-        s.putInt8(protocolVersion.major);
-        s.putInt8(protocolVersion.minor);
-        svr_random.send(s);
-        s.putBytes8(sessionId.getId());
-        s.putInt8(cipherSuite.id >> 8);
-        s.putInt8(cipherSuite.id & 0xff);
-        s.putInt8(compression_method);
-        extensions.send(s);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException
-    {
-        s.println("*** ServerHello, " + protocolVersion);
-
-        if (debug != null && Debug.isOn("verbose")) {
-            s.print("RandomCookie:  ");
-            svr_random.print(s);
-
-            s.print("Session ID:  ");
-            s.println(sessionId);
-
-            s.println("Cipher Suite: " + cipherSuite);
-            s.println("Compression Method: " + compression_method);
-            extensions.print(s);
-            s.println("***");
-        }
-    }
-}
-
-
-/*
- * CertificateMsg ... send by both CLIENT and SERVER
- *
- * Each end of a connection may need to pass its certificate chain to
- * the other end.  Such chains are intended to validate an identity with
- * reference to some certifying authority.  Examples include companies
- * like Verisign, or financial institutions.  There's some control over
- * the certifying authorities which are sent.
- *
- * NOTE: that these messages might be huge, taking many handshake records.
- * Up to 2^48 bytes of certificate may be sent, in records of at most 2^14
- * bytes each ... up to 2^32 records sent on the output stream.
- */
-static final
-class CertificateMsg extends HandshakeMessage
-{
-    @Override
-    int messageType() { return ht_certificate; }
-
-    private X509Certificate[] chain;
-
-    private List<byte[]> encodedChain;
-
-    private int messageLength;
-
-    CertificateMsg(X509Certificate[] certs) {
-        chain = certs;
-    }
-
-    CertificateMsg(HandshakeInStream input) throws IOException {
-        int chainLen = input.getInt24();
-        List<Certificate> v = new ArrayList<>(4);
-
-        CertificateFactory cf = null;
-        while (chainLen > 0) {
-            byte[] cert = input.getBytes24();
-            chainLen -= (3 + cert.length);
-            try {
-                if (cf == null) {
-                    cf = CertificateFactory.getInstance("X.509");
-                }
-                v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
-            } catch (CertificateException e) {
-                throw (SSLProtocolException)new SSLProtocolException(
-                    e.getMessage()).initCause(e);
-            }
-        }
-
-        chain = v.toArray(new X509Certificate[v.size()]);
-    }
-
-    @Override
-    int messageLength() {
-        if (encodedChain == null) {
-            messageLength = 3;
-            encodedChain = new ArrayList<byte[]>(chain.length);
-            try {
-                for (X509Certificate cert : chain) {
-                    byte[] b = cert.getEncoded();
-                    encodedChain.add(b);
-                    messageLength += b.length + 3;
-                }
-            } catch (CertificateEncodingException e) {
-                encodedChain = null;
-                throw new RuntimeException("Could not encode certificates", e);
-            }
-        }
-        return messageLength;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt24(messageLength() - 3);
-        for (byte[] b : encodedChain) {
-            s.putBytes24(b);
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** Certificate chain");
-
-        if (chain.length == 0) {
-            s.println("<Empty>");
-        } else if (debug != null && Debug.isOn("verbose")) {
-            for (int i = 0; i < chain.length; i++) {
-                s.println("chain [" + i + "] = " + chain[i]);
-            }
-        }
-        s.println("***");
-    }
-
-    X509Certificate[] getCertificateChain() {
-        return chain.clone();
-    }
-}
-
-/*
- * ServerKeyExchange ... SERVER --> CLIENT
- *
- * The cipher suite selected, when combined with the certificate exchanged,
- * implies one of several different kinds of key exchange.  Most current
- * cipher suites require the server to send more than its certificate.
- *
- * The primary exceptions are when a server sends an encryption-capable
- * RSA public key in its cert, to be used with RSA (or RSA_export) key
- * exchange; and when a server sends its Diffie-Hellman cert.  Those kinds
- * of key exchange do not require a ServerKeyExchange message.
- *
- * Key exchange can be viewed as having three modes, which are explicit
- * for the Diffie-Hellman flavors and poorly specified for RSA ones:
- *
- *      - "Ephemeral" keys.  Here, a "temporary" key is allocated by the
- *        server, and signed.  Diffie-Hellman keys signed using RSA or
- *        DSS are ephemeral (DHE flavor).  RSA keys get used to do the same
- *        thing, to cut the key size down to 512 bits (export restrictions)
- *        or for signing-only RSA certificates.
- *
- *      - Anonymity.  Here no server certificate is sent, only the public
- *        key of the server.  This case is subject to man-in-the-middle
- *        attacks.  This can be done with Diffie-Hellman keys (DH_anon) or
- *        with RSA keys, but is only used in SSLv3 for DH_anon.
- *
- *      - "Normal" case.  Here a server certificate is sent, and the public
- *        key there is used directly in exchanging the premaster secret.
- *        For example, Diffie-Hellman "DH" flavor, and any RSA flavor with
- *        only 512 bit keys.
- *
- * If a server certificate is sent, there is no anonymity.  However,
- * when a certificate is sent, ephemeral keys may still be used to
- * exchange the premaster secret.  That's how RSA_EXPORT often works,
- * as well as how the DHE_* flavors work.
- */
-static abstract class ServerKeyExchange extends HandshakeMessage
-{
-    @Override
-    int messageType() { return ht_server_key_exchange; }
-}
-
-
-/*
- * Using RSA for Key Exchange:  exchange a session key that's not as big
- * as the signing-only key.  Used for export applications, since exported
- * RSA encryption keys can't be bigger than 512 bytes.
- *
- * This is never used when keys are 512 bits or smaller, and isn't used
- * on "US Domestic" ciphers in any case.
- */
-static final
-class RSA_ServerKeyExchange extends ServerKeyExchange
-{
-    private byte rsa_modulus[];     // 1 to 2^16 - 1 bytes
-    private byte rsa_exponent[];    // 1 to 2^16 - 1 bytes
-
-    private Signature signature;
-    private byte[] signatureBytes;
-
-    /*
-     * Hash the nonces and the ephemeral RSA public key.
-     */
-    private void updateSignature(byte clntNonce[], byte svrNonce[])
-            throws SignatureException {
-        int tmp;
-
-        signature.update(clntNonce);
-        signature.update(svrNonce);
-
-        tmp = rsa_modulus.length;
-        signature.update((byte)(tmp >> 8));
-        signature.update((byte)(tmp & 0x0ff));
-        signature.update(rsa_modulus);
-
-        tmp = rsa_exponent.length;
-        signature.update((byte)(tmp >> 8));
-        signature.update((byte)(tmp & 0x0ff));
-        signature.update(rsa_exponent);
-    }
-
-
-    /*
-     * Construct an RSA server key exchange message, using data
-     * known _only_ to the server.
-     *
-     * The client knows the public key corresponding to this private
-     * key, from the Certificate message sent previously.  To comply
-     * with US export regulations we use short RSA keys ... either
-     * long term ones in the server's X509 cert, or else ephemeral
-     * ones sent using this message.
-     */
-    RSA_ServerKeyExchange(PublicKey ephemeralKey, PrivateKey privateKey,
-            RandomCookie clntNonce, RandomCookie svrNonce, SecureRandom sr)
-            throws GeneralSecurityException {
-        RSAPublicKeySpec rsaKey = JsseJce.getRSAPublicKeySpec(ephemeralKey);
-        rsa_modulus = toByteArray(rsaKey.getModulus());
-        rsa_exponent = toByteArray(rsaKey.getPublicExponent());
-        signature = RSASignature.getInstance();
-        signature.initSign(privateKey, sr);
-        updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
-        signatureBytes = signature.sign();
-    }
-
-
-    /*
-     * Parse an RSA server key exchange message, using data known
-     * to the client (and, in some situations, eavesdroppers).
-     */
-    RSA_ServerKeyExchange(HandshakeInStream input)
-            throws IOException, NoSuchAlgorithmException {
-        signature = RSASignature.getInstance();
-        rsa_modulus = input.getBytes16();
-        rsa_exponent = input.getBytes16();
-        signatureBytes = input.getBytes16();
-    }
-
-    /*
-     * Get the ephemeral RSA public key that will be used in this
-     * SSL connection.
-     */
-    PublicKey getPublicKey() {
-        try {
-            KeyFactory kfac = JsseJce.getKeyFactory("RSA");
-            // modulus and exponent are always positive
-            RSAPublicKeySpec kspec = new RSAPublicKeySpec(
-                new BigInteger(1, rsa_modulus),
-                new BigInteger(1, rsa_exponent));
-            return kfac.generatePublic(kspec);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /*
-     * Verify the signed temporary key using the hashes computed
-     * from it and the two nonces.  This is called by clients
-     * with "exportable" RSA flavors.
-     */
-    boolean verify(PublicKey certifiedKey, RandomCookie clntNonce,
-            RandomCookie svrNonce) throws GeneralSecurityException {
-        signature.initVerify(certifiedKey);
-        updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
-        return signature.verify(signatureBytes);
-    }
-
-    @Override
-    int messageLength() {
-        return 6 + rsa_modulus.length + rsa_exponent.length
-               + signatureBytes.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putBytes16(rsa_modulus);
-        s.putBytes16(rsa_exponent);
-        s.putBytes16(signatureBytes);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** RSA ServerKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "RSA Modulus", rsa_modulus);
-            Debug.println(s, "RSA Public Exponent", rsa_exponent);
-        }
-    }
-}
-
-
-/*
- * Using Diffie-Hellman algorithm for key exchange.  All we really need to
- * do is securely get Diffie-Hellman keys (using the same P, G parameters)
- * to our peer, then we automatically have a shared secret without need
- * to exchange any more data.  (D-H only solutions, such as SKIP, could
- * eliminate key exchange negotiations and get faster connection setup.
- * But they still need a signature algorithm like DSS/DSA to support the
- * trusted distribution of keys without relying on unscalable physical
- * key distribution systems.)
- *
- * This class supports several DH-based key exchange algorithms, though
- * perhaps eventually each deserves its own class.  Notably, this has
- * basic support for DH_anon and its DHE_DSS and DHE_RSA signed variants.
- */
-static final
-class DH_ServerKeyExchange extends ServerKeyExchange
-{
-    // Fix message encoding, see 4348279
-    private final static boolean dhKeyExchangeFix =
-        Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true);
-
-    private byte                dh_p [];        // 1 to 2^16 - 1 bytes
-    private byte                dh_g [];        // 1 to 2^16 - 1 bytes
-    private byte                dh_Ys [];       // 1 to 2^16 - 1 bytes
-
-    private byte                signature [];
-
-    // protocol version being established using this ServerKeyExchange message
-    ProtocolVersion protocolVersion;
-
-    // the preferable signature algorithm used by this ServerKeyExchange message
-    private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
-    /*
-     * Construct from initialized DH key object, for DH_anon
-     * key exchange.
-     */
-    DH_ServerKeyExchange(DHCrypt obj, ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        this.preferableSignatureAlgorithm = null;
-
-        // The DH key has been validated in the constructor of DHCrypt.
-        setValues(obj);
-        signature = null;
-    }
-
-    /*
-     * Construct from initialized DH key object and the key associated
-     * with the cert chain which was sent ... for DHE_DSS and DHE_RSA
-     * key exchange.  (Constructor called by server.)
-     */
-    DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
-            byte svrNonce[], SecureRandom sr,
-            SignatureAndHashAlgorithm signAlgorithm,
-            ProtocolVersion protocolVersion) throws GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        // The DH key has been validated in the constructor of DHCrypt.
-        setValues(obj);
-
-        Signature sig;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            this.preferableSignatureAlgorithm = signAlgorithm;
-            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
-        } else {
-            this.preferableSignatureAlgorithm = null;
-            if (key.getAlgorithm().equals("DSA")) {
-                sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
-            } else {
-                sig = RSASignature.getInstance();
-            }
-        }
-
-        sig.initSign(key, sr);
-        updateSignature(sig, clntNonce, svrNonce);
-        signature = sig.sign();
-    }
-
-    /*
-     * Construct a DH_ServerKeyExchange message from an input
-     * stream, as if sent from server to client for use with
-     * DH_anon key exchange
-     */
-    DH_ServerKeyExchange(HandshakeInStream input,
-            ProtocolVersion protocolVersion)
-            throws IOException, GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-        this.preferableSignatureAlgorithm = null;
-
-        dh_p = input.getBytes16();
-        dh_g = input.getBytes16();
-        dh_Ys = input.getBytes16();
-        KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
-                                             new BigInteger(1, dh_p),
-                                             new BigInteger(1, dh_g)));
-
-        signature = null;
-    }
-
-    /*
-     * Construct a DH_ServerKeyExchange message from an input stream
-     * and a certificate, as if sent from server to client for use with
-     * DHE_DSS or DHE_RSA key exchange.  (Called by client.)
-     */
-    DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
-            byte clntNonce[], byte svrNonce[], int messageSize,
-            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
-            ProtocolVersion protocolVersion)
-            throws IOException, GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        // read params: ServerDHParams
-        dh_p = input.getBytes16();
-        dh_g = input.getBytes16();
-        dh_Ys = input.getBytes16();
-        KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
-                                             new BigInteger(1, dh_p),
-                                             new BigInteger(1, dh_g)));
-
-        // read the signature and hash algorithm
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            int hash = input.getInt8();         // hash algorithm
-            int signature = input.getInt8();    // signature algorithm
-
-            preferableSignatureAlgorithm =
-                SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
-
-            // Is it a local supported signature algorithm?
-            if (!localSupportedSignAlgs.contains(
-                    preferableSignatureAlgorithm)) {
-                throw new SSLHandshakeException(
-                    "Unsupported SignatureAndHashAlgorithm in " +
-                    "ServerKeyExchange message: " +
-                    preferableSignatureAlgorithm);
-            }
-        } else {
-            this.preferableSignatureAlgorithm = null;
-        }
-
-        // read the signature
-        byte signature[];
-        if (dhKeyExchangeFix) {
-            signature = input.getBytes16();
-        } else {
-            messageSize -= (dh_p.length + 2);
-            messageSize -= (dh_g.length + 2);
-            messageSize -= (dh_Ys.length + 2);
-
-            signature = new byte[messageSize];
-            input.read(signature);
-        }
-
-        Signature sig;
-        String algorithm = publicKey.getAlgorithm();
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            sig = JsseJce.getSignature(
-                        preferableSignatureAlgorithm.getAlgorithmName());
-        } else {
-                switch (algorithm) {
-                    case "DSA":
-                        sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
-                        break;
-                    case "RSA":
-                        sig = RSASignature.getInstance();
-                        break;
-                    default:
-                        throw new SSLKeyException(
-                            "neither an RSA or a DSA key: " + algorithm);
-                }
-        }
-
-        sig.initVerify(publicKey);
-        updateSignature(sig, clntNonce, svrNonce);
-
-        if (sig.verify(signature) == false ) {
-            throw new SSLKeyException("Server D-H key verification failed");
-        }
-    }
-
-    /* Return the Diffie-Hellman modulus */
-    BigInteger getModulus() {
-        return new BigInteger(1, dh_p);
-    }
-
-    /* Return the Diffie-Hellman base/generator */
-    BigInteger getBase() {
-        return new BigInteger(1, dh_g);
-    }
-
-    /* Return the server's Diffie-Hellman public key */
-    BigInteger getServerPublicKey() {
-        return new BigInteger(1, dh_Ys);
-    }
-
-    /*
-     * Update sig with nonces and Diffie-Hellman public key.
-     */
-    private void updateSignature(Signature sig, byte clntNonce[],
-            byte svrNonce[]) throws SignatureException {
-        int tmp;
-
-        sig.update(clntNonce);
-        sig.update(svrNonce);
-
-        tmp = dh_p.length;
-        sig.update((byte)(tmp >> 8));
-        sig.update((byte)(tmp & 0x0ff));
-        sig.update(dh_p);
-
-        tmp = dh_g.length;
-        sig.update((byte)(tmp >> 8));
-        sig.update((byte)(tmp & 0x0ff));
-        sig.update(dh_g);
-
-        tmp = dh_Ys.length;
-        sig.update((byte)(tmp >> 8));
-        sig.update((byte)(tmp & 0x0ff));
-        sig.update(dh_Ys);
-    }
-
-    private void setValues(DHCrypt obj) {
-        dh_p = toByteArray(obj.getModulus());
-        dh_g = toByteArray(obj.getBase());
-        dh_Ys = toByteArray(obj.getPublicKey());
-    }
-
-    @Override
-    int messageLength() {
-        int temp = 6;   // overhead for p, g, y(s) values.
-
-        temp += dh_p.length;
-        temp += dh_g.length;
-        temp += dh_Ys.length;
-
-        if (signature != null) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                temp += SignatureAndHashAlgorithm.sizeInRecord();
-            }
-
-            temp += signature.length;
-            if (dhKeyExchangeFix) {
-                temp += 2;
-            }
-        }
-
-        return temp;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putBytes16(dh_p);
-        s.putBytes16(dh_g);
-        s.putBytes16(dh_Ys);
-
-        if (signature != null) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                s.putInt8(preferableSignatureAlgorithm.getHashValue());
-                s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
-            }
-
-            if (dhKeyExchangeFix) {
-                s.putBytes16(signature);
-            } else {
-                s.write(signature);
-            }
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** Diffie-Hellman ServerKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "DH Modulus", dh_p);
-            Debug.println(s, "DH Base", dh_g);
-            Debug.println(s, "Server DH Public Key", dh_Ys);
-
-            if (signature == null) {
-                s.println("Anonymous");
-            } else {
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    s.println("Signature Algorithm " +
-                        preferableSignatureAlgorithm.getAlgorithmName());
-                }
-
-                s.println("Signed with a DSA or RSA public key");
-            }
-        }
-    }
-}
-
-/*
- * ECDH server key exchange message. Sent by the server for ECDHE and ECDH_anon
- * ciphersuites to communicate its ephemeral public key (including the
- * EC domain parameters).
- *
- * We support named curves only, no explicitly encoded curves.
- */
-static final
-class ECDH_ServerKeyExchange extends ServerKeyExchange {
-
-    // constants for ECCurveType
-    private final static int CURVE_EXPLICIT_PRIME = 1;
-    private final static int CURVE_EXPLICIT_CHAR2 = 2;
-    private final static int CURVE_NAMED_CURVE    = 3;
-
-    // id of the curve we are using
-    private int curveId;
-    // encoded public point
-    private byte[] pointBytes;
-
-    // signature bytes (or null if anonymous)
-    private byte[] signatureBytes;
-
-    // public key object encapsulated in this message
-    private ECPublicKey publicKey;
-
-    // protocol version being established using this ServerKeyExchange message
-    ProtocolVersion protocolVersion;
-
-    // the preferable signature algorithm used by this ServerKeyExchange message
-    private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
-    ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
-            byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
-            SignatureAndHashAlgorithm signAlgorithm,
-            ProtocolVersion protocolVersion) throws GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        publicKey = (ECPublicKey)obj.getPublicKey();
-        ECParameterSpec params = publicKey.getParams();
-        ECPoint point = publicKey.getW();
-        pointBytes = JsseJce.encodePoint(point, params.getCurve());
-        curveId = EllipticCurvesExtension.getCurveIndex(params);
-
-        if (privateKey == null) {
-            // ECDH_anon
-            return;
-        }
-
-        Signature sig;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            this.preferableSignatureAlgorithm = signAlgorithm;
-            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(privateKey.getAlgorithm());
-        }
-        sig.initSign(privateKey, sr);
-
-        updateSignature(sig, clntNonce, svrNonce);
-        signatureBytes = sig.sign();
-    }
-
-    /*
-     * Parse an ECDH server key exchange message.
-     */
-    ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
-            byte[] clntNonce, byte[] svrNonce,
-            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
-            ProtocolVersion protocolVersion)
-            throws IOException, GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        // read params: ServerECDHParams
-        int curveType = input.getInt8();
-        ECParameterSpec parameters;
-        // These parsing errors should never occur as we negotiated
-        // the supported curves during the exchange of the Hello messages.
-        if (curveType == CURVE_NAMED_CURVE) {
-            curveId = input.getInt16();
-            if (!EllipticCurvesExtension.isSupported(curveId)) {
-                throw new SSLHandshakeException(
-                    "Unsupported curveId: " + curveId);
-            }
-            String curveOid = EllipticCurvesExtension.getCurveOid(curveId);
-            if (curveOid == null) {
-                throw new SSLHandshakeException(
-                    "Unknown named curve: " + curveId);
-            }
-            parameters = JsseJce.getECParameterSpec(curveOid);
-            if (parameters == null) {
-                throw new SSLHandshakeException(
-                    "Unsupported curve: " + curveOid);
-            }
-        } else {
-            throw new SSLHandshakeException(
-                "Unsupported ECCurveType: " + curveType);
-        }
-        pointBytes = input.getBytes8();
-
-        ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());
-        KeyFactory factory = JsseJce.getKeyFactory("EC");
-        publicKey = (ECPublicKey)factory.generatePublic(
-            new ECPublicKeySpec(point, parameters));
-
-        if (signingKey == null) {
-            // ECDH_anon
-            return;
-        }
-
-        // read the signature and hash algorithm
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            int hash = input.getInt8();         // hash algorithm
-            int signature = input.getInt8();    // signature algorithm
-
-            preferableSignatureAlgorithm =
-                SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
-
-            // Is it a local supported signature algorithm?
-            if (!localSupportedSignAlgs.contains(
-                    preferableSignatureAlgorithm)) {
-                throw new SSLHandshakeException(
-                        "Unsupported SignatureAndHashAlgorithm in " +
-                        "ServerKeyExchange message: " +
-                        preferableSignatureAlgorithm);
-            }
-        }
-
-        // read the signature
-        signatureBytes = input.getBytes16();
-
-        // verify the signature
-        Signature sig;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            sig = JsseJce.getSignature(
-                        preferableSignatureAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(signingKey.getAlgorithm());
-        }
-        sig.initVerify(signingKey);
-
-        updateSignature(sig, clntNonce, svrNonce);
-
-        if (sig.verify(signatureBytes) == false ) {
-            throw new SSLKeyException(
-                "Invalid signature on ECDH server key exchange message");
-        }
-    }
-
-    /*
-     * Get the ephemeral EC public key encapsulated in this message.
-     */
-    ECPublicKey getPublicKey() {
-        return publicKey;
-    }
-
-    private static Signature getSignature(String keyAlgorithm)
-            throws NoSuchAlgorithmException {
-            switch (keyAlgorithm) {
-                case "EC":
-                    return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
-                case "RSA":
-                    return RSASignature.getInstance();
-                default:
-                    throw new NoSuchAlgorithmException(
-                        "neither an RSA or a EC key : " + keyAlgorithm);
-            }
-    }
-
-    private void updateSignature(Signature sig, byte clntNonce[],
-            byte svrNonce[]) throws SignatureException {
-        sig.update(clntNonce);
-        sig.update(svrNonce);
-
-        sig.update((byte)CURVE_NAMED_CURVE);
-        sig.update((byte)(curveId >> 8));
-        sig.update((byte)curveId);
-        sig.update((byte)pointBytes.length);
-        sig.update(pointBytes);
-    }
-
-    @Override
-    int messageLength() {
-        int sigLen = 0;
-        if (signatureBytes != null) {
-            sigLen = 2 + signatureBytes.length;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                sigLen += SignatureAndHashAlgorithm.sizeInRecord();
-            }
-        }
-
-        return 4 + pointBytes.length + sigLen;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt8(CURVE_NAMED_CURVE);
-        s.putInt16(curveId);
-        s.putBytes8(pointBytes);
-
-        if (signatureBytes != null) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                s.putInt8(preferableSignatureAlgorithm.getHashValue());
-                s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
-            }
-
-            s.putBytes16(signatureBytes);
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** ECDH ServerKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            if (signatureBytes == null) {
-                s.println("Anonymous");
-            } else {
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    s.println("Signature Algorithm " +
-                            preferableSignatureAlgorithm.getAlgorithmName());
-                }
-            }
-
-            s.println("Server key: " + publicKey);
-        }
-    }
-}
-
-static final class DistinguishedName {
-
-    /*
-     * DER encoded distinguished name.
-     * TLS requires that its not longer than 65535 bytes.
-     */
-    byte name[];
-
-    DistinguishedName(HandshakeInStream input) throws IOException {
-        name = input.getBytes16();
-    }
-
-    DistinguishedName(X500Principal dn) {
-        name = dn.getEncoded();
-    }
-
-    X500Principal getX500Principal() throws IOException {
-        try {
-            return new X500Principal(name);
-        } catch (IllegalArgumentException e) {
-            throw (SSLProtocolException)new SSLProtocolException(
-                e.getMessage()).initCause(e);
-        }
-    }
-
-    int length() {
-        return 2 + name.length;
-    }
-
-    void send(HandshakeOutStream output) throws IOException {
-        output.putBytes16(name);
-    }
-
-    void print(PrintStream output) throws IOException {
-        X500Principal principal = new X500Principal(name);
-        output.println("<" + principal.toString() + ">");
-    }
-}
-
-/*
- * CertificateRequest ... SERVER --> CLIENT
- *
- * Authenticated servers may ask clients to authenticate themselves
- * in turn, using this message.
- *
- * Prior to TLS 1.2, the structure of the message is defined as:
- *     struct {
- *         ClientCertificateType certificate_types<1..2^8-1>;
- *         DistinguishedName certificate_authorities<0..2^16-1>;
- *     } CertificateRequest;
- *
- * In TLS 1.2, the structure is changed to:
- *     struct {
- *         ClientCertificateType certificate_types<1..2^8-1>;
- *         SignatureAndHashAlgorithm
- *           supported_signature_algorithms<2^16-1>;
- *         DistinguishedName certificate_authorities<0..2^16-1>;
- *     } CertificateRequest;
- *
- */
-static final
-class CertificateRequest extends HandshakeMessage
-{
-    // enum ClientCertificateType
-    static final int   cct_rsa_sign = 1;
-    static final int   cct_dss_sign = 2;
-    static final int   cct_rsa_fixed_dh = 3;
-    static final int   cct_dss_fixed_dh = 4;
-
-    // The existance of these two values is a bug in the SSL specification.
-    // They are never used in the protocol.
-    static final int   cct_rsa_ephemeral_dh = 5;
-    static final int   cct_dss_ephemeral_dh = 6;
-
-    // From RFC 4492 (ECC)
-    static final int    cct_ecdsa_sign       = 64;
-    static final int    cct_rsa_fixed_ecdh   = 65;
-    static final int    cct_ecdsa_fixed_ecdh = 66;
-
-    private final static byte[] TYPES_NO_ECC = { cct_rsa_sign, cct_dss_sign };
-    private final static byte[] TYPES_ECC =
-        { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };
-
-    byte                types [];               // 1 to 255 types
-    DistinguishedName   authorities [];         // 3 to 2^16 - 1
-        // ... "3" because that's the smallest DER-encoded X500 DN
-
-    // protocol version being established using this CertificateRequest message
-    ProtocolVersion protocolVersion;
-
-    // supported_signature_algorithms for TLS 1.2 or later
-    private Collection<SignatureAndHashAlgorithm> algorithms;
-
-    // length of supported_signature_algorithms
-    private int algorithmsLen;
-
-    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange,
-            Collection<SignatureAndHashAlgorithm> signAlgs,
-            ProtocolVersion protocolVersion) throws IOException {
-
-        this.protocolVersion = protocolVersion;
-
-        // always use X500Principal
-        authorities = new DistinguishedName[ca.length];
-        for (int i = 0; i < ca.length; i++) {
-            X500Principal x500Principal = ca[i].getSubjectX500Principal();
-            authorities[i] = new DistinguishedName(x500Principal);
-        }
-        // we support RSA, DSS, and ECDSA client authentication and they
-        // can be used with all ciphersuites. If this changes, the code
-        // needs to be adapted to take keyExchange into account.
-        // We only request ECDSA client auth if we have ECC crypto available.
-        this.types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;
-
-        // Use supported_signature_algorithms for TLS 1.2 or later.
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            if (signAlgs == null || signAlgs.isEmpty()) {
-                throw new SSLProtocolException(
-                        "No supported signature algorithms");
-            }
-
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
-            algorithmsLen =
-                SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
-        } else {
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-            algorithmsLen = 0;
-        }
-    }
-
-    CertificateRequest(HandshakeInStream input,
-            ProtocolVersion protocolVersion) throws IOException {
-
-        this.protocolVersion = protocolVersion;
-
-        // Read the certificate_types.
-        types = input.getBytes8();
-
-        // Read the supported_signature_algorithms for TLS 1.2 or later.
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            algorithmsLen = input.getInt16();
-            if (algorithmsLen < 2) {
-                throw new SSLProtocolException(
-                    "Invalid supported_signature_algorithms field: " +
-                    algorithmsLen);
-            }
-
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-            int remains = algorithmsLen;
-            int sequence = 0;
-            while (remains > 1) {    // needs at least two bytes
-                int hash = input.getInt8();         // hash algorithm
-                int signature = input.getInt8();    // signature algorithm
-
-                SignatureAndHashAlgorithm algorithm =
-                    SignatureAndHashAlgorithm.valueOf(hash, signature,
-                                                                ++sequence);
-                algorithms.add(algorithm);
-                remains -= 2;  // one byte for hash, one byte for signature
-            }
-
-            if (remains != 0) {
-                throw new SSLProtocolException(
-                    "Invalid supported_signature_algorithms field. remains: " +
-                    remains);
-            }
-        } else {
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-            algorithmsLen = 0;
-        }
-
-        // read the certificate_authorities
-        int len = input.getInt16();
-        ArrayList<DistinguishedName> v = new ArrayList<>();
-        while (len >= 3) {
-            DistinguishedName dn = new DistinguishedName(input);
-            v.add(dn);
-            len -= dn.length();
-        }
-
-        if (len != 0) {
-            throw new SSLProtocolException(
-                "Bad CertificateRequest DN length: " + len);
-        }
-
-        authorities = v.toArray(new DistinguishedName[v.size()]);
-    }
-
-    X500Principal[] getAuthorities() throws IOException {
-        X500Principal[] ret = new X500Principal[authorities.length];
-        for (int i = 0; i < authorities.length; i++) {
-            ret[i] = authorities[i].getX500Principal();
-        }
-        return ret;
-    }
-
-    Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
-        return algorithms;
-    }
-
-    @Override
-    int messageType() {
-        return ht_certificate_request;
-    }
-
-    @Override
-    int messageLength() {
-        int len = 1 + types.length + 2;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            len += algorithmsLen + 2;
-        }
-
-        for (int i = 0; i < authorities.length; i++) {
-            len += authorities[i].length();
-        }
-
-        return len;
-    }
-
-    @Override
-    void send(HandshakeOutStream output) throws IOException {
-        // put certificate_types
-        output.putBytes8(types);
-
-        // put supported_signature_algorithms
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            output.putInt16(algorithmsLen);
-            for (SignatureAndHashAlgorithm algorithm : algorithms) {
-                output.putInt8(algorithm.getHashValue());      // hash
-                output.putInt8(algorithm.getSignatureValue()); // signature
-            }
-        }
-
-        // put certificate_authorities
-        int len = 0;
-        for (int i = 0; i < authorities.length; i++) {
-            len += authorities[i].length();
-        }
-
-        output.putInt16(len);
-        for (int i = 0; i < authorities.length; i++) {
-            authorities[i].send(output);
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** CertificateRequest");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            s.print("Cert Types: ");
-            for (int i = 0; i < types.length; i++) {
-                switch (types[i]) {
-                  case cct_rsa_sign:
-                    s.print("RSA"); break;
-                  case cct_dss_sign:
-                    s.print("DSS"); break;
-                  case cct_rsa_fixed_dh:
-                    s.print("Fixed DH (RSA sig)"); break;
-                  case cct_dss_fixed_dh:
-                    s.print("Fixed DH (DSS sig)"); break;
-                  case cct_rsa_ephemeral_dh:
-                    s.print("Ephemeral DH (RSA sig)"); break;
-                  case cct_dss_ephemeral_dh:
-                    s.print("Ephemeral DH (DSS sig)"); break;
-                  case cct_ecdsa_sign:
-                    s.print("ECDSA"); break;
-                  case cct_rsa_fixed_ecdh:
-                    s.print("Fixed ECDH (RSA sig)"); break;
-                  case cct_ecdsa_fixed_ecdh:
-                    s.print("Fixed ECDH (ECDSA sig)"); break;
-                  default:
-                    s.print("Type-" + (types[i] & 0xff)); break;
-                }
-                if (i != types.length - 1) {
-                    s.print(", ");
-                }
-            }
-            s.println();
-
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                StringBuffer buffer = new StringBuffer();
-                boolean opened = false;
-                for (SignatureAndHashAlgorithm signAlg : algorithms) {
-                    if (opened) {
-                        buffer.append(", " + signAlg.getAlgorithmName());
-                    } else {
-                        buffer.append(signAlg.getAlgorithmName());
-                        opened = true;
-                    }
-                }
-                s.println("Supported Signature Algorithms: " + buffer);
-            }
-
-            s.println("Cert Authorities:");
-            if (authorities.length == 0) {
-                s.println("<Empty>");
-            } else {
-                for (int i = 0; i < authorities.length; i++) {
-                    authorities[i].print(s);
-                }
-            }
-        }
-    }
-}
-
-
-/*
- * ServerHelloDone ... SERVER --> CLIENT
- *
- * When server's done sending its messages in response to the client's
- * "hello" (e.g. its own hello, certificate, key exchange message, perhaps
- * client certificate request) it sends this message to flag that it's
- * done that part of the handshake.
- */
-static final
-class ServerHelloDone extends HandshakeMessage
-{
-    @Override
-    int messageType() { return ht_server_hello_done; }
-
-    ServerHelloDone() { }
-
-    ServerHelloDone(HandshakeInStream input)
-    {
-        // nothing to do
-    }
-
-    @Override
-    int messageLength()
-    {
-        return 0;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException
-    {
-        // nothing to send
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException
-    {
-        s.println("*** ServerHelloDone");
-    }
-}
-
-
-/*
- * CertificateVerify ... CLIENT --> SERVER
- *
- * Sent after client sends signature-capable certificates (e.g. not
- * Diffie-Hellman) to verify.
- */
-static final class CertificateVerify extends HandshakeMessage {
-
-    // the signature bytes
-    private byte[] signature;
-
-    // protocol version being established using this CertificateVerify message
-    ProtocolVersion protocolVersion;
-
-    // the preferable signature algorithm used by this CertificateVerify message
-    private SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
-
-    /*
-     * Create an RSA or DSA signed certificate verify message.
-     */
-    CertificateVerify(ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, PrivateKey privateKey,
-            SecretKey masterSecret, SecureRandom sr,
-            SignatureAndHashAlgorithm signAlgorithm)
-            throws GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        String algorithm = privateKey.getAlgorithm();
-        Signature sig = null;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            this.preferableSignatureAlgorithm = signAlgorithm;
-            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(protocolVersion, algorithm);
-        }
-        sig.initSign(privateKey, sr);
-        updateSignature(sig, protocolVersion, handshakeHash, algorithm,
-                        masterSecret);
-        signature = sig.sign();
-    }
-
-    //
-    // Unmarshal the signed data from the input stream.
-    //
-    CertificateVerify(HandshakeInStream input,
-            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
-            ProtocolVersion protocolVersion) throws IOException  {
-
-        this.protocolVersion = protocolVersion;
-
-        // read the signature and hash algorithm
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            int hashAlg = input.getInt8();         // hash algorithm
-            int signAlg = input.getInt8();         // signature algorithm
-
-            preferableSignatureAlgorithm =
-                SignatureAndHashAlgorithm.valueOf(hashAlg, signAlg, 0);
-
-            // Is it a local supported signature algorithm?
-            if (!localSupportedSignAlgs.contains(
-                    preferableSignatureAlgorithm)) {
-                throw new SSLHandshakeException(
-                    "Unsupported SignatureAndHashAlgorithm in " +
-                    "CertificateVerify message: " + preferableSignatureAlgorithm);
-            }
-        }
-
-        // read the signature
-        signature = input.getBytes16();
-    }
-
-    /*
-     * Get the preferable signature algorithm used by this message
-     */
-    SignatureAndHashAlgorithm getPreferableSignatureAlgorithm() {
-        return preferableSignatureAlgorithm;
-    }
-
-    /*
-     * Verify a certificate verify message. Return the result of verification,
-     * if there is a problem throw a GeneralSecurityException.
-     */
-    boolean verify(ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, PublicKey publicKey,
-            SecretKey masterSecret) throws GeneralSecurityException {
-        String algorithm = publicKey.getAlgorithm();
-        Signature sig = null;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            sig = JsseJce.getSignature(
-                        preferableSignatureAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(protocolVersion, algorithm);
-        }
-        sig.initVerify(publicKey);
-        updateSignature(sig, protocolVersion, handshakeHash, algorithm,
-                        masterSecret);
-        return sig.verify(signature);
-    }
-
-    /*
-     * Get the Signature object appropriate for verification using the
-     * given signature algorithm and protocol version.
-     */
-    private static Signature getSignature(ProtocolVersion protocolVersion,
-            String algorithm) throws GeneralSecurityException {
-            switch (algorithm) {
-                case "RSA":
-                    return RSASignature.getInternalInstance();
-                case "DSA":
-                    return JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
-                case "EC":
-                    return JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
-                default:
-                    throw new SignatureException("Unrecognized algorithm: "
-                        + algorithm);
-            }
-    }
-
-    /*
-     * Update the Signature with the data appropriate for the given
-     * signature algorithm and protocol version so that the object is
-     * ready for signing or verifying.
-     */
-    private static void updateSignature(Signature sig,
-            ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
-            throws SignatureException {
-
-        if (algorithm.equals("RSA")) {
-            if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
-                MessageDigest md5Clone = handshakeHash.getMD5Clone();
-                MessageDigest shaClone = handshakeHash.getSHAClone();
-
-                if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
-                    updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
-                    updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
-                }
-
-                // The signature must be an instance of RSASignature, need
-                // to use these hashes directly.
-                RSASignature.setHashes(sig, md5Clone, shaClone);
-            } else {  // TLS1.2+
-                sig.update(handshakeHash.getAllHandshakeMessages());
-            }
-        } else { // DSA, ECDSA
-            if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
-                MessageDigest shaClone = handshakeHash.getSHAClone();
-
-                if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
-                    updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
-                }
-
-                sig.update(shaClone.digest());
-            } else {  // TLS1.2+
-                sig.update(handshakeHash.getAllHandshakeMessages());
-            }
-        }
-    }
-
-    /*
-     * Update the MessageDigest for SSLv3 certificate verify or finished
-     * message calculation. The digest must already have been updated with
-     * all preceding handshake messages.
-     * Used by the Finished class as well.
-     */
-    private static void updateDigest(MessageDigest md,
-            byte[] pad1, byte[] pad2,
-            SecretKey masterSecret) {
-        // Digest the key bytes if available.
-        // Otherwise (sensitive key), try digesting the key directly.
-        // That is currently only implemented in SunPKCS11 using a private
-        // reflection API, so we avoid that if possible.
-        byte[] keyBytes = "RAW".equals(masterSecret.getFormat())
-                        ? masterSecret.getEncoded() : null;
-        if (keyBytes != null) {
-            md.update(keyBytes);
-        } else {
-            digestKey(md, masterSecret);
-        }
-        md.update(pad1);
-        byte[] temp = md.digest();
-
-        if (keyBytes != null) {
-            md.update(keyBytes);
-        } else {
-            digestKey(md, masterSecret);
-        }
-        md.update(pad2);
-        md.update(temp);
-    }
-
-    private final static Class<?> delegate;
-    private final static Field spiField;
-
-    static {
-        try {
-            delegate = Class.forName("java.security.MessageDigest$Delegate");
-            spiField = delegate.getDeclaredField("digestSpi");
-        } catch (Exception e) {
-            throw new RuntimeException("Reflection failed", e);
-        }
-        makeAccessible(spiField);
-    }
-
-    private static void makeAccessible(final AccessibleObject o) {
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            @Override
-            public Object run() {
-                o.setAccessible(true);
-                return null;
-            }
-        });
-    }
-
-    // ConcurrentHashMap does not allow null values, use this marker object
-    private final static Object NULL_OBJECT = new Object();
-
-    // cache Method objects per Spi class
-    // Note that this will prevent the Spi classes from being GC'd. We assume
-    // that is not a problem.
-    private final static Map<Class<?>,Object> methodCache =
-                                        new ConcurrentHashMap<>();
-
-    private static void digestKey(MessageDigest md, SecretKey key) {
-        try {
-            // Verify that md is implemented via MessageDigestSpi, not
-            // via JDK 1.1 style MessageDigest subclassing.
-            if (md.getClass() != delegate) {
-                throw new Exception("Digest is not a MessageDigestSpi");
-            }
-            MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md);
-            Class<?> clazz = spi.getClass();
-            Object r = methodCache.get(clazz);
-            if (r == null) {
-                try {
-                    r = clazz.getDeclaredMethod("implUpdate", SecretKey.class);
-                    makeAccessible((Method)r);
-                } catch (NoSuchMethodException e) {
-                    r = NULL_OBJECT;
-                }
-                methodCache.put(clazz, r);
-            }
-            if (r == NULL_OBJECT) {
-                throw new Exception(
-                    "Digest does not support implUpdate(SecretKey)");
-            }
-            Method update = (Method)r;
-            update.invoke(spi, key);
-        } catch (Exception e) {
-            throw new RuntimeException(
-                "Could not obtain encoded key and "
-                + "MessageDigest cannot digest key", e);
-        }
-    }
-
-    @Override
-    int messageType() {
-        return ht_certificate_verify;
-    }
-
-    @Override
-    int messageLength() {
-        int temp = 2;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            temp += SignatureAndHashAlgorithm.sizeInRecord();
-        }
-
-        return temp + signature.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            s.putInt8(preferableSignatureAlgorithm.getHashValue());
-            s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
-        }
-
-        s.putBytes16(signature);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** CertificateVerify");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                s.println("Signature Algorithm " +
-                        preferableSignatureAlgorithm.getAlgorithmName());
-            }
-        }
-    }
-}
-
-
-/*
- * FINISHED ... sent by both CLIENT and SERVER
- *
- * This is the FINISHED message as defined in the SSL and TLS protocols.
- * Both protocols define this handshake message slightly differently.
- * This class supports both formats.
- *
- * When handshaking is finished, each side sends a "change_cipher_spec"
- * record, then immediately sends a "finished" handshake message prepared
- * according to the newly adopted cipher spec.
- *
- * NOTE that until this is sent, no application data may be passed, unless
- * some non-default cipher suite has already been set up on this connection
- * connection (e.g. a previous handshake arranged one).
- */
-static final class Finished extends HandshakeMessage {
-
-    // constant for a Finished message sent by the client
-    final static int CLIENT = 1;
-
-    // constant for a Finished message sent by the server
-    final static int SERVER = 2;
-
-    // enum Sender:  "CLNT" and "SRVR"
-    private static final byte[] SSL_CLIENT = { 0x43, 0x4C, 0x4E, 0x54 };
-    private static final byte[] SSL_SERVER = { 0x53, 0x52, 0x56, 0x52 };
-
-    /*
-     * Contents of the finished message ("checksum"). For TLS, it
-     * is 12 bytes long, for SSLv3 36 bytes.
-     */
-    private byte[] verifyData;
-
-    /*
-     * Current cipher suite we are negotiating.  TLS 1.2 has
-     * ciphersuite-defined PRF algorithms.
-     */
-    private ProtocolVersion protocolVersion;
-    private CipherSuite cipherSuite;
-
-    /*
-     * Create a finished message to send to the remote peer.
-     */
-    Finished(ProtocolVersion protocolVersion, HandshakeHash handshakeHash,
-            int sender, SecretKey master, CipherSuite cipherSuite) {
-        this.protocolVersion = protocolVersion;
-        this.cipherSuite = cipherSuite;
-        verifyData = getFinished(handshakeHash, sender, master);
-    }
-
-    /*
-     * Constructor that reads FINISHED message from stream.
-     */
-    Finished(ProtocolVersion protocolVersion, HandshakeInStream input,
-            CipherSuite cipherSuite) throws IOException {
-        this.protocolVersion = protocolVersion;
-        this.cipherSuite = cipherSuite;
-        int msgLen = (protocolVersion.v >= ProtocolVersion.TLS10.v) ? 12 : 36;
-        verifyData = new byte[msgLen];
-        input.read(verifyData);
-    }
-
-    /*
-     * Verify that the hashes here are what would have been produced
-     * according to a given set of inputs.  This is used to ensure that
-     * both client and server are fully in sync, and that the handshake
-     * computations have been successful.
-     */
-    boolean verify(HandshakeHash handshakeHash, int sender, SecretKey master) {
-        byte[] myFinished = getFinished(handshakeHash, sender, master);
-        return MessageDigest.isEqual(myFinished, verifyData);
-    }
-
-    /*
-     * Perform the actual finished message calculation.
-     */
-    private byte[] getFinished(HandshakeHash handshakeHash,
-            int sender, SecretKey masterKey) {
-        byte[] sslLabel;
-        String tlsLabel;
-        if (sender == CLIENT) {
-            sslLabel = SSL_CLIENT;
-            tlsLabel = "client finished";
-        } else if (sender == SERVER) {
-            sslLabel = SSL_SERVER;
-            tlsLabel = "server finished";
-        } else {
-            throw new RuntimeException("Invalid sender: " + sender);
-        }
-
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            // TLS 1.0+
-            try {
-                byte [] seed;
-                String prfAlg;
-                PRF prf;
-
-                // Get the KeyGenerator alg and calculate the seed.
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    // TLS 1.2
-                    seed = handshakeHash.getFinishedHash();
-
-                    prfAlg = "SunTls12Prf";
-                    prf = cipherSuite.prfAlg;
-                } else {
-                    // TLS 1.0/1.1
-                    MessageDigest md5Clone = handshakeHash.getMD5Clone();
-                    MessageDigest shaClone = handshakeHash.getSHAClone();
-                    seed = new byte[36];
-                    md5Clone.digest(seed, 0, 16);
-                    shaClone.digest(seed, 16, 20);
-
-                    prfAlg = "SunTlsPrf";
-                    prf = P_NONE;
-                }
-
-                String prfHashAlg = prf.getPRFHashAlg();
-                int prfHashLength = prf.getPRFHashLength();
-                int prfBlockSize = prf.getPRFBlockSize();
-
-                /*
-                 * RFC 5246/7.4.9 says that finished messages can
-                 * be ciphersuite-specific in both length/PRF hash
-                 * algorithm.  If we ever run across a different
-                 * length, this call will need to be updated.
-                 */
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
-                    masterKey, tlsLabel, seed, 12,
-                    prfHashAlg, prfHashLength, prfBlockSize);
-
-                KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
-                kg.init(spec);
-                SecretKey prfKey = kg.generateKey();
-                if ("RAW".equals(prfKey.getFormat()) == false) {
-                    throw new ProviderException(
-                        "Invalid PRF output, format must be RAW. " +
-                        "Format received: " + prfKey.getFormat());
-                }
-                byte[] finished = prfKey.getEncoded();
-                return finished;
-            } catch (GeneralSecurityException e) {
-                throw new RuntimeException("PRF failed", e);
-            }
-        } else {
-            // SSLv3
-            MessageDigest md5Clone = handshakeHash.getMD5Clone();
-            MessageDigest shaClone = handshakeHash.getSHAClone();
-            updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
-            updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
-            byte[] finished = new byte[36];
-            try {
-                md5Clone.digest(finished, 0, 16);
-                shaClone.digest(finished, 16, 20);
-            } catch (DigestException e) {
-                // cannot occur
-                throw new RuntimeException("Digest failed", e);
-            }
-            return finished;
-        }
-    }
-
-    /*
-     * Update the MessageDigest for SSLv3 finished message calculation.
-     * The digest must already have been updated with all preceding handshake
-     * messages. This operation is almost identical to the certificate verify
-     * hash, reuse that code.
-     */
-    private static void updateDigest(MessageDigest md, byte[] sender,
-            byte[] pad1, byte[] pad2, SecretKey masterSecret) {
-        md.update(sender);
-        CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
-    }
-
-    // get the verify_data of the finished message
-    byte[] getVerifyData() {
-        return verifyData;
-    }
-
-    @Override
-    int messageType() { return ht_finished; }
-
-    @Override
-    int messageLength() {
-        return verifyData.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream out) throws IOException {
-        out.write(verifyData);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** Finished");
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "verify_data", verifyData);
-            s.println("***");
-        }
-    }
-}
-
-//
-// END of nested classes
-//
-
-}
--- a/src/share/classes/sun/security/ssl/HandshakeOutStream.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, 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.OutputStream;
-import java.io.IOException;
-
-/**
- * Output stream for handshake data.  This is used only internally
- * to the SSL classes.
- *
- * MT note:  one thread at a time is presumed be writing handshake
- * messages, but (after initial connection setup) it's possible to
- * have other threads reading/writing application data.  It's the
- * SSLSocketImpl class that synchronizes record writes.
- *
- * @author  David Brownell
- */
-public class HandshakeOutStream extends OutputStream {
-
-    private SSLSocketImpl socket;
-    private SSLEngineImpl engine;
-
-    OutputRecord r;
-
-    HandshakeOutStream(ProtocolVersion protocolVersion,
-            ProtocolVersion helloVersion, HandshakeHash handshakeHash,
-            SSLSocketImpl socket) {
-        this.socket = socket;
-        r = new OutputRecord(Record.ct_handshake);
-        init(protocolVersion, helloVersion, handshakeHash);
-    }
-
-    HandshakeOutStream(ProtocolVersion protocolVersion,
-            ProtocolVersion helloVersion, HandshakeHash handshakeHash,
-            SSLEngineImpl engine) {
-        this.engine = engine;
-        r = new EngineOutputRecord(Record.ct_handshake, engine);
-        init(protocolVersion, helloVersion, handshakeHash);
-    }
-
-    private void init(ProtocolVersion protocolVersion,
-            ProtocolVersion helloVersion, HandshakeHash handshakeHash) {
-        r.setVersion(protocolVersion);
-        r.setHelloVersion(helloVersion);
-        r.setHandshakeHash(handshakeHash);
-    }
-
-
-    /*
-     * Update the handshake data hashes ... mostly for use after a
-     * client cert has been sent, so the cert verify message can be
-     * constructed correctly yet without forcing extra I/O.  In all
-     * other cases, automatic hash calculation suffices.
-     */
-    void doHashes() {
-        r.doHashes();
-    }
-
-    /*
-     * Write some data out onto the stream ... buffers as much as possible.
-     * Hashes are updated automatically if something gets flushed to the
-     * network (e.g. a big cert message etc).
-     */
-    @Override
-    public void write(byte buf[], int off, int len) throws IOException {
-        while (len > 0) {
-            int howmuch = Math.min(len, r.availableDataBytes());
-
-            if (howmuch == 0) {
-                flush();
-            } else {
-                r.write(buf, off, howmuch);
-                off += howmuch;
-                len -= howmuch;
-            }
-        }
-    }
-
-    /*
-     * write-a-byte
-     */
-    @Override
-    public void write(int i) throws IOException {
-        if (r.availableDataBytes() < 1) {
-            flush();
-        }
-        r.write(i);
-    }
-
-    @Override
-    public void flush() throws IOException {
-        if (socket != null) {
-            try {
-                socket.writeRecord(r);
-            } catch (IOException e) {
-                // Had problems writing; check if there was an
-                // alert from peer. If alert received, waitForClose
-                // will throw an exception for the alert
-                socket.waitForClose(true);
-
-                // No alert was received, just rethrow exception
-                throw e;
-            }
-        } else {  // engine != null
-            /*
-             * Even if record might be empty, flush anyway in case
-             * there is a finished handshake message that we need
-             * to queue.
-             */
-            engine.writeRecord((EngineOutputRecord)r);
-        }
-    }
-
-    /*
-     * Tell the OutputRecord that a finished message was
-     * contained either in this record or the one immeiately
-     * preceding it.  We need to reliably pass back notifications
-     * that a finish message occurred.
-     */
-    void setFinishedMsg() {
-        assert(socket == null);
-
-        ((EngineOutputRecord)r).setFinishedMsg();
-    }
-
-    /*
-     * Put integers encoded in standard 8, 16, 24, and 32 bit
-     * big endian formats. Note that OutputStream.write(int) only
-     * writes the least significant 8 bits and ignores the rest.
-     */
-
-    void putInt8(int i) throws IOException {
-        checkOverflow(i, Record.OVERFLOW_OF_INT08);
-        r.write(i);
-    }
-
-    void putInt16(int i) throws IOException {
-        checkOverflow(i, Record.OVERFLOW_OF_INT16);
-        if (r.availableDataBytes() < 2) {
-            flush();
-        }
-        r.write(i >> 8);
-        r.write(i);
-    }
-
-    void putInt24(int i) throws IOException {
-        checkOverflow(i, Record.OVERFLOW_OF_INT24);
-        if (r.availableDataBytes() < 3) {
-            flush();
-        }
-        r.write(i >> 16);
-        r.write(i >> 8);
-        r.write(i);
-    }
-
-    void putInt32(int i) throws IOException {
-        if (r.availableDataBytes() < 4) {
-            flush();
-        }
-        r.write(i >> 24);
-        r.write(i >> 16);
-        r.write(i >> 8);
-        r.write(i);
-    }
-
-    /*
-     * Put byte arrays with length encoded as 8, 16, 24 bit
-     * integers in big-endian format.
-     */
-    void putBytes8(byte b[]) throws IOException {
-        if (b == null) {
-            putInt8(0);
-            return;
-        } else {
-            checkOverflow(b.length, Record.OVERFLOW_OF_INT08);
-        }
-        putInt8(b.length);
-        write(b, 0, b.length);
-    }
-
-    public void putBytes16(byte b[]) throws IOException {
-        if (b == null) {
-            putInt16(0);
-            return;
-        } else {
-            checkOverflow(b.length, Record.OVERFLOW_OF_INT16);
-        }
-        putInt16(b.length);
-        write(b, 0, b.length);
-    }
-
-    void putBytes24(byte b[]) throws IOException {
-        if (b == null) {
-            putInt24(0);
-            return;
-        } else {
-            checkOverflow(b.length, Record.OVERFLOW_OF_INT24);
-        }
-        putInt24(b.length);
-        write(b, 0, b.length);
-    }
-
-    private void checkOverflow(int length, int overflow) {
-        if (length >= overflow) {
-            // internal_error alert will be triggered
-            throw new RuntimeException(
-                    "Field length overflow, the field length (" +
-                    length + ") should be less than " + overflow);
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/HandshakeStateManager.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,765 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.HashMap;
-import javax.net.ssl.SSLProtocolException;
-
-import static sun.security.ssl.CipherSuite.KeyExchange;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-import static sun.security.ssl.HandshakeStateManager.HandshakeState.*;
-import static sun.security.ssl.HandshakeMessage.*;
-
-/*
- * Handshake state manager.
- *
- * Messages flow for a full handshake:
- *
- *      -                                                         -
- *      |          HelloRequest       (No.0, RFC 5246) [*]        |
- *      |     <--------------------------------------------       |
- *      |                                                         |
- *      |          ClientHello        (No.1, RFC 5246)            |
- *      |     -------------------------------------------->       |
- *      |                                                         |
- *   C  |          ServerHello        (No.2, RFC 5246)            |  S
- *   L  |          SupplementalData   (No.23, RFC4680) [*]        |  E
- *   I  |          Certificate        (No.11, RFC 5246) [*]       |  R
- *   E  |          CertificateStatus  (No.22, RFC 6066) [*]       |  V
- *   N  |          ServerKeyExchange  (No.12, RFC 5246) [*]       |  E
- *   T  |          CertificateRequest (No.13, RFC 5246) [*]       |  R
- *      |          ServerHelloDone    (No.14, RFC 5246)           |
- *      |     <--------------------------------------------       |
- *      |                                                         |
- *      |          SupplementalData   (No.23, RFC4680) [*]        |
- *      |          Certificate        (No.11, RFC 5246) [*] Or    |
- *      |              CertificateURL (No.21, RFC6066) [*]        |
- *      |          ClientKeyExchange  (No.16, RFC 5246)           |
- *      |          CertificateVerify  (No.15, RFC 5246) [*]       |
- *      |          [ChangeCipherSpec] (RFC 5246)                  |
- *      |          Finished           (No.20, RFC 5246)           |
- *      |     -------------------------------------------->       |
- *      |                                                         |
- *      |          NewSessionTicket   (No.4, RFC4507) [*]         |
- *      |          [ChangeCipherSpec] (RFC 5246)                  |
- *      |          Finished           (No.20, RFC 5246)           |
- *      |     <--------------------------------------------       |
- *      -                                                         -
- * [*] Indicates optional or situation-dependent messages that are not
- * always sent.
- *
- * Message flow for an abbreviated handshake:
- *      -                                                         -
- *      |          ClientHello        (No.1, RFC 5246)            |
- *      |     -------------------------------------------->       |
- *      |                                                         |
- *   C  |          ServerHello        (No.2, RFC 5246)            |  S
- *   L  |          NewSessionTicket   (No.4, RFC4507) [*]         |  E
- *   I  |          [ChangeCipherSpec] (RFC 5246)                  |  R
- *   E  |          Finished           (No.20, RFC 5246)           |  V
- *   N  |     <--------------------------------------------       |  E
- *   T  |                                                         |  R
- *      |          [ChangeCipherSpec] (RFC 5246)                  |
- *      |          Finished           (No.20, RFC 5246)           |
- *      |     -------------------------------------------->       |
- *      -                                                         -
- *
- *
- * State machine of handshake states:
- *
- *                   +--------------+
- *      START -----> | HelloRequest |
- *        |          +--------------+
- *        |               |
- *        v               v
- *     +---------------------+   -->  +---------------------+
- *     |    ClientHello      |        | HelloVerifyRequest  |
- *     +---------------------+   <--  +---------------------+
- *               |
- *               |
- * =========================================================================
- *               |
- *               v
- *     +---------------------+
- *     |    ServerHello      |  ----------------------------------+------+
- *     +---------------------+  -->  +-------------------------+  |      |
- *                    |              | Server SupplementalData |  |      |
- *                    |              +-------------------------+  |      |
- *                    |                |                          |      |
- *                    v                v                          |      |
- *                +---------------------+                         |      |
- *         +----  | Server Certificate  |                         |      |
- *         |      +---------------------+                         |      |
- *         |          |                                           |      |
- *         |          |   +--------------------+                  |      |
- *         |          +-> | CertificateStatus  |                  |      |
- *         |          |   +--------------------+                  v      |
- *         |          |      |          |     +--------------------+     |
- *         |          v      v          +-->  | ServerKeyExchange  |     |
- *         |  +---------------------+   |     +--------------------+     |
- *         |  | CertificateRequest  |   |         |                      |
- *         |  +---------------------+ <-+---------+                      |
- *         |            |               |         |                      |
- *         v            v               |         |                      |
- *     +---------------------+  <-------+         |                      |
- *     |  ServerHelloDone    |  <-----------------+                      |
- *     +---------------------+                                           |
- *       |         |                                                     |
- *       |         |                                                     |
- *       |         |                                                     |
- * =========================================================================
- *       |         |                                                     |
- *       |         v                                                     |
- *       |   +-------------------------+                                 |
- *       |   | Client SupplementalData | --------------+                 |
- *       |   +-------------------------+               |                 |
- *       |             |                               |                 |
- *       |             v                               |                 |
- *       |   +--------------------+                    |                 |
- *       +-> | Client Certificate | ALT.               |                 |
- *       |   +--------------------+----------------+   |                 |
- *       |                        | CertificateURL |   |                 |
- *       |                        +----------------+   |                 |
- *       v                                             |                 |
- *     +-------------------+  <------------------------+                 |
- *     | ClientKeyExchange |                                             |
- *     +-------------------+                                             |
- *          |           |                                                |
- *          |           v                                                |
- *          |      +-------------------+                                 |
- *          |      | CertificateVerify |                                 |
- *          |      +-------------------+                                 |
- *          |          |                                                 |
- *          v          v                                                 |
- *     +-------------------------+                                       |
- *     | Client ChangeCipherSpec |  <---------------+                    |
- *     +-------------------------+                  |                    |
- *               |                                  |                    |
- *               v                                  |                    |
- *     +-----------------+  (abbreviated)           |                    |
- *     | Client Finished |  -------------> END      |                    |
- *     +-----------------+  (Abbreviated handshake) |                    |
- *                      |                           |                    |
- *                      | (full)                    |                    |
- *                      |                           |                    |
- * ================================                 |                    |
- *                      |                           |                    |
- *                      |                   ================================
- *                      |                           |                    |
- *                      v                           |                    |
- *                 +------------------+             |    (abbreviated)   |
- *                 | NewSessionTicket | <--------------------------------+
- *                 +------------------+             |                    |
- *                      |                           |                    |
- *                      v                           |                    |
- *     +-------------------------+                  |    (abbreviated)   |
- *     | Server ChangeCipherSpec | <-------------------------------------+
- *     +-------------------------+                  |
- *               |                                  |
- *               v                                  |
- *     +-----------------+    (abbreviated)         |
- *     | Server Finished | -------------------------+
- *     +-----------------+
- *            | (full)
- *            v
- *        END (Full handshake)
- *
- *
- * The scenarios of the use of this class:
- * 1. Create an instance of HandshakeStateManager during the initializtion
- *    handshake.
- * 2. If receiving a handshake message, call HandshakeStateManager.check()
- *    to make sure that the message is of the expected handshake type.  And
- *    then call HandshakeStateManager.update() in case handshake states may
- *    be impacted by this new incoming handshake message.
- * 3. On delivering a handshake message, call HandshakeStateManager.update()
- *    in case handshake states may by thie new outgoing handshake message.
- * 4. On receiving and delivering ChangeCipherSpec message, call
- *    HandshakeStateManager.changeCipherSpec() to check the present sequence
- *    of this message, and update the states if necessary.
- */
-final class HandshakeStateManager {
-    // upcoming handshake states.
-    private LinkedList<HandshakeState> upcomingStates;
-    private LinkedList<HandshakeState> alternatives;
-
-    private static final boolean debugIsOn;
-
-    private static final HashMap<Byte, String> handshakeTypes;
-
-    static {
-        debugIsOn = (Handshaker.debug != null) &&
-                Debug.isOn("handshake") && Debug.isOn("verbose");
-        handshakeTypes = new HashMap<>(8);
-
-        handshakeTypes.put(ht_hello_request,            "hello_request");
-        handshakeTypes.put(ht_client_hello,             "client_hello");
-        handshakeTypes.put(ht_server_hello,             "server_hello");
-        handshakeTypes.put(ht_certificate,              "certificate");
-        handshakeTypes.put(ht_server_key_exchange,      "server_key_exchange");
-        handshakeTypes.put(ht_server_hello_done,        "server_hello_done");
-        handshakeTypes.put(ht_certificate_verify,       "certificate_verify");
-        handshakeTypes.put(ht_client_key_exchange,      "client_key_exchange");
-        handshakeTypes.put(ht_finished,                 "finished");
-    }
-
-    HandshakeStateManager() {
-        this.upcomingStates = new LinkedList<>();
-        this.alternatives = new LinkedList<>();
-    }
-
-    //
-    // enumation of handshake type
-    //
-    static enum HandshakeState {
-        HS_HELLO_REQUEST(
-                "hello_request",
-                HandshakeMessage.ht_hello_request),
-        HS_CLIENT_HELLO(
-                "client_hello",
-                HandshakeMessage.ht_client_hello),
-        HS_SERVER_HELLO(
-                "server_hello",
-                HandshakeMessage.ht_server_hello),
-        HS_SERVER_CERTIFICATE(
-                "server certificate",
-                HandshakeMessage.ht_certificate),
-        HS_SERVER_KEY_EXCHANGE(
-                "server_key_exchange",
-                HandshakeMessage.ht_server_key_exchange, true),
-        HS_CERTIFICATE_REQUEST(
-                "certificate_request",
-                HandshakeMessage.ht_certificate_request, true),
-        HS_SERVER_HELLO_DONE(
-                "server_hello_done",
-                HandshakeMessage.ht_server_hello_done),
-        HS_CLIENT_CERTIFICATE(
-                "client certificate",
-                HandshakeMessage.ht_certificate, true),
-        HS_CLIENT_KEY_EXCHANGE(
-                "client_key_exchange",
-                HandshakeMessage.ht_client_key_exchange),
-        HS_CERTIFICATE_VERIFY(
-                "certificate_verify",
-                HandshakeMessage.ht_certificate_verify, true),
-        HS_CLIENT_CHANGE_CIPHER_SPEC(
-                "client change_cipher_spec",
-                HandshakeMessage.ht_not_applicable),
-        HS_CLIENT_FINISHED(
-                "client finished",
-                HandshakeMessage.ht_finished),
-        HS_SERVER_CHANGE_CIPHER_SPEC(
-                "server change_cipher_spec",
-                HandshakeMessage.ht_not_applicable),
-        HS_SERVER_FINISHED(
-                "server finished",
-                HandshakeMessage.ht_finished);
-
-        final String description;
-        final byte handshakeType;
-        final boolean isOptional;
-
-        HandshakeState(String description, byte handshakeType) {
-            this.description = description;
-            this.handshakeType = handshakeType;
-            this.isOptional = false;
-        }
-
-        HandshakeState(String description,
-                byte handshakeType, boolean isOptional) {
-
-            this.description = description;
-            this.handshakeType = handshakeType;
-            this.isOptional = isOptional;
-        }
-
-        public String toString() {
-            return description + "[" + handshakeType + "]" +
-                    (isOptional ? "(optional)" : "");
-        }
-    }
-
-    boolean isEmpty() {
-        return upcomingStates.isEmpty();
-    }
-
-    List<Byte> check(byte handshakeType) throws SSLProtocolException {
-        List<Byte> ignoredOptional = new LinkedList<>();
-        String exceptionMsg =
-                 "Handshake message sequence violation, " + handshakeType;
-
-        if (debugIsOn) {
-            System.out.println(
-                    "check handshake state: " + toString(handshakeType));
-        }
-
-        if (upcomingStates.isEmpty()) {
-            // Is it a kickstart message?
-            if ((handshakeType != HandshakeMessage.ht_hello_request) &&
-                (handshakeType != HandshakeMessage.ht_client_hello)) {
-                throw new SSLProtocolException(
-                    "Handshake message sequence violation, " + handshakeType);
-            }
-
-            // It is a kickstart message.
-            return Collections.emptyList();
-        }
-
-        // Ignore the checking for HelloRequest messages as they
-        // may be sent by the server at any time.
-        if (handshakeType == HandshakeMessage.ht_hello_request) {
-            return Collections.emptyList();
-        }
-
-        for (HandshakeState handshakeState : upcomingStates) {
-            if (handshakeState.handshakeType == handshakeType) {
-                // It's the expected next handshake type.
-                return ignoredOptional;
-            }
-
-            if (handshakeState.isOptional) {
-                ignoredOptional.add(handshakeState.handshakeType);
-                continue;
-            } else {
-                for (HandshakeState alternative : alternatives) {
-                    if (alternative.handshakeType == handshakeType) {
-                        return ignoredOptional;
-                    }
-
-                    if (alternative.isOptional) {
-                        continue;
-                    } else {
-                        throw new SSLProtocolException(exceptionMsg);
-                    }
-                }
-            }
-            throw new SSLProtocolException(exceptionMsg);
-        }
-
-        // Not an expected Handshake message.
-        throw new SSLProtocolException(
-                "Handshake message sequence violation, " + handshakeType);
-    }
-
-    void update(HandshakeMessage handshakeMessage,
-            boolean isAbbreviated) throws SSLProtocolException {
-
-        byte handshakeType = (byte)handshakeMessage.messageType();
-        String exceptionMsg =
-                 "Handshake message sequence violation, " + handshakeType;
-
-        if (debugIsOn) {
-            System.out.println(
-                    "update handshake state: " + toString(handshakeType));
-        }
-
-        boolean hasPresentState = false;
-        switch (handshakeType) {
-        case HandshakeMessage.ht_hello_request:
-            //
-            // State machine:
-            //     PRESENT: START
-            //        TO  : ClientHello
-            //
-
-            // No old state to update.
-
-            // Add the upcoming states.
-            if (!upcomingStates.isEmpty()) {
-                // A ClientHello message should be followed.
-                upcomingStates.add(HS_CLIENT_HELLO);
-
-            }   // Otherwise, ignore this HelloRequest message.
-
-            break;
-
-        case HandshakeMessage.ht_client_hello:
-            //
-            // State machine:
-            //     PRESENT: START
-            //              HS_CLIENT_HELLO
-            //        TO  : HS_SERVER_HELLO
-            //
-
-            // Check and update the present state.
-            if (!upcomingStates.isEmpty()) {
-                // The current state should be HS_CLIENT_HELLO.
-                HandshakeState handshakeState = upcomingStates.pop();
-                if (handshakeState != HS_CLIENT_HELLO) {
-                    throw new SSLProtocolException(exceptionMsg);
-                }
-            }
-
-            // Add the upcoming states.
-            ClientHello clientHello = (ClientHello)handshakeMessage;
-            upcomingStates.add(HS_SERVER_HELLO);
-
-            break;
-
-        case HandshakeMessage.ht_server_hello:
-            //
-            // State machine:
-            //     PRESENT: HS_SERVER_HELLO
-            //        TO  :
-            //          Full handshake state stacks
-            //              (ServerHello Flight)
-            //              HS_SERVER_SUPPLEMENTAL_DATA [optional]
-            //          --> HS_SERVER_CERTIFICATE [optional]
-            //          --> HS_CERTIFICATE_STATUS [optional]
-            //          --> HS_SERVER_KEY_EXCHANGE [optional]
-            //          --> HS_CERTIFICATE_REQUEST [optional]
-            //          --> HS_SERVER_HELLO_DONE
-            //              (Client ClientKeyExchange Flight)
-            //          --> HS_CLIENT_SUPPLEMENTAL_DATA [optional]
-            //          --> HS_CLIENT_CERTIFICATE or
-            //              HS_CERTIFICATE_URL
-            //          --> HS_CLIENT_KEY_EXCHANGE
-            //          --> HS_CERTIFICATE_VERIFY [optional]
-            //          --> HS_CLIENT_CHANGE_CIPHER_SPEC
-            //          --> HS_CLIENT_FINISHED
-            //              (Server Finished Flight)
-            //          --> HS_CLIENT_SUPPLEMENTAL_DATA [optional]
-            //
-            //          Abbreviated handshake state stacks
-            //              (Server Finished Flight)
-            //              HS_NEW_SESSION_TICKET
-            //          --> HS_SERVER_CHANGE_CIPHER_SPEC
-            //          --> HS_SERVER_FINISHED
-            //              (Client Finished Flight)
-            //          --> HS_CLIENT_CHANGE_CIPHER_SPEC
-            //          --> HS_CLIENT_FINISHED
-            //
-            // Note that this state may have an alternative option.
-
-            // Check and update the present state.
-            if (!upcomingStates.isEmpty()) {
-                // The current state should be HS_SERVER_HELLO
-                HandshakeState handshakeState = upcomingStates.pop();
-                HandshakeState alternative = null;
-                if (!alternatives.isEmpty()) {
-                    alternative = alternatives.pop();
-                }
-
-                if ((handshakeState != HS_SERVER_HELLO) &&
-                        (alternative != HS_SERVER_HELLO)) {
-                    throw new SSLProtocolException(exceptionMsg);
-                }
-            } else {
-                // No present state.
-                throw new SSLProtocolException(exceptionMsg);
-            }
-
-            // Add the upcoming states.
-            ServerHello serverHello = (ServerHello)handshakeMessage;
-            HelloExtensions hes = serverHello.extensions;
-
-
-            // Not support SessionTicket extension yet.
-            //
-            // boolean hasSessionTicketExt =
-            //     (hes.get(HandshakeMessage.ht_new_session_ticket) != null);
-
-            if (isAbbreviated) {
-                // Not support SessionTicket extension yet.
-                //
-                // // Mandatory NewSessionTicket message
-                // if (hasSessionTicketExt) {
-                //     upcomingStates.add(HS_NEW_SESSION_TICKET);
-                // }
-
-                // Mandatory server ChangeCipherSpec and Finished messages
-                upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
-                upcomingStates.add(HS_SERVER_FINISHED);
-
-                // Mandatory client ChangeCipherSpec and Finished messages
-                upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
-                upcomingStates.add(HS_CLIENT_FINISHED);
-            } else {
-                // Not support SupplementalData extension yet.
-                //
-                // boolean hasSupplementalDataExt =
-                //     (hes.get(HandshakeMessage.ht_supplemental_data) != null);
-
-                // Not support CertificateURL extension yet.
-                //
-                // boolean hasCertificateUrlExt =
-                //     (hes.get(ExtensionType EXT_CLIENT_CERTIFICATE_URL)
-                //          != null);
-
-                // Not support SupplementalData extension yet.
-                //
-                // // Optional SupplementalData message
-                // if (hasSupplementalDataExt) {
-                //     upcomingStates.add(HS_SERVER_SUPPLEMENTAL_DATA);
-                // }
-
-                // Need server Certificate message or not?
-                KeyExchange keyExchange = serverHello.cipherSuite.keyExchange;
-                if ((keyExchange != K_KRB5) &&
-                        (keyExchange != K_KRB5_EXPORT) &&
-                        (keyExchange != K_DH_ANON) &&
-                        (keyExchange != K_ECDH_ANON)) {
-                    // Mandatory Certificate message
-                    upcomingStates.add(HS_SERVER_CERTIFICATE);
-                }
-
-                // Need ServerKeyExchange message or not?
-                if ((keyExchange == K_RSA_EXPORT) ||
-                        (keyExchange == K_DHE_RSA) ||
-                        (keyExchange == K_DHE_DSS) ||
-                        (keyExchange == K_DH_ANON) ||
-                        (keyExchange == K_ECDHE_RSA) ||
-                        (keyExchange == K_ECDHE_ECDSA) ||
-                        (keyExchange == K_ECDH_ANON)) {
-                    // Optional ServerKeyExchange message
-                    upcomingStates.add(HS_SERVER_KEY_EXCHANGE);
-                }
-
-                // Optional CertificateRequest message
-                upcomingStates.add(HS_CERTIFICATE_REQUEST);
-
-                // Mandatory ServerHelloDone message
-                upcomingStates.add(HS_SERVER_HELLO_DONE);
-
-                // Not support SupplementalData extension yet.
-                //
-                // // Optional SupplementalData message
-                // if (hasSupplementalDataExt) {
-                //     upcomingStates.add(HS_CLIENT_SUPPLEMENTAL_DATA);
-                // }
-
-                // Optional client Certificate message
-                upcomingStates.add(HS_CLIENT_CERTIFICATE);
-
-                // Not support CertificateURL extension yet.
-                //
-                // // Alternative CertificateURL message, optional too.
-                // //
-                // // Please put CertificateURL rather than Certificate
-                // // message in the alternatives list.  So that we can
-                // // simplify the process of this alternative pair later.
-                // if (hasCertificateUrlExt) {
-                //     alternatives.add(HS_CERTIFICATE_URL);
-                // }
-
-                // Mandatory ClientKeyExchange message
-                upcomingStates.add(HS_CLIENT_KEY_EXCHANGE);
-
-                // Optional CertificateVerify message
-                upcomingStates.add(HS_CERTIFICATE_VERIFY);
-
-                // Mandatory client ChangeCipherSpec and Finished messages
-                upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
-                upcomingStates.add(HS_CLIENT_FINISHED);
-
-                // Not support SessionTicket extension yet.
-                //
-                // // Mandatory NewSessionTicket message
-                // if (hasSessionTicketExt) {
-                //     upcomingStates.add(HS_NEW_SESSION_TICKET);
-                // }
-
-                // Mandatory server ChangeCipherSpec and Finished messages
-                upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
-                upcomingStates.add(HS_SERVER_FINISHED);
-            }
-
-            break;
-
-        case HandshakeMessage.ht_certificate:
-            //
-            // State machine:
-            //     PRESENT: HS_CERTIFICATE_URL or
-            //              HS_CLIENT_CERTIFICATE
-            //        TO  : HS_CLIENT_KEY_EXCHANGE
-            //
-            //     Or
-            //
-            //     PRESENT: HS_SERVER_CERTIFICATE
-            //        TO  : HS_CERTIFICATE_STATUS [optional]
-            //              HS_SERVER_KEY_EXCHANGE [optional]
-            //              HS_CERTIFICATE_REQUEST [optional]
-            //              HS_SERVER_HELLO_DONE
-            //
-            // Note that this state may have an alternative option.
-
-            // Check and update the present state.
-            while (!upcomingStates.isEmpty()) {
-                HandshakeState handshakeState = upcomingStates.pop();
-                if (handshakeState.handshakeType == handshakeType) {
-                    hasPresentState = true;
-
-                    // The current state should be HS_CLIENT_CERTIFICATE or
-                    // HS_SERVER_CERTIFICATE.
-                    //
-                    // Note that we won't put HS_CLIENT_CERTIFICATE into
-                    // the alternative list.
-                    if ((handshakeState != HS_CLIENT_CERTIFICATE) &&
-                            (handshakeState != HS_SERVER_CERTIFICATE)) {
-                        throw new SSLProtocolException(exceptionMsg);
-                    }
-
-                    // Is it an expected client Certificate message?
-                    boolean isClientMessage = false;
-                    if (!upcomingStates.isEmpty()) {
-                        // If the next expected message is ClientKeyExchange,
-                        // this one should be an expected client Certificate
-                        // message.
-                        HandshakeState nextState = upcomingStates.getFirst();
-                        if (nextState == HS_CLIENT_KEY_EXCHANGE) {
-                            isClientMessage = true;
-                        }
-                    }
-
-                    if (isClientMessage) {
-                        if (handshakeState != HS_CLIENT_CERTIFICATE) {
-                            throw new SSLProtocolException(exceptionMsg);
-                        }
-
-                        // Not support CertificateURL extension yet.
-                        /*******************************************
-                        // clear up the alternatives list
-                        if (!alternatives.isEmpty()) {
-                            HandshakeState alternative = alternatives.pop();
-
-                            if (alternative != HS_CERTIFICATE_URL) {
-                                throw new SSLProtocolException(exceptionMsg);
-                            }
-                        }
-                        ********************************************/
-                    } else {
-                        if ((handshakeState != HS_SERVER_CERTIFICATE)) {
-                            throw new SSLProtocolException(exceptionMsg);
-                        }
-                    }
-
-                    break;
-                } else if (!handshakeState.isOptional) {
-                    throw new SSLProtocolException(exceptionMsg);
-                }   // Otherwise, looking for next state track.
-            }
-
-            // No present state.
-            if (!hasPresentState) {
-                throw new SSLProtocolException(exceptionMsg);
-            }
-
-            // no new upcoming states.
-
-            break;
-
-        default:
-            // Check and update the present state.
-            while (!upcomingStates.isEmpty()) {
-                HandshakeState handshakeState = upcomingStates.pop();
-                if (handshakeState.handshakeType == handshakeType) {
-                    hasPresentState = true;
-                    break;
-                } else if (!handshakeState.isOptional) {
-                    throw new SSLProtocolException(exceptionMsg);
-                }   // Otherwise, looking for next state track.
-            }
-
-            // No present state.
-            if (!hasPresentState) {
-                throw new SSLProtocolException(exceptionMsg);
-            }
-
-            // no new upcoming states.
-        }
-
-        if (debugIsOn) {
-            for (HandshakeState handshakeState : upcomingStates) {
-                System.out.println(
-                    "upcoming handshake states: " + handshakeState);
-            }
-            for (HandshakeState handshakeState : alternatives) {
-                System.out.println(
-                    "upcoming handshake alternative state: " + handshakeState);
-            }
-        }
-    }
-
-    void changeCipherSpec(boolean isInput,
-            boolean isClient) throws SSLProtocolException {
-
-        if (debugIsOn) {
-            System.out.println(
-                    "update handshake state: change_cipher_spec");
-        }
-
-        String exceptionMsg = "ChangeCipherSpec message sequence violation";
-
-        HandshakeState expectedState;
-        if ((isClient && isInput) || (!isClient && !isInput)) {
-            expectedState = HS_SERVER_CHANGE_CIPHER_SPEC;
-        } else {
-            expectedState = HS_CLIENT_CHANGE_CIPHER_SPEC;
-        }
-
-        boolean hasPresentState = false;
-
-        // Check and update the present state.
-        while (!upcomingStates.isEmpty()) {
-            HandshakeState handshakeState = upcomingStates.pop();
-            if (handshakeState == expectedState) {
-                hasPresentState = true;
-                break;
-            } else if (!handshakeState.isOptional) {
-                throw new SSLProtocolException(exceptionMsg);
-            }   // Otherwise, looking for next state track.
-        }
-
-        // No present state.
-        if (!hasPresentState) {
-            throw new SSLProtocolException(exceptionMsg);
-        }
-
-        // no new upcoming states.
-
-        if (debugIsOn) {
-            for (HandshakeState handshakeState : upcomingStates) {
-                System.out.println(
-                    "upcoming handshake states: " + handshakeState);
-            }
-            for (HandshakeState handshakeState : alternatives) {
-                System.out.println(
-                    "upcoming handshake alternative state: " + handshakeState);
-            }
-        }
-    }
-
-    private static String toString(byte handshakeType) {
-        String s = handshakeTypes.get(handshakeType);
-        if (s == null) {
-            s = "unknown";
-        }
-        return (s + "[" + handshakeType + "]");
-    }
-}
--- a/src/share/classes/sun/security/ssl/Handshaker.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1587 +0,0 @@
-/*
- * Copyright (c) 1996, 2020, 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.*;
-import java.util.*;
-import java.util.function.BiFunction;
-import java.security.*;
-
-import javax.crypto.*;
-import javax.crypto.spec.*;
-
-import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
-
-import sun.security.internal.spec.*;
-import sun.security.internal.interfaces.TlsMasterSecret;
-
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-
-import static sun.security.ssl.CipherSuite.PRF.*;
-import static sun.security.ssl.CipherSuite.CipherType.*;
-
-/**
- * Handshaker ... processes handshake records from an SSL V3.0
- * data stream, handling all the details of the handshake protocol.
- *
- * Note that the real protocol work is done in two subclasses, the  base
- * class just provides the control flow and key generation framework.
- *
- * @author David Brownell
- */
-abstract class Handshaker {
-
-    // protocol version being established using this Handshaker
-    ProtocolVersion protocolVersion;
-
-    // the currently active protocol version during a renegotiation
-    ProtocolVersion activeProtocolVersion;
-
-    // security parameters for secure renegotiation.
-    boolean secureRenegotiation;
-    byte[] clientVerifyData;
-    byte[] serverVerifyData;
-
-    // Is it an initial negotiation  or a renegotiation?
-    boolean isInitialHandshake;
-
-    // List of enabled protocols
-    private ProtocolList enabledProtocols;
-
-    // List of enabled CipherSuites
-    private CipherSuiteList enabledCipherSuites;
-
-    // The endpoint identification protocol
-    String identificationProtocol;
-
-    // The cryptographic algorithm constraints
-    AlgorithmConstraints algorithmConstraints = null;
-
-    // Local supported signature and algorithms
-    private Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs;
-
-    // Peer supported signature and algorithms
-    Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs;
-
-    /*
-     * List of active protocols
-     *
-     * Active protocols is a subset of enabled protocols, and will
-     * contain only those protocols that have vaild cipher suites
-     * enabled.
-     */
-    private ProtocolList activeProtocols;
-
-    /*
-     * List of active cipher suites
-     *
-     * Active cipher suites is a subset of enabled cipher suites, and will
-     * contain only those cipher suites available for the active protocols.
-     */
-    private CipherSuiteList activeCipherSuites;
-
-    // The server name indication and matchers
-    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;
-
-    SSLSocketImpl conn = null;
-    SSLEngineImpl engine = null;
-
-    HandshakeHash handshakeHash;
-    HandshakeInStream input;
-    HandshakeOutStream output;
-    SSLContextImpl sslContext;
-    RandomCookie clnt_random, svr_random;
-    SSLSessionImpl session;
-    HandshakeStateManager handshakeState;
-    boolean clientHelloDelivered;
-    boolean serverHelloRequested;
-    boolean handshakeActivated;
-    boolean handshakeFinished;
-
-    // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
-    CipherSuite cipherSuite;
-
-    // current key exchange. Never null, initially K_NULL
-    KeyExchange keyExchange;
-
-    // True if this session is being resumed (fast handshake)
-    boolean resumingSession;
-
-    // True if it's OK to start a new SSL session
-    boolean enableNewSession;
-
-    // Whether local cipher suites preference should be honored during
-    // handshaking?
-    //
-    // Note that in this provider, this option only applies to server side.
-    // Local cipher suites preference is always honored in client side in
-    // this provider.
-    boolean preferLocalCipherSuites = false;
-
-    // Temporary storage for the individual keys. Set by
-    // calculateConnectionKeys() and cleared once the ciphers are
-    // activated.
-    private SecretKey clntWriteKey, svrWriteKey;
-    private IvParameterSpec clntWriteIV, svrWriteIV;
-    private SecretKey clntMacSecret, svrMacSecret;
-
-    /*
-     * Delegated task subsystem data structures.
-     *
-     * If thrown is set, we need to propagate this back immediately
-     * on entry into processMessage().
-     *
-     * Data is protected by the SSLEngine.this lock.
-     */
-    private volatile boolean taskDelegated = false;
-    private volatile DelegatedTask<?> delegatedTask = null;
-    private volatile Exception thrown = null;
-
-    // Could probably use a java.util.concurrent.atomic.AtomicReference
-    // here instead of using this lock.  Consider changing.
-    private Object thrownLock = new Object();
-
-    // Class and subclass dynamic debugging support
-    static final Debug debug = Debug.getInstance("ssl");
-
-    // By default, disable the unsafe legacy session renegotiation
-    static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty(
-                    "sun.security.ssl.allowUnsafeRenegotiation", false);
-
-    // For maximum interoperability and backward compatibility, RFC 5746
-    // allows server (or client) to accept ClientHello (or ServerHello)
-    // message without the secure renegotiation_info extension or SCSV.
-    //
-    // For maximum security, RFC 5746 also allows server (or client) to
-    // reject such message with a fatal "handshake_failure" alert.
-    //
-    // By default, allow such legacy hello messages.
-    static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty(
-                    "sun.security.ssl.allowLegacyHelloMessages", true);
-
-    // To prevent the TLS renegotiation issues, by setting system property
-    // "jdk.tls.rejectClientInitiatedRenegotiation" to true, applications in
-    // server side can disable all client initiated SSL renegotiations
-    // regardless of the support of TLS protocols.
-    //
-    // By default, allow client initiated renegotiations.
-    static final boolean rejectClientInitiatedRenego =
-            Debug.getBooleanProperty(
-                "jdk.tls.rejectClientInitiatedRenegotiation", false);
-
-    // To switch off the extended_master_secret extension.
-    static final boolean useExtendedMasterSecret;
-
-    // Allow session resumption without Extended Master Secret extension.
-    static final boolean allowLegacyResumption =
-            Debug.getBooleanProperty("jdk.tls.allowLegacyResumption", true);
-
-    // Allow full handshake without Extended Master Secret extension.
-    static final boolean allowLegacyMasterSecret =
-            Debug.getBooleanProperty("jdk.tls.allowLegacyMasterSecret", true);
-
-    // Is it requested to use extended master secret extension?
-    boolean requestedToUseEMS = false;
-
-    // need to dispose the object when it is invalidated
-    boolean invalidated;
-
-    // Is the extended_master_secret extension supported?
-    static {
-        boolean supportExtendedMasterSecret = true;
-        try {
-            KeyGenerator kg =
-                JsseJce.getKeyGenerator("SunTlsExtendedMasterSecret");
-        } catch (NoSuchAlgorithmException nae) {
-            supportExtendedMasterSecret = false;
-        }
-
-        if (supportExtendedMasterSecret) {
-            useExtendedMasterSecret = Debug.getBooleanProperty(
-                    "jdk.tls.useExtendedMasterSecret", true);
-        } else {
-            useExtendedMasterSecret = false;
-        }
-    }
-
-    Handshaker(SSLSocketImpl c, SSLContextImpl context,
-            ProtocolList enabledProtocols, boolean needCertVerify,
-            boolean isClient, ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-        this.conn = c;
-        init(context, enabledProtocols, needCertVerify, isClient,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-   }
-
-    Handshaker(SSLEngineImpl engine, SSLContextImpl context,
-            ProtocolList enabledProtocols, boolean needCertVerify,
-            boolean isClient, ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-        this.engine = engine;
-        init(context, enabledProtocols, needCertVerify, isClient,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-    }
-
-    private void init(SSLContextImpl context, ProtocolList enabledProtocols,
-            boolean needCertVerify, boolean isClient,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println(
-                "Allow unsafe renegotiation: " + allowUnsafeRenegotiation +
-                "\nAllow legacy hello messages: " + allowLegacyHelloMessages +
-                "\nIs initial handshake: " + isInitialHandshake +
-                "\nIs secure renegotiation: " + secureRenegotiation);
-        }
-
-        this.sslContext = context;
-        this.isClient = isClient;
-        this.needCertVerify = needCertVerify;
-        this.activeProtocolVersion = activeProtocolVersion;
-        this.isInitialHandshake = isInitialHandshake;
-        this.secureRenegotiation = secureRenegotiation;
-        this.clientVerifyData = clientVerifyData;
-        this.serverVerifyData = serverVerifyData;
-        this.enableNewSession = true;
-        this.invalidated = false;
-        this.handshakeState = new HandshakeStateManager();
-        this.clientHelloDelivered = false;
-        this.serverHelloRequested = false;
-        this.handshakeActivated = false;
-        this.handshakeFinished = false;
-
-        setCipherSuite(CipherSuite.C_NULL);
-        setEnabledProtocols(enabledProtocols);
-
-        if (conn != null) {
-            algorithmConstraints = new SSLAlgorithmConstraints(conn, true);
-        } else {        // engine != null
-            algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
-        }
-    }
-
-    /*
-     * Reroutes calls to the SSLSocket or SSLEngine (*SE).
-     *
-     * We could have also done it by extra classes
-     * and letting them override, but this seemed much
-     * less involved.
-     */
-    void fatalSE(byte b, String diagnostic) throws IOException {
-        fatalSE(b, diagnostic, null);
-    }
-
-    void fatalSE(byte b, Throwable cause) throws IOException {
-        fatalSE(b, null, cause);
-    }
-
-    void fatalSE(byte b, String diagnostic, Throwable cause)
-            throws IOException {
-        if (conn != null) {
-            conn.fatal(b, diagnostic, cause);
-        } else {
-            engine.fatal(b, diagnostic, cause);
-        }
-    }
-
-    void warningSE(byte b) {
-        if (conn != null) {
-            conn.warning(b);
-        } else {
-            engine.warning(b);
-        }
-    }
-
-    // ONLY used by ClientHandshaker to setup the peer host in SSLSession.
-    String getHostSE() {
-        if (conn != null) {
-            return conn.getHost();
-        } else {
-            return engine.getPeerHost();
-        }
-    }
-
-    // ONLY used by ServerHandshaker to setup the peer host in SSLSession.
-    String getHostAddressSE() {
-        if (conn != null) {
-            return conn.getInetAddress().getHostAddress();
-        } else {
-            /*
-             * This is for caching only, doesn't matter that's is really
-             * a hostname.  The main thing is that it doesn't do
-             * a reverse DNS lookup, potentially slowing things down.
-             */
-            return engine.getPeerHost();
-        }
-    }
-
-    int getPortSE() {
-        if (conn != null) {
-            return conn.getPort();
-        } else {
-            return engine.getPeerPort();
-        }
-    }
-
-    int getLocalPortSE() {
-        if (conn != null) {
-            return conn.getLocalPort();
-        } else {
-            return -1;
-        }
-    }
-
-    AccessControlContext getAccSE() {
-        if (conn != null) {
-            return conn.getAcc();
-        } else {
-            return engine.getAcc();
-        }
-    }
-
-    String getEndpointIdentificationAlgorithmSE() {
-        SSLParameters paras;
-        if (conn != null) {
-            paras = conn.getSSLParameters();
-        } else {
-            paras = engine.getSSLParameters();
-        }
-
-        return paras.getEndpointIdentificationAlgorithm();
-    }
-
-    private void setVersionSE(ProtocolVersion protocolVersion) {
-        if (conn != null) {
-            conn.setVersion(protocolVersion);
-        } else {
-            engine.setVersion(protocolVersion);
-        }
-    }
-
-    /**
-     * Set the active protocol version and propagate it to the SSLSocket
-     * and our handshake streams. Called from ClientHandshaker
-     * and ServerHandshaker with the negotiated protocol version.
-     */
-    void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        setVersionSE(protocolVersion);
-
-        output.r.setVersion(protocolVersion);
-    }
-
-    /**
-     * Set the enabled protocols. Called from the constructor or
-     * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
-     * handshake is not yet in progress).
-     */
-    void setEnabledProtocols(ProtocolList enabledProtocols) {
-        activeCipherSuites = null;
-        activeProtocols = null;
-
-        this.enabledProtocols = enabledProtocols;
-    }
-
-    /**
-     * Set the enabled cipher suites. Called from
-     * SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the
-     * handshake is not yet in progress).
-     */
-    void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) {
-        activeCipherSuites = null;
-        activeProtocols = null;
-        this.enabledCipherSuites = enabledCipherSuites;
-    }
-
-    /**
-     * Set the algorithm constraints. Called from the constructor or
-     * SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the
-     * handshake is not yet in progress).
-     */
-    void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
-        activeCipherSuites = null;
-        activeProtocols = null;
-
-        this.algorithmConstraints =
-            new SSLAlgorithmConstraints(algorithmConstraints);
-        this.localSupportedSignAlgs = null;
-    }
-
-    Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() {
-        if (localSupportedSignAlgs == null) {
-            localSupportedSignAlgs =
-                SignatureAndHashAlgorithm.getSupportedAlgorithms(
-                                                    algorithmConstraints);
-        }
-
-        return localSupportedSignAlgs;
-    }
-
-    void setPeerSupportedSignAlgs(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        peerSupportedSignAlgs =
-            new ArrayList<SignatureAndHashAlgorithm>(algorithms);
-    }
-
-    Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() {
-        return peerSupportedSignAlgs;
-    }
-
-
-    /**
-     * Set the identification protocol. Called from the constructor or
-     * SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the
-     * handshake is not yet in progress).
-     */
-    void setIdentificationProtocol(String protocol) {
-        this.identificationProtocol = protocol;
-    }
-
-    /**
-     * Sets the server name indication of the handshake.
-     */
-    void setSNIServerNames(List<SNIServerName> serverNames) {
-        // The serverNames parameter is unmodifiable.
-        this.serverNames = serverNames;
-    }
-
-    /**
-     * Sets the server name matchers of the handshaking.
-     */
-    void setSNIMatchers(Collection<SNIMatcher> sniMatchers) {
-        // The sniMatchers parameter is unmodifiable.
-        this.sniMatchers = sniMatchers;
-    }
-
-    /**
-     * 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) {
-        this.preferLocalCipherSuites = on;
-    }
-
-    /**
-     * Prior to handshaking, activate the handshake and initialize the version,
-     * input stream and output stream.
-     */
-    void activate(ProtocolVersion helloVersion) throws IOException {
-        if (activeProtocols == null) {
-            activeProtocols = getActiveProtocols();
-        }
-
-        if (activeProtocols.collection().isEmpty() ||
-                activeProtocols.max.v == ProtocolVersion.NONE.v) {
-            throw new SSLHandshakeException(
-                    "No appropriate protocol (protocol is disabled or " +
-                    "cipher suites are inappropriate)");
-        }
-
-        if (activeCipherSuites == null) {
-            activeCipherSuites = getActiveCipherSuites();
-        }
-
-        if (activeCipherSuites.collection().isEmpty()) {
-            throw new SSLHandshakeException("No appropriate cipher suite");
-        }
-
-        // temporary protocol version until the actual protocol version
-        // is negotiated in the Hello exchange. This affects the record
-        // version we sent with the ClientHello.
-        if (!isInitialHandshake) {
-            protocolVersion = activeProtocolVersion;
-        } else {
-            protocolVersion = activeProtocols.max;
-        }
-
-        if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) {
-            helloVersion = activeProtocols.helloVersion;
-        }
-
-        // We accumulate digests of the handshake messages so that
-        // we can read/write CertificateVerify and Finished messages,
-        // getting assurance against some particular active attacks.
-        handshakeHash = new HandshakeHash(needCertVerify);
-
-        // Generate handshake input/output stream.
-        input = new HandshakeInStream(handshakeHash);
-        if (conn != null) {
-            output = new HandshakeOutStream(protocolVersion, helloVersion,
-                                        handshakeHash, conn);
-            conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
-            conn.getAppInputStream().r.setHelloVersion(helloVersion);
-            conn.getAppOutputStream().r.setHelloVersion(helloVersion);
-        } else {
-            output = new HandshakeOutStream(protocolVersion, helloVersion,
-                                        handshakeHash, engine);
-            engine.inputRecord.setHandshakeHash(handshakeHash);
-            engine.inputRecord.setHelloVersion(helloVersion);
-            engine.outputRecord.setHelloVersion(helloVersion);
-        }
-
-        handshakeActivated = true;
-    }
-
-    /**
-     * Set cipherSuite and keyExchange to the given CipherSuite.
-     * Does not perform any verification that this is a valid selection,
-     * this must be done before calling this method.
-     */
-    void setCipherSuite(CipherSuite s) {
-        this.cipherSuite = s;
-        this.keyExchange = s.keyExchange;
-    }
-
-    /**
-     * Check if the given ciphersuite is enabled and available within the
-     * current active cipher suites.
-     *
-     * Does not check if the required server certificates are available.
-     */
-    boolean isNegotiable(CipherSuite s) {
-        if (activeCipherSuites == null) {
-            activeCipherSuites = getActiveCipherSuites();
-        }
-
-        return isNegotiable(activeCipherSuites, s);
-    }
-
-    /**
-     * Check if the given ciphersuite is enabled and available within the
-     * proposed cipher suite list.
-     *
-     * Does not check if the required server certificates are available.
-     */
-    final static boolean isNegotiable(CipherSuiteList proposed, CipherSuite s) {
-        return proposed.contains(s) && s.isNegotiable();
-    }
-
-    /**
-     * Check if the given protocol version is enabled and available.
-     */
-    boolean isNegotiable(ProtocolVersion protocolVersion) {
-        if (activeProtocols == null) {
-            activeProtocols = getActiveProtocols();
-        }
-
-        return activeProtocols.contains(protocolVersion);
-    }
-
-    /**
-     * Select a protocol version from the list. Called from
-     * ServerHandshaker to negotiate protocol version.
-     *
-     * Return the lower of the protocol version suggested in the
-     * clien hello and the highest supported by the server.
-     */
-    ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
-        if (activeProtocols == null) {
-            activeProtocols = getActiveProtocols();
-        }
-
-        return activeProtocols.selectProtocolVersion(protocolVersion);
-    }
-
-    /**
-     * Get the active cipher suites.
-     *
-     * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
-     * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
-     * negotiate these cipher suites in TLS 1.1 or later mode.
-     *
-     * Therefore, when the active protocols only include TLS 1.1 or later,
-     * the client cannot request to negotiate those obsoleted cipher
-     * suites.  That is, the obsoleted suites should not be included in the
-     * client hello. So we need to create a subset of the enabled cipher
-     * suites, the active cipher suites, which does not contain obsoleted
-     * cipher suites of the minimum active protocol.
-     *
-     * Return empty list instead of null if no active cipher suites.
-     */
-    CipherSuiteList getActiveCipherSuites() {
-        if (activeCipherSuites == null) {
-            if (activeProtocols == null) {
-                activeProtocols = getActiveProtocols();
-            }
-
-            ArrayList<CipherSuite> suites = new ArrayList<>();
-            if (!(activeProtocols.collection().isEmpty()) &&
-                    activeProtocols.min.v != ProtocolVersion.NONE.v) {
-                boolean checkedCurves = false;
-                boolean hasCurves = false;
-                for (CipherSuite suite : enabledCipherSuites.collection()) {
-                    if (suite.obsoleted > activeProtocols.min.v &&
-                            suite.supported <= activeProtocols.max.v) {
-                        if (algorithmConstraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                suite.name, null)) {
-                            boolean available = true;
-                            if (suite.keyExchange.isEC) {
-                                if (!checkedCurves) {
-                                    hasCurves = EllipticCurvesExtension
-                                        .hasActiveCurves(algorithmConstraints);
-                                    checkedCurves = true;
-
-                                    if (!hasCurves && debug != null &&
-                                                Debug.isOn("verbose")) {
-                                        System.out.println(
-                                           "No available elliptic curves");
-                                    }
-                                }
-
-                                available = hasCurves;
-
-                               if (!available && debug != null &&
-                                        Debug.isOn("verbose")) {
-                                    System.out.println(
-                                        "No active elliptic curves, ignore " +
-                                       suite);
-                                }
-                            }
-
-                            if (available) {
-                                suites.add(suite);
-                            }
-                        }
-                    } else if (debug != null && Debug.isOn("verbose")) {
-                        if (suite.obsoleted <= activeProtocols.min.v) {
-                            System.out.println(
-                                "Ignoring obsoleted cipher suite: " + suite);
-                        } else {
-                            System.out.println(
-                                "Ignoring unsupported cipher suite: " + suite);
-                        }
-                    }
-                }
-            }
-            activeCipherSuites = new CipherSuiteList(suites);
-        }
-
-        return activeCipherSuites;
-    }
-
-    /*
-     * Get the active protocol versions.
-     *
-     * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
-     * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
-     * negotiate these cipher suites in TLS 1.1 or later mode.
-     *
-     * For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the
-     * only enabled cipher suite, the client cannot request TLS 1.1 or
-     * later, even though TLS 1.1 or later is enabled.  We need to create a
-     * subset of the enabled protocols, called the active protocols, which
-     * contains protocols appropriate to the list of enabled Ciphersuites.
-     *
-     * Return empty list instead of null if no active protocol versions.
-     */
-    ProtocolList getActiveProtocols() {
-        if (activeProtocols == null) {
-            boolean enabledSSL20Hello = false;
-            boolean checkedCurves = false;
-            boolean hasCurves = false;
-            ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
-            for (ProtocolVersion protocol : enabledProtocols.collection()) {
-                // Need not to check the SSL20Hello protocol.
-                if (protocol.v == ProtocolVersion.SSL20Hello.v) {
-                    enabledSSL20Hello = true;
-                    continue;
-                }
-
-                if (!algorithmConstraints.permits(
-                        EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                        protocol.name, null)) {
-                    if (debug != null && Debug.isOn("verbose")) {
-                        System.out.println(
-                            "Ignoring disabled protocol: " + protocol);
-                    }
-
-                    continue;
-                }
-                boolean found = false;
-                for (CipherSuite suite : enabledCipherSuites.collection()) {
-                    if (suite.isAvailable() && suite.obsoleted > protocol.v &&
-                                               suite.supported <= protocol.v) {
-                        if (algorithmConstraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                suite.name, null)) {
-
-                            boolean available = true;
-                            if (suite.keyExchange.isEC) {
-                                if (!checkedCurves) {
-                                    hasCurves = EllipticCurvesExtension
-                                        .hasActiveCurves(algorithmConstraints);
-                                    checkedCurves = true;
-
-                                    if (!hasCurves && debug != null &&
-                                                Debug.isOn("verbose")) {
-                                        System.out.println(
-                                            "No activated elliptic curves");
-                                    }
-                                }
-
-                                available = hasCurves;
-
-                                if (!available && debug != null &&
-                                        Debug.isOn("verbose")) {
-                                    System.out.println(
-                                        "No active elliptic curves, ignore " +
-                                        suite + " for " + protocol);
-                                }
-                            }
-
-                            if (available) {
-                                protocols.add(protocol);
-                                found = true;
-                                break;
-                            }
-                        } else if (debug != null && Debug.isOn("verbose")) {
-                            System.out.println(
-                                "Ignoring disabled cipher suite: " + suite +
-                                 " for " + protocol);
-                        }
-                    } else if (debug != null && Debug.isOn("verbose")) {
-                        System.out.println(
-                            "Ignoring unsupported cipher suite: " + suite +
-                                 " for " + protocol);
-                    }
-                }
-                if (!found && (debug != null) && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "No available cipher suite for " + protocol);
-                }
-            }
-
-            if (!protocols.isEmpty() && enabledSSL20Hello) {
-                protocols.add(ProtocolVersion.SSL20Hello);
-            }
-
-            activeProtocols = new ProtocolList(protocols);
-        }
-
-        return activeProtocols;
-    }
-
-    /**
-     * As long as handshaking has not activated, we can
-     * change whether session creations are allowed.
-     *
-     * Callers should do their own checking if handshaking
-     * has activated.
-     */
-    void setEnableSessionCreation(boolean newSessions) {
-        enableNewSession = newSessions;
-    }
-
-    /**
-     * Create a new read cipher and return it to caller.
-     */
-    CipherBox newReadCipher() throws NoSuchAlgorithmException {
-        BulkCipher cipher = cipherSuite.cipher;
-        CipherBox box;
-        if (isClient) {
-            box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   sslContext.getSecureRandom(), false);
-            svrWriteKey = null;
-            svrWriteIV = null;
-        } else {
-            box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   sslContext.getSecureRandom(), false);
-            clntWriteKey = null;
-            clntWriteIV = null;
-        }
-        return box;
-    }
-
-    /**
-     * Create a new write cipher and return it to caller.
-     */
-    CipherBox newWriteCipher() throws NoSuchAlgorithmException {
-        BulkCipher cipher = cipherSuite.cipher;
-        CipherBox box;
-        if (isClient) {
-            box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   sslContext.getSecureRandom(), true);
-            clntWriteKey = null;
-            clntWriteIV = null;
-        } else {
-            box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   sslContext.getSecureRandom(), true);
-            svrWriteKey = null;
-            svrWriteIV = null;
-        }
-        return box;
-    }
-
-    /**
-     * Create a new read MAC and return it to caller.
-     */
-    Authenticator newReadAuthenticator()
-            throws NoSuchAlgorithmException, InvalidKeyException {
-
-        Authenticator authenticator = null;
-        if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
-            authenticator = new Authenticator(protocolVersion);
-        } else {
-            MacAlg macAlg = cipherSuite.macAlg;
-            if (isClient) {
-                authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
-                svrMacSecret = null;
-            } else {
-                authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
-                clntMacSecret = null;
-            }
-        }
-
-        return authenticator;
-    }
-
-    /**
-     * Create a new write MAC and return it to caller.
-     */
-    Authenticator newWriteAuthenticator()
-            throws NoSuchAlgorithmException, InvalidKeyException {
-
-        Authenticator authenticator = null;
-        if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
-            authenticator = new Authenticator(protocolVersion);
-        } else {
-            MacAlg macAlg = cipherSuite.macAlg;
-            if (isClient) {
-                authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
-                clntMacSecret = null;
-            } else {
-                authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
-                svrMacSecret = null;
-            }
-        }
-
-        return authenticator;
-    }
-
-    /*
-     * Returns true iff the handshake sequence is done, so that
-     * this freshly created session can become the current one.
-     */
-    boolean isDone() {
-        return started() && handshakeState.isEmpty() && handshakeFinished;
-    }
-
-    /*
-     * Returns the session which was created through this
-     * handshake sequence ... should be called after isDone()
-     * returns true.
-     */
-    SSLSessionImpl getSession() {
-        return session;
-    }
-
-    /*
-     * Set the handshake session
-     */
-    void setHandshakeSessionSE(SSLSessionImpl handshakeSession) {
-        if (conn != null) {
-            conn.setHandshakeSession(handshakeSession);
-        } else {
-            engine.setHandshakeSession(handshakeSession);
-        }
-    }
-
-    /*
-     * Returns true if renegotiation is in use for this connection.
-     */
-    boolean isSecureRenegotiation() {
-        return secureRenegotiation;
-    }
-
-    /*
-     * Returns the verify_data from the Finished message sent by the client.
-     */
-    byte[] getClientVerifyData() {
-        return clientVerifyData;
-    }
-
-    /*
-     * Returns the verify_data from the Finished message sent by the server.
-     */
-    byte[] getServerVerifyData() {
-        return serverVerifyData;
-    }
-
-    /*
-     * This routine is fed SSL handshake records when they become available,
-     * and processes messages found therein.
-     */
-    void process_record(InputRecord r, boolean expectingFinished)
-            throws IOException {
-
-        checkThrown();
-
-        /*
-         * Store the incoming handshake data, then see if we can
-         * now process any completed handshake messages
-         */
-        input.incomingRecord(r);
-
-        /*
-         * We don't need to create a separate delegatable task
-         * for finished messages.
-         */
-        if ((conn != null) || expectingFinished) {
-            processLoop();
-        } else {
-            delegateTask(new PrivilegedExceptionAction<Void>() {
-                @Override
-                public Void run() throws Exception {
-                    processLoop();
-                    return null;
-                }
-            });
-        }
-    }
-
-    /*
-     * On input, we hash messages one at a time since servers may need
-     * to access an intermediate hash to validate a CertificateVerify
-     * message.
-     *
-     * Note that many handshake messages can come in one record (and often
-     * do, to reduce network resource utilization), and one message can also
-     * require multiple records (e.g. very large Certificate messages).
-     */
-    void processLoop() throws IOException {
-
-        // need to read off 4 bytes at least to get the handshake
-        // message type and length.
-        while (input.available() >= 4) {
-            byte messageType;
-            int messageLen;
-
-            /*
-             * See if we can read the handshake message header, and
-             * then the entire handshake message.  If not, wait till
-             * we can read and process an entire message.
-             */
-            input.mark(4);
-
-            messageType = (byte)input.getInt8();
-            messageLen = input.getInt24();
-
-            if (input.available() < messageLen) {
-                input.reset();
-                return;
-            }
-
-            // Set the flags in the message receiving side.
-            if (messageType == HandshakeMessage.ht_client_hello) {
-                clientHelloDelivered = true;
-            } else if (messageType == HandshakeMessage.ht_hello_request) {
-                serverHelloRequested = true;
-            }
-
-            /*
-             * Process the message.  We require
-             * that processMessage() consumes the entire message.  In
-             * lieu of explicit error checks (how?!) we assume that the
-             * data will look like garbage on encoding/processing errors,
-             * and that other protocol code will detect such errors.
-             *
-             * Note that digesting is normally deferred till after the
-             * message has been processed, though to process at least the
-             * client's Finished message (i.e. send the server's) we need
-             * to acccelerate that digesting.
-             *
-             * Also, note that hello request messages are never hashed;
-             * that includes the hello request header, too.
-             */
-            if (messageType == HandshakeMessage.ht_hello_request) {
-                input.reset();
-                processMessage(messageType, messageLen);
-                input.ignore(4 + messageLen);
-            } else {
-                input.mark(messageLen);
-                processMessage(messageType, messageLen);
-                input.digestNow();
-            }
-        }
-    }
-
-
-    /**
-     * Returns true iff the handshaker has been activated.
-     *
-     * In activated state, the handshaker may not send any messages out.
-     */
-    boolean activated() {
-        return handshakeActivated;
-    }
-
-    /**
-     * Returns true iff the handshaker has sent any messages.
-     */
-    boolean started() {
-        return (serverHelloRequested || clientHelloDelivered);
-    }
-
-
-    /*
-     * Used to kickstart the negotiation ... either writing a
-     * ClientHello or a HelloRequest as appropriate, whichever
-     * the subclass returns.  NOP if handshaking's already started.
-     */
-    void kickstart() throws IOException {
-        if ((isClient && clientHelloDelivered) ||
-                (!isClient && serverHelloRequested)) {
-            return;
-        }
-
-        HandshakeMessage m = getKickstartMessage();
-        handshakeState.update(m, resumingSession);
-
-        if (debug != null && Debug.isOn("handshake")) {
-            m.print(System.out);
-        }
-        m.write(output);
-        output.flush();
-
-        // Set the flags in the message delivering side.
-        int handshakeType = m.messageType();
-        if (handshakeType == HandshakeMessage.ht_hello_request) {
-            serverHelloRequested = true;
-        } else {        // HandshakeMessage.ht_client_hello
-            clientHelloDelivered = true;
-        }
-
-    }
-
-    /**
-     * Both client and server modes can start handshaking; but the
-     * message they send to do so is different.
-     */
-    abstract HandshakeMessage getKickstartMessage() throws SSLException;
-
-    /*
-     * Client and Server side protocols are each driven though this
-     * call, which processes a single message and drives the appropriate
-     * side of the protocol state machine (depending on the subclass).
-     */
-    abstract void processMessage(byte messageType, int messageLen)
-        throws IOException;
-
-    /*
-     * Most alerts in the protocol relate to handshaking problems.
-     * Alerts are detected as the connection reads data.
-     */
-    abstract void handshakeAlert(byte description) throws SSLProtocolException;
-
-    /*
-     * Sends a change cipher spec message and updates the write side
-     * cipher state so that future messages use the just-negotiated spec.
-     */
-    void sendChangeCipherSpec(Finished mesg, boolean lastMessage)
-            throws IOException {
-
-        output.flush(); // i.e. handshake data
-
-        OutputRecord r;
-        if (conn != null) {
-            r = new OutputRecord(Record.ct_change_cipher_spec);
-        } else {
-            r = new EngineOutputRecord(Record.ct_change_cipher_spec, engine);
-        }
-
-        r.setVersion(protocolVersion);
-        r.write(1);     // single byte of data
-
-        /*
-         * The write cipher state is protected by the connection write lock
-         * so we must grab it while making the change. We also
-         * make sure no writes occur between sending the ChangeCipherSpec
-         * message, installing the new cipher state, and sending the
-         * Finished message.
-         *
-         * We already hold SSLEngine/SSLSocket "this" by virtue
-         * of this being called from the readRecord code.
-         */
-        if (conn != null) {
-            conn.writeLock.lock();
-            try {
-                handshakeState.changeCipherSpec(false, isClient);
-                conn.writeRecord(r);
-                conn.changeWriteCiphers();
-                if (debug != null && Debug.isOn("handshake")) {
-                    mesg.print(System.out);
-                }
-
-                handshakeState.update(mesg, resumingSession);
-                mesg.write(output);
-                output.flush();
-            } finally {
-                conn.writeLock.unlock();
-            }
-        } else {
-            synchronized (engine.writeLock) {
-                handshakeState.changeCipherSpec(false, isClient);
-                engine.writeRecord((EngineOutputRecord)r);
-                engine.changeWriteCiphers();
-                if (debug != null && Debug.isOn("handshake")) {
-                    mesg.print(System.out);
-                }
-
-                handshakeState.update(mesg, resumingSession);
-                mesg.write(output);
-                if (lastMessage) {
-                    output.setFinishedMsg();
-                }
-                output.flush();
-            }
-        }
-        if (lastMessage) {
-            handshakeFinished = true;
-        }
-    }
-
-    void receiveChangeCipherSpec() throws IOException {
-        handshakeState.changeCipherSpec(true, isClient);
-    }
-
-    /*
-     * Single access point to key calculation logic.  Given the
-     * pre-master secret and the nonces from client and server,
-     * produce all the keying material to be used.
-     */
-    void calculateKeys(SecretKey preMasterSecret, ProtocolVersion version) {
-        SecretKey master = calculateMasterSecret(preMasterSecret, version);
-        session.setMasterSecret(master);
-        calculateConnectionKeys(master);
-    }
-
-
-    /*
-     * Calculate the master secret from its various components.  This is
-     * used for key exchange by all cipher suites.
-     *
-     * The master secret is the catenation of three MD5 hashes, each
-     * consisting of the pre-master secret and a SHA1 hash.  Those three
-     * SHA1 hashes are of (different) constant strings, the pre-master
-     * secret, and the nonces provided by the client and the server.
-     */
-    @SuppressWarnings("deprecation")
-    private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
-            ProtocolVersion requestedVersion) {
-
-        if (debug != null && Debug.isOn("keygen")) {
-            HexDumpEncoder      dump = new HexDumpEncoder();
-
-            System.out.println("SESSION KEYGEN:");
-
-            System.out.println("PreMaster Secret:");
-            printHex(dump, preMasterSecret.getEncoded());
-
-            // Nonces are dumped with connection keygen, no
-            // benefit to doing it twice
-        }
-
-        // What algs/params do we need to use?
-        String masterAlg;
-        PRF prf;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            masterAlg = "SunTls12MasterSecret";
-            prf = cipherSuite.prfAlg;
-        } else {
-            masterAlg = "SunTlsMasterSecret";
-            prf = P_NONE;
-        }
-
-        String prfHashAlg = prf.getPRFHashAlg();
-        int prfHashLength = prf.getPRFHashLength();
-        int prfBlockSize = prf.getPRFBlockSize();
-
-        TlsMasterSecretParameterSpec spec;
-        if (session.getUseExtendedMasterSecret()) {
-            // reset to use the extended master secret algorithm
-            masterAlg = "SunTlsExtendedMasterSecret";
-
-            byte[] sessionHash = null;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                sessionHash = handshakeHash.getFinishedHash();
-            } else {
-                // TLS 1.0/1.1
-                sessionHash = new byte[36];
-                try {
-                    handshakeHash.getMD5Clone().digest(sessionHash, 0, 16);
-                    handshakeHash.getSHAClone().digest(sessionHash, 16, 20);
-                } catch (DigestException de) {
-                    throw new ProviderException(de);
-                }
-            }
-
-            spec = new TlsMasterSecretParameterSpec(
-                    preMasterSecret, protocolVersion.major, protocolVersion.minor,
-                    sessionHash, prfHashAlg, prfHashLength, prfBlockSize);
-        } else {
-            spec = new TlsMasterSecretParameterSpec(
-                    preMasterSecret, protocolVersion.major, protocolVersion.minor,
-                    clnt_random.random_bytes, svr_random.random_bytes,
-                    prfHashAlg, prfHashLength, prfBlockSize);
-        }
-
-        try {
-            KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
-            kg.init(spec);
-            return kg.generateKey();
-        } catch (InvalidAlgorithmParameterException |
-                NoSuchAlgorithmException iae) {
-            // unlikely to happen, otherwise, must be a provider exception
-            //
-            // For RSA premaster secrets, do not signal a protocol error
-            // due to the Bleichenbacher attack. See comments further down.
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("RSA master secret generation error:");
-                iae.printStackTrace(System.out);
-            }
-            throw new ProviderException(iae);
-
-        }
-    }
-
-    /*
-     * Calculate the keys needed for this connection, once the session's
-     * master secret has been calculated.  Uses the master key and nonces;
-     * the amount of keying material generated is a function of the cipher
-     * suite that's been negotiated.
-     *
-     * This gets called both on the "full handshake" (where we exchanged
-     * a premaster secret and started a new session) as well as on the
-     * "fast handshake" (where we just resumed a pre-existing session).
-     */
-    void calculateConnectionKeys(SecretKey masterKey) {
-        /*
-         * For both the read and write sides of the protocol, we use the
-         * master to generate MAC secrets and cipher keying material.  Block
-         * ciphers need initialization vectors, which we also generate.
-         *
-         * First we figure out how much keying material is needed.
-         */
-        int hashSize = cipherSuite.macAlg.size;
-        boolean is_exportable = cipherSuite.exportable;
-        BulkCipher cipher = cipherSuite.cipher;
-        int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
-
-        // Which algs/params do we need to use?
-        String keyMaterialAlg;
-        PRF prf;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            keyMaterialAlg = "SunTls12KeyMaterial";
-            prf = cipherSuite.prfAlg;
-        } else {
-            keyMaterialAlg = "SunTlsKeyMaterial";
-            prf = P_NONE;
-        }
-
-        String prfHashAlg = prf.getPRFHashAlg();
-        int prfHashLength = prf.getPRFHashLength();
-        int prfBlockSize = prf.getPRFBlockSize();
-
-        // TLS v1.1 or later uses an explicit IV in CBC cipher suites to
-        // protect against the CBC attacks.  AEAD/GCM cipher suites in TLS
-        // v1.2 or later use a fixed IV as the implicit part of the partially
-        // implicit nonce technique described in RFC 5116.
-        int ivSize = cipher.ivSize;
-        if (cipher.cipherType == AEAD_CIPHER) {
-            ivSize = cipher.fixedIvSize;
-        } else if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
-                cipher.cipherType == BLOCK_CIPHER) {
-            ivSize = 0;
-        }
-
-        TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
-            masterKey, protocolVersion.major, protocolVersion.minor,
-            clnt_random.random_bytes, svr_random.random_bytes,
-            cipher.algorithm, cipher.keySize, expandedKeySize,
-            ivSize, hashSize,
-            prfHashAlg, prfHashLength, prfBlockSize);
-
-        try {
-            KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);
-            kg.init(spec);
-            TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
-
-            // Return null if cipher keys are not supposed to be generated.
-            clntWriteKey = keySpec.getClientCipherKey();
-            svrWriteKey = keySpec.getServerCipherKey();
-
-            // Return null if IVs are not supposed to be generated.
-            clntWriteIV = keySpec.getClientIv();
-            svrWriteIV = keySpec.getServerIv();
-
-            // Return null if MAC keys are not supposed to be generated.
-            clntMacSecret = keySpec.getClientMacKey();
-            svrMacSecret = keySpec.getServerMacKey();
-        } catch (GeneralSecurityException e) {
-            throw new ProviderException(e);
-        }
-
-        //
-        // Dump the connection keys as they're generated.
-        //
-        if (debug != null && Debug.isOn("keygen")) {
-            synchronized (System.out) {
-                HexDumpEncoder  dump = new HexDumpEncoder();
-
-                System.out.println("CONNECTION KEYGEN:");
-
-                // Inputs:
-                System.out.println("Client Nonce:");
-                printHex(dump, clnt_random.random_bytes);
-                System.out.println("Server Nonce:");
-                printHex(dump, svr_random.random_bytes);
-                System.out.println("Master Secret:");
-                printHex(dump, masterKey.getEncoded());
-
-                // Outputs:
-                if (clntMacSecret != null) {
-                    System.out.println("Client MAC write Secret:");
-                    printHex(dump, clntMacSecret.getEncoded());
-                    System.out.println("Server MAC write Secret:");
-                    printHex(dump, svrMacSecret.getEncoded());
-                } else {
-                    System.out.println("... no MAC keys used for this cipher");
-                }
-
-                if (clntWriteKey != null) {
-                    System.out.println("Client write key:");
-                    printHex(dump, clntWriteKey.getEncoded());
-                    System.out.println("Server write key:");
-                    printHex(dump, svrWriteKey.getEncoded());
-                } else {
-                    System.out.println("... no encryption keys used");
-                }
-
-                if (clntWriteIV != null) {
-                    System.out.println("Client write IV:");
-                    printHex(dump, clntWriteIV.getIV());
-                    System.out.println("Server write IV:");
-                    printHex(dump, svrWriteIV.getIV());
-                } else {
-                    if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                        System.out.println(
-                                "... no IV derived for this protocol");
-                    } else {
-                        System.out.println("... no IV used for this cipher");
-                    }
-                }
-                System.out.flush();
-            }
-        }
-    }
-
-    private static void printHex(HexDumpEncoder dump, byte[] bytes) {
-        if (bytes == null) {
-            System.out.println("(key bytes not available)");
-        } else {
-            try {
-                dump.encodeBuffer(bytes, System.out);
-            } catch (IOException e) {
-                // just for debugging, ignore this
-            }
-        }
-    }
-
-    /**
-     * Throw an SSLException with the specified message and cause.
-     * Shorthand until a new SSLException constructor is added.
-     * This method never returns.
-     */
-    static void throwSSLException(String msg, Throwable cause)
-            throws SSLException {
-        SSLException e = new SSLException(msg);
-        e.initCause(cause);
-        throw e;
-    }
-
-
-    /*
-     * Implement a simple task delegator.
-     *
-     * We are currently implementing this as a single delegator, may
-     * try for parallel tasks later.  Client Authentication could
-     * benefit from this, where ClientKeyExchange/CertificateVerify
-     * could be carried out in parallel.
-     */
-    class DelegatedTask<E> implements Runnable {
-
-        private PrivilegedExceptionAction<E> pea;
-
-        DelegatedTask(PrivilegedExceptionAction<E> pea) {
-            this.pea = pea;
-        }
-
-        public void run() {
-            synchronized (engine) {
-                try {
-                    AccessController.doPrivileged(pea, engine.getAcc());
-                } catch (PrivilegedActionException pae) {
-                    thrown = pae.getException();
-                } catch (RuntimeException rte) {
-                    thrown = rte;
-                }
-                delegatedTask = null;
-                taskDelegated = false;
-            }
-        }
-    }
-
-    private <T> void delegateTask(PrivilegedExceptionAction<T> pea) {
-        delegatedTask = new DelegatedTask<T>(pea);
-        taskDelegated = false;
-        thrown = null;
-    }
-
-    DelegatedTask<?> getTask() {
-        if (!taskDelegated) {
-            taskDelegated = true;
-            return delegatedTask;
-        } else {
-            return null;
-        }
-    }
-
-    /*
-     * See if there are any tasks which need to be delegated
-     *
-     * Locked by SSLEngine.this.
-     */
-    boolean taskOutstanding() {
-        return (delegatedTask != null);
-    }
-
-    /*
-     * The previous caller failed for some reason, report back the
-     * Exception.  We won't worry about Error's.
-     *
-     * Locked by SSLEngine.this.
-     */
-    void checkThrown() throws SSLException {
-        synchronized (thrownLock) {
-            if (thrown != null) {
-
-                String msg = thrown.getMessage();
-
-                if (msg == null) {
-                    msg = "Delegated task threw Exception/Error";
-                }
-
-                /*
-                 * See what the underlying type of exception is.  We should
-                 * throw the same thing.  Chain thrown to the new exception.
-                 */
-                Exception e = thrown;
-                thrown = null;
-
-                if (e instanceof RuntimeException) {
-                    throw new RuntimeException(msg, e);
-                } else if (e instanceof SSLHandshakeException) {
-                    throw (SSLHandshakeException)
-                        new SSLHandshakeException(msg).initCause(e);
-                } else if (e instanceof SSLKeyException) {
-                    throw (SSLKeyException)
-                        new SSLKeyException(msg).initCause(e);
-                } else if (e instanceof SSLPeerUnverifiedException) {
-                    throw (SSLPeerUnverifiedException)
-                        new SSLPeerUnverifiedException(msg).initCause(e);
-                } else if (e instanceof SSLProtocolException) {
-                    throw (SSLProtocolException)
-                        new SSLProtocolException(msg).initCause(e);
-                } else {
-                    /*
-                     * If it's SSLException or any other Exception,
-                     * we'll wrap it in an SSLException.
-                     */
-                    throw new SSLException(msg, e);
-                }
-            }
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/HelloExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2006, 2012, 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;
-
-abstract class HelloExtension {
-
-    final ExtensionType type;
-
-    HelloExtension(ExtensionType type) {
-        this.type = type;
-    }
-
-    // Length of the encoded extension, including the type and length fields
-    abstract int length();
-
-    abstract void send(HandshakeOutStream s) throws IOException;
-
-    @Override
-    public abstract String toString();
-
-}
--- a/src/share/classes/sun/security/ssl/HelloExtensions.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2006, 2020, 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.io.PrintStream;
-import java.util.*;
-import javax.net.ssl.*;
-
-/**
- * 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 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.
- *
- * The classes contained in this file are:
- *  . HelloExtensions: a List of extensions as used in the client hello
- *      and server hello messages.
- *  . ExtensionType: an enum style class for the extension type
- *  . HelloExtension: abstract base class for all extensions. All subclasses
- *      must be immutable.
- *
- *  . UnknownExtension: used to represent all parsed extensions that we do not
- *      explicitly support.
- *  . ServerNameExtension: the server_name extension.
- *  . SignatureAlgorithmsExtension: the signature_algorithms extension.
- *  . EllipticCurvesExtension: the ECC supported curves extension.
- *  . EllipticPointFormatsExtension: the ECC supported point formats
- *      (compressed/uncompressed) extension.
- *  . ALPNExtension: the application_layer_protocol_negotiation extension.
- *
- * @since   1.6
- * @author  Andreas Sterbenz
- */
-final class HelloExtensions {
-
-    private List<HelloExtension> extensions;
-    private int encodedLength;
-
-    HelloExtensions() {
-        extensions = Collections.emptyList();
-    }
-
-    HelloExtensions(HandshakeInStream s) throws IOException {
-        int len = s.getInt16();
-        extensions = new ArrayList<HelloExtension>();
-        encodedLength = len + 2;
-        while (len > 0) {
-            int type = s.getInt16();
-            int extlen = s.getInt16();
-            ExtensionType extType = ExtensionType.get(type);
-            HelloExtension extension;
-            if (extType == ExtensionType.EXT_SERVER_NAME) {
-                extension = new ServerNameExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
-                extension = new SignatureAlgorithmsExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
-                extension = new EllipticCurvesExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
-                extension = new EllipticPointFormatsExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
-                extension = new RenegotiationInfoExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_EXTENDED_MASTER_SECRET) {
-                extension = new ExtendedMasterSecretExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_ALPN) {
-                extension = new ALPNExtension(s, extlen);
-            } else {
-                extension = new UnknownExtension(s, extlen, extType);
-            }
-            extensions.add(extension);
-            len -= extlen + 4;
-        }
-        if (len != 0) {
-            throw new SSLProtocolException(
-                        "Error parsing extensions: extra data");
-        }
-    }
-
-    // Return the List of extensions. Must not be modified by the caller.
-    List<HelloExtension> list() {
-        return extensions;
-    }
-
-    void add(HelloExtension ext) {
-        if (extensions.isEmpty()) {
-            extensions = new ArrayList<HelloExtension>();
-        }
-        extensions.add(ext);
-        encodedLength = -1;
-    }
-
-    HelloExtension get(ExtensionType type) {
-        for (HelloExtension ext : extensions) {
-            if (ext.type == type) {
-                return ext;
-            }
-        }
-        return null;
-    }
-
-    int length() {
-        if (encodedLength >= 0) {
-            return encodedLength;
-        }
-        if (extensions.isEmpty()) {
-            encodedLength = 0;
-        } else {
-            encodedLength = 2;
-            for (HelloExtension ext : extensions) {
-                encodedLength += ext.length();
-            }
-        }
-        return encodedLength;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        int length = length();
-        if (length == 0) {
-            return;
-        }
-        s.putInt16(length - 2);
-        for (HelloExtension ext : extensions) {
-            ext.send(s);
-        }
-    }
-
-    void print(PrintStream s) throws IOException {
-        for (HelloExtension ext : extensions) {
-            s.println(ext.toString());
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/InputRecord.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,872 +0,0 @@
-/*
- * Copyright (c) 1996, 2014, 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.*;
-import java.nio.*;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * SSL 3.0 records, as pulled off a TCP stream.  Input records are
- * basically buffers tied to a particular input stream ... a layer
- * above this must map these records into the model of a continuous
- * stream of data.
- *
- * Since this returns SSL 3.0 records, it's the layer that needs to
- * map SSL 2.0 style handshake records into SSL 3.0 ones for those
- * "old" clients that interop with both V2 and V3 servers.  Not as
- * pretty as might be desired.
- *
- * NOTE:  During handshaking, each message must be hashed to support
- * verification that the handshake process wasn't compromised.
- *
- * @author David Brownell
- */
-class InputRecord extends ByteArrayInputStream implements Record {
-
-    private HandshakeHash       handshakeHash;
-    private int                 lastHashed;
-    boolean                     formatVerified = true;  // SSLv2 ruled out?
-    private boolean             isClosed;
-    private boolean             appDataValid;
-
-    // The ClientHello version to accept. If set to ProtocolVersion.SSL20Hello
-    // and the first message we read is a ClientHello in V2 format, we convert
-    // it to V3. Otherwise we throw an exception when encountering a V2 hello.
-    private ProtocolVersion     helloVersion;
-
-    /* Class and subclass dynamic debugging support */
-    static final Debug debug = Debug.getInstance("ssl");
-
-    /* The existing record length */
-    private int exlen;
-
-    /* V2 handshake message */
-    private byte v2Buf[];
-
-    /*
-     * Construct the record to hold the maximum sized input record.
-     * Data will be filled in separately.
-     *
-     * The structure of the byte buffer looks like:
-     *
-     *     |--------+---------+---------------------------------|
-     *     | header |   IV    | content, MAC/TAG, padding, etc. |
-     *     | headerPlusIVSize |
-     *
-     * header: the header of an SSL records
-     * IV:     the optional IV/nonce field, it is only required for block
-     *         (TLS 1.1 or later) and AEAD cipher suites.
-     *
-     */
-    InputRecord() {
-        super(new byte[maxRecordSize]);
-        setHelloVersion(ProtocolVersion.DEFAULT_HELLO);
-        pos = headerSize;
-        count = headerSize;
-        lastHashed = count;
-        exlen = 0;
-        v2Buf = null;
-    }
-
-    void setHelloVersion(ProtocolVersion helloVersion) {
-        this.helloVersion = helloVersion;
-    }
-
-    ProtocolVersion getHelloVersion() {
-        return helloVersion;
-    }
-
-    /*
-     * Enable format checks if initial handshaking hasn't completed
-     */
-    void enableFormatChecks() {
-        formatVerified = false;
-    }
-
-    // return whether the data in this record is valid, decrypted data
-    boolean isAppDataValid() {
-        return appDataValid;
-    }
-
-    void setAppDataValid(boolean value) {
-        appDataValid = value;
-    }
-
-    /*
-     * Return the content type of the record.
-     */
-    byte contentType() {
-        return buf[0];
-    }
-
-    /*
-     * For handshaking, we need to be able to hash every byte above the
-     * record marking layer.  This is where we're guaranteed to see those
-     * bytes, so this is where we can hash them ... especially in the
-     * case of hashing the initial V2 message!
-     */
-    void setHandshakeHash(HandshakeHash handshakeHash) {
-        this.handshakeHash = handshakeHash;
-    }
-
-    HandshakeHash getHandshakeHash() {
-        return handshakeHash;
-    }
-
-    void decrypt(Authenticator authenticator,
-            CipherBox box) throws BadPaddingException {
-        BadPaddingException reservedBPE = null;
-        int tagLen =
-            (authenticator instanceof MAC) ? ((MAC)authenticator).MAClen() : 0;
-        int cipheredLength = count - headerSize;
-
-        if (!box.isNullCipher()) {
-            try {
-                // apply explicit nonce for AEAD/CBC cipher suites if needed
-                int nonceSize = box.applyExplicitNonce(authenticator,
-                        contentType(), buf, headerSize, cipheredLength);
-                pos = headerSize + nonceSize;
-                lastHashed = pos;   // don't digest the explicit nonce
-
-                // decrypt the content
-                int offset = headerSize;
-                if (box.isAEADMode()) {
-                    // DON'T encrypt the nonce_explicit for AEAD mode
-                    offset += nonceSize;
-                }   // The explicit IV for CBC mode can be decrypted.
-
-                // Note that the CipherBox.decrypt() does not change
-                // the capacity of the buffer.
-                count = offset +
-                    box.decrypt(buf, offset, count - offset, tagLen);
-
-                // Note that we don't remove the nonce from the buffer.
-            } catch (BadPaddingException bpe) {
-                // RFC 2246 states that decryption_failed should be used
-                // for this purpose. However, that allows certain attacks,
-                // so we just send bad record MAC. We also need to make
-                // sure to always check the MAC to avoid a timing attack
-                // for the same issue. See paper by Vaudenay et al and the
-                // update in RFC 4346/5246.
-                //
-                // Failover to message authentication code checking.
-                reservedBPE = bpe;
-            }
-        }
-
-        // Requires message authentication code for null, stream and block
-        // cipher suites.
-        if (authenticator instanceof MAC && tagLen != 0) {
-            MAC signer = (MAC)authenticator;
-            int macOffset = count - tagLen;
-            int contentLen = macOffset - pos;
-
-            // Note that although it is not necessary, we run the same MAC
-            // computation and comparison on the payload for both stream
-            // cipher and CBC block cipher.
-            if (contentLen < 0) {
-                // negative data length, something is wrong
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record");
-                }
-
-                // set offset of the dummy MAC
-                macOffset = headerSize + cipheredLength - tagLen;
-                contentLen = macOffset - headerSize;
-            }
-
-            count -= tagLen;  // Set the count before any MAC checking
-                              // exception occurs, so that the following
-                              // process can read the actual decrypted
-                              // content (minus the MAC) in the fragment
-                              // if necessary.
-
-            // Run MAC computation and comparison on the payload.
-            if (checkMacTags(contentType(),
-                    buf, pos, contentLen, signer, false)) {
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record MAC");
-                }
-            }
-
-            // Run MAC computation and comparison on the remainder.
-            //
-            // It is only necessary for CBC block cipher.  It is used to get a
-            // constant time of MAC computation and comparison on each record.
-            if (box.isCBCMode()) {
-                int remainingLen = calculateRemainingLen(
-                                        signer, cipheredLength, contentLen);
-
-                // NOTE: remainingLen may be bigger (less than 1 block of the
-                // hash algorithm of the MAC) than the cipheredLength. However,
-                // We won't need to worry about it because we always use a
-                // maximum buffer for every record.  We need a change here if
-                // we use small buffer size in the future.
-                if (remainingLen > buf.length) {
-                    // unlikely to happen, just a placehold
-                    throw new RuntimeException(
-                        "Internal buffer capacity error");
-                }
-
-                // Won't need to worry about the result on the remainder. And
-                // then we won't need to worry about what's actual data to
-                // check MAC tag on.  We start the check from the header of the
-                // buffer so that we don't need to construct a new byte buffer.
-                checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
-            }
-        }
-
-        // Is it a failover?
-        if (reservedBPE != null) {
-            throw reservedBPE;
-        }
-    }
-
-    /*
-     * Run MAC computation and comparison
-     *
-     * Please DON'T change the content of the byte buffer parameter!
-     */
-    static boolean checkMacTags(byte contentType, byte[] buffer,
-            int offset, int contentLen, MAC signer, boolean isSimulated) {
-
-        int tagLen = signer.MAClen();
-        byte[] hash = signer.compute(
-                contentType, buffer, offset, contentLen, isSimulated);
-        if (hash == null || tagLen != hash.length) {
-            // Something is wrong with MAC implementation.
-            throw new RuntimeException("Internal MAC error");
-        }
-
-        int[] results = compareMacTags(buffer, offset + contentLen, hash);
-        return (results[0] != 0);
-    }
-
-    /*
-     * A constant-time comparison of the MAC tags.
-     *
-     * Please DON'T change the content of the byte buffer parameter!
-     */
-    private static int[] compareMacTags(
-            byte[] buffer, int offset, byte[] tag) {
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};    // {missed #, matched #}
-
-        // The caller ensures there are enough bytes available in the buffer.
-        // So we won't need to check the length of the buffer.
-        for (int i = 0; i < tag.length; i++) {
-            if (buffer[offset + i] != tag[i]) {
-                results[0]++;       // mismatched bytes
-            } else {
-                results[1]++;       // matched bytes
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * Calculate the length of a dummy buffer to run MAC computation
-     * and comparison on the remainder.
-     *
-     * The caller MUST ensure that the fullLen is not less than usedLen.
-     */
-    static int calculateRemainingLen(
-            MAC signer, int fullLen, int usedLen) {
-
-        int blockLen = signer.hashBlockLen();
-        int minimalPaddingLen = signer.minimalPaddingLen();
-
-        // (blockLen - minimalPaddingLen) is the maximum message size of
-        // the last block of hash function operation. See FIPS 180-4, or
-        // MD5 specification.
-        fullLen += 13 - (blockLen - minimalPaddingLen);
-        usedLen += 13 - (blockLen - minimalPaddingLen);
-
-        // Note: fullLen is always not less than usedLen, and blockLen
-        // is always bigger than minimalPaddingLen, so we don't worry
-        // about negative values. 0x01 is added to the result to ensure
-        // that the return value is positive.  The extra one byte does
-        // not impact the overall MAC compression function evaluations.
-        return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) -
-                Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen();
-    }
-
-    /*
-     * Well ... hello_request messages are _never_ hashed since we can't
-     * know when they'd appear in the sequence.
-     */
-    void ignore(int bytes) {
-        if (bytes > 0) {
-            pos += bytes;
-            lastHashed = pos;
-        }
-    }
-
-    /*
-     * We hash the (plaintext) we've processed, but only on demand.
-     *
-     * There is one place where we want to access the hash in the middle
-     * of a record:  client cert message gets hashed, and part of the
-     * same record is the client cert verify message which uses that hash.
-     * So we track how much we've read and hashed.
-     */
-    void doHashes() {
-        int len = pos - lastHashed;
-
-        if (len > 0) {
-            hashInternal(buf, lastHashed, len);
-            lastHashed = pos;
-        }
-    }
-
-    /*
-     * Need a helper function so we can hash the V2 hello correctly
-     */
-    private void hashInternal(byte databuf [], int offset, int len) {
-        if (debug != null && Debug.isOn("data")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-
-                System.out.println("[read] MD5 and SHA1 hashes:  len = "
-                    + len);
-                hd.encodeBuffer(new ByteArrayInputStream(databuf, offset, len),
-                    System.out);
-            } catch (IOException e) { }
-        }
-        handshakeHash.update(databuf, offset, len);
-    }
-
-
-    /*
-     * Handshake messages may cross record boundaries.  We "queue"
-     * these in big buffers if we need to cope with this problem.
-     * This is not anticipated to be a common case; if this turns
-     * out to be wrong, this can readily be sped up.
-     */
-    void queueHandshake(InputRecord r) throws IOException {
-        int len;
-
-        /*
-         * Hash any data that's read but unhashed.
-         */
-        doHashes();
-
-        /*
-         * Move any unread data to the front of the buffer,
-         * flagging it all as unhashed.
-         */
-        if (pos > headerSize) {
-            len = count - pos;
-            if (len != 0) {
-                System.arraycopy(buf, pos, buf, headerSize, len);
-            }
-            pos = headerSize;
-            lastHashed = pos;
-            count = headerSize + len;
-        }
-
-        /*
-         * Grow "buf" if needed
-         */
-        len = r.available() + count;
-        if (buf.length < len) {
-            byte        newbuf [];
-
-            newbuf = new byte [len];
-            System.arraycopy(buf, 0, newbuf, 0, count);
-            buf = newbuf;
-        }
-
-        /*
-         * Append the new buffer to this one.
-         */
-        System.arraycopy(r.buf, r.pos, buf, count, len - count);
-        count = len;
-
-        /*
-         * Adjust lastHashed; important for now with clients which
-         * send SSL V2 client hellos.  This will go away eventually,
-         * by buffer code cleanup.
-         */
-        len = r.lastHashed - r.pos;
-        if (pos == headerSize) {
-            lastHashed += len;
-        } else {
-            throw new SSLProtocolException("?? confused buffer hashing ??");
-        }
-        // we've read the record, advance the pointers
-        r.pos = r.count;
-    }
-
-
-    /**
-     * Prevent any more data from being read into this record,
-     * and flag the record as holding no data.
-     */
-    @Override
-    public void close() {
-        appDataValid = false;
-        isClosed = true;
-        mark = 0;
-        pos = 0;
-        count = 0;
-    }
-
-
-    /*
-     * We may need to send this SSL v2 "No Cipher" message back, if we
-     * are faced with an SSLv2 "hello" that's not saying "I talk v3".
-     * It's the only one documented in the V2 spec as a fatal error.
-     */
-    private static final byte[] v2NoCipher = {
-        (byte)0x80, (byte)0x03, // unpadded 3 byte record
-        (byte)0x00,             // ... error message
-        (byte)0x00, (byte)0x01  // ... NO_CIPHER error
-    };
-
-    private int readFully(InputStream s, byte b[], int off, int len)
-            throws IOException {
-        int n = 0;
-        while (n < len) {
-            int readLen = s.read(b, off + n, len - n);
-            if (readLen < 0) {
-                return readLen;
-            }
-
-            if (debug != null && Debug.isOn("packet")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-                    ByteBuffer bb = ByteBuffer.wrap(b, off + n, readLen);
-
-                    System.out.println("[Raw read]: length = " +
-                        bb.remaining());
-                    hd.encodeBuffer(bb, System.out);
-                } catch (IOException e) { }
-            }
-
-            n += readLen;
-            exlen += readLen;
-        }
-
-        return n;
-    }
-
-    /*
-     * Read the SSL V3 record ... first time around, check to see if it
-     * really IS a V3 record.  Handle SSL V2 clients which can talk V3.0,
-     * as well as real V3 record format; otherwise report an error.
-     */
-    void read(InputStream s, OutputStream o) throws IOException {
-        if (isClosed) {
-            return;
-        }
-
-        /*
-         * For SSL it really _is_ an error if the other end went away
-         * so ungracefully as to not shut down cleanly.
-         */
-        if(exlen < headerSize) {
-            int really = readFully(s, buf, exlen, headerSize - exlen);
-            if (really < 0) {
-                throw new EOFException("SSL peer shut down incorrectly");
-            }
-
-            pos = headerSize;
-            count = headerSize;
-            lastHashed = pos;
-        }
-
-        /*
-         * The first record might use some other record marking convention,
-         * typically SSL v2 header.  (PCT could also be detected here.)
-         * This case is currently common -- Navigator 3.0 usually works
-         * this way, as do IE 3.0 and other products.
-         */
-        if (!formatVerified) {
-            formatVerified = true;
-            /*
-             * The first record must either be a handshake record or an
-             * alert message. If it's not, it is either invalid or an
-             * SSLv2 message.
-             */
-            if (buf[0] != ct_handshake && buf[0] != ct_alert) {
-                handleUnknownRecord(s, o);
-            } else {
-                readV3Record(s, o);
-            }
-        } else { // formatVerified == true
-            readV3Record(s, o);
-        }
-    }
-
-    /**
-     * Return true if the specified record protocol version is out of the
-     * range of the possible supported versions.
-     */
-    static void checkRecordVersion(ProtocolVersion version,
-            boolean allowSSL20Hello) throws SSLException {
-        // Check if the record version is too old (currently not possible)
-        // or if the major version does not match.
-        //
-        // The actual version negotiation is in the handshaker classes
-        if ((version.v < ProtocolVersion.MIN.v) ||
-            ((version.major & 0xFF) > (ProtocolVersion.MAX.major & 0xFF))) {
-
-            // if it's not SSLv2, we're out of here.
-            if (!allowSSL20Hello ||
-                    (version.v != ProtocolVersion.SSL20Hello.v)) {
-                throw new SSLException("Unsupported record version " + version);
-            }
-        }
-    }
-
-    /**
-     * Read a SSL/TLS record. Throw an IOException if the format is invalid.
-     */
-    private void readV3Record(InputStream s, OutputStream o)
-            throws IOException {
-        ProtocolVersion recordVersion = ProtocolVersion.valueOf(buf[1], buf[2]);
-
-        // check the record version
-        checkRecordVersion(recordVersion, false);
-
-        /*
-         * Get and check length, then the data.
-         */
-        int contentLen = ((buf[3] & 0x0ff) << 8) + (buf[4] & 0xff);
-
-        /*
-         * Check for upper bound.
-         */
-        if (contentLen < 0 || contentLen > maxLargeRecordSize - headerSize) {
-            throw new SSLProtocolException("Bad InputRecord size"
-                + ", count = " + contentLen
-                + ", buf.length = " + buf.length);
-        }
-
-        /*
-         * Grow "buf" if needed. Since buf is maxRecordSize by default,
-         * this only occurs when we receive records which violate the
-         * SSL specification. This is a workaround for a Microsoft SSL bug.
-         */
-        if (contentLen > buf.length - headerSize) {
-            byte[] newbuf = new byte[contentLen + headerSize];
-            System.arraycopy(buf, 0, newbuf, 0, headerSize);
-            buf = newbuf;
-        }
-
-        if (exlen < contentLen + headerSize) {
-            int really = readFully(
-                s, buf, exlen, contentLen + headerSize - exlen);
-            if (really < 0) {
-                throw new SSLException("SSL peer shut down incorrectly");
-            }
-        }
-
-        // now we've got a complete record.
-        count = contentLen + headerSize;
-        exlen = 0;
-
-        if (debug != null && Debug.isOn("record")) {
-            if (count < 0 || count > (maxRecordSize - headerSize)) {
-                System.out.println(Thread.currentThread().getName()
-                    + ", Bad InputRecord size" + ", count = " + count);
-            }
-            System.out.println(Thread.currentThread().getName()
-                + ", READ: " + recordVersion + " "
-                + contentName(contentType()) + ", length = " + available());
-        }
-        /*
-         * then caller decrypts, verifies, and uncompresses
-         */
-    }
-
-    /**
-     * Deal with unknown records. Called if the first data we read on this
-     * connection does not look like an SSL/TLS record. It could a SSLv2
-     * message, or just garbage.
-     */
-    private void handleUnknownRecord(InputStream s, OutputStream o)
-            throws IOException {
-        /*
-         * No?  Oh well; does it look like a V2 "ClientHello"?
-         * That'd be an unpadded handshake message; we don't
-         * bother checking length just now.
-         */
-        if (((buf[0] & 0x080) != 0) && buf[2] == 1) {
-            /*
-             * if the user has disabled SSLv2Hello (using
-             * setEnabledProtocol) then throw an
-             * exception
-             */
-            if (helloVersion != ProtocolVersion.SSL20Hello) {
-                throw new SSLHandshakeException("SSLv2Hello is disabled");
-            }
-
-            ProtocolVersion recordVersion =
-                                ProtocolVersion.valueOf(buf[3], buf[4]);
-
-            if (recordVersion == ProtocolVersion.SSL20Hello) {
-                /*
-                 * Looks like a V2 client hello, but not one saying
-                 * "let's talk SSLv3".  So we send an SSLv2 error
-                 * message, one that's treated as fatal by clients.
-                 * (Otherwise we'll hang.)
-                 */
-                try {
-                    writeBuffer(o, v2NoCipher, 0, v2NoCipher.length);
-                } catch (Exception e) {
-                    /* NOTHING */
-                }
-                throw new SSLException("Unsupported SSL v2.0 ClientHello");
-            }
-
-            /*
-             * If we can map this into a V3 ClientHello, read and
-             * hash the rest of the V2 handshake, turn it into a
-             * V3 ClientHello message, and pass it up.
-             */
-            int len = ((buf[0] & 0x7f) << 8) +
-                (buf[1] & 0xff) - 3;
-            if (v2Buf == null) {
-                v2Buf = new byte[len];
-            }
-            if (exlen < len + headerSize) {
-                int really = readFully(
-                        s, v2Buf, exlen - headerSize, len + headerSize - exlen);
-                if (really < 0) {
-                    throw new EOFException("SSL peer shut down incorrectly");
-                }
-            }
-
-            // now we've got a complete record.
-            exlen = 0;
-
-            hashInternal(buf, 2, 3);
-            hashInternal(v2Buf, 0, len);
-            V2toV3ClientHello(v2Buf);
-            v2Buf = null;
-            lastHashed = count;
-
-            if (debug != null && Debug.isOn("record"))  {
-                System.out.println(
-                    Thread.currentThread().getName()
-                    + ", READ:  SSL v2, contentType = "
-                    + contentName(contentType())
-                    + ", translated length = " + available());
-            }
-            return;
-
-        } else {
-            /*
-             * Does it look like a V2 "ServerHello"?
-             */
-            if (((buf [0] & 0x080) != 0) && buf [2] == 4) {
-                throw new SSLException(
-                    "SSL V2.0 servers are not supported.");
-            }
-
-            /*
-             * If this is a V2 NoCipher message then this means
-             * the other server doesn't support V3. Otherwise, we just
-             * don't understand what it's saying.
-             */
-            for (int i = 0; i < v2NoCipher.length; i++) {
-                if (buf[i] != v2NoCipher[i]) {
-                    throw new SSLException(
-                        "Unrecognized SSL message, plaintext connection?");
-                }
-            }
-
-            throw new SSLException("SSL V2.0 servers are not supported.");
-        }
-    }
-
-    /*
-     * Actually do the write here.  For SSLEngine's HS data,
-     * we'll override this method and let it take the appropriate
-     * action.
-     */
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len)
-            throws IOException {
-        s.write(buf, 0, len);
-        s.flush();
-    }
-
-    /*
-     * Support "old" clients which are capable of SSL V3.0 protocol ... for
-     * example, Navigator 3.0 clients.  The V2 message is in the header and
-     * the bytes passed as parameter.  This routine translates the V2 message
-     * into an equivalent V3 one.
-     */
-    private void V2toV3ClientHello(byte v2Msg []) throws SSLException
-    {
-        int i;
-
-        /*
-         * Build the first part of the V3 record header from the V2 one
-         * that's now buffered up.  (Lengths are fixed up later).
-         */
-        buf [0] = ct_handshake;
-        buf [1] = buf [3];      // V3.x
-        buf[2] = buf[4];
-        // header [3..4] for handshake message length
-        // count = 5;
-
-        /*
-         * Store the generic V3 handshake header:  4 bytes
-         */
-        buf [5] = 1;    // HandshakeMessage.ht_client_hello
-        // buf [6..8] for length of ClientHello (int24)
-        // count += 4;
-
-        /*
-         * ClientHello header starts with SSL version
-         */
-        buf [9] = buf [1];
-        buf [10] = buf [2];
-        // count += 2;
-        count = 11;
-
-        /*
-         * Start parsing the V2 message ...
-         */
-        int      cipherSpecLen, sessionIdLen, nonceLen;
-
-        cipherSpecLen = ((v2Msg [0] & 0xff) << 8) + (v2Msg [1] & 0xff);
-        sessionIdLen  = ((v2Msg [2] & 0xff) << 8) + (v2Msg [3] & 0xff);
-        nonceLen   = ((v2Msg [4] & 0xff) << 8) + (v2Msg [5] & 0xff);
-
-        /*
-         * Copy Random value/nonce ... if less than the 32 bytes of
-         * a V3 "Random", right justify and zero pad to the left.  Else
-         * just take the last 32 bytes.
-         */
-        int      offset = 6 + cipherSpecLen + sessionIdLen;
-
-        if (nonceLen < 32) {
-            for (i = 0; i < (32 - nonceLen); i++)
-                buf [count++] = 0;
-            System.arraycopy(v2Msg, offset, buf, count, nonceLen);
-            count += nonceLen;
-        } else {
-            System.arraycopy(v2Msg, offset + (nonceLen - 32),
-                    buf, count, 32);
-            count += 32;
-        }
-
-        /*
-         * Copy Session ID (only one byte length!)
-         */
-        offset -= sessionIdLen;
-        buf [count++] = (byte) sessionIdLen;
-
-        System.arraycopy(v2Msg, offset, buf, count, sessionIdLen);
-        count += sessionIdLen;
-
-        /*
-         * Copy and translate cipher suites ... V2 specs with first byte zero
-         * are really V3 specs (in the last 2 bytes), just copy those and drop
-         * the other ones.  Preference order remains unchanged.
-         *
-         * Example:  Netscape Navigator 3.0 (exportable) says:
-         *
-         * 0/3,     SSL_RSA_EXPORT_WITH_RC4_40_MD5
-         * 0/6,     SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
-         *
-         * Microsoft Internet Explorer 3.0 (exportable) supports only
-         *
-         * 0/3,     SSL_RSA_EXPORT_WITH_RC4_40_MD5
-         */
-        int j;
-
-        offset -= cipherSpecLen;
-        j = count + 2;
-
-        for (i = 0; i < cipherSpecLen; i += 3) {
-            if (v2Msg [offset + i] != 0)
-                continue;
-            buf [j++] = v2Msg [offset + i + 1];
-            buf [j++] = v2Msg [offset + i + 2];
-        }
-
-        j -= count + 2;
-        buf [count++] = (byte) (j >>> 8);
-        buf [count++] = (byte) j;
-        count += j;
-
-        /*
-         * Append compression methods (default/null only)
-         */
-        buf [count++] = 1;
-        buf [count++] = 0;      // Session.compression_null
-
-        /*
-         * Fill in lengths of the messages we synthesized (nested:
-         * V3 handshake message within V3 record) and then return
-         */
-        buf [3] = (byte) (count - headerSize);
-        buf [4] = (byte) ((count - headerSize) >>> 8);
-
-        buf [headerSize + 1] = 0;
-        buf [headerSize + 2] = (byte) (((count - headerSize) - 4) >>> 8);
-        buf [headerSize + 3] = (byte) ((count - headerSize) - 4);
-
-        pos = headerSize;
-    }
-
-    /**
-     * Return a description for the given content type. This method should be
-     * in Record, but since that is an interface this is not possible.
-     * Called from InputRecord and OutputRecord.
-     */
-    static String contentName(int contentType) {
-        switch (contentType) {
-        case ct_change_cipher_spec:
-            return "Change Cipher Spec";
-        case ct_alert:
-            return "Alert";
-        case ct_handshake:
-            return "Handshake";
-        case ct_application_data:
-            return "Application Data";
-        default:
-            return "contentType = " + contentType;
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/JsseJce.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,429 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-import java.math.BigInteger;
-
-import java.security.*;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.*;
-
-import javax.crypto.*;
-
-// explicit import to override the Provider class in this package
-import java.security.Provider;
-
-// need internal Sun classes for FIPS tricks
-import sun.security.jca.Providers;
-import sun.security.jca.ProviderList;
-
-import sun.security.util.ECUtil;
-
-import static sun.security.ssl.SunJSSE.cryptoProvider;
-
-/**
- * This class contains a few static methods for interaction with the JCA/JCE
- * to obtain implementations, etc.
- *
- * @author  Andreas Sterbenz
- */
-final class JsseJce {
-
-    private final static ProviderList fipsProviderList;
-
-    // Flag indicating whether Kerberos crypto is available.
-    // If true, then all the Kerberos-based crypto we need is available.
-    private final static boolean kerberosAvailable;
-    static {
-        boolean temp;
-        try {
-            AccessController.doPrivileged(
-                new PrivilegedExceptionAction<Void>() {
-                    @Override
-                    public Void run() throws Exception {
-                        // Test for Kerberos using the bootstrap class loader
-                        Class.forName("sun.security.krb5.PrincipalName", true,
-                                null);
-                        return null;
-                    }
-                });
-            temp = true;
-
-        } catch (Exception e) {
-            temp = false;
-        }
-        kerberosAvailable = temp;
-    }
-
-    static {
-        // force FIPS flag initialization
-        // Because isFIPS() is synchronized and cryptoProvider is not modified
-        // after it completes, this also eliminates the need for any further
-        // synchronization when accessing cryptoProvider
-        if (SunJSSE.isFIPS() == false) {
-            fipsProviderList = null;
-        } else {
-            // Setup a ProviderList that can be used by the trust manager
-            // during certificate chain validation. All the crypto must be
-            // from the FIPS provider, but we also allow the required
-            // certificate related services from the SUN provider.
-            Provider sun = Security.getProvider("SUN");
-            if (sun == null) {
-                throw new RuntimeException
-                    ("FIPS mode: SUN provider must be installed");
-            }
-            Provider sunCerts = new SunCertificates(sun);
-            fipsProviderList = ProviderList.newList(cryptoProvider, sunCerts);
-        }
-    }
-
-    private static final class SunCertificates extends Provider {
-        private static final long serialVersionUID = -3284138292032213752L;
-
-        SunCertificates(final Provider p) {
-            super("SunCertificates", 1.8d, "SunJSSE internal");
-            AccessController.doPrivileged(new PrivilegedAction<Object>() {
-                @Override
-                public Object run() {
-                    // copy certificate related services from the Sun provider
-                    for (Map.Entry<Object,Object> entry : p.entrySet()) {
-                        String key = (String)entry.getKey();
-                        if (key.startsWith("CertPathValidator.")
-                                || key.startsWith("CertPathBuilder.")
-                                || key.startsWith("CertStore.")
-                                || key.startsWith("CertificateFactory.")) {
-                            put(key, entry.getValue());
-                        }
-                    }
-                    return null;
-                }
-            });
-        }
-    }
-
-    /**
-     * JCE transformation string for RSA with PKCS#1 v1.5 padding.
-     * Can be used for encryption, decryption, signing, verifying.
-     */
-    final static String CIPHER_RSA_PKCS1 = "RSA/ECB/PKCS1Padding";
-    /**
-     * JCE transformation string for the stream cipher RC4.
-     */
-    final static String CIPHER_RC4 = "RC4";
-    /**
-     * JCE transformation string for DES in CBC mode without padding.
-     */
-    final static String CIPHER_DES = "DES/CBC/NoPadding";
-    /**
-     * JCE transformation string for (3-key) Triple DES in CBC mode
-     * without padding.
-     */
-    final static String CIPHER_3DES = "DESede/CBC/NoPadding";
-    /**
-     * JCE transformation string for AES in CBC mode
-     * without padding.
-     */
-    final static String CIPHER_AES = "AES/CBC/NoPadding";
-    /**
-     * JCE transformation string for AES in GCM mode
-     * without padding.
-     */
-    final static String CIPHER_AES_GCM = "AES/GCM/NoPadding";
-    /**
-     * JCA identifier string for DSA, i.e. a DSA with SHA-1.
-     */
-    final static String SIGNATURE_DSA = "DSA";
-    /**
-     * JCA identifier string for ECDSA, i.e. a ECDSA with SHA-1.
-     */
-    final static String SIGNATURE_ECDSA = "SHA1withECDSA";
-    /**
-     * JCA identifier string for Raw DSA, i.e. a DSA signature without
-     * hashing where the application provides the SHA-1 hash of the data.
-     * Note that the standard name is "NONEwithDSA" but we use "RawDSA"
-     * for compatibility.
-     */
-    final static String SIGNATURE_RAWDSA = "RawDSA";
-    /**
-     * JCA identifier string for Raw ECDSA, i.e. a DSA signature without
-     * hashing where the application provides the SHA-1 hash of the data.
-     */
-    final static String SIGNATURE_RAWECDSA = "NONEwithECDSA";
-    /**
-     * JCA identifier string for Raw RSA, i.e. a RSA PKCS#1 v1.5 signature
-     * without hashing where the application provides the hash of the data.
-     * Used for RSA client authentication with a 36 byte hash.
-     */
-    final static String SIGNATURE_RAWRSA = "NONEwithRSA";
-    /**
-     * JCA identifier string for the SSL/TLS style RSA Signature. I.e.
-     * an signature using RSA with PKCS#1 v1.5 padding signing a
-     * concatenation of an MD5 and SHA-1 digest.
-     */
-    final static String SIGNATURE_SSLRSA = "MD5andSHA1withRSA";
-
-    private JsseJce() {
-        // no instantiation of this class
-    }
-
-    static boolean isEcAvailable() {
-        return EcAvailability.isAvailable;
-    }
-
-    static boolean isKerberosAvailable() {
-        return kerberosAvailable;
-    }
-
-    /**
-     * Return an JCE cipher implementation for the specified algorithm.
-     */
-    static Cipher getCipher(String transformation)
-            throws NoSuchAlgorithmException {
-        try {
-            if (cryptoProvider == null) {
-                return Cipher.getInstance(transformation);
-            } else {
-                return Cipher.getInstance(transformation, cryptoProvider);
-            }
-        } catch (NoSuchPaddingException e) {
-            throw new NoSuchAlgorithmException(e);
-        }
-    }
-
-    /**
-     * Return an JCA signature implementation for the specified algorithm.
-     * The algorithm string should be one of the constants defined
-     * in this class.
-     */
-    static Signature getSignature(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return Signature.getInstance(algorithm);
-        } else {
-            // reference equality
-            if (algorithm == SIGNATURE_SSLRSA) {
-                // The SunPKCS11 provider currently does not support this
-                // special algorithm. We allow a fallback in this case because
-                // the SunJSSE implementation does the actual crypto using
-                // a NONEwithRSA signature obtained from the cryptoProvider.
-                if (cryptoProvider.getService("Signature", algorithm) == null) {
-                    // Calling Signature.getInstance() and catching the
-                    // exception would be cleaner, but exceptions are a little
-                    // expensive. So we check directly via getService().
-                    try {
-                        return Signature.getInstance(algorithm, "SunJSSE");
-                    } catch (NoSuchProviderException e) {
-                        throw new NoSuchAlgorithmException(e);
-                    }
-                }
-            }
-            return Signature.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyGenerator getKeyGenerator(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyGenerator.getInstance(algorithm);
-        } else {
-            return KeyGenerator.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyPairGenerator getKeyPairGenerator(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyPairGenerator.getInstance(algorithm);
-        } else {
-            return KeyPairGenerator.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyAgreement getKeyAgreement(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyAgreement.getInstance(algorithm);
-        } else {
-            return KeyAgreement.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static Mac getMac(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return Mac.getInstance(algorithm);
-        } else {
-            return Mac.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyFactory getKeyFactory(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyFactory.getInstance(algorithm);
-        } else {
-            return KeyFactory.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static AlgorithmParameters getAlgorithmParameters(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return AlgorithmParameters.getInstance(algorithm);
-        } else {
-            return AlgorithmParameters.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static SecureRandom getSecureRandom() throws KeyManagementException {
-        if (cryptoProvider == null) {
-            return new SecureRandom();
-        }
-        // Try "PKCS11" first. If that is not supported, iterate through
-        // the provider and return the first working implementation.
-        try {
-            return SecureRandom.getInstance("PKCS11", cryptoProvider);
-        } catch (NoSuchAlgorithmException e) {
-            // ignore
-        }
-        for (Provider.Service s : cryptoProvider.getServices()) {
-            if (s.getType().equals("SecureRandom")) {
-                try {
-                    return SecureRandom.getInstance(s.getAlgorithm(), cryptoProvider);
-                } catch (NoSuchAlgorithmException ee) {
-                    // ignore
-                }
-            }
-        }
-        throw new KeyManagementException("FIPS mode: no SecureRandom "
-            + " implementation found in provider " + cryptoProvider.getName());
-    }
-
-    static MessageDigest getMD5() {
-        return getMessageDigest("MD5");
-    }
-
-    static MessageDigest getSHA() {
-        return getMessageDigest("SHA");
-    }
-
-    static MessageDigest getMessageDigest(String algorithm) {
-        try {
-            if (cryptoProvider == null) {
-                return MessageDigest.getInstance(algorithm);
-            } else {
-                return MessageDigest.getInstance(algorithm, cryptoProvider);
-            }
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException
-                        ("Algorithm " + algorithm + " not available", e);
-        }
-    }
-
-    static int getRSAKeyLength(PublicKey key) {
-        BigInteger modulus;
-        if (key instanceof RSAPublicKey) {
-            modulus = ((RSAPublicKey)key).getModulus();
-        } else {
-            RSAPublicKeySpec spec = getRSAPublicKeySpec(key);
-            modulus = spec.getModulus();
-        }
-        return modulus.bitLength();
-    }
-
-    static RSAPublicKeySpec getRSAPublicKeySpec(PublicKey key) {
-        if (key instanceof RSAPublicKey) {
-            RSAPublicKey rsaKey = (RSAPublicKey)key;
-            return new RSAPublicKeySpec(rsaKey.getModulus(),
-                                        rsaKey.getPublicExponent());
-        }
-        try {
-            KeyFactory factory = JsseJce.getKeyFactory("RSA");
-            return factory.getKeySpec(key, RSAPublicKeySpec.class);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    static ECParameterSpec getECParameterSpec(String namedCurveOid) {
-        return ECUtil.getECParameterSpec(cryptoProvider, namedCurveOid);
-    }
-
-    static String getNamedCurveOid(ECParameterSpec params) {
-        return ECUtil.getCurveName(cryptoProvider, params);
-    }
-
-    static ECPoint decodePoint(byte[] encoded, EllipticCurve curve)
-            throws java.io.IOException {
-        return ECUtil.decodePoint(encoded, curve);
-    }
-
-    static byte[] encodePoint(ECPoint point, EllipticCurve curve) {
-        return ECUtil.encodePoint(point, curve);
-    }
-
-    // In FIPS mode, set thread local providers; otherwise a no-op.
-    // Must be paired with endFipsProvider.
-    static Object beginFipsProvider() {
-        if (fipsProviderList == null) {
-            return null;
-        } else {
-            return Providers.beginThreadProviderList(fipsProviderList);
-        }
-    }
-
-    static void endFipsProvider(Object o) {
-        if (fipsProviderList != null) {
-            Providers.endThreadProviderList((ProviderList)o);
-        }
-    }
-
-
-    // lazy initialization holder class idiom for static default parameters
-    //
-    // See Effective Java Second Edition: Item 71.
-    private static class EcAvailability {
-        // Is EC crypto available?
-        private final static boolean isAvailable;
-
-        static {
-            boolean mediator = true;
-            try {
-                JsseJce.getSignature(SIGNATURE_ECDSA);
-                JsseJce.getSignature(SIGNATURE_RAWECDSA);
-                JsseJce.getKeyAgreement("ECDH");
-                JsseJce.getKeyFactory("EC");
-                JsseJce.getKeyPairGenerator("EC");
-                JsseJce.getAlgorithmParameters("EC");
-            } catch (Exception e) {
-                mediator = false;
-            }
-
-            isAvailable = mediator;
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.List;
-import java.util.Collections;
-
-import java.security.*;
-import java.security.KeyStore.*;
-
-import javax.net.ssl.*;
-
-abstract class KeyManagerFactoryImpl extends KeyManagerFactorySpi {
-
-    X509ExtendedKeyManager keyManager;
-    boolean isInitialized;
-
-    KeyManagerFactoryImpl() {
-        // empty
-    }
-
-    /**
-     * Returns one key manager for each type of key material.
-     */
-    @Override
-    protected KeyManager[] engineGetKeyManagers() {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                        "KeyManagerFactoryImpl is not initialized");
-        }
-        return new KeyManager[] { keyManager };
-    }
-
-    // Factory for the SunX509 keymanager
-    public static final class SunX509 extends KeyManagerFactoryImpl {
-
-        @Override
-        protected void engineInit(KeyStore ks, char[] password) throws
-                KeyStoreException, NoSuchAlgorithmException,
-                UnrecoverableKeyException {
-            if ((ks != null) && SunJSSE.isFIPS()) {
-                if (ks.getProvider() != SunJSSE.cryptoProvider) {
-                    throw new KeyStoreException("FIPS mode: KeyStore must be "
-                        + "from provider " + SunJSSE.cryptoProvider.getName());
-                }
-            }
-            keyManager = new SunX509KeyManagerImpl(ks, password);
-            isInitialized = true;
-        }
-
-        @Override
-        protected void engineInit(ManagerFactoryParameters spec) throws
-                InvalidAlgorithmParameterException {
-            throw new InvalidAlgorithmParameterException(
-                "SunX509KeyManager does not use ManagerFactoryParameters");
-        }
-
-    }
-
-    // Factory for the X509 keymanager
-    public static final class X509 extends KeyManagerFactoryImpl {
-
-        @Override
-        protected void engineInit(KeyStore ks, char[] password) throws
-                KeyStoreException, NoSuchAlgorithmException,
-                UnrecoverableKeyException {
-            if (ks == null) {
-                keyManager = new X509KeyManagerImpl(
-                        Collections.<Builder>emptyList());
-            } else {
-                if (SunJSSE.isFIPS() && (ks.getProvider() != SunJSSE.cryptoProvider)) {
-                    throw new KeyStoreException("FIPS mode: KeyStore must be "
-                        + "from provider " + SunJSSE.cryptoProvider.getName());
-                }
-                try {
-                    Builder builder = Builder.newInstance(ks,
-                        new PasswordProtection(password));
-                    keyManager = new X509KeyManagerImpl(builder);
-                } catch (RuntimeException e) {
-                    throw new KeyStoreException("initialization failed", e);
-                }
-            }
-            isInitialized = true;
-        }
-
-        @Override
-        protected void engineInit(ManagerFactoryParameters params) throws
-                InvalidAlgorithmParameterException {
-            if (params instanceof KeyStoreBuilderParameters == false) {
-                throw new InvalidAlgorithmParameterException(
-                "Parameters must be instance of KeyStoreBuilderParameters");
-            }
-            if (SunJSSE.isFIPS()) {
-                // XXX should be fixed
-                throw new InvalidAlgorithmParameterException
-                    ("FIPS mode: KeyStoreBuilderParameters not supported");
-            }
-            List<Builder> builders =
-                ((KeyStoreBuilderParameters)params).getParameters();
-            keyManager = new X509KeyManagerImpl(builders);
-            isInitialized = true;
-        }
-
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/MAC.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, 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.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-
-import java.nio.ByteBuffer;
-
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-
-import sun.security.ssl.CipherSuite.MacAlg;
-import static sun.security.ssl.CipherSuite.*;
-
-/**
- * This class computes the "Message Authentication Code" (MAC) for each
- * SSL stream and block cipher message.  This is essentially a shared-secret
- * signature, used to provide integrity protection for SSL messages.  The
- * MAC is actually one of several keyed hashes, as associated with the cipher
- * suite and protocol version. (SSL v3.0 uses one construct, TLS uses another.)
- *
- * @author David Brownell
- * @author Andreas Sterbenz
- */
-final class MAC extends Authenticator {
-
-    final static MAC NULL = new MAC();
-
-    // Value of the null MAC is fixed
-    private static final byte nullMAC[] = new byte[0];
-
-    // internal identifier for the MAC algorithm
-    private final MacAlg        macAlg;
-
-    // JCE Mac object
-    private final Mac mac;
-
-    private MAC() {
-        macAlg = M_NULL;
-        mac = null;
-    }
-
-    /**
-     * Set up, configured for the given SSL/TLS MAC type and version.
-     */
-    MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
-            throws NoSuchAlgorithmException, InvalidKeyException {
-        super(protocolVersion);
-        this.macAlg = macAlg;
-
-        String algorithm;
-        boolean tls = (protocolVersion.v >= ProtocolVersion.TLS10.v);
-
-        if (macAlg == M_MD5) {
-            algorithm = tls ? "HmacMD5" : "SslMacMD5";
-        } else if (macAlg == M_SHA) {
-            algorithm = tls ? "HmacSHA1" : "SslMacSHA1";
-        } else if (macAlg == M_SHA256) {
-            algorithm = "HmacSHA256";    // TLS 1.2+
-        } else if (macAlg == M_SHA384) {
-            algorithm = "HmacSHA384";    // TLS 1.2+
-        } else {
-            throw new RuntimeException("Unknown Mac " + macAlg);
-        }
-
-        mac = JsseJce.getMac(algorithm);
-        mac.init(key);
-    }
-
-    /**
-     * Returns the length of the MAC.
-     */
-    int MAClen() {
-        return macAlg.size;
-    }
-
-    /**
-     * Returns the hash function block length of the MAC alorithm.
-     */
-    int hashBlockLen() {
-        return macAlg.hashBlockSize;
-    }
-
-    /**
-     * Returns the hash function minimal padding length of the MAC alorithm.
-     */
-    int minimalPaddingLen() {
-        return macAlg.minimalPaddingSize;
-    }
-
-    /**
-     * Computes and returns the MAC for the data in this byte array.
-     *
-     * @param type record type
-     * @param buf compressed record on which the MAC is computed
-     * @param offset start of compressed record data
-     * @param len the size of the compressed record
-     * @param isSimulated if true, simulate the the MAC computation
-     */
-    final byte[] compute(byte type, byte buf[],
-            int offset, int len, boolean isSimulated) {
-        if (macAlg.size == 0) {
-            return nullMAC;
-        }
-
-        if (!isSimulated) {
-            byte[] additional = acquireAuthenticationBytes(type, len);
-            mac.update(additional);
-        }
-        mac.update(buf, offset, len);
-
-        return mac.doFinal();
-    }
-
-    /**
-     * Compute and returns the MAC for the remaining data
-     * in this ByteBuffer.
-     *
-     * On return, the bb position == limit, and limit will
-     * have not changed.
-     *
-     * @param type record type
-     * @param bb a ByteBuffer in which the position and limit
-     *          demarcate the data to be MAC'd.
-     * @param isSimulated if true, simulate the the MAC computation
-     */
-    final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) {
-        if (macAlg.size == 0) {
-            return nullMAC;
-        }
-
-        if (!isSimulated) {
-            byte[] additional =
-                    acquireAuthenticationBytes(type, bb.remaining());
-            mac.update(additional);
-        }
-        mac.update(bb);
-
-        return mac.doFinal();
-    }
-
-}
-
--- a/src/share/classes/sun/security/ssl/OutputRecord.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,573 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, 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.*;
-import java.nio.*;
-import java.util.Arrays;
-
-import javax.net.ssl.SSLException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * SSL 3.0 records, as written to a TCP stream.
- *
- * Each record has a message area that starts out with data supplied by the
- * application.  It may grow/shrink due to compression and will be modified
- * in place for mac-ing and encryption.
- *
- * Handshake records have additional needs, notably accumulation of a set
- * of hashes which are used to establish that handshaking was done right.
- * Handshake records usually have several handshake messages each, and we
- * need message-level control over what's hashed.
- *
- * @author David Brownell
- */
-class OutputRecord extends ByteArrayOutputStream implements Record {
-
-    private HandshakeHash       handshakeHash;
-    private int                 lastHashed;
-    private boolean             firstMessage;
-    final private byte          contentType;
-    private int                 headerOffset;
-
-    // current protocol version, sent as record version
-    ProtocolVersion     protocolVersion;
-
-    // version for the ClientHello message. Only relevant if this is a
-    // client handshake record. If set to ProtocolVersion.SSL20Hello,
-    // the V3 client hello is converted to V2 format.
-    private ProtocolVersion     helloVersion;
-
-    /* Class and subclass dynamic debugging support */
-    static final Debug debug = Debug.getInstance("ssl");
-
-    /*
-     * Default constructor makes a record supporting the maximum
-     * SSL record size.  It allocates the header bytes directly.
-     *
-     * The structure of the byte buffer looks like:
-     *
-     *     |---------+--------+-------+---------------------------------|
-     *     | unused  | header |  IV   | content, MAC/TAG, padding, etc. |
-     *     |    headerPlusMaxIVSize   |
-     *
-     * unused: unused part of the buffer of size
-     *
-     *             headerPlusMaxIVSize - header size - IV size
-     *
-     *         When this object is created, we don't know the protocol
-     *         version number, IV length, etc., so reserve space in front
-     *         to avoid extra data movement (copies).
-     * header: the header of an SSL record
-     * IV:     the optional IV/nonce field, it is only required for block
-     *         (TLS 1.1 or later) and AEAD cipher suites.
-     *
-     * @param type the content type for the record
-     */
-    OutputRecord(byte type, int size) {
-        super(size);
-        this.protocolVersion = ProtocolVersion.DEFAULT;
-        this.helloVersion = ProtocolVersion.DEFAULT_HELLO;
-        firstMessage = true;
-        count = headerPlusMaxIVSize;
-        contentType = type;
-        lastHashed = count;
-        headerOffset = headerPlusMaxIVSize - headerSize;
-    }
-
-    OutputRecord(byte type) {
-        this(type, recordSize(type));
-    }
-
-    /**
-     * Get the size of the buffer we need for records of the specified
-     * type.
-     */
-    private static int recordSize(byte type) {
-        if ((type == ct_change_cipher_spec) || (type == ct_alert)) {
-            return maxAlertRecordSize;
-        } else {
-            return maxRecordSize;
-        }
-    }
-
-    /*
-     * Updates the SSL version of this record.
-     */
-    synchronized void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-    }
-
-    /*
-     * Updates helloVersion of this record.
-     */
-    synchronized void setHelloVersion(ProtocolVersion helloVersion) {
-        this.helloVersion = helloVersion;
-    }
-
-    /*
-     * Reset the record so that it can be refilled, starting
-     * immediately after the header.
-     */
-    @Override
-    public synchronized void reset() {
-        super.reset();
-        count = headerPlusMaxIVSize;
-        lastHashed = count;
-        headerOffset = headerPlusMaxIVSize - headerSize;
-    }
-
-    /*
-     * For handshaking, we need to be able to hash every byte above the
-     * record marking layer.  This is where we're guaranteed to see those
-     * bytes, so this is where we can hash them.
-     */
-    void setHandshakeHash(HandshakeHash handshakeHash) {
-        assert(contentType == ct_handshake);
-        this.handshakeHash = handshakeHash;
-    }
-
-    /*
-     * We hash (the plaintext) on demand.  There is one place where
-     * we want to access the hash in the middle of a record:  client
-     * cert message gets hashed, and part of the same record is the
-     * client cert verify message which uses that hash.  So we track
-     * how much of each record we've hashed so far.
-     */
-    void doHashes() {
-        int len = count - lastHashed;
-
-        if (len > 0) {
-            hashInternal(buf, lastHashed, len);
-            lastHashed = count;
-        }
-    }
-
-    /*
-     * Need a helper function so we can hash the V2 hello correctly
-     */
-    private void hashInternal(byte buf [], int offset, int len) {
-        if (debug != null && Debug.isOn("data")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-
-                System.out.println("[write] MD5 and SHA1 hashes:  len = "
-                    + len);
-                hd.encodeBuffer(new ByteArrayInputStream(buf,
-                    lastHashed, len), System.out);
-            } catch (IOException e) { }
-        }
-
-        handshakeHash.update(buf, lastHashed, len);
-        lastHashed = count;
-    }
-
-    /*
-     * Return true iff the record is empty -- to avoid doing the work
-     * of sending empty records over the network.
-     */
-    boolean isEmpty() {
-        return count == headerPlusMaxIVSize;
-    }
-
-    /*
-     * Return true if the record is of an alert of the given description.
-     *
-     * Per SSL/TLS specifications, alert messages convey the severity of the
-     * message (warning or fatal) and a description of the alert. An alert
-     * is defined with a two bytes struct, {byte level, byte description},
-     * following after the header bytes.
-     */
-    boolean isAlert(byte description) {
-        if ((count > (headerPlusMaxIVSize + 1)) && (contentType == ct_alert)) {
-            return buf[headerPlusMaxIVSize + 1] == description;
-        }
-
-        return false;
-    }
-
-    /*
-     * Encrypt ... length may grow due to block cipher padding, or
-     * message authentication code or tag.
-     */
-    void encrypt(Authenticator authenticator, CipherBox box)
-            throws IOException {
-
-        // In case we are automatically flushing a handshake stream, make
-        // sure we have hashed the message first.
-        //
-        // when we support compression, hashing can't go here
-        // since it'll need to be done on the uncompressed data,
-        // and the MAC applies to the compressed data.
-        if (contentType == ct_handshake) {
-            doHashes();
-        }
-
-        // Requires message authentication code for stream and block
-        // cipher suites.
-        if (authenticator instanceof MAC) {
-            MAC signer = (MAC)authenticator;
-            if (signer.MAClen() != 0) {
-                byte[] hash = signer.compute(contentType, buf,
-                    headerPlusMaxIVSize, count - headerPlusMaxIVSize, false);
-                write(hash);
-            }
-        }
-
-        if (!box.isNullCipher()) {
-            // Requires explicit IV/nonce for CBC/AEAD cipher suites for
-            // TLS 1.1 or later.
-            if ((protocolVersion.v >= ProtocolVersion.TLS11.v) &&
-                                    (box.isCBCMode() || box.isAEADMode())) {
-                byte[] nonce = box.createExplicitNonce(authenticator,
-                                    contentType, count - headerPlusMaxIVSize);
-                int offset = headerPlusMaxIVSize - nonce.length;
-                System.arraycopy(nonce, 0, buf, offset, nonce.length);
-                headerOffset = offset - headerSize;
-            } else {
-                headerOffset = headerPlusMaxIVSize - headerSize;
-            }
-
-            // encrypt the content
-            int offset = headerPlusMaxIVSize;
-            if (!box.isAEADMode()) {
-                // The explicit IV can be encrypted.
-                offset = headerOffset + headerSize;
-            }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
-
-            count = offset + box.encrypt(buf, offset, count - offset);
-        }
-    }
-
-    /*
-     * Tell how full the buffer is ... for filling it with application or
-     * handshake data.
-     */
-    final int availableDataBytes() {
-        int dataSize = count - headerPlusMaxIVSize;
-        return maxDataSize - dataSize;
-    }
-
-    /*
-     * Increases the capacity if necessary to ensure that it can hold
-     * at least the number of elements specified by the minimum
-     * capacity argument.
-     *
-     * Note that the increased capacity is only can be used for held
-     * record buffer. Please DO NOT update the availableDataBytes()
-     * according to the expended buffer capacity.
-     *
-     * @see availableDataBytes()
-     */
-    private void ensureCapacity(int minCapacity) {
-        // overflow-conscious code
-        if (minCapacity > buf.length) {
-            buf = Arrays.copyOf(buf, minCapacity);
-        }
-    }
-
-    /*
-     * Return the type of SSL record that's buffered here.
-     */
-    final byte contentType() {
-        return contentType;
-    }
-
-    /*
-     * Write the record out on the stream.  Note that you must have (in
-     * order) compressed the data, appended the MAC, and encrypted it in
-     * order for the record to be understood by the other end.  (Some of
-     * those steps will be null early in handshaking.)
-     *
-     * Note that this does no locking for the connection, it's required
-     * that synchronization be done elsewhere.  Also, this does its work
-     * in a single low level write, for efficiency.
-     */
-    void write(OutputStream s, boolean holdRecord,
-            ByteArrayOutputStream heldRecordBuffer) throws IOException {
-
-        /*
-         * Don't emit content-free records.  (Even change cipher spec
-         * messages have a byte of data!)
-         */
-        if (count == headerPlusMaxIVSize) {
-            return;
-        }
-
-        int length = count - headerOffset - headerSize;
-        // "should" really never write more than about 14 Kb...
-        if (length < 0) {
-            throw new SSLException("output record size too small: "
-                + length);
-        }
-
-        if (debug != null
-                && (Debug.isOn("record") || Debug.isOn("handshake"))) {
-            if ((debug != null && Debug.isOn("record"))
-                    || contentType() == ct_change_cipher_spec)
-                System.out.println(Thread.currentThread().getName()
-                    // v3.0/v3.1 ...
-                    + ", WRITE: " + protocolVersion
-                    + " " + InputRecord.contentName(contentType())
-                    + ", length = " + length);
-        }
-
-        /*
-         * If this is the initial ClientHello on this connection and
-         * we're not trying to resume a (V3) session then send a V2
-         * ClientHello instead so we can detect V2 servers cleanly.
-         */
-         if (firstMessage && useV2Hello()) {
-            byte[] v3Msg = new byte[length - 4];
-            System.arraycopy(buf, headerPlusMaxIVSize + 4,
-                                        v3Msg, 0, v3Msg.length);
-            headerOffset = 0;   // reset the header offset
-            V3toV2ClientHello(v3Msg);
-            handshakeHash.reset();
-            lastHashed = 2;
-            doHashes();
-            if (debug != null && Debug.isOn("record"))  {
-                System.out.println(
-                    Thread.currentThread().getName()
-                    + ", WRITE: SSLv2 client hello message"
-                    + ", length = " + (count - 2)); // 2 byte SSLv2 header
-            }
-        } else {
-            /*
-             * Fill out the header, write it and the message.
-             */
-            buf[headerOffset + 0] = contentType;
-            buf[headerOffset + 1] = protocolVersion.major;
-            buf[headerOffset + 2] = protocolVersion.minor;
-            buf[headerOffset + 3] = (byte)(length >> 8);
-            buf[headerOffset + 4] = (byte)(length);
-        }
-        firstMessage = false;
-
-        /*
-         * The upper levels may want us to delay sending this packet so
-         * multiple TLS Records can be sent in one (or more) TCP packets.
-         * If so, add this packet to the heldRecordBuffer.
-         *
-         * NOTE:  all writes have been synchronized by upper levels.
-         */
-        int debugOffset = 0;
-        if (holdRecord) {
-            /*
-             * If holdRecord is true, we must have a heldRecordBuffer.
-             *
-             * Don't worry about the override of writeBuffer(), because
-             * when holdRecord is true, the implementation in this class
-             * will be used.
-             */
-            writeBuffer(heldRecordBuffer,
-                        buf, headerOffset, count - headerOffset, debugOffset);
-        } else {
-            // It's time to send, do we have buffered data?
-            // May or may not have a heldRecordBuffer.
-            if (heldRecordBuffer != null && heldRecordBuffer.size() > 0) {
-                int heldLen = heldRecordBuffer.size();
-
-                // Ensure the capacity of this buffer.
-                int newCount = count + heldLen - headerOffset;
-                ensureCapacity(newCount);
-
-                // Slide everything in the buffer to the right.
-                System.arraycopy(buf, headerOffset,
-                                    buf, heldLen, count - headerOffset);
-
-                // Prepend the held record to the buffer.
-                System.arraycopy(
-                    heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen);
-                count = newCount;
-                headerOffset = 0;
-
-                // Clear the held buffer.
-                heldRecordBuffer.reset();
-
-                // The held buffer has been dumped, set the debug dump offset.
-                debugOffset = heldLen;
-            }
-            writeBuffer(s, buf, headerOffset,
-                        count - headerOffset, debugOffset);
-        }
-
-        reset();
-    }
-
-    /*
-     * Actually do the write here.  For SSLEngine's HS data,
-     * we'll override this method and let it take the appropriate
-     * action.
-     */
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len,
-            int debugOffset) throws IOException {
-        s.write(buf, off, len);
-        s.flush();
-
-        // Output only the record from the specified debug offset.
-        if (debug != null && Debug.isOn("packet")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-
-                System.out.println("[Raw write]: length = " +
-                                                    (len - debugOffset));
-                hd.encodeBuffer(new ByteArrayInputStream(buf,
-                    off + debugOffset, len - debugOffset), System.out);
-            } catch (IOException e) { }
-        }
-    }
-
-    /*
-     * Return whether the buffer contains a ClientHello message that should
-     * be converted to V2 format.
-     */
-    private boolean useV2Hello() {
-        return firstMessage
-            && (helloVersion == ProtocolVersion.SSL20Hello)
-            && (contentType == ct_handshake)
-            && (buf[headerOffset + 5] == HandshakeMessage.ht_client_hello)
-                                            //  5: recode header size
-            && (buf[headerPlusMaxIVSize + 4 + 2 + 32] == 0);
-                                            // V3 session ID is empty
-                                            //  4: handshake header size
-                                            //  2: client_version in ClientHello
-                                            // 32: random in ClientHello
-    }
-
-    /*
-     * Detect "old" servers which are capable of SSL V2.0 protocol ... for
-     * example, Netscape Commerce 1.0 servers.  The V3 message is in the
-     * header and the bytes passed as parameter.  This routine translates
-     * the V3 message into an equivalent V2 one.
-     *
-     * Note that the translation will strip off all hello extensions as
-     * SSL V2.0 does not support hello extension.
-     */
-    private void V3toV2ClientHello(byte v3Msg []) throws SSLException {
-        int v3SessionIdLenOffset = 2 + 32; // version + nonce
-        int v3SessionIdLen = v3Msg[v3SessionIdLenOffset];
-        int v3CipherSpecLenOffset = v3SessionIdLenOffset + 1 + v3SessionIdLen;
-        int v3CipherSpecLen = ((v3Msg[v3CipherSpecLenOffset] & 0xff) << 8) +
-          (v3Msg[v3CipherSpecLenOffset + 1] & 0xff);
-        int cipherSpecs = v3CipherSpecLen / 2; // 2 bytes each in V3
-
-        /*
-         * Copy over the cipher specs. We don't care about actually translating
-         * them for use with an actual V2 server since we only talk V3.
-         * Therefore, just copy over the V3 cipher spec values with a leading
-         * 0.
-         */
-        int v3CipherSpecOffset = v3CipherSpecLenOffset + 2; // skip length
-        int v2CipherSpecLen = 0;
-        count = 11;
-        boolean containsRenegoInfoSCSV = false;
-        for (int i = 0; i < cipherSpecs; i++) {
-            byte byte1, byte2;
-
-            byte1 = v3Msg[v3CipherSpecOffset++];
-            byte2 = v3Msg[v3CipherSpecOffset++];
-            v2CipherSpecLen += V3toV2CipherSuite(byte1, byte2);
-            if (!containsRenegoInfoSCSV &&
-                        byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
-                containsRenegoInfoSCSV = true;
-            }
-        }
-
-        if (!containsRenegoInfoSCSV) {
-            v2CipherSpecLen += V3toV2CipherSuite((byte)0x00, (byte)0xFF);
-        }
-
-        /*
-         * Build the first part of the V3 record header from the V2 one
-         * that's now buffered up.  (Lengths are fixed up later).
-         */
-        buf[2] = HandshakeMessage.ht_client_hello;
-        buf[3] = v3Msg[0];      // major version
-        buf[4] = v3Msg[1];      // minor version
-        buf[5] = (byte)(v2CipherSpecLen >>> 8);
-        buf[6] = (byte)v2CipherSpecLen;
-        buf[7] = 0;
-        buf[8] = 0;             // always no session
-        buf[9] = 0;
-        buf[10] = 32;           // nonce length (always 32 in V3)
-
-        /*
-         * Copy in the nonce.
-         */
-        System.arraycopy(v3Msg, 2, buf, count, 32);
-        count += 32;
-
-        /*
-         * Set the length of the message.
-         */
-        count -= 2; // don't include length field itself
-        buf[0] = (byte)(count >>> 8);
-        buf[0] |= 0x80;
-        buf[1] = (byte)(count);
-        count += 2;
-    }
-
-    /*
-     * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
-     * This is taken from the SSL V3 specification, Appendix E.
-     */
-    private static int[] V3toV2CipherMap1 =
-        {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
-    private static int[] V3toV2CipherMap3 =
-        {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
-
-    /*
-     * See which matching pure-V2 cipher specs we need to include.
-     * We are including these not because we are actually prepared
-     * to talk V2 but because the Oracle Web Server insists on receiving
-     * at least 1 "pure V2" cipher suite that it supports and returns an
-     * illegal_parameter alert unless one is present. Rather than mindlessly
-     * claiming to implement all documented pure V2 cipher suites the code below
-     * just claims to implement the V2 cipher suite that is "equivalent"
-     * in terms of cipher algorithm & exportability with the actual V3 cipher
-     * suite that we do support.
-     */
-    private int V3toV2CipherSuite(byte byte1, byte byte2) {
-        buf[count++] = 0;
-        buf[count++] = byte1;
-        buf[count++] = byte2;
-
-        if (((byte2 & 0xff) > 0xA) ||
-                (V3toV2CipherMap1[byte2] == -1)) {
-            return 3;
-        }
-
-        buf[count++] = (byte)V3toV2CipherMap1[byte2];
-        buf[count++] = 0;
-        buf[count++] = (byte)V3toV2CipherMap3[byte2];
-
-        return 6;
-    }
-}
--- a/src/share/classes/sun/security/ssl/ProtocolList.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-
-/**
- * A list of ProtocolVersions. Also maintains the list of supported protocols.
- * Instances of this class are immutable. Some member variables are final
- * and can be accessed directly without method accessors.
- *
- * @author  Andreas Sterbenz
- * @since   1.4.1
- */
-final class ProtocolList {
-
-    // the sorted protocol version list
-    private final ArrayList<ProtocolVersion> protocols;
-
-    private String[] protocolNames;
-
-    // the minimum and maximum ProtocolVersions in this list
-    final ProtocolVersion min, max;
-
-    // the format for the hello version to use
-    final ProtocolVersion helloVersion;
-
-    ProtocolList(String[] names) {
-        this(convert(names));
-    }
-
-    ProtocolList(ArrayList<ProtocolVersion> versions) {
-        this.protocols = versions;
-
-        if ((protocols.size() == 1) &&
-                protocols.contains(ProtocolVersion.SSL20Hello)) {
-            throw new IllegalArgumentException("SSLv2Hello cannot be " +
-                "enabled unless at least one other supported version " +
-                "is also enabled.");
-        }
-
-        if (protocols.size() != 0) {
-            Collections.sort(protocols);
-            min = protocols.get(0);
-            max = protocols.get(protocols.size() - 1);
-            helloVersion = protocols.get(0);
-        } else {
-            min = ProtocolVersion.NONE;
-            max = ProtocolVersion.NONE;
-            helloVersion = ProtocolVersion.NONE;
-        }
-    }
-
-    private static ArrayList<ProtocolVersion> convert(String[] names) {
-        if (names == null) {
-            throw new IllegalArgumentException("Protocols may not be null");
-        }
-
-        ArrayList<ProtocolVersion> versions = new ArrayList<>(names.length);
-        for (int i = 0; i < names.length; i++ ) {
-            ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
-            if (versions.contains(version) == false) {
-                versions.add(version);
-            }
-        }
-
-        return versions;
-    }
-
-    /**
-     * Return whether this list contains the specified protocol version.
-     * SSLv2Hello is not a real protocol version we support, we always
-     * return false for it.
-     */
-    boolean contains(ProtocolVersion protocolVersion) {
-        if (protocolVersion == ProtocolVersion.SSL20Hello) {
-            return false;
-        }
-        return protocols.contains(protocolVersion);
-    }
-
-    /**
-     * Return a reference to the internal Collection of CipherSuites.
-     * The Collection MUST NOT be modified.
-     */
-    Collection<ProtocolVersion> collection() {
-        return protocols;
-    }
-
-    /**
-     * Select a protocol version from the list.
-     *
-     * Return the lower of the protocol version of that suggested by
-     * the <code>protocolVersion</code> and the highest version of this
-     * protocol list, or null if no protocol version is available.
-     *
-     * The method is used by TLS server to negotiated the protocol
-     * version between client suggested protocol version in the
-     * client hello and protocol versions supported by the server.
-     */
-    ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
-        ProtocolVersion selectedVersion = null;
-        for (ProtocolVersion pv : protocols) {
-            if (pv.v > protocolVersion.v) {
-                break;  // Safe to break here as this.protocols is sorted
-            }
-            selectedVersion = pv;
-        }
-
-        return selectedVersion;
-    }
-
-    /**
-     * Return an array with the names of the ProtocolVersions in this list.
-     */
-    synchronized String[] toStringArray() {
-        if (protocolNames == null) {
-            protocolNames = new String[protocols.size()];
-            int i = 0;
-            for (ProtocolVersion version : protocols) {
-                protocolNames[i++] = version.name;
-            }
-        }
-        return protocolNames.clone();
-    }
-
-    @Override
-    public String toString() {
-        return protocols.toString();
-    }
-}
--- a/src/share/classes/sun/security/ssl/ProtocolVersion.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-import java.security.CryptoPrimitive;
-
-/**
- * Type safe enum for an SSL/TLS protocol version. Instances are obtained
- * using the static factory methods or by referencing the static members
- * in this class. Member variables are final and can be accessed without
- * accessor methods.
- *
- * There is only ever one instance per supported protocol version, this
- * means == can be used for comparision instead of equals() if desired.
- *
- * Checks for a particular version number should generally take this form:
- *
- * if (protocolVersion.v >= ProtocolVersion.TLS10) {
- *   // TLS 1.0 code goes here
- * } else {
- *   // SSL 3.0 code here
- * }
- *
- * @author  Andreas Sterbenz
- * @since   1.4.1
- */
-public final class ProtocolVersion implements Comparable<ProtocolVersion> {
-
-    // The limit of maximum protocol version
-    final static int LIMIT_MAX_VALUE = 0xFFFF;
-
-    // The limit of minimum protocol version
-    final static int LIMIT_MIN_VALUE = 0x0000;
-
-    // Dummy protocol version value for invalid SSLSession
-    final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
-
-    // If enabled, send/ accept SSLv2 hello messages
-    final static ProtocolVersion SSL20Hello = new ProtocolVersion(0x0002,
-                                                                "SSLv2Hello");
-
-    // SSL 3.0
-    final static ProtocolVersion SSL30 = new ProtocolVersion(0x0300, "SSLv3");
-
-    // TLS 1.0
-    final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
-
-    // TLS 1.1
-    final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
-
-    // TLS 1.2
-    final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
-
-    private static final boolean FIPS = SunJSSE.isFIPS();
-
-    // minimum version we implement (SSL 3.0)
-    final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
-
-    // maximum version we implement (TLS 1.2)
-    final static ProtocolVersion MAX = TLS12;
-
-    // ProtocolVersion to use by default (TLS 1.2)
-    final static ProtocolVersion DEFAULT = TLS12;
-
-    // Default version for hello messages (SSLv2Hello)
-    final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
-
-    // Available protocols
-    //
-    // Including all supported protocols except the disabled ones.
-    final static Set<ProtocolVersion> availableProtocols;
-
-    // version in 16 bit MSB format as it appears in records and
-    // messages, i.e. 0x0301 for TLS 1.0
-    public final int v;
-
-    // major and minor version
-    public final byte major, minor;
-
-    // name used in JSSE (e.g. TLSv1 for TLS 1.0)
-    final String name;
-
-    // Initialize the available protocols.
-    static {
-        Set<ProtocolVersion> protocols = new HashSet<>(5);
-
-        ProtocolVersion[] pvs = new ProtocolVersion[] {
-                SSL20Hello, SSL30, TLS10, TLS11, TLS12};
-        for (ProtocolVersion p : pvs) {
-            if (SSLAlgorithmConstraints.DEFAULT_SSL_ONLY.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                    p.name, null)) {
-                protocols.add(p);
-            }
-        }
-
-        availableProtocols =
-                Collections.<ProtocolVersion>unmodifiableSet(protocols);
-    }
-
-    // private
-    private ProtocolVersion(int v, String name) {
-        this.v = v;
-        this.name = name;
-        major = (byte)(v >>> 8);
-        minor = (byte)(v & 0xFF);
-    }
-
-    // private
-    private static ProtocolVersion valueOf(int v) {
-        if (v == SSL30.v) {
-            return SSL30;
-        } else if (v == TLS10.v) {
-            return TLS10;
-        } else if (v == TLS11.v) {
-            return TLS11;
-        } else if (v == TLS12.v) {
-            return TLS12;
-        } else if (v == SSL20Hello.v) {
-            return SSL20Hello;
-        } else {
-            int major = (v >>> 8) & 0xFF;
-            int minor = v & 0xFF;
-            return new ProtocolVersion(v, "Unknown-" + major + "." + minor);
-        }
-    }
-
-    /**
-     * Return a ProtocolVersion with the specified major and minor version
-     * numbers. Never throws exceptions.
-     */
-    public static ProtocolVersion valueOf(int major, int minor) {
-        return valueOf(((major & 0xFF) << 8) | (minor & 0xFF));
-    }
-
-    /**
-     * Return a ProtocolVersion for the given name.
-     *
-     * @exception IllegalArgumentException if name is null or does not
-     * identify a supported protocol
-     */
-    static ProtocolVersion valueOf(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("Protocol cannot be null");
-        }
-
-        if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
-            throw new IllegalArgumentException
-                ("Only TLS 1.0 or later allowed in FIPS mode");
-        }
-
-        if (name.equals(SSL30.name)) {
-            return SSL30;
-        } else if (name.equals(TLS10.name)) {
-            return TLS10;
-        } else if (name.equals(TLS11.name)) {
-            return TLS11;
-        } else if (name.equals(TLS12.name)) {
-            return TLS12;
-        } else if (name.equals(SSL20Hello.name)) {
-            return SSL20Hello;
-        } else {
-            throw new IllegalArgumentException(name);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    /**
-     * Compares this object with the specified object for order.
-     */
-    @Override
-    public int compareTo(ProtocolVersion protocolVersion) {
-        return this.v - protocolVersion.v;
-    }
-}
--- a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
-/*
- * Copyright (c) 1996, 2016, 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.*;
-import java.security.*;
-
-import javax.crypto.*;
-
-import javax.net.ssl.*;
-
-import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
-import sun.security.util.KeyUtil;
-
-/**
- * This is the client key exchange message (CLIENT --> SERVER) used with
- * all RSA key exchanges; it holds the RSA-encrypted pre-master secret.
- *
- * The message is encrypted using PKCS #1 block type 02 encryption with the
- * server's public key.  The padding and resulting message size is a function
- * of this server's public key modulus size, but the pre-master secret is
- * always exactly 48 bytes.
- *
- */
-final class RSAClientKeyExchange extends HandshakeMessage {
-
-    /*
-     * The following field values were encrypted with the server's public
-     * key (or temp key from server key exchange msg) and are presented
-     * here in DECRYPTED form.
-     */
-    private ProtocolVersion protocolVersion; // preMaster [0,1]
-    SecretKey preMaster;
-    private byte[] encrypted;           // same size as public modulus
-
-    /*
-     * Client randomly creates a pre-master secret and encrypts it
-     * using the server's RSA public key; only the server can decrypt
-     * it, using its RSA private key.  Result is the same size as the
-     * server's public key, and uses PKCS #1 block format 02.
-     */
-    RSAClientKeyExchange(ProtocolVersion protocolVersion,
-            ProtocolVersion maxVersion,
-            SecureRandom generator, PublicKey publicKey) throws IOException {
-        if (publicKey.getAlgorithm().equals("RSA") == false) {
-            throw new SSLKeyException("Public key not of type RSA: " +
-                publicKey.getAlgorithm());
-        }
-        this.protocolVersion = protocolVersion;
-
-        try {
-            String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
-                "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
-            KeyGenerator kg = JsseJce.getKeyGenerator(s);
-            kg.init(new TlsRsaPremasterSecretParameterSpec(
-                    maxVersion.v, protocolVersion.v), generator);
-            preMaster = kg.generateKey();
-
-            Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
-            cipher.init(Cipher.WRAP_MODE, publicKey, generator);
-            encrypted = cipher.wrap(preMaster);
-        } catch (GeneralSecurityException e) {
-            throw (SSLKeyException)new SSLKeyException
-                                ("RSA premaster secret error").initCause(e);
-        }
-    }
-
-    /*
-     * Retrieving the cipher's provider name for the debug purposes
-     * can throw an exception by itself.
-     */
-    private static String safeProviderName(Cipher cipher) {
-        try {
-            return cipher.getProvider().toString();
-        } catch (Exception e) {
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("Retrieving The Cipher provider name" +
-                        " caused exception " + e.getMessage());
-            }
-        }
-        try {
-            return cipher.toString() + " (provider name not available)";
-        } catch (Exception e) {
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("Retrieving The Cipher name" +
-                        " caused exception " + e.getMessage());
-            }
-        }
-        return "(cipher/provider names not available)";
-    }
-
-    /*
-     * Server gets the PKCS #1 (block format 02) data, decrypts
-     * it with its private key.
-     */
-    RSAClientKeyExchange(ProtocolVersion currentVersion,
-            ProtocolVersion maxVersion,
-            SecureRandom generator, HandshakeInStream input,
-            int messageSize, PrivateKey privateKey) throws IOException {
-
-        if (privateKey.getAlgorithm().equals("RSA") == false) {
-            throw new SSLKeyException("Private key not of type RSA: " +
-                 privateKey.getAlgorithm());
-        }
-
-        if (currentVersion.v >= ProtocolVersion.TLS10.v) {
-            encrypted = input.getBytes16();
-        } else {
-            encrypted = new byte [messageSize];
-            if (input.read(encrypted) != messageSize) {
-                throw new SSLProtocolException(
-                        "SSL: read PreMasterSecret: short read");
-            }
-        }
-
-        byte[] encoded = null;
-        try {
-            boolean needFailover = false;
-            Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
-            try {
-                // Try UNWRAP_MODE mode firstly.
-                cipher.init(Cipher.UNWRAP_MODE, privateKey,
-                        new TlsRsaPremasterSecretParameterSpec(
-                                maxVersion.v, currentVersion.v),
-                        generator);
-
-                // The provider selection can be delayed, please don't call
-                // any Cipher method before the call to Cipher.init().
-                needFailover = !KeyUtil.isOracleJCEProvider(
-                        cipher.getProvider().getName());
-            } catch (InvalidKeyException | UnsupportedOperationException iue) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("The Cipher provider "
-                            + safeProviderName(cipher)
-                            + " caused exception: " + iue.getMessage());
-                }
-
-                needFailover = true;
-            }
-
-            if (needFailover) {
-                // The cipher might be spoiled by unsuccessful call to init(),
-                // so request a fresh instance
-                cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
-
-                // Use DECRYPT_MODE and dispose the previous initialization.
-                cipher.init(Cipher.DECRYPT_MODE, privateKey);
-                boolean failed = false;
-                try {
-                    encoded = cipher.doFinal(encrypted);
-                } catch (BadPaddingException bpe) {
-                    // Note: encoded == null
-                    failed = true;
-                }
-                encoded = KeyUtil.checkTlsPreMasterSecretKey(
-                                maxVersion.v, currentVersion.v,
-                                generator, encoded, failed);
-                preMaster = generatePreMasterSecret(
-                                maxVersion.v, currentVersion.v,
-                                encoded, generator);
-            } else {
-                // the cipher should have been initialized
-                preMaster = (SecretKey)cipher.unwrap(encrypted,
-                        "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
-            }
-        } catch (InvalidKeyException ibk) {
-            // the message is too big to process with RSA
-            throw new SSLException(
-                "Unable to process PreMasterSecret", ibk);
-        } catch (Exception e) {
-            // unlikely to happen, otherwise, must be a provider exception
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("RSA premaster secret decryption error:");
-                e.printStackTrace(System.out);
-            }
-            throw new RuntimeException("Could not generate dummy secret", e);
-        }
-    }
-
-    // generate a premaster secret with the specified version number
-    @SuppressWarnings("deprecation")
-    private static SecretKey generatePreMasterSecret(
-            int clientVersion, int serverVersion,
-            byte[] encodedSecret, SecureRandom generator) {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("Generating a premaster secret");
-        }
-
-        try {
-            String s = ((clientVersion >= ProtocolVersion.TLS12.v) ?
-                "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
-            KeyGenerator kg = JsseJce.getKeyGenerator(s);
-            kg.init(new TlsRsaPremasterSecretParameterSpec(
-                    clientVersion, serverVersion, encodedSecret),
-                    generator);
-            return kg.generateKey();
-        } catch (InvalidAlgorithmParameterException |
-                NoSuchAlgorithmException iae) {
-            // unlikely to happen, otherwise, must be a provider exception
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("RSA premaster secret generation error:");
-                iae.printStackTrace(System.out);
-            }
-            throw new RuntimeException("Could not generate premaster secret", iae);
-        }
-    }
-
-    @Override
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
-    @Override
-    int messageLength() {
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            return encrypted.length + 2;
-        } else {
-            return encrypted.length;
-        }
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            s.putBytes16(encrypted);
-        } else {
-            s.write(encrypted);
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        String version = "version not available/extractable";
-
-        byte[] ba = preMaster.getEncoded();
-        if (ba != null && ba.length >= 2) {
-            version = ProtocolVersion.valueOf(ba[0], ba[1]).name;
-        }
-
-        s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + version);
-    }
-}
--- a/src/share/classes/sun/security/ssl/RSASignature.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-/*
- * Copyright (c) 1996, 2020, 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.security.*;
-import java.security.spec.AlgorithmParameterSpec;
-
-/**
- * Signature implementation for the SSL/TLS RSA Signature variant with both
- * MD5 and SHA-1 MessageDigests. Used for explicit RSA server authentication
- * (RSA signed server key exchange for RSA_EXPORT and DHE_RSA) and RSA client
- * authentication (RSA signed certificate verify message).
- *
- * It conforms to the standard JCA Signature API. It is registered in the
- * SunJSSE provider to avoid more complicated getInstance() code and
- * negative interaction with the JCA mechanisms for hardware providers.
- *
- * The class should be instantiated via the getInstance() method in this class,
- * which returns the implementation from the preferred provider. The internal
- * implementation allows the hashes to be explicitly set, which is required
- * for RSA client authentication. It can be obtained via the
- * getInternalInstance() method.
- *
- * This class is not thread safe.
- *
- */
-public final class RSASignature extends SignatureSpi {
-
-    private final Signature rawRsa;
-    private MessageDigest md5, sha;
-
-    // flag indicating if the MessageDigests are in reset state
-    private boolean isReset;
-
-    public RSASignature() throws NoSuchAlgorithmException {
-        super();
-        rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);
-        isReset = true;
-    }
-
-    /**
-     * Get an implementation for the RSA signature. Follows the standard
-     * JCA getInstance() model, so it return the implementation from the
-     * provider with the highest precedence, which may be this class.
-     */
-    static Signature getInstance() throws NoSuchAlgorithmException {
-        return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA);
-    }
-
-    /**
-     * Get an internal implementation for the RSA signature. Used for RSA
-     * client authentication, which needs the ability to set the digests
-     * to externally provided values via the setHashes() method.
-     */
-    static Signature getInternalInstance()
-            throws NoSuchAlgorithmException, NoSuchProviderException {
-        return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE");
-    }
-
-    /**
-     * Set the MD5 and SHA hashes to the provided objects.
-     */
-    static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) {
-        sig.setParameter("hashes", new MessageDigest[] {md5, sha});
-    }
-
-    /**
-     * Reset the MessageDigests unless they are already reset.
-     */
-    private void reset() {
-        if (isReset == false) {
-            md5.reset();
-            sha.reset();
-            isReset = true;
-        }
-    }
-
-    private static void checkNull(Key key) throws InvalidKeyException {
-        if (key == null) {
-            throw new InvalidKeyException("Key must not be null");
-        }
-    }
-
-    @Override
-    protected void engineInitVerify(PublicKey publicKey)
-            throws InvalidKeyException {
-        checkNull(publicKey);
-        reset();
-        rawRsa.initVerify(publicKey);
-    }
-
-    @Override
-    protected void engineInitSign(PrivateKey privateKey)
-            throws InvalidKeyException {
-        engineInitSign(privateKey, null);
-    }
-
-    @Override
-    protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
-            throws InvalidKeyException {
-        checkNull(privateKey);
-        reset();
-        rawRsa.initSign(privateKey, random);
-    }
-
-    // lazily initialize the MessageDigests
-    private void initDigests() {
-        if (md5 == null) {
-            md5 = JsseJce.getMD5();
-            sha = JsseJce.getSHA();
-        }
-    }
-
-    @Override
-    protected void engineUpdate(byte b) {
-        initDigests();
-        isReset = false;
-        md5.update(b);
-        sha.update(b);
-    }
-
-    @Override
-    protected void engineUpdate(byte[] b, int off, int len) {
-        initDigests();
-        isReset = false;
-        md5.update(b, off, len);
-        sha.update(b, off, len);
-    }
-
-    private byte[] getDigest() throws SignatureException {
-        try {
-            initDigests();
-            byte[] data = new byte[36];
-            md5.digest(data, 0, 16);
-            sha.digest(data, 16, 20);
-            isReset = true;
-            return data;
-        } catch (DigestException e) {
-            // should never occur
-            throw new SignatureException(e);
-        }
-    }
-
-    @Override
-    protected byte[] engineSign() throws SignatureException {
-        rawRsa.update(getDigest());
-        return rawRsa.sign();
-    }
-
-    @Override
-    protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
-        return engineVerify(sigBytes, 0, sigBytes.length);
-    }
-
-    @Override
-    protected boolean engineVerify(byte[] sigBytes, int offset, int length)
-            throws SignatureException {
-        rawRsa.update(getDigest());
-        return rawRsa.verify(sigBytes, offset, length);
-    }
-
-    @Override
-    protected void engineSetParameter(String param, Object value)
-            throws InvalidParameterException {
-        if (param.equals("hashes") == false) {
-            throw new InvalidParameterException
-                ("Parameter not supported: " + param);
-        }
-        if (value instanceof MessageDigest[] == false) {
-            throw new InvalidParameterException
-                ("value must be MessageDigest[]");
-        }
-        MessageDigest[] digests = (MessageDigest[])value;
-        md5 = digests[0];
-        sha = digests[1];
-    }
-
-    @Override
-    protected void engineSetParameter(AlgorithmParameterSpec params)
-            throws InvalidAlgorithmParameterException {
-        if (params != null) {
-            throw new InvalidAlgorithmParameterException("No parameters accepted");
-        }
-    }
-
-    @Override
-    protected Object engineGetParameter(String param)
-            throws InvalidParameterException {
-        throw new InvalidParameterException("Parameters not supported");
-    }
-
-    @Override
-    protected AlgorithmParameters engineGetParameters() {
-        return null;
-    }
-}
--- a/src/share/classes/sun/security/ssl/RandomCookie.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 1996, 2007, 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.*;
-import java.security.SecureRandom;
-
-/*
- * RandomCookie ... SSL hands standard format random cookies (nonces)
- * around.  These know how to encode/decode themselves on SSL streams,
- * and can be created and printed.
- *
- * @author David Brownell
- */
-final class RandomCookie {
-
-    byte random_bytes[];  // exactly 32 bytes
-
-    RandomCookie(SecureRandom generator) {
-        long temp = System.currentTimeMillis() / 1000;
-        int gmt_unix_time;
-        if (temp < Integer.MAX_VALUE) {
-            gmt_unix_time = (int) temp;
-        } else {
-            gmt_unix_time = Integer.MAX_VALUE;          // Whoops!
-        }
-
-        random_bytes = new byte[32];
-        generator.nextBytes(random_bytes);
-
-        random_bytes[0] = (byte)(gmt_unix_time >> 24);
-        random_bytes[1] = (byte)(gmt_unix_time >> 16);
-        random_bytes[2] = (byte)(gmt_unix_time >>  8);
-        random_bytes[3] = (byte)gmt_unix_time;
-    }
-
-    RandomCookie(HandshakeInStream m) throws IOException {
-        random_bytes = new byte[32];
-        m.read(random_bytes, 0, 32);
-    }
-
-    void send(HandshakeOutStream out) throws IOException {
-        out.write(random_bytes, 0, 32);
-    }
-
-    void print(PrintStream s) {
-        int i, gmt_unix_time;
-
-        gmt_unix_time = random_bytes[0] << 24;
-        gmt_unix_time += random_bytes[1] << 16;
-        gmt_unix_time += random_bytes[2] << 8;
-        gmt_unix_time += random_bytes[3];
-
-        s.print("GMT: " + gmt_unix_time + " ");
-        s.print("bytes = { ");
-
-        for (i = 4; i < 32; i++) {
-            if (i != 4) {
-                s.print(", ");
-            }
-            s.print(random_bytes[i] & 0x0ff);
-        }
-        s.println(" }");
-    }
-}
--- a/src/share/classes/sun/security/ssl/Record.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, 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;
-
-
-/**
- * SSL/TLS records, as pulled off (and put onto) a TCP stream.  This is
- * the base interface, which defines common information and interfaces
- * used by both Input and Output records.
- *
- * @author David Brownell
- */
-interface Record {
-    /*
-     * There are four SSL record types, which are part of the interface
-     * to this level (along with the maximum record size)
-     *
-     * enum { change_cipher_spec(20), alert(21), handshake(22),
-     *      application_data(23), (255) } ContentType;
-     */
-    static final byte   ct_change_cipher_spec = 20;
-    static final byte   ct_alert = 21;
-    static final byte   ct_handshake = 22;
-    static final byte   ct_application_data = 23;
-
-    static final int    headerSize = 5;         // SSLv3 record header
-    static final int    maxExpansion = 1024;    // for bad compression
-    static final int    trailerSize = 20;       // SHA1 hash size
-    static final int    maxDataSize = 16384;    // 2^14 bytes of data
-    static final int    maxPadding = 256;       // block cipher padding
-    static final int    maxIVLength = 256;      // IV length
-
-    /*
-     * The size of the header plus the max IV length
-     */
-    static final int    headerPlusMaxIVSize =
-                                      headerSize        // header
-                                    + maxIVLength;      // iv
-
-    /*
-     * SSL has a maximum record size.  It's header, (compressed) data,
-     * padding, and a trailer for the message authentication information (MAC
-     * for block and stream ciphers, and message authentication tag for AEAD
-     * ciphers).
-     *
-     * Some compression algorithms have rare cases where they expand the data.
-     * As we don't support compression at this time, leave that out.
-     */
-    static final int    maxRecordSize =
-                                      headerPlusMaxIVSize   // header + iv
-                                    + maxDataSize           // data
-                                    + maxPadding            // padding
-                                    + trailerSize;          // MAC or AEAD tag
-
-    static final boolean enableCBCProtection =
-            Debug.getBooleanProperty("jsse.enableCBCProtection", true);
-
-    /*
-     * For CBC protection in SSL3/TLS1, we break some plaintext into two
-     * packets.  Max application data size for the second packet.
-     */
-    static final int    maxDataSizeMinusOneByteRecord =
-                                  maxDataSize       // max data size
-                                - (                 // max one byte record size
-                                      headerPlusMaxIVSize   // header + iv
-                                    + 1             // one byte data
-                                    + maxPadding    // padding
-                                    + trailerSize   // MAC
-                                  );
-
-    /*
-     * The maximum large record size.
-     *
-     * Some SSL/TLS implementations support large fragment upto 2^15 bytes,
-     * such as Microsoft. We support large incoming fragments.
-     *
-     * The maximum large record size is defined as maxRecordSize plus 2^14,
-     * this is the amount OpenSSL is using.
-     */
-    static final int    maxLargeRecordSize =
-                maxRecordSize   // Max size with a conforming implementation
-              + maxDataSize;    // extra 2^14 bytes for large data packets.
-
-
-    /*
-     * Maximum record size for alert and change cipher spec records.
-     * They only contain 2 and 1 bytes of data, respectively.
-     * Allocate a smaller array.
-     */
-    static final int    maxAlertRecordSize =
-                                      headerPlusMaxIVSize   // header + iv
-                                    + 2                     // alert
-                                    + maxPadding            // padding
-                                    + trailerSize;          // MAC
-
-    /*
-     * The overflow values of integers of 8, 16 and 24 bits.
-     */
-    static final int OVERFLOW_OF_INT08 = (1 << 8);
-    static final int OVERFLOW_OF_INT16 = (1 << 16);
-    static final int OVERFLOW_OF_INT24 = (1 << 24);
-}
--- a/src/share/classes/sun/security/ssl/RenegotiationInfoExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2006, 2012, 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 javax.net.ssl.SSLProtocolException;
-
-/*
- * For secure renegotiation, RFC5746 defines a new TLS extension,
- * "renegotiation_info" (with extension type 0xff01), which contains a
- * cryptographic binding to the enclosing TLS connection (if any) for
- * which the renegotiation is being performed.  The "extension data"
- * field of this extension contains a "RenegotiationInfo" structure:
- *
- *      struct {
- *          opaque renegotiated_connection<0..255>;
- *      } RenegotiationInfo;
- */
-final class RenegotiationInfoExtension extends HelloExtension {
-    private final byte[] renegotiated_connection;
-
-    RenegotiationInfoExtension(byte[] clientVerifyData,
-                byte[] serverVerifyData) {
-        super(ExtensionType.EXT_RENEGOTIATION_INFO);
-
-        if (clientVerifyData.length != 0) {
-            renegotiated_connection =
-                    new byte[clientVerifyData.length + serverVerifyData.length];
-            System.arraycopy(clientVerifyData, 0, renegotiated_connection,
-                    0, clientVerifyData.length);
-
-            if (serverVerifyData.length != 0) {
-                System.arraycopy(serverVerifyData, 0, renegotiated_connection,
-                        clientVerifyData.length, serverVerifyData.length);
-            }
-        } else {
-            // ignore both the client and server verify data.
-            renegotiated_connection = new byte[0];
-        }
-    }
-
-    RenegotiationInfoExtension(HandshakeInStream s, int len)
-                throws IOException {
-        super(ExtensionType.EXT_RENEGOTIATION_INFO);
-
-        // check the extension length
-        if (len < 1) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        int renegoInfoDataLen = s.getInt8();
-        if (renegoInfoDataLen + 1 != len) {  // + 1 = the byte we just read
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        renegotiated_connection = new byte[renegoInfoDataLen];
-        if (renegoInfoDataLen != 0) {
-            s.read(renegotiated_connection, 0, renegoInfoDataLen);
-        }
-    }
-
-
-    // Length of the encoded extension, including the type and length fields
-    @Override
-    int length() {
-        return 5 + renegotiated_connection.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putInt16(renegotiated_connection.length + 1);
-        s.putBytes8(renegotiated_connection);
-    }
-
-    boolean isEmpty() {
-        return renegotiated_connection.length == 0;
-    }
-
-    byte[] getRenegotiatedConnection() {
-        return renegotiated_connection;
-    }
-
-    @Override
-    public String toString() {
-        return "Extension " + type + ", renegotiated_connection: " +
-                    (renegotiated_connection.length == 0 ? "<empty>" :
-                    Debug.toString(renegotiated_connection));
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.AlgorithmParameters;
-
-import javax.net.ssl.*;
-
-import java.security.Key;
-
-import java.util.Set;
-
-import sun.security.util.DisabledAlgorithmConstraints;
-import static sun.security.util.DisabledAlgorithmConstraints.*;
-import sun.security.ssl.CipherSuite.*;
-
-/**
- * Algorithm constraints for disabled algorithms property
- *
- * See the "jdk.certpath.disabledAlgorithms" specification in java.security
- * for the syntax of the disabled algorithm string.
- */
-final class SSLAlgorithmConstraints implements AlgorithmConstraints {
-
-    private final static AlgorithmConstraints tlsDisabledAlgConstraints =
-            new DisabledAlgorithmConstraints(PROPERTY_TLS_DISABLED_ALGS,
-                    new SSLAlgorithmDecomposer());
-
-    private final static AlgorithmConstraints x509DisabledAlgConstraints =
-            new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS,
-                    new SSLAlgorithmDecomposer(true));
-
-    private AlgorithmConstraints userAlgConstraints = null;
-    private AlgorithmConstraints peerAlgConstraints = null;
-
-    private boolean enabledX509DisabledAlgConstraints = true;
-
-    // the default algorithm constraints
-    final static AlgorithmConstraints DEFAULT =
-                        new SSLAlgorithmConstraints(null);
-
-    // the default SSL only algorithm constraints
-    final static AlgorithmConstraints DEFAULT_SSL_ONLY =
-                        new SSLAlgorithmConstraints((SSLSocket)null, false);
-
-    SSLAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
-        userAlgConstraints = algorithmConstraints;
-    }
-
-    SSLAlgorithmConstraints(SSLSocket socket,
-            boolean withDefaultCertPathConstraints) {
-        if (socket != null) {
-            userAlgConstraints =
-                socket.getSSLParameters().getAlgorithmConstraints();
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    SSLAlgorithmConstraints(SSLEngine engine,
-            boolean withDefaultCertPathConstraints) {
-        if (engine != null) {
-            userAlgConstraints =
-                engine.getSSLParameters().getAlgorithmConstraints();
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
-            boolean withDefaultCertPathConstraints) {
-        if (socket != null) {
-            userAlgConstraints =
-                socket.getSSLParameters().getAlgorithmConstraints();
-            peerAlgConstraints =
-                new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
-            boolean withDefaultCertPathConstraints) {
-        if (engine != null) {
-            userAlgConstraints =
-                engine.getSSLParameters().getAlgorithmConstraints();
-            peerAlgConstraints =
-                new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    @Override
-    public boolean permits(Set<CryptoPrimitive> primitives,
-            String algorithm, AlgorithmParameters parameters) {
-
-        boolean permitted = true;
-
-        if (peerAlgConstraints != null) {
-            permitted = peerAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        if (permitted && userAlgConstraints != null) {
-            permitted = userAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        if (permitted) {
-            permitted = tlsDisabledAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        if (permitted && enabledX509DisabledAlgConstraints) {
-            permitted = x509DisabledAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        return permitted;
-    }
-
-    @Override
-    public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
-
-        boolean permitted = true;
-
-        if (peerAlgConstraints != null) {
-            permitted = peerAlgConstraints.permits(primitives, key);
-        }
-
-        if (permitted && userAlgConstraints != null) {
-            permitted = userAlgConstraints.permits(primitives, key);
-        }
-
-        if (permitted) {
-            permitted = tlsDisabledAlgConstraints.permits(primitives, key);
-        }
-
-        if (permitted && enabledX509DisabledAlgConstraints) {
-            permitted = x509DisabledAlgConstraints.permits(primitives, key);
-        }
-
-        return permitted;
-    }
-
-    @Override
-    public boolean permits(Set<CryptoPrimitive> primitives,
-            String algorithm, Key key, AlgorithmParameters parameters) {
-
-        boolean permitted = true;
-
-        if (peerAlgConstraints != null) {
-            permitted = peerAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        if (permitted && userAlgConstraints != null) {
-            permitted = userAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        if (permitted) {
-            permitted = tlsDisabledAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        if (permitted && enabledX509DisabledAlgConstraints) {
-            permitted = x509DisabledAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        return permitted;
-    }
-
-
-    static private class SupportedSignatureAlgorithmConstraints
-                                    implements AlgorithmConstraints {
-        // supported signature algorithms
-        private String[] supportedAlgorithms;
-
-        SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
-            if (supportedAlgorithms != null) {
-                this.supportedAlgorithms = supportedAlgorithms.clone();
-            } else {
-                this.supportedAlgorithms = null;
-            }
-        }
-
-        @Override
-        public boolean permits(Set<CryptoPrimitive> primitives,
-                String algorithm, AlgorithmParameters parameters) {
-
-            if (algorithm == null || algorithm.length() == 0) {
-                throw new IllegalArgumentException(
-                        "No algorithm name specified");
-            }
-
-            if (primitives == null || primitives.isEmpty()) {
-                throw new IllegalArgumentException(
-                        "No cryptographic primitive specified");
-            }
-
-            if (supportedAlgorithms == null ||
-                        supportedAlgorithms.length == 0) {
-                return false;
-            }
-
-            // trim the MGF part: <digest>with<encryption>and<mgf>
-            int position = algorithm.indexOf("and");
-            if (position > 0) {
-                algorithm = algorithm.substring(0, position);
-            }
-
-            for (String supportedAlgorithm : supportedAlgorithms) {
-                if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        @Override
-        final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
-            return true;
-        }
-
-        @Override
-        final public boolean permits(Set<CryptoPrimitive> primitives,
-                String algorithm, Key key, AlgorithmParameters parameters) {
-
-            if (algorithm == null || algorithm.length() == 0) {
-                throw new IllegalArgumentException(
-                        "No algorithm name specified");
-            }
-
-            return permits(primitives, algorithm, parameters);
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-/*
- * 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.util.HashSet;
-import java.util.Set;
-import sun.security.util.AlgorithmDecomposer;
-import static sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * The class decomposes standard SSL/TLS cipher suites into sub-elements.
- */
-class SSLAlgorithmDecomposer extends AlgorithmDecomposer {
-
-    // indicates that only certification path algorithms need to be used
-    private final boolean onlyX509;
-
-    SSLAlgorithmDecomposer(boolean onlyX509) {
-        this.onlyX509 = onlyX509;
-    }
-
-    SSLAlgorithmDecomposer() {
-        this(false);
-    }
-
-    private Set<String> decomposes(CipherSuite.KeyExchange keyExchange) {
-        Set<String> components = new HashSet<>();
-        switch (keyExchange) {
-            case K_NULL:
-                if (!onlyX509) {
-                    components.add("K_NULL");
-                }
-                break;
-            case K_RSA:
-                components.add("RSA");
-                break;
-            case K_RSA_EXPORT:
-                components.add("RSA");
-                components.add("RSA_EXPORT");
-                break;
-            case K_DH_RSA:
-                components.add("RSA");
-                components.add("DH");
-                components.add("DiffieHellman");
-                components.add("DH_RSA");
-                break;
-            case K_DH_DSS:
-                components.add("DSA");
-                components.add("DSS");
-                components.add("DH");
-                components.add("DiffieHellman");
-                components.add("DH_DSS");
-                break;
-            case K_DHE_DSS:
-                components.add("DSA");
-                components.add("DSS");
-                components.add("DH");
-                components.add("DHE");
-                components.add("DiffieHellman");
-                components.add("DHE_DSS");
-                break;
-            case K_DHE_RSA:
-                components.add("RSA");
-                components.add("DH");
-                components.add("DHE");
-                components.add("DiffieHellman");
-                components.add("DHE_RSA");
-                break;
-            case K_DH_ANON:
-                if (!onlyX509) {
-                    components.add("ANON");
-                    components.add("DH");
-                    components.add("DiffieHellman");
-                    components.add("DH_ANON");
-                }
-                break;
-            case K_ECDH_ECDSA:
-                components.add("ECDH");
-                components.add("ECDSA");
-                components.add("ECDH_ECDSA");
-                break;
-            case K_ECDH_RSA:
-                components.add("ECDH");
-                components.add("RSA");
-                components.add("ECDH_RSA");
-                break;
-            case K_ECDHE_ECDSA:
-                components.add("ECDHE");
-                components.add("ECDSA");
-                components.add("ECDHE_ECDSA");
-                break;
-            case K_ECDHE_RSA:
-                components.add("ECDHE");
-                components.add("RSA");
-                components.add("ECDHE_RSA");
-                break;
-            case K_ECDH_ANON:
-                if (!onlyX509) {
-                    components.add("ECDH");
-                    components.add("ANON");
-                    components.add("ECDH_ANON");
-                }
-                break;
-            case K_KRB5:
-                if (!onlyX509) {
-                    components.add("KRB5");
-                }
-                break;
-            case K_KRB5_EXPORT:
-                if (!onlyX509) {
-                    components.add("KRB5_EXPORT");
-                }
-                break;
-            default:
-                // ignore
-            }
-
-        return components;
-    }
-
-    private Set<String> decomposes(CipherSuite.BulkCipher bulkCipher) {
-        Set<String> components = new HashSet<>();
-
-        if (bulkCipher.transformation != null) {
-            components.addAll(super.decompose(bulkCipher.transformation));
-        }
-
-        if (bulkCipher == B_NULL) {
-            components.add("C_NULL");
-        } else if (bulkCipher == B_RC2_40) {
-            components.add("RC2_CBC_40");
-        } else if (bulkCipher == B_RC4_40) {
-            components.add("RC4_40");
-        } else if (bulkCipher == B_RC4_128) {
-            components.add("RC4_128");
-        } else if (bulkCipher == B_DES_40) {
-            components.add("DES40_CBC");
-            components.add("DES_CBC_40");
-        } else if (bulkCipher == B_DES) {
-            components.add("DES_CBC");
-        } else if (bulkCipher == B_3DES) {
-            components.add("3DES_EDE_CBC");
-        } else if (bulkCipher == B_AES_128) {
-            components.add("AES_128_CBC");
-        } else if (bulkCipher == B_AES_256) {
-            components.add("AES_256_CBC");
-        } else if (bulkCipher == B_AES_128_GCM) {
-            components.add("AES_128_GCM");
-        } else if (bulkCipher == B_AES_256_GCM) {
-            components.add("AES_256_GCM");
-        }
-
-        return components;
-    }
-
-    private Set<String> decomposes(CipherSuite.MacAlg macAlg,
-            BulkCipher cipher) {
-        Set<String> components = new HashSet<>();
-
-        if (macAlg == M_NULL
-                && cipher.cipherType != CipherType.AEAD_CIPHER) {
-            components.add("M_NULL");
-        } else if (macAlg == M_MD5) {
-            components.add("MD5");
-            components.add("HmacMD5");
-        } else if (macAlg == M_SHA) {
-            components.add("SHA1");
-            components.add("SHA-1");
-            components.add("HmacSHA1");
-        } else if (macAlg == M_SHA256) {
-            components.add("SHA256");
-            components.add("SHA-256");
-            components.add("HmacSHA256");
-        } else if (macAlg == M_SHA384) {
-            components.add("SHA384");
-            components.add("SHA-384");
-            components.add("HmacSHA384");
-        }
-
-        return components;
-    }
-
-    private Set<String> decompose(KeyExchange keyExchange, BulkCipher cipher,
-            MacAlg macAlg) {
-        Set<String> components = new HashSet<>();
-
-        if (keyExchange != null) {
-            components.addAll(decomposes(keyExchange));
-        }
-
-        if (onlyX509) {
-            // Certification path algorithm constraints do not apply
-            // to cipher and macAlg.
-            return components;
-        }
-
-        if (cipher != null) {
-            components.addAll(decomposes(cipher));
-        }
-
-        if (macAlg != null) {
-            components.addAll(decomposes(macAlg, cipher));
-        }
-
-        return components;
-    }
-
-    @Override
-    public Set<String> decompose(String algorithm) {
-        if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
-            CipherSuite cipherSuite = null;
-            try {
-                cipherSuite = CipherSuite.valueOf(algorithm);
-            } catch (IllegalArgumentException iae) {
-                // ignore: unknown or unsupported ciphersuite
-            }
-
-            if (cipherSuite != null &&
-                cipherSuite != CipherSuite.C_SCSV /* TLS_EMPTY_RENEGOTIATION_INFO_SCSV */) {
-                return decompose(cipherSuite.keyExchange, cipherSuite.cipher,
-                        cipherSuite.macAlg);
-            }
-        }
-
-        return super.decompose(algorithm);
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/SSLContextImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1466 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, 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.net.Socket;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import javax.net.ssl.*;
-
-import sun.security.provider.certpath.AlgorithmChecker;
-import sun.security.action.GetPropertyAction;
-import sun.security.validator.Validator;
-
-public abstract class SSLContextImpl extends SSLContextSpi {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private final EphemeralKeyManager ephemeralKeyManager;
-    private final SSLSessionContextImpl clientCache;
-    private final SSLSessionContextImpl serverCache;
-
-    private boolean isInitialized;
-
-    private X509ExtendedKeyManager keyManager;
-    private X509TrustManager trustManager;
-    private SecureRandom secureRandom;
-
-    private final static Collection<CipherSuite> clientCustomizedCipherSuites =
-            getCustomizedCipherSuites("jdk.tls.client.cipherSuites");
-    private final static Collection<CipherSuite> serverCustomizedCipherSuites =
-            getCustomizedCipherSuites("jdk.tls.server.cipherSuites");
-
-    SSLContextImpl() {
-        ephemeralKeyManager = new EphemeralKeyManager();
-        clientCache = new SSLSessionContextImpl();
-        serverCache = new SSLSessionContextImpl();
-    }
-
-    @Override
-    protected void engineInit(KeyManager[] km, TrustManager[] tm,
-                                SecureRandom sr) throws KeyManagementException {
-        isInitialized = false;
-        keyManager = chooseKeyManager(km);
-
-        if (tm == null) {
-            try {
-                TrustManagerFactory tmf = TrustManagerFactory.getInstance(
-                        TrustManagerFactory.getDefaultAlgorithm());
-                tmf.init((KeyStore)null);
-                tm = tmf.getTrustManagers();
-            } catch (Exception e) {
-                // eat
-            }
-        }
-        trustManager = chooseTrustManager(tm);
-
-        if (sr == null) {
-            secureRandom = JsseJce.getSecureRandom();
-        } else {
-            if (SunJSSE.isFIPS() &&
-                        (sr.getProvider() != SunJSSE.cryptoProvider)) {
-                throw new KeyManagementException
-                    ("FIPS mode: SecureRandom must be from provider "
-                    + SunJSSE.cryptoProvider.getName());
-            }
-            secureRandom = sr;
-        }
-
-        /*
-         * The initial delay of seeding the random number generator
-         * could be long enough to cause the initial handshake on our
-         * first connection to timeout and fail. Make sure it is
-         * primed and ready by getting some initial output from it.
-         */
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println("trigger seeding of SecureRandom");
-        }
-        secureRandom.nextInt();
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println("done seeding SecureRandom");
-        }
-        isInitialized = true;
-    }
-
-    private X509TrustManager chooseTrustManager(TrustManager[] tm)
-            throws KeyManagementException {
-        // We only use the first instance of X509TrustManager passed to us.
-        for (int i = 0; tm != null && i < tm.length; i++) {
-            if (tm[i] instanceof X509TrustManager) {
-                if (SunJSSE.isFIPS() &&
-                        !(tm[i] instanceof X509TrustManagerImpl)) {
-                    throw new KeyManagementException
-                        ("FIPS mode: only SunJSSE TrustManagers may be used");
-                }
-
-                if (tm[i] instanceof X509ExtendedTrustManager) {
-                    return (X509TrustManager)tm[i];
-                } else {
-                    return new AbstractTrustManagerWrapper(
-                                        (X509TrustManager)tm[i]);
-                }
-            }
-        }
-
-        // nothing found, return a dummy X509TrustManager.
-        return DummyX509TrustManager.INSTANCE;
-    }
-
-    private X509ExtendedKeyManager chooseKeyManager(KeyManager[] kms)
-            throws KeyManagementException {
-        for (int i = 0; kms != null && i < kms.length; i++) {
-            KeyManager km = kms[i];
-            if (!(km instanceof X509KeyManager)) {
-                continue;
-            }
-            if (SunJSSE.isFIPS()) {
-                // In FIPS mode, require that one of SunJSSE's own keymanagers
-                // is used. Otherwise, we cannot be sure that only keys from
-                // the FIPS token are used.
-                if ((km instanceof X509KeyManagerImpl)
-                            || (km instanceof SunX509KeyManagerImpl)) {
-                    return (X509ExtendedKeyManager)km;
-                } else {
-                    // throw exception, we don't want to silently use the
-                    // dummy keymanager without telling the user.
-                    throw new KeyManagementException
-                        ("FIPS mode: only SunJSSE KeyManagers may be used");
-                }
-            }
-            if (km instanceof X509ExtendedKeyManager) {
-                return (X509ExtendedKeyManager)km;
-            }
-            if (debug != null && Debug.isOn("sslctx")) {
-                System.out.println(
-                    "X509KeyManager passed to " +
-                    "SSLContext.init():  need an " +
-                    "X509ExtendedKeyManager for SSLEngine use");
-            }
-            return new AbstractKeyManagerWrapper((X509KeyManager)km);
-        }
-
-        // nothing found, return a dummy X509ExtendedKeyManager
-        return DummyX509KeyManager.INSTANCE;
-    }
-
-    @Override
-    protected SSLSocketFactory engineGetSocketFactory() {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                "SSLContextImpl is not initialized");
-        }
-       return new SSLSocketFactoryImpl(this);
-    }
-
-    @Override
-    protected SSLServerSocketFactory engineGetServerSocketFactory() {
-        if (!isInitialized) {
-            throw new IllegalStateException("SSLContext is not initialized");
-        }
-        return new SSLServerSocketFactoryImpl(this);
-    }
-    abstract SSLEngine createSSLEngineImpl();
-    abstract SSLEngine createSSLEngineImpl(String host, int port);
-
-    @Override
-    protected SSLEngine engineCreateSSLEngine() {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                "SSLContextImpl is not initialized");
-        }
-        return createSSLEngineImpl();
-    }
-
-    @Override
-    protected SSLEngine engineCreateSSLEngine(String host, int port) {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                "SSLContextImpl is not initialized");
-        }
-        return createSSLEngineImpl(host, port);
-    }
-
-    @Override
-    protected SSLSessionContext engineGetClientSessionContext() {
-        return clientCache;
-    }
-
-    @Override
-    protected SSLSessionContext engineGetServerSessionContext() {
-        return serverCache;
-    }
-
-    SecureRandom getSecureRandom() {
-        return secureRandom;
-    }
-
-    X509ExtendedKeyManager getX509KeyManager() {
-        return keyManager;
-    }
-
-    X509TrustManager getX509TrustManager() {
-        return trustManager;
-    }
-
-    EphemeralKeyManager getEphemeralKeyManager() {
-        return ephemeralKeyManager;
-    }
-
-
-    // Get supported ProtocolList.
-    abstract ProtocolList getSuportedProtocolList();
-
-    // Get default ProtocolList for server mode.
-    abstract ProtocolList getServerDefaultProtocolList();
-
-    // Get default ProtocolList for client mode.
-    abstract ProtocolList getClientDefaultProtocolList();
-
-    // Get supported CipherSuiteList.
-    abstract CipherSuiteList getSupportedCipherSuiteList();
-
-    // Get default CipherSuiteList for server mode.
-    abstract CipherSuiteList getServerDefaultCipherSuiteList();
-
-    // Get default CipherSuiteList for client mode.
-    abstract CipherSuiteList getClientDefaultCipherSuiteList();
-
-    // Get default ProtocolList.
-    ProtocolList getDefaultProtocolList(boolean roleIsServer) {
-        return roleIsServer ? getServerDefaultProtocolList()
-                : getClientDefaultProtocolList();
-    }
-
-    // Get default CipherSuiteList.
-    CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
-        return roleIsServer ? getServerDefaultCipherSuiteList()
-                : getClientDefaultCipherSuiteList();
-    }
-
-    /**
-     * Return whether a protocol list is the original default enabled
-     * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
-     */
-    boolean isDefaultProtocolList(ProtocolList protocols) {
-        return (protocols == getServerDefaultProtocolList()) ||
-                (protocols == getClientDefaultProtocolList());
-    }
-
-    /**
-     * Return whether a protocol list is the original default enabled
-     * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
-     */
-    boolean isDefaultCipherSuiteList(CipherSuiteList cipherSuites) {
-        return (cipherSuites == getServerDefaultCipherSuiteList()) ||
-                (cipherSuites == getClientDefaultCipherSuiteList());
-    }
-
-    /*
-     * Return the list of all available CipherSuites that are supported
-     * using currently installed providers.
-     */
-    private static CipherSuiteList getApplicableSupportedCipherSuiteList(
-            ProtocolList protocols) {
-
-        return getApplicableCipherSuiteList(
-                CipherSuite.allowedCipherSuites(),
-                protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
-    }
-
-    /*
-     * Return the list of all available CipherSuites that are default enabled
-     * in client or server side.
-     */
-    private static CipherSuiteList getApplicableEnabledCipherSuiteList(
-            ProtocolList protocols, boolean isClient) {
-
-        if (isClient) {
-            if (!clientCustomizedCipherSuites.isEmpty()) {
-                return getApplicableCipherSuiteList(
-                        clientCustomizedCipherSuites,
-                        protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
-            }
-        } else {
-            if (!serverCustomizedCipherSuites.isEmpty()) {
-                return getApplicableCipherSuiteList(
-                        serverCustomizedCipherSuites,
-                        protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
-            }
-        }
-
-        return getApplicableCipherSuiteList(
-                CipherSuite.allowedCipherSuites(),
-                protocols, CipherSuite.DEFAULT_SUITES_PRIORITY);
-    }
-
-    /*
-     * Return the list of available CipherSuites which are applicable to
-     * the specified protocols.
-     */
-    private static CipherSuiteList getApplicableCipherSuiteList(
-            Collection<CipherSuite> allowedCipherSuites,
-            ProtocolList protocols, int minPriority) {
-
-        TreeSet<CipherSuite> suites = new TreeSet<>();
-        if (!(protocols.collection().isEmpty()) &&
-                protocols.min.v != ProtocolVersion.NONE.v) {
-            for (CipherSuite suite : allowedCipherSuites) {
-                if (!suite.allowed || suite.priority < minPriority) {
-                    continue;
-                }
-
-                if (suite.isAvailable() &&
-                        suite.obsoleted > protocols.min.v &&
-                        suite.supported <= protocols.max.v) {
-                    if (SSLAlgorithmConstraints.DEFAULT.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            suite.name, null)) {
-                        suites.add(suite);
-                    } else {
-                        if (debug != null && Debug.isOn("sslctx") &&
-                                Debug.isOn("verbose")) {
-                            System.out.println(
-                                    "Ignoring disabled cipher suite: " +
-                                            suite.name);
-                        }
-                    }
-                } else if (debug != null &&
-                        Debug.isOn("sslctx") && Debug.isOn("verbose")) {
-                    if (suite.obsoleted <= protocols.min.v) {
-                        System.out.println(
-                            "Ignoring obsoleted cipher suite: " + suite);
-                    } else if (suite.supported > protocols.max.v) {
-                        System.out.println(
-                            "Ignoring unsupported cipher suite: " + suite);
-                    } else {
-                        System.out.println(
-                            "Ignoring unavailable cipher suite: " + suite);
-                    }
-                }
-            }
-        }
-
-        return new CipherSuiteList(suites);
-    }
-
-    /*
-     * Get the customized cipher suites specified by the given system property.
-     */
-    private static Collection<CipherSuite> getCustomizedCipherSuites(
-            String propertyName) {
-
-        String property = AccessController.doPrivileged(
-                    new GetPropertyAction(propertyName));
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println(
-                    "System property " + propertyName + " is set to '" +
-                    property + "'");
-        }
-        if (property != null && property.length() != 0) {
-            // remove double quote marks from beginning/end of the property
-            if (property.length() > 1 && property.charAt(0) == '"' &&
-                    property.charAt(property.length() - 1) == '"') {
-                property = property.substring(1, property.length() - 1);
-            }
-        }
-
-        if (property != null && property.length() != 0) {
-            String[] cipherSuiteNames = property.split(",");
-            Collection<CipherSuite> cipherSuites =
-                        new ArrayList<>(cipherSuiteNames.length);
-            for (int i = 0; i < cipherSuiteNames.length; i++) {
-                cipherSuiteNames[i] = cipherSuiteNames[i].trim();
-                if (cipherSuiteNames[i].isEmpty()) {
-                    continue;
-                }
-
-                CipherSuite suite;
-                try {
-                    suite = CipherSuite.valueOf(cipherSuiteNames[i]);
-                } catch (IllegalArgumentException iae) {
-                    if (debug != null && Debug.isOn("sslctx")) {
-                        System.out.println(
-                                "Unknown or unsupported cipher suite name: " +
-                                cipherSuiteNames[i]);
-                    }
-
-                    continue;
-                }
-
-                if (suite.isAvailable()) {
-                    cipherSuites.add(suite);
-                } else {
-                    if (debug != null && Debug.isOn("sslctx")) {
-                        System.out.println(
-                                "The current installed providers do not " +
-                                "support cipher suite: " + cipherSuiteNames[i]);
-                    }
-                }
-            }
-
-            return cipherSuites;
-        }
-
-        return Collections.emptyList();
-    }
-
-    private static String[] getAvailableProtocols(
-            ProtocolVersion[] protocolCandidates) {
-
-        List<String> availableProtocols = Collections.<String>emptyList();
-        if (protocolCandidates !=  null && protocolCandidates.length != 0) {
-            availableProtocols = new ArrayList<>(protocolCandidates.length);
-            for (ProtocolVersion p : protocolCandidates) {
-                if (ProtocolVersion.availableProtocols.contains(p)) {
-                    availableProtocols.add(p.name);
-                }
-            }
-        }
-
-        return availableProtocols.toArray(new String[0]);
-    }
-
-    /*
-     * The SSLContext implementation for TLS/SSL algorithm
-     *
-     * SSL/TLS protocols specify the forward compatibility and version
-     * roll-back attack protections, however, a number of SSL/TLS server
-     * vendors did not implement these aspects properly, and some current
-     * SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
-     *
-     * Considering above interoperability issues, SunJSSE will not set
-     * TLS 1.1 and TLS 1.2 as the enabled protocols for client by default.
-     *
-     * For SSL/TLS servers, there is no such interoperability issues as
-     * SSL/TLS clients. In SunJSSE, TLS 1.1 or later version will be the
-     * enabled protocols for server by default.
-     *
-     * We may change the behavior when popular TLS/SSL vendors support TLS
-     * forward compatibility properly.
-     *
-     * SSLv2Hello is no longer necessary.  This interoperability option was
-     * put in place in the late 90's when SSLv3/TLS1.0 were relatively new
-     * and there were a fair number of SSLv2-only servers deployed.  Because
-     * of the security issues in SSLv2, it is rarely (if ever) used, as
-     * deployments should now be using SSLv3 and TLSv1.
-     *
-     * Considering the issues of SSLv2Hello, we should not enable SSLv2Hello
-     * by default. Applications still can use it by enabling SSLv2Hello with
-     * the series of setEnabledProtocols APIs.
-     */
-
-    /*
-     * The base abstract SSLContext implementation for the Transport Layer
-     * Security (TLS) protocols.
-     *
-     * This abstract class encapsulates supported and the default server
-     * SSL/TLS parameters.
-     *
-     * @see SSLContext
-     */
-    private abstract static class AbstractTLSContext extends SSLContextImpl {
-        private static final ProtocolList supportedProtocolList;
-        private static final ProtocolList serverDefaultProtocolList;
-
-        private static final CipherSuiteList supportedCipherSuiteList;
-        private static final CipherSuiteList serverDefaultCipherSuiteList;
-
-        static {
-            if (SunJSSE.isFIPS()) {
-                supportedProtocolList = new ProtocolList(new String[] {
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                serverDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
-            } else {
-                supportedProtocolList = new ProtocolList(new String[] {
-                    ProtocolVersion.SSL20Hello.name,
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                serverDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL20Hello,
-                    ProtocolVersion.SSL30,
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
-            }
-
-            supportedCipherSuiteList = getApplicableSupportedCipherSuiteList(
-                    supportedProtocolList);
-            serverDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    serverDefaultProtocolList, false);
-        }
-
-        @Override
-        ProtocolList getSuportedProtocolList() {
-            return supportedProtocolList;
-        }
-
-        @Override
-        CipherSuiteList getSupportedCipherSuiteList() {
-            return supportedCipherSuiteList;
-        }
-
-        @Override
-        ProtocolList getServerDefaultProtocolList() {
-            return serverDefaultProtocolList;
-        }
-
-        @Override
-        CipherSuiteList getServerDefaultCipherSuiteList() {
-            return serverDefaultCipherSuiteList;
-        }
-
-        @Override
-        SSLEngine createSSLEngineImpl() {
-            return new SSLEngineImpl(this);
-        }
-
-        @Override
-        SSLEngine createSSLEngineImpl(String host, int port) {
-            return new SSLEngineImpl(this, host, port);
-        }
-    }
-
-    /*
-     * The SSLContext implementation for SSLv3 and TLS10 algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class TLS10Context extends AbstractTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
-
-        static {
-            if (SunJSSE.isFIPS()) {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.TLS10
-                }));
-            } else {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL30,
-                    ProtocolVersion.TLS10
-                }));
-            }
-
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
-        }
-
-        @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
-        }
-
-        @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
-        }
-    }
-
-    /*
-     * The SSLContext implementation for TLS11 algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class TLS11Context extends AbstractTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
-
-        static {
-            if (SunJSSE.isFIPS()) {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11
-                }));
-            } else {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL30,
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11
-                }));
-            }
-
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
-
-        }
-
-        @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
-        }
-
-        @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
-        }
-    }
-
-    /*
-     * The SSLContext implementation for TLS12 algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class TLS12Context extends AbstractTLSContext {
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
-
-        static {
-            if (SunJSSE.isFIPS()) {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
-            } else {
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(new ProtocolVersion[] {
-                    ProtocolVersion.SSL30,
-                    ProtocolVersion.TLS10,
-                    ProtocolVersion.TLS11,
-                    ProtocolVersion.TLS12
-                }));
-            }
-
-            clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
-                    clientDefaultProtocolList, true);
-        }
-
-        @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
-        }
-
-        @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
-        }
-    }
-
-    /*
-     * The interface for the customized SSL/(D)TLS SSLContext.
-     *
-     * @see SSLContext
-     */
-    private static class CustomizedSSLProtocols {
-        private static final String PROPERTY_NAME = "jdk.tls.client.protocols";
-        static IllegalArgumentException reservedException = null;
-        static ArrayList<ProtocolVersion>
-                customizedProtocols = new ArrayList<>();
-
-        // Don't want a java.lang.LinkageError for illegal system property.
-        //
-        // Please don't throw exception in this static block.  Otherwise,
-        // java.lang.LinkageError may be thrown during the instantiation of
-        // the provider service. Instead, please handle the initialization
-        // exception in the caller's constructor.
-        static {
-            String property = AccessController.doPrivileged(
-                    new GetPropertyAction(PROPERTY_NAME));
-            if (property != null && property.length() != 0) {
-                // remove double quote marks from beginning/end of the property
-                if (property.length() > 1 && property.charAt(0) == '"' &&
-                        property.charAt(property.length() - 1) == '"') {
-                    property = property.substring(1, property.length() - 1);
-                }
-            }
-
-            if (property != null && property.length() != 0) {
-                String[] protocols = property.split(",");
-                for (int i = 0; i < protocols.length; i++) {
-                    protocols[i] = protocols[i].trim();
-                    // Is it a supported protocol name?
-                    try {
-                        ProtocolVersion pro =
-                                ProtocolVersion.valueOf(protocols[i]);
-
-                        if (SunJSSE.isFIPS() &&
-                                ((pro.v == ProtocolVersion.SSL30.v) ||
-                                        (pro.v == ProtocolVersion.SSL20Hello.v))) {
-                            reservedException = new IllegalArgumentException(
-                                    PROPERTY_NAME + ": " + pro +
-                                            " is not FIPS compliant");
-
-                            break;
-                        }
-
-                        // ignore duplicated protocols
-                        if (!customizedProtocols.contains(pro)) {
-                            customizedProtocols.add(pro);
-                        }
-                    } catch (IllegalArgumentException iae) {
-                        reservedException = new IllegalArgumentException(
-                                PROPERTY_NAME + ": " + protocols[i] +
-                                        " is not a standard SSL protocol name", iae);
-                    }
-                }
-            }
-        }
-    }
-
-    /*
-     * The SSLContext implementation for customized TLS protocols
-     *
-     * @see SSLContext
-     */
-    private static class CustomizedTLSContext extends AbstractTLSContext {
-
-        private static final ProtocolList clientDefaultProtocolList;
-        private static final CipherSuiteList clientDefaultCipherSuiteList;
-
-        private static IllegalArgumentException reservedException = null;
-
-        // Don't want a java.lang.LinkageError for illegal system property.
-        //
-        // Please don't throw exception in this static block.  Otherwise,
-        // java.lang.LinkageError may be thrown during the instantiation of
-        // the provider service. Instead, let's handle the initialization
-        // exception in constructor.
-        static {
-            reservedException = CustomizedSSLProtocols.reservedException;
-            if (reservedException == null) {
-                ArrayList<ProtocolVersion>
-                        customizedTLSProtocols = new ArrayList<>();
-                for (ProtocolVersion protocol :
-                        CustomizedSSLProtocols.customizedProtocols) {
-                        customizedTLSProtocols.add(protocol);
-                }
-
-                // candidates for available protocols
-                ProtocolVersion[] candidates;
-                if (customizedTLSProtocols.isEmpty()) {
-                    // Use the default enabled client protocols if no
-                    // customized TLS protocols.
-                    if (SunJSSE.isFIPS()) {
-                        candidates = new ProtocolVersion[] {
-                                ProtocolVersion.TLS10,
-                                ProtocolVersion.TLS11,
-                                ProtocolVersion.TLS12
-                        };
-                    } else {
-                        candidates = new ProtocolVersion[] {
-                                ProtocolVersion.SSL30,
-                                ProtocolVersion.TLS10,
-                                ProtocolVersion.TLS11,
-                                ProtocolVersion.TLS12
-                        };
-                    }
-                } else {
-                    // Use the customized TLS protocols.
-                    candidates =
-                            new ProtocolVersion[customizedTLSProtocols.size()];
-                    candidates = customizedTLSProtocols.toArray(candidates);
-                }
-
-                clientDefaultProtocolList = new ProtocolList(
-                        getAvailableProtocols(candidates));
-                clientDefaultCipherSuiteList =
-                        getApplicableEnabledCipherSuiteList(
-                                clientDefaultProtocolList, true);
-            } else {
-                clientDefaultProtocolList = null;       // unlikely to be used
-                clientDefaultCipherSuiteList = null;    // unlikely to be used
-            }
-        }
-
-        protected CustomizedTLSContext() {
-            if (reservedException != null) {
-                throw reservedException;
-            }
-        }
-
-        @Override
-        ProtocolList getClientDefaultProtocolList() {
-            return clientDefaultProtocolList;
-        }
-
-        @Override
-        CipherSuiteList getClientDefaultCipherSuiteList() {
-            return clientDefaultCipherSuiteList;
-        }
-    }
-
-    /*
-     * The SSLContext implementation for default "TLS" algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class TLSContext extends CustomizedTLSContext {
-        // use the default constructor and methods
-    }
-
-    // lazy initialization holder class idiom for static default parameters
-    //
-    // See Effective Java Second Edition: Item 71.
-    private static final class DefaultManagersHolder {
-        private static final String NONE = "NONE";
-        private static final String P11KEYSTORE = "PKCS11";
-
-        private static final TrustManager[] trustManagers;
-        private static final KeyManager[] keyManagers;
-
-        static Exception reservedException = null;
-
-        static {
-            TrustManager[] tmMediator;
-            try {
-                tmMediator = getTrustManagers();
-            } catch (Exception e) {
-                reservedException = e;
-                tmMediator = new TrustManager[0];
-            }
-            trustManagers = tmMediator;
-
-            if (reservedException == null) {
-                KeyManager[] kmMediator;
-                try {
-                    kmMediator = getKeyManagers();
-                } catch (Exception e) {
-                    reservedException = e;
-                    kmMediator = new KeyManager[0];
-                }
-                keyManagers = kmMediator;
-            } else {
-                keyManagers = new KeyManager[0];
-            }
-        }
-
-        private static TrustManager[] getTrustManagers() throws Exception {
-            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
-                    TrustManagerFactory.getDefaultAlgorithm());
-            if ("SunJSSE".equals(tmf.getProvider().getName())) {
-                // The implementation will load the default KeyStore
-                // automatically.  Cached trust materials may be used
-                // for performance improvement.
-                tmf.init((KeyStore)null);
-            } else {
-                // Use the explicitly specified KeyStore for third party's
-                // TrustManagerFactory implementation.
-                KeyStore ks = TrustStoreManager.getTrustedKeyStore();
-                tmf.init(ks);
-            }
-
-            return tmf.getTrustManagers();
-        }
-
-        private static KeyManager[] getKeyManagers() throws Exception {
-
-            final Map<String,String> props = new HashMap<>();
-            AccessController.doPrivileged(
-                        new PrivilegedExceptionAction<Object>() {
-                @Override
-                public Object run() throws Exception {
-                    props.put("keyStore",  System.getProperty(
-                                "javax.net.ssl.keyStore", ""));
-                    props.put("keyStoreType", System.getProperty(
-                                "javax.net.ssl.keyStoreType",
-                                KeyStore.getDefaultType()));
-                    props.put("keyStoreProvider", System.getProperty(
-                                "javax.net.ssl.keyStoreProvider", ""));
-                    props.put("keyStorePasswd", System.getProperty(
-                                "javax.net.ssl.keyStorePassword", ""));
-                    return null;
-                }
-            });
-
-            final String defaultKeyStore = props.get("keyStore");
-            String defaultKeyStoreType = props.get("keyStoreType");
-            String defaultKeyStoreProvider = props.get("keyStoreProvider");
-            if (debug != null && Debug.isOn("defaultctx")) {
-                System.out.println("keyStore is : " + defaultKeyStore);
-                System.out.println("keyStore type is : " +
-                                        defaultKeyStoreType);
-                System.out.println("keyStore provider is : " +
-                                        defaultKeyStoreProvider);
-            }
-
-            if (P11KEYSTORE.equals(defaultKeyStoreType) &&
-                    !NONE.equals(defaultKeyStore)) {
-                throw new IllegalArgumentException("if keyStoreType is "
-                    + P11KEYSTORE + ", then keyStore must be " + NONE);
-            }
-
-            FileInputStream fs = null;
-            KeyStore ks = null;
-            char[] passwd = null;
-            try {
-                if (defaultKeyStore.length() != 0 &&
-                        !NONE.equals(defaultKeyStore)) {
-                    fs = AccessController.doPrivileged(
-                            new PrivilegedExceptionAction<FileInputStream>() {
-                        @Override
-                        public FileInputStream run() throws Exception {
-                            return new FileInputStream(defaultKeyStore);
-                        }
-                    });
-                }
-
-                String defaultKeyStorePassword = props.get("keyStorePasswd");
-                if (defaultKeyStorePassword.length() != 0) {
-                    passwd = defaultKeyStorePassword.toCharArray();
-                }
-
-                /**
-                 * Try to initialize key store.
-                 */
-                if ((defaultKeyStoreType.length()) != 0) {
-                    if (debug != null && Debug.isOn("defaultctx")) {
-                        System.out.println("init keystore");
-                    }
-                    if (defaultKeyStoreProvider.length() == 0) {
-                        ks = KeyStore.getInstance(defaultKeyStoreType);
-                    } else {
-                        ks = KeyStore.getInstance(defaultKeyStoreType,
-                                            defaultKeyStoreProvider);
-                    }
-
-                    // if defaultKeyStore is NONE, fs will be null
-                    ks.load(fs, passwd);
-                }
-            } finally {
-                if (fs != null) {
-                    fs.close();
-                    fs = null;
-                }
-            }
-
-            /*
-             * Try to initialize key manager.
-             */
-            if (debug != null && Debug.isOn("defaultctx")) {
-                System.out.println("init keymanager of type " +
-                    KeyManagerFactory.getDefaultAlgorithm());
-            }
-            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
-                KeyManagerFactory.getDefaultAlgorithm());
-
-            if (P11KEYSTORE.equals(defaultKeyStoreType)) {
-                kmf.init(ks, null); // do not pass key passwd if using token
-            } else {
-                kmf.init(ks, passwd);
-            }
-
-            return kmf.getKeyManagers();
-        }
-    }
-
-    // lazy initialization holder class idiom for static default parameters
-    //
-    // See Effective Java Second Edition: Item 71.
-    private static final class DefaultSSLContextHolder {
-
-        private static final SSLContextImpl sslContext;
-        static Exception reservedException = null;
-
-        static {
-            SSLContextImpl mediator = null;
-            if (DefaultManagersHolder.reservedException != null) {
-                reservedException = DefaultManagersHolder.reservedException;
-            } else {
-                try {
-                    mediator = new DefaultSSLContext();
-                } catch (Exception e) {
-                    reservedException = e;
-                }
-            }
-
-            sslContext = mediator;
-        }
-    }
-
-    /*
-     * The SSLContext implementation for default "Default" algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class DefaultSSLContext extends CustomizedTLSContext {
-
-        // public constructor for SSLContext.getInstance("Default")
-        public DefaultSSLContext() throws Exception {
-            if (DefaultManagersHolder.reservedException != null) {
-                throw DefaultManagersHolder.reservedException;
-            }
-
-            try {
-                super.engineInit(DefaultManagersHolder.keyManagers,
-                        DefaultManagersHolder.trustManagers, null);
-            } catch (Exception e) {
-                if (debug != null && Debug.isOn("defaultctx")) {
-                    System.out.println("default context init failed: " + e);
-                }
-                throw e;
-            }
-        }
-
-        @Override
-        protected void engineInit(KeyManager[] km, TrustManager[] tm,
-                                  SecureRandom sr) throws KeyManagementException {
-            throw new KeyManagementException
-                    ("Default SSLContext is initialized automatically");
-        }
-
-        static SSLContextImpl getDefaultImpl() throws Exception {
-            if (DefaultSSLContextHolder.reservedException != null) {
-                throw DefaultSSLContextHolder.reservedException;
-            }
-
-            return DefaultSSLContextHolder.sslContext;
-        }
-    }
-
-
-}
-
-
-final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
-            implements X509TrustManager {
-
-    // the delegated trust manager
-    private final X509TrustManager tm;
-
-    AbstractTrustManagerWrapper(X509TrustManager tm) {
-        this.tm = tm;
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        tm.checkClientTrusted(chain, authType);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        tm.checkServerTrusted(chain, authType);
-    }
-
-    @Override
-    public X509Certificate[] getAcceptedIssuers() {
-        return tm.getAcceptedIssuers();
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-                Socket socket) throws CertificateException {
-        tm.checkClientTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, socket, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            Socket socket) throws CertificateException {
-        tm.checkServerTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, socket, false);
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        tm.checkClientTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, engine, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        tm.checkServerTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, engine, false);
-    }
-
-    private void checkAdditionalTrust(X509Certificate[] chain,
-            String authType, Socket socket,
-            boolean checkClientTrusted) throws CertificateException {
-        if (socket != null && socket.isConnected() &&
-                                    socket instanceof SSLSocket) {
-
-            SSLSocket sslSocket = (SSLSocket)socket;
-            SSLSession session = sslSocket.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = sslSocket.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                X509TrustManagerImpl.checkIdentity(session, chain,
-                                    identityAlg, checkClientTrusted);
-            }
-
-            // try the best to check the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            AlgorithmConstraints constraints = null;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] peerSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    sslSocket, peerSupportedSignAlgs, true);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(sslSocket, true);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(sslSocket, true);
-            }
-
-            checkAlgorithmConstraints(chain, constraints, checkClientTrusted);
-        }
-    }
-
-    private void checkAdditionalTrust(X509Certificate[] chain,
-            String authType, SSLEngine engine,
-            boolean checkClientTrusted) throws CertificateException {
-        if (engine != null) {
-            SSLSession session = engine.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = engine.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                X509TrustManagerImpl.checkIdentity(session, chain,
-                                    identityAlg, checkClientTrusted);
-            }
-
-            // try the best to check the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            AlgorithmConstraints constraints = null;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] peerSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    engine, peerSupportedSignAlgs, true);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(engine, true);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(engine, true);
-            }
-
-            checkAlgorithmConstraints(chain, constraints, checkClientTrusted);
-        }
-    }
-
-    private void checkAlgorithmConstraints(X509Certificate[] chain,
-            AlgorithmConstraints constraints,
-            boolean checkClientTrusted) throws CertificateException {
-
-        try {
-            // Does the certificate chain end with a trusted certificate?
-            int checkedLength = chain.length - 1;
-
-            Collection<X509Certificate> trustedCerts = new HashSet<>();
-            X509Certificate[] certs = tm.getAcceptedIssuers();
-            if ((certs != null) && (certs.length > 0)){
-                Collections.addAll(trustedCerts, certs);
-            }
-
-            if (trustedCerts.contains(chain[checkedLength])) {
-                    checkedLength--;
-            }
-
-            // A forward checker, need to check from trust to target
-            if (checkedLength >= 0) {
-                AlgorithmChecker checker =
-                        new AlgorithmChecker(constraints, null,
-                                (checkClientTrusted ? Validator.VAR_TLS_CLIENT :
-                                            Validator.VAR_TLS_SERVER));
-                checker.init(false);
-                for (int i = checkedLength; i >= 0; i--) {
-                    Certificate cert = chain[i];
-                    // We don't care about the unresolved critical extensions.
-                    checker.check(cert, Collections.<String>emptySet());
-                }
-            }
-        } catch (CertPathValidatorException cpve) {
-            throw new CertificateException(
-                "Certificates do not conform to algorithm constraints", cpve);
-        }
-    }
-}
-
-// Dummy X509TrustManager implementation, rejects all peer certificates.
-// Used if the application did not specify a proper X509TrustManager.
-final class DummyX509TrustManager extends X509ExtendedTrustManager
-            implements X509TrustManager {
-
-    static final X509TrustManager INSTANCE = new DummyX509TrustManager();
-
-    private DummyX509TrustManager() {
-        // empty
-    }
-
-    /*
-     * Given the partial or complete certificate chain
-     * provided by the peer, build a certificate path
-     * to a trusted root and return if it can be
-     * validated and is trusted for client SSL authentication.
-     * If not, it throws an exception.
-     */
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation avaiable");
-    }
-
-    /*
-     * Given the partial or complete certificate chain
-     * provided by the peer, build a certificate path
-     * to a trusted root and return if it can be
-     * validated and is trusted for server SSL authentication.
-     * If not, it throws an exception.
-     */
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    /*
-     * Return an array of issuer certificates which are trusted
-     * for authenticating peers.
-     */
-    @Override
-    public X509Certificate[] getAcceptedIssuers() {
-        return new X509Certificate[0];
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-                Socket socket) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            Socket socket) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-}
-
-/*
- * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
- */
-final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
-
-    private final X509KeyManager km;
-
-    AbstractKeyManagerWrapper(X509KeyManager km) {
-        this.km = km;
-    }
-
-    @Override
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return km.getClientAliases(keyType, issuers);
-    }
-
-    @Override
-    public String chooseClientAlias(String[] keyType, Principal[] issuers,
-            Socket socket) {
-        return km.chooseClientAlias(keyType, issuers, socket);
-    }
-
-    @Override
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return km.getServerAliases(keyType, issuers);
-    }
-
-    @Override
-    public String chooseServerAlias(String keyType, Principal[] issuers,
-            Socket socket) {
-        return km.chooseServerAlias(keyType, issuers, socket);
-    }
-
-    @Override
-    public X509Certificate[] getCertificateChain(String alias) {
-        return km.getCertificateChain(alias);
-    }
-
-    @Override
-    public PrivateKey getPrivateKey(String alias) {
-        return km.getPrivateKey(alias);
-    }
-
-    // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
-    // X509ExtendedKeymanager. It defines them to return null;
-}
-
-
-// Dummy X509KeyManager implementation, never returns any certificates/keys.
-// Used if the application did not specify a proper X509TrustManager.
-final class DummyX509KeyManager extends X509ExtendedKeyManager {
-
-    static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
-
-    private DummyX509KeyManager() {
-        // empty
-    }
-
-    /*
-     * Get the matching aliases for authenticating the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
-            Socket socket) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of an
-     * engine given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String chooseEngineClientAlias(
-            String[] keyTypes, Principal[] issuers, SSLEngine engine) {
-        return null;
-    }
-
-    /*
-     * Get the matching aliases for authenticating the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String chooseServerAlias(String keyType, Principal[] issuers,
-            Socket socket) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of an engine
-     * given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String chooseEngineServerAlias(
-            String keyType, Principal[] issuers, SSLEngine engine) {
-        return null;
-    }
-
-    /**
-     * Returns the certificate chain associated with the given alias.
-     *
-     * @param alias the alias name
-     *
-     * @return the certificate chain (ordered with the user's certificate first
-     * and the root certificate authority last)
-     */
-    @Override
-    public X509Certificate[] getCertificateChain(String alias) {
-        return null;
-    }
-
-    /*
-     * Returns the key associated with the given alias, using the given
-     * password to recover it.
-     *
-     * @param alias the alias name
-     *
-     * @return the requested key
-     */
-    @Override
-    public PrivateKey getPrivateKey(String alias) {
-        return null;
-    }
-}
--- a/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2203 +0,0 @@
-/*
- * Copyright (c) 2003, 2020, 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.*;
-import java.nio.*;
-import java.util.*;
-import java.security.*;
-import java.util.function.BiFunction;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-import javax.net.ssl.SSLEngineResult.*;
-
-/**
- * Implementation of an non-blocking SSLEngine.
- *
- * *Currently*, the SSLEngine code exists in parallel with the current
- * SSLSocket.  As such, the current implementation is using legacy code
- * with many of the same abstractions.  However, it varies in many
- * areas, most dramatically in the IO handling.
- *
- * There are three main I/O threads that can be existing in parallel:
- * wrap(), unwrap(), and beginHandshake().  We are encouraging users to
- * not call multiple instances of wrap or unwrap, because the data could
- * appear to flow out of the SSLEngine in a non-sequential order.  We
- * take all steps we can to at least make sure the ordering remains
- * consistent, but once the calls returns, anything can happen.  For
- * example, thread1 and thread2 both call wrap, thread1 gets the first
- * packet, thread2 gets the second packet, but thread2 gets control back
- * before thread1, and sends the data.  The receiving side would see an
- * out-of-order error.
- *
- * Handshaking is still done the same way as SSLSocket using the normal
- * InputStream/OutputStream abstactions.  We create
- * ClientHandshakers/ServerHandshakers, which produce/consume the
- * handshaking data.  The transfer of the data is largely handled by the
- * HandshakeInStream/HandshakeOutStreams.  Lastly, the
- * InputRecord/OutputRecords still have the same functionality, except
- * that they are overridden with EngineInputRecord/EngineOutputRecord,
- * which provide SSLEngine-specific functionality.
- *
- * Some of the major differences are:
- *
- * EngineInputRecord/EngineOutputRecord/EngineWriter:
- *
- *      In order to avoid writing whole new control flows for
- *      handshaking, and to reuse most of the same code, we kept most
- *      of the actual handshake code the same.  As usual, reading
- *      handshake data may trigger output of more handshake data, so
- *      what we do is write this data to internal buffers, and wait for
- *      wrap() to be called to give that data a ride.
- *
- *      All data is routed through
- *      EngineInputRecord/EngineOutputRecord.  However, all handshake
- *      data (ct_alert/ct_change_cipher_spec/ct_handshake) are passed
- *      through to the the underlying InputRecord/OutputRecord, and
- *      the data uses the internal buffers.
- *
- *      Application data is handled slightly different, we copy the data
- *      directly from the src to the dst buffers, and do all operations
- *      on those buffers, saving the overhead of multiple copies.
- *
- *      In the case of an inbound record, unwrap passes the inbound
- *      ByteBuffer to the InputRecord.  If the data is handshake data,
- *      the data is read into the InputRecord's internal buffer.  If
- *      the data is application data, the data is decoded directly into
- *      the dst buffer.
- *
- *      In the case of an outbound record, when the write to the
- *      "real" OutputStream's would normally take place, instead we
- *      call back up to the EngineOutputRecord's version of
- *      writeBuffer, at which time we capture the resulting output in a
- *      ByteBuffer, and send that back to the EngineWriter for internal
- *      storage.
- *
- *      EngineWriter is responsible for "handling" all outbound
- *      data, be it handshake or app data, and for returning the data
- *      to wrap() in the proper order.
- *
- * ClientHandshaker/ServerHandshaker/Handshaker:
- *      Methods which relied on SSLSocket now have work on either
- *      SSLSockets or SSLEngines.
- *
- * @author Brad Wetmore
- */
-final public class SSLEngineImpl extends SSLEngine {
-
-    //
-    // Fields and global comments
-    //
-
-    /*
-     * There's a state machine associated with each connection, which
-     * among other roles serves to negotiate session changes.
-     *
-     * - START with constructor, until the TCP connection's around.
-     * - HANDSHAKE picks session parameters before allowing traffic.
-     *          There are many substates due to sequencing requirements
-     *          for handshake messages.
-     * - DATA may be transmitted.
-     * - RENEGOTIATE state allows concurrent data and handshaking
-     *          traffic ("same" substates as HANDSHAKE), and terminates
-     *          in selection of new session (and connection) parameters
-     * - ERROR state immediately precedes abortive disconnect.
-     * - CLOSED when one side closes down, used to start the shutdown
-     *          process.  SSL connection objects are not reused.
-     *
-     * State affects what SSL record types may legally be sent:
-     *
-     * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
-     * - App Data ... only in DATA and RENEGOTIATE states
-     * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
-     *
-     * Re what may be received:  same as what may be sent, except that
-     * HandshakeRequest handshaking messages can come from servers even
-     * in the application data state, to request entry to RENEGOTIATE.
-     *
-     * The state machine within HANDSHAKE and RENEGOTIATE states controls
-     * the pending session, not the connection state, until the change
-     * cipher spec and "Finished" handshake messages are processed and
-     * make the "new" session become the current one.
-     *
-     * NOTE: details of the SMs always need to be nailed down better.
-     * The text above illustrates the core ideas.
-     *
-     *                +---->-------+------>--------->-------+
-     *                |            |                        |
-     *     <-----<    ^            ^  <-----<               |
-     *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE    |
-     *                v            v               v        |
-     *                |            |               |        |
-     *                +------------+---------------+        |
-     *                |                                     |
-     *                v                                     |
-     *               ERROR>------>----->CLOSED<--------<----+
-     *
-     * ALSO, note that the the purpose of handshaking (renegotiation is
-     * included) is to assign a different, and perhaps new, session to
-     * the connection.  The SSLv3 spec is a bit confusing on that new
-     * protocol feature.
-     */
-    private int                 connectionState;
-
-    private static final int    cs_START = 0;
-    private static final int    cs_HANDSHAKE = 1;
-    private static final int    cs_DATA = 2;
-    private static final int    cs_RENEGOTIATE = 3;
-    private static final int    cs_ERROR = 4;
-    private static final int    cs_CLOSED = 6;
-
-    /*
-     * Once we're in state cs_CLOSED, we can continue to
-     * wrap/unwrap until we finish sending/receiving the messages
-     * for close_notify.  EngineWriter handles outboundDone.
-     */
-    private boolean             inboundDone = false;
-
-    EngineWriter                writer;
-
-    /*
-     * The authentication context holds all information used to establish
-     * who this end of the connection is (certificate chains, private keys,
-     * etc) and who is trusted (e.g. as CAs or websites).
-     */
-    private SSLContextImpl      sslContext;
-
-    /*
-     * This connection is one of (potentially) many associated with
-     * any given session.  The output of the handshake protocol is a
-     * new session ... although all the protocol description talks
-     * about changing the cipher spec (and it does change), in fact
-     * that's incidental since it's done by changing everything that
-     * is associated with a session at the same time.  (TLS/IETF may
-     * change that to add client authentication w/o new key exchg.)
-     */
-    private Handshaker                  handshaker;
-    private SSLSessionImpl              sess;
-    private volatile SSLSessionImpl     handshakeSession;
-
-
-    /*
-     * Client authentication be off, requested, or required.
-     *
-     * This will be used by both this class and SSLSocket's variants.
-     */
-    static final byte           clauth_none = 0;
-    static final byte           clauth_requested = 1;
-    static final byte           clauth_required = 2;
-
-    /*
-     * Flag indicating if the next record we receive MUST be a Finished
-     * message. Temporarily set during the handshake to ensure that
-     * a change cipher spec message is followed by a finished message.
-     */
-    private boolean             expectingFinished;
-
-
-    /*
-     * If someone tries to closeInbound() (say at End-Of-Stream)
-     * our engine having received a close_notify, we need to
-     * notify the app that we may have a truncation attack underway.
-     */
-    private boolean             recvCN;
-
-    /*
-     * For improved diagnostics, we detail connection closure
-     * If the engine is closed (connectionState >= cs_ERROR),
-     * closeReason != null indicates if the engine was closed
-     * because of an error or because or normal shutdown.
-     */
-    private SSLException        closeReason;
-
-    /*
-     * Per-connection private state that doesn't change when the
-     * session is changed.
-     */
-    private byte                        doClientAuth;
-    private boolean                     enableSessionCreation = true;
-    EngineInputRecord                   inputRecord;
-    EngineOutputRecord                  outputRecord;
-    private AccessControlContext        acc;
-
-    // The cipher suites enabled for use on this connection.
-    private CipherSuiteList             enabledCipherSuites;
-
-    // the endpoint identification protocol
-    private String                      identificationProtocol = null;
-
-    // The cryptographic algorithm constraints
-    private AlgorithmConstraints        algorithmConstraints = null;
-
-    // The server name indication and matchers
-    List<SNIServerName>         serverNames =
-                                    Collections.<SNIServerName>emptyList();
-    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;
-
-    /*
-     * The protocol versions enabled for use on this connection.
-     *
-     * Note: we support a pseudo protocol called SSLv2Hello which when
-     * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
-     * or TLS (version 3.1, 3.2, etc.) version info.
-     */
-    private ProtocolList        enabledProtocols;
-
-    /*
-     * The SSL version associated with this connection.
-     */
-    private ProtocolVersion     protocolVersion = ProtocolVersion.DEFAULT;
-
-    /*
-     * Crypto state that's reinitialized when the session changes.
-     */
-    private Authenticator       readAuthenticator, writeAuthenticator;
-    private CipherBox           readCipher, writeCipher;
-    // NOTE: compression state would be saved here
-
-    /*
-     * security parameters for secure renegotiation.
-     */
-    private boolean             secureRenegotiation;
-    private byte[]              clientVerifyData;
-    private byte[]              serverVerifyData;
-
-    /*
-     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
-     * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
-     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
-     *
-     * There are several locks here.
-     *
-     * The primary lock is the per-instance lock used by
-     * synchronized(this) and the synchronized methods.  It controls all
-     * access to things such as the connection state and variables which
-     * affect handshaking.  If we are inside a synchronized method, we
-     * can access the state directly, otherwise, we must use the
-     * synchronized equivalents.
-     *
-     * Note that we must never acquire the <code>this</code> lock after
-     * <code>writeLock</code> or run the risk of deadlock.
-     *
-     * Grab some coffee, and be careful with any code changes.
-     */
-    private Object              wrapLock;
-    private Object              unwrapLock;
-    Object                      writeLock;
-
-    /*
-     * Is it the first application record to write?
-     */
-    private boolean isFirstAppOutputRecord = true;
-
-    /*
-     * Whether local cipher suites preference in server side should be
-     * honored during handshaking?
-     */
-    private boolean preferLocalCipherSuites = false;
-
-    /*
-     * Class and subclass dynamic debugging support
-     */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    //
-    // Initialization/Constructors
-    //
-
-    /**
-     * Constructor for an SSLEngine from SSLContext, without
-     * host/port hints.  This Engine will not be able to cache
-     * sessions, but must renegotiate everything by hand.
-     */
-    SSLEngineImpl(SSLContextImpl ctx) {
-        super();
-        init(ctx);
-    }
-
-    /**
-     * Constructor for an SSLEngine from SSLContext.
-     */
-    SSLEngineImpl(SSLContextImpl ctx, String host, int port) {
-        super(host, port);
-        init(ctx);
-    }
-
-    /**
-     * Initializes the Engine
-     */
-    private void init(SSLContextImpl ctx) {
-        if (debug != null && Debug.isOn("ssl")) {
-            System.out.println("Using SSLEngineImpl.");
-        }
-
-        sslContext = ctx;
-        sess = new SSLSessionImpl();
-        handshakeSession = null;
-
-        /*
-         * State is cs_START until we initialize the handshaker.
-         *
-         * Apps using SSLEngine are probably going to be server.
-         * Somewhat arbitrary choice.
-         */
-        roleIsServer = true;
-        connectionState = cs_START;
-
-        // default server name indication
-        serverNames =
-            Utilities.addToSNIServerNameList(serverNames, getPeerHost());
-
-        /*
-         * default read and write side cipher and MAC support
-         *
-         * Note:  compression support would go here too
-         */
-        readCipher = CipherBox.NULL;
-        readAuthenticator = MAC.NULL;
-        writeCipher = CipherBox.NULL;
-        writeAuthenticator = MAC.NULL;
-
-        // default security parameters for secure renegotiation
-        secureRenegotiation = false;
-        clientVerifyData = new byte[0];
-        serverVerifyData = new byte[0];
-
-        enabledCipherSuites =
-                sslContext.getDefaultCipherSuiteList(roleIsServer);
-        enabledProtocols =
-                sslContext.getDefaultProtocolList(roleIsServer);
-
-        wrapLock = new Object();
-        unwrapLock = new Object();
-        writeLock = new Object();
-
-        /*
-         * Save the Access Control Context.  This will be used later
-         * for a couple of things, including providing a context to
-         * run tasks in, and for determining which credentials
-         * to use for Subject based (JAAS) decisions
-         */
-        acc = AccessController.getContext();
-
-        /*
-         * All outbound application data goes through this OutputRecord,
-         * other data goes through their respective records created
-         * elsewhere.  All inbound data goes through this one
-         * input record.
-         */
-        outputRecord =
-            new EngineOutputRecord(Record.ct_application_data, this);
-        inputRecord = new EngineInputRecord(this);
-        inputRecord.enableFormatChecks();
-
-        writer = new EngineWriter();
-    }
-
-    /**
-     * Initialize the handshaker object. This means:
-     *
-     *  . if a handshake is already in progress (state is cs_HANDSHAKE
-     *    or cs_RENEGOTIATE), do nothing and return
-     *
-     *  . if the engine is already closed, throw an Exception (internal error)
-     *
-     *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object and advance the connection state (to cs_HANDSHAKE or
-     *    cs_RENEGOTIATE, respectively).
-     *
-     * This method is called right after a new engine is created, when
-     * starting renegotiation, or when changing client/server mode of the
-     * engine.
-     */
-    private void initHandshaker() {
-        switch (connectionState) {
-
-        //
-        // Starting a new handshake.
-        //
-        case cs_START:
-        case cs_DATA:
-            break;
-
-        //
-        // We're already in the middle of a handshake.
-        //
-        case cs_HANDSHAKE:
-        case cs_RENEGOTIATE:
-            return;
-
-        //
-        // Anyone allowed to call this routine is required to
-        // do so ONLY if the connection state is reasonable...
-        //
-        default:
-            throw new IllegalStateException("Internal error");
-        }
-
-        // state is either cs_START or cs_DATA
-        if (connectionState == cs_START) {
-            connectionState = cs_HANDSHAKE;
-        } else { // cs_DATA
-            connectionState = cs_RENEGOTIATE;
-        }
-        if (roleIsServer) {
-            handshaker = new ServerHandshaker(this, sslContext,
-                    enabledProtocols, doClientAuth,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-            handshaker.setSNIMatchers(sniMatchers);
-            handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
-        } else {
-            handshaker = new ClientHandshaker(this, sslContext,
-                    enabledProtocols,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-            handshaker.setSNIServerNames(serverNames);
-        }
-        handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        handshaker.setEnableSessionCreation(enableSessionCreation);
-        handshaker.setApplicationProtocols(applicationProtocols);
-        handshaker.setApplicationProtocolSelectorSSLEngine(
-            applicationProtocolSelector);
-    }
-
-    /*
-     * Report the current status of the Handshaker
-     */
-    private HandshakeStatus getHSStatus(HandshakeStatus hss) {
-
-        if (hss != null) {
-            return hss;
-        }
-
-        synchronized (this) {
-            if (writer.hasOutboundData()) {
-                return HandshakeStatus.NEED_WRAP;
-            } else if (handshaker != null) {
-                if (handshaker.taskOutstanding()) {
-                    return HandshakeStatus.NEED_TASK;
-                } else {
-                    return HandshakeStatus.NEED_UNWRAP;
-                }
-            } else if (connectionState == cs_CLOSED) {
-                /*
-                 * Special case where we're closing, but
-                 * still need the close_notify before we
-                 * can officially be closed.
-                 *
-                 * Note isOutboundDone is taken care of by
-                 * hasOutboundData() above.
-                 */
-                if (!isInboundDone()) {
-                    return HandshakeStatus.NEED_UNWRAP;
-                } // else not handshaking
-            }
-            return HandshakeStatus.NOT_HANDSHAKING;
-        }
-    }
-
-    synchronized private void checkTaskThrown() throws SSLException {
-        if (handshaker != null) {
-            handshaker.checkThrown();
-        }
-    }
-
-    //
-    // Handshaking and connection state code
-    //
-
-    /*
-     * Provides "this" synchronization for connection state.
-     * Otherwise, you can access it directly.
-     */
-    synchronized private int getConnectionState() {
-        return connectionState;
-    }
-
-    synchronized private void setConnectionState(int state) {
-        connectionState = state;
-    }
-
-    /*
-     * Get the Access Control Context.
-     *
-     * Used for a known context to
-     * run tasks in, and for determining which credentials
-     * to use for Subject-based (JAAS) decisions.
-     */
-    AccessControlContext getAcc() {
-        return acc;
-    }
-
-    /*
-     * Is a handshake currently underway?
-     */
-    @Override
-    public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
-        return getHSStatus(null);
-    }
-
-    /*
-     * When a connection finishes handshaking by enabling use of a newly
-     * negotiated session, each end learns about it in two halves (read,
-     * and write).  When both read and write ciphers have changed, and the
-     * last handshake message has been read, the connection has joined
-     * (rejoined) the new session.
-     *
-     * NOTE:  The SSLv3 spec is rather unclear on the concepts here.
-     * Sessions don't change once they're established (including cipher
-     * suite and master secret) but connections can join them (and leave
-     * them).  They're created by handshaking, though sometime handshaking
-     * causes connections to join up with pre-established sessions.
-     *
-     * Synchronized on "this" from readRecord.
-     */
-    private void changeReadCiphers() throws SSLException {
-        CipherBox oldCipher = readCipher;
-
-        try {
-            readCipher = handshaker.newReadCipher();
-            readAuthenticator = handshaker.newReadAuthenticator();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw new SSLException("Algorithm missing:  ", e);
-        }
-
-        /*
-         * Dispose of any intermediate state in the underlying cipher.
-         * For PKCS11 ciphers, this will release any attached sessions,
-         * and thus make finalization faster.
-         *
-         * Since MAC's doFinal() is called for every SSL/TLS packet, it's
-         * not necessary to do the same with MAC's.
-         */
-        oldCipher.dispose();
-    }
-
-    /*
-     * used by Handshaker to change the active write cipher, follows
-     * the output of the CCS message.
-     *
-     * Also synchronized on "this" from readRecord/delegatedTask.
-     */
-    void changeWriteCiphers() throws SSLException {
-        if (connectionState != cs_HANDSHAKE
-                && connectionState != cs_RENEGOTIATE) {
-            throw new SSLProtocolException(
-                "State error, change cipher specs");
-        }
-
-        // ... create compressor
-
-        CipherBox oldCipher = writeCipher;
-
-        try {
-            writeCipher = handshaker.newWriteCipher();
-            writeAuthenticator = handshaker.newWriteAuthenticator();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw new SSLException("Algorithm missing:  ", e);
-        }
-
-        // See comment above.
-        oldCipher.dispose();
-
-        // reset the flag of the first application record
-        isFirstAppOutputRecord = true;
-    }
-
-    /*
-     * Updates the SSL version associated with this connection.
-     * Called from Handshaker once it has determined the negotiated version.
-     */
-    synchronized void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        outputRecord.setVersion(protocolVersion);
-    }
-
-
-    /**
-     * Kickstart the handshake if it is not already in progress.
-     * This means:
-     *
-     *  . if handshaking is already underway, do nothing and return
-     *
-     *  . if the engine is not connected or already closed, throw an
-     *    Exception.
-     *
-     *  . otherwise, call initHandshake() to initialize the handshaker
-     *    object and progress the state. Then, send the initial
-     *    handshaking message if appropriate (always on clients and
-     *    on servers when renegotiating).
-     */
-    private synchronized void kickstartHandshake() throws IOException {
-        switch (connectionState) {
-
-        case cs_START:
-            if (!serverModeSet) {
-                throw new IllegalStateException(
-                    "Client/Server mode not yet set.");
-            }
-            initHandshaker();
-            break;
-
-        case cs_HANDSHAKE:
-            // handshaker already setup, proceed
-            break;
-
-        case cs_DATA:
-            if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
-                throw new SSLHandshakeException(
-                        "Insecure renegotiation is not allowed");
-            }
-
-            if (!secureRenegotiation) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "Warning: Using insecure renegotiation");
-                }
-            }
-
-            // initialize the handshaker, move to cs_RENEGOTIATE
-            initHandshaker();
-            break;
-
-        case cs_RENEGOTIATE:
-            // handshaking already in progress, return
-            return;
-
-        default:
-            // cs_ERROR/cs_CLOSED
-            throw new SSLException("SSLEngine is closing/closed");
-        }
-
-        //
-        // Kickstart handshake state machine if we need to ...
-        //
-        // Note that handshaker.kickstart() writes the message
-        // to its HandshakeOutStream, which calls back into
-        // SSLSocketImpl.writeRecord() to send it.
-        //
-        if (!handshaker.activated()) {
-             // prior to handshaking, activate the handshake
-            if (connectionState == cs_RENEGOTIATE) {
-                // don't use SSLv2Hello when renegotiating
-                handshaker.activate(protocolVersion);
-            } else {
-                handshaker.activate(null);
-            }
-
-            if (handshaker instanceof ClientHandshaker) {
-                // send client hello
-                handshaker.kickstart();
-            } else {    // instanceof ServerHandshaker
-                if (connectionState == cs_HANDSHAKE) {
-                    // initial handshake, no kickstart message to send
-                } else {
-                    // we want to renegotiate, send hello request
-                    handshaker.kickstart();
-
-                    // hello request is not included in the handshake
-                    // hashes, reset them
-                    handshaker.handshakeHash.reset();
-                }
-            }
-        }
-    }
-
-    /*
-     * Start a SSLEngine handshake
-     */
-    @Override
-    public void beginHandshake() throws SSLException {
-        try {
-            kickstartHandshake();
-        } catch (Exception e) {
-            fatal(Alerts.alert_handshake_failure,
-                "Couldn't kickstart handshaking", e);
-        }
-    }
-
-
-    //
-    // Read/unwrap side
-    //
-
-
-    /**
-     * Unwraps a buffer.  Does a variety of checks before grabbing
-     * the unwrapLock, which blocks multiple unwraps from occurring.
-     */
-    @Override
-    public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer [] appData,
-            int offset, int length) throws SSLException {
-
-        EngineArgs ea = new EngineArgs(netData, appData, offset, length);
-
-        try {
-            synchronized (unwrapLock) {
-                return readNetRecord(ea);
-            }
-        } catch (SSLProtocolException spe) {
-            // may be an unexpected handshake message
-            fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
-            return null;  // make compiler happy
-        } catch (Exception e) {
-            /*
-             * Don't reset position so it looks like we didn't
-             * consume anything.  We did consume something, and it
-             * got us into this situation, so report that much back.
-             * Our days of consuming are now over anyway.
-             */
-            fatal(Alerts.alert_internal_error,
-                "problem unwrapping net record", e);
-            return null;  // make compiler happy
-        } finally {
-            /*
-             * Just in case something failed to reset limits properly.
-             */
-            ea.resetLim();
-        }
-    }
-
-    /*
-     * Makes additional checks for unwrap, but this time more
-     * specific to this packet and the current state of the machine.
-     */
-    private SSLEngineResult readNetRecord(EngineArgs ea) throws IOException {
-
-        Status status = null;
-        HandshakeStatus hsStatus = null;
-
-        /*
-         * See if the handshaker needs to report back some SSLException.
-         */
-        checkTaskThrown();
-
-        /*
-         * Check if we are closing/closed.
-         */
-        if (isInboundDone()) {
-            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
-        }
-
-        /*
-         * If we're still in cs_HANDSHAKE, make sure it's been
-         * started.
-         */
-        synchronized (this) {
-            if ((connectionState == cs_HANDSHAKE) ||
-                    (connectionState == cs_START)) {
-                kickstartHandshake();
-
-                /*
-                 * If there's still outbound data to flush, we
-                 * can return without trying to unwrap anything.
-                 */
-                hsStatus = getHSStatus(null);
-
-                if (hsStatus == HandshakeStatus.NEED_WRAP) {
-                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
-                }
-            }
-        }
-
-        /*
-         * Grab a copy of this if it doesn't already exist,
-         * and we can use it several places before anything major
-         * happens on this side.  Races aren't critical
-         * here.
-         */
-        if (hsStatus == null) {
-            hsStatus = getHSStatus(null);
-        }
-
-        /*
-         * If we have a task outstanding, this *MUST* be done before
-         * doing any more unwrapping, because we could be in the middle
-         * of receiving a handshake message, for example, a finished
-         * message which would change the ciphers.
-         */
-        if (hsStatus == HandshakeStatus.NEED_TASK) {
-            return new SSLEngineResult(
-                Status.OK, hsStatus, 0, 0);
-        }
-
-        /*
-         * Check the packet to make sure enough is here.
-         * This will also indirectly check for 0 len packets.
-         */
-        int packetLen = inputRecord.bytesInCompletePacket(ea.netData);
-
-        // Is this packet bigger than SSL/TLS normally allows?
-        if (packetLen > sess.getPacketBufferSize()) {
-            if (packetLen > Record.maxLargeRecordSize) {
-                throw new SSLProtocolException(
-                    "Input SSL/TLS record too big: max = " +
-                    Record.maxLargeRecordSize +
-                    " len = " + packetLen);
-            } else {
-                // Expand the expected maximum packet/application buffer
-                // sizes.
-                sess.expandBufferSizes();
-            }
-        }
-
-        /*
-         * Check for OVERFLOW.
-         *
-         * To be considered: We could delay enforcing the application buffer
-         * free space requirement until after the initial handshaking.
-         */
-        if ((packetLen - Record.headerSize) > ea.getAppRemaining()) {
-            return new SSLEngineResult(Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
-        }
-
-        // check for UNDERFLOW.
-        if ((packetLen == -1) || (ea.netData.remaining() < packetLen)) {
-            return new SSLEngineResult(
-                Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
-        }
-
-        /*
-         * We're now ready to actually do the read.
-         * The only result code we really need to be exactly
-         * right is the HS finished, for signaling to
-         * HandshakeCompletedListeners.
-         */
-        try {
-            hsStatus = readRecord(ea);
-        } catch (SSLException e) {
-            throw e;
-        } catch (IOException e) {
-            throw new SSLException("readRecord", e);
-        }
-
-        /*
-         * Check the various condition that we could be reporting.
-         *
-         * It's *possible* something might have happened between the
-         * above and now, but it was better to minimally lock "this"
-         * during the read process.  We'll return the current
-         * status, which is more representative of the current state.
-         *
-         * status above should cover:  FINISHED, NEED_TASK
-         */
-        status = (isInboundDone() ? Status.CLOSED : Status.OK);
-        hsStatus = getHSStatus(hsStatus);
-
-        return new SSLEngineResult(status, hsStatus,
-            ea.deltaNet(), ea.deltaApp());
-    }
-
-    /*
-     * Actually do the read record processing.
-     *
-     * Returns a Status if it can make specific determinations
-     * of the engine state.  In particular, we need to signal
-     * that a handshake just completed.
-     *
-     * It would be nice to be symmetrical with the write side and move
-     * the majority of this to EngineInputRecord, but there's too much
-     * SSLEngine state to do that cleanly.  It must still live here.
-     */
-    private HandshakeStatus readRecord(EngineArgs ea) throws IOException {
-
-        HandshakeStatus hsStatus = null;
-
-        /*
-         * The various operations will return new sliced BB's,
-         * this will avoid having to worry about positions and
-         * limits in the netBB.
-         */
-        ByteBuffer readBB = null;
-        ByteBuffer decryptedBB = null;
-
-        if (getConnectionState() != cs_ERROR) {
-
-            /*
-             * Read a record ... maybe emitting an alert if we get a
-             * comprehensible but unsupported "hello" message during
-             * format checking (e.g. V2).
-             */
-            try {
-                readBB = inputRecord.read(ea.netData);
-            } catch (IOException e) {
-                fatal(Alerts.alert_unexpected_message, e);
-            }
-
-            /*
-             * The basic SSLv3 record protection involves (optional)
-             * encryption for privacy, and an integrity check ensuring
-             * data origin authentication.  We do them both here, and
-             * throw a fatal alert if the integrity check fails.
-             */
-            try {
-                decryptedBB = inputRecord.decrypt(
-                                    readAuthenticator, readCipher, readBB);
-            } catch (BadPaddingException e) {
-                byte alertType = (inputRecord.contentType() ==
-                    Record.ct_handshake) ?
-                        Alerts.alert_handshake_failure :
-                        Alerts.alert_bad_record_mac;
-                fatal(alertType, e.getMessage(), e);
-            }
-
-            // if (!inputRecord.decompress(c))
-            //     fatal(Alerts.alert_decompression_failure,
-            //     "decompression failure");
-
-
-            /*
-             * Process the record.
-             */
-
-            synchronized (this) {
-                switch (inputRecord.contentType()) {
-                case Record.ct_handshake:
-                    /*
-                     * Handshake messages always go to a pending session
-                     * handshaker ... if there isn't one, create one.  This
-                     * must work asynchronously, for renegotiation.
-                     *
-                     * NOTE that handshaking will either resume a session
-                     * which was in the cache (and which might have other
-                     * connections in it already), or else will start a new
-                     * session (new keys exchanged) with just this connection
-                     * in it.
-                     */
-
-                    initHandshaker();
-                    if (!handshaker.activated()) {
-                        // prior to handshaking, activate the handshake
-                        if (connectionState == cs_RENEGOTIATE) {
-                            // don't use SSLv2Hello when renegotiating
-                            handshaker.activate(protocolVersion);
-                        } else {
-                            handshaker.activate(null);
-                        }
-                    }
-
-                    /*
-                     * process the handshake record ... may contain just
-                     * a partial handshake message or multiple messages.
-                     *
-                     * The handshaker state machine will ensure that it's
-                     * a finished message.
-                     */
-                    handshaker.process_record(inputRecord, expectingFinished);
-                    expectingFinished = false;
-
-                    if (handshaker.invalidated) {
-                        handshaker = null;
-                        // if state is cs_RENEGOTIATE, revert it to cs_DATA
-                        if (connectionState == cs_RENEGOTIATE) {
-                            connectionState = cs_DATA;
-                        }
-                    } else if (handshaker.isDone()) {
-                        // reset the parameters for secure renegotiation.
-                        secureRenegotiation =
-                                        handshaker.isSecureRenegotiation();
-                        clientVerifyData = handshaker.getClientVerifyData();
-                        serverVerifyData = handshaker.getServerVerifyData();
-                        // set connection ALPN value
-                        applicationProtocol =
-                            handshaker.getHandshakeApplicationProtocol();
-
-                        sess = handshaker.getSession();
-                        handshakeSession = null;
-                        if (!writer.hasOutboundData()) {
-                            hsStatus = HandshakeStatus.FINISHED;
-                        }
-                        handshaker = null;
-                        connectionState = cs_DATA;
-                        // No handshakeListeners here.  That's a
-                        // SSLSocket thing.
-                    } else if (handshaker.taskOutstanding()) {
-                        hsStatus = HandshakeStatus.NEED_TASK;
-                    }
-                    break;
-
-                case Record.ct_application_data:
-                    // Pass this right back up to the application.
-                    if ((connectionState != cs_DATA)
-                            && (connectionState != cs_RENEGOTIATE)
-                            && (connectionState != cs_CLOSED)) {
-                        throw new SSLProtocolException(
-                            "Data received in non-data state: " +
-                            connectionState);
-                    }
-
-                    if (expectingFinished) {
-                        throw new SSLProtocolException
-                                ("Expecting finished message, received data");
-                    }
-
-                    /*
-                     * Don't return data once the inbound side is
-                     * closed.
-                     */
-                    if (!inboundDone) {
-                        ea.scatter(decryptedBB.slice());
-                    }
-                    break;
-
-                case Record.ct_alert:
-                    recvAlert();
-                    break;
-
-                case Record.ct_change_cipher_spec:
-                    if ((connectionState != cs_HANDSHAKE
-                                && connectionState != cs_RENEGOTIATE)) {
-                        // For the CCS message arriving in the wrong state
-                        fatal(Alerts.alert_unexpected_message,
-                                "illegal change cipher spec msg, conn state = "
-                                + connectionState);
-                    } else if (inputRecord.available() != 1
-                            || inputRecord.read() != 1) {
-                        // For structural/content issues with the CCS
-                        fatal(Alerts.alert_unexpected_message,
-                                "Malformed change cipher spec msg");
-                    }
-
-                    //
-                    // The first message after a change_cipher_spec
-                    // record MUST be a "Finished" handshake record,
-                    // else it's a protocol violation.  We force this
-                    // to be checked by a minor tweak to the state
-                    // machine.
-                    //
-                    handshaker.receiveChangeCipherSpec();
-                    changeReadCiphers();
-                    // next message MUST be a finished message
-                    expectingFinished = true;
-                    break;
-
-                default:
-                    //
-                    // TLS requires that unrecognized records be ignored.
-                    //
-                    if (debug != null && Debug.isOn("ssl")) {
-                        System.out.println(Thread.currentThread().getName() +
-                            ", Received record type: "
-                            + inputRecord.contentType());
-                    }
-                    break;
-                } // switch
-
-                /*
-                 * We only need to check the sequence number state for
-                 * non-handshaking record.
-                 *
-                 * Note that in order to maintain the handshake status
-                 * properly, we check the sequence number after the last
-                 * record reading process. As we request renegotiation
-                 * or close the connection for wrapped sequence number
-                 * when there is enough sequence number space left to
-                 * handle a few more records, so the sequence number
-                 * of the last record cannot be wrapped.
-                 */
-                hsStatus = getHSStatus(hsStatus);
-                if (connectionState < cs_ERROR && !isInboundDone() &&
-                        (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
-                    if (checkSequenceNumber(readAuthenticator,
-                            inputRecord.contentType())) {
-                        hsStatus = getHSStatus(null);
-                    }
-                }
-            } // synchronized (this)
-        }
-        return hsStatus;
-    }
-
-
-    //
-    // write/wrap side
-    //
-
-
-    /**
-     * Wraps a buffer.  Does a variety of checks before grabbing
-     * the wrapLock, which blocks multiple wraps from occurring.
-     */
-    @Override
-    public SSLEngineResult wrap(ByteBuffer [] appData,
-            int offset, int length, ByteBuffer netData) throws SSLException {
-
-        EngineArgs ea = new EngineArgs(appData, offset, length, netData);
-
-        /*
-         * We can be smarter about using smaller buffer sizes later.
-         * For now, force it to be large enough to handle any
-         * valid SSL/TLS record.
-         */
-        if (netData.remaining() < EngineOutputRecord.maxRecordSize) {
-            return new SSLEngineResult(
-                Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);
-        }
-
-        try {
-            synchronized (wrapLock) {
-                return writeAppRecord(ea);
-            }
-        } catch (SSLProtocolException spe) {
-            // may be an unexpected handshake message
-            fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
-            return null;  // make compiler happy
-        } catch (Exception e) {
-            ea.resetPos();
-
-            fatal(Alerts.alert_internal_error,
-                "problem wrapping app data", e);
-            return null;  // make compiler happy
-        } finally {
-            /*
-             * Just in case something didn't reset limits properly.
-             */
-            ea.resetLim();
-        }
-    }
-
-    /*
-     * Makes additional checks for unwrap, but this time more
-     * specific to this packet and the current state of the machine.
-     */
-    private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException {
-
-        Status status = null;
-        HandshakeStatus hsStatus = null;
-
-        /*
-         * See if the handshaker needs to report back some SSLException.
-         */
-        checkTaskThrown();
-        /*
-         * short circuit if we're closed/closing.
-         */
-        if (writer.isOutboundDone()) {
-            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
-        }
-
-        /*
-         * If we're still in cs_HANDSHAKE, make sure it's been
-         * started.
-         */
-        synchronized (this) {
-            if ((connectionState == cs_HANDSHAKE) ||
-                    (connectionState == cs_START)) {
-                kickstartHandshake();
-
-                /*
-                 * If there's no HS data available to write, we can return
-                 * without trying to wrap anything.
-                 */
-                hsStatus = getHSStatus(null);
-                if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
-                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
-                }
-            }
-        }
-
-        /*
-         * Grab a copy of this if it doesn't already exist,
-         * and we can use it several places before anything major
-         * happens on this side.  Races aren't critical
-         * here.
-         */
-        if (hsStatus == null) {
-            hsStatus = getHSStatus(null);
-        }
-
-        /*
-         * If we have a task outstanding, this *MUST* be done before
-         * doing any more wrapping, because we could be in the middle
-         * of receiving a handshake message, for example, a finished
-         * message which would change the ciphers.
-         */
-        if (hsStatus == HandshakeStatus.NEED_TASK) {
-            return new SSLEngineResult(
-                Status.OK, hsStatus, 0, 0);
-        }
-
-        /*
-         * This will obtain any waiting outbound data, or will
-         * process the outbound appData.
-         */
-        try {
-            synchronized (writeLock) {
-                hsStatus = writeRecord(outputRecord, ea);
-            }
-        } catch (SSLException e) {
-            throw e;
-        } catch (IOException e) {
-            throw new SSLException("Write problems", e);
-        }
-
-        /*
-         * writeRecord might have reported some status.
-         * Now check for the remaining cases.
-         *
-         * status above should cover:  NEED_WRAP/FINISHED
-         */
-        status = (isOutboundDone() ? Status.CLOSED : Status.OK);
-        hsStatus = getHSStatus(hsStatus);
-
-        return new SSLEngineResult(status, hsStatus,
-            ea.deltaApp(), ea.deltaNet());
-    }
-
-    /*
-     * Central point to write/get all of the outgoing data.
-     */
-    private HandshakeStatus writeRecord(EngineOutputRecord eor,
-            EngineArgs ea) throws IOException {
-
-        // eventually compress as well.
-        HandshakeStatus hsStatus =
-                writer.writeRecord(eor, ea, writeAuthenticator, writeCipher);
-
-        /*
-         * We only need to check the sequence number state for
-         * non-handshaking record.
-         *
-         * Note that in order to maintain the handshake status
-         * properly, we check the sequence number after the last
-         * record writing process. As we request renegotiation
-         * or close the connection for wrapped sequence number
-         * when there is enough sequence number space left to
-         * handle a few more records, so the sequence number
-         * of the last record cannot be wrapped.
-         */
-        hsStatus = getHSStatus(hsStatus);
-        if (connectionState < cs_ERROR && !isOutboundDone() &&
-                (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
-            if (checkSequenceNumber(writeAuthenticator, eor.contentType())) {
-                hsStatus = getHSStatus(null);
-            }
-        }
-
-        /*
-         * turn off the flag of the first application record if we really
-         * consumed at least byte.
-         */
-        if (isFirstAppOutputRecord && ea.deltaApp() > 0) {
-            isFirstAppOutputRecord = false;
-        }
-
-        return hsStatus;
-    }
-
-    /*
-     * Need to split the payload except the following cases:
-     *
-     * 1. protocol version is TLS 1.1 or later;
-     * 2. bulk cipher does not use CBC mode, including null bulk cipher suites.
-     * 3. the payload is the first application record of a freshly
-     *    negotiated TLS session.
-     * 4. the CBC protection is disabled;
-     *
-     * More details, please refer to
-     * EngineOutputRecord.write(EngineArgs, MAC, CipherBox).
-     */
-    boolean needToSplitPayload(CipherBox cipher, ProtocolVersion protocol) {
-        return (protocol.v <= ProtocolVersion.TLS10.v) &&
-                cipher.isCBCMode() && !isFirstAppOutputRecord &&
-                Record.enableCBCProtection;
-    }
-
-    /*
-     * Non-application OutputRecords go through here.
-     */
-    void writeRecord(EngineOutputRecord eor) throws IOException {
-        // eventually compress as well.
-        writer.writeRecord(eor, writeAuthenticator, writeCipher);
-
-        /*
-         * Check the sequence number state
-         *
-         * Note that in order to maintain the connection I/O
-         * properly, we check the sequence number after the last
-         * record writing process. As we request renegotiation
-         * or close the connection for wrapped sequence number
-         * when there is enough sequence number space left to
-         * handle a few more records, so the sequence number
-         * of the last record cannot be wrapped.
-         */
-        if ((connectionState < cs_ERROR) && !isOutboundDone()) {
-            checkSequenceNumber(writeAuthenticator, eor.contentType());
-        }
-    }
-
-    //
-    // Close code
-    //
-
-    /**
-     * Check the sequence number state
-     *
-     * RFC 4346 states that, "Sequence numbers are of type uint64 and
-     * may not exceed 2^64-1.  Sequence numbers do not wrap. If a TLS
-     * implementation would need to wrap a sequence number, it must
-     * renegotiate instead."
-     *
-     * Return true if the handshake status may be changed.
-     */
-    private boolean checkSequenceNumber(Authenticator authenticator, byte type)
-            throws IOException {
-
-        /*
-         * Don't bother to check the sequence number for error or
-         * closed connections, or NULL MAC
-         */
-        if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
-            return false;
-        }
-
-        /*
-         * Conservatively, close the connection immediately when the
-         * sequence number is close to overflow
-         */
-        if (authenticator.seqNumOverflow()) {
-            /*
-             * TLS protocols do not define a error alert for sequence
-             * number overflow. We use handshake_failure error alert
-             * for handshaking and bad_record_mac for other records.
-             */
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", sequence number extremely close to overflow " +
-                    "(2^64-1 packets). Closing connection.");
-            }
-
-            fatal(Alerts.alert_handshake_failure, "sequence number overflow");
-
-            return true; // make the compiler happy
-        }
-
-        /*
-         * Ask for renegotiation when need to renew sequence number.
-         *
-         * Don't bother to kickstart the renegotiation when the local is
-         * asking for it.
-         */
-        if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                        ", request renegotiation " +
-                        "to avoid sequence number overflow");
-            }
-
-            beginHandshake();
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Signals that no more outbound application data will be sent
-     * on this <code>SSLEngine</code>.
-     */
-    private void closeOutboundInternal() {
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                                    ", closeOutboundInternal()");
-        }
-
-        /*
-         * Already closed, ignore
-         */
-        if (writer.isOutboundDone()) {
-            return;
-        }
-
-        switch (connectionState) {
-
-        /*
-         * If we haven't even started yet, don't bother reading inbound.
-         */
-        case cs_START:
-            writer.closeOutbound();
-            inboundDone = true;
-            break;
-
-        case cs_ERROR:
-        case cs_CLOSED:
-            break;
-
-        /*
-         * Otherwise we indicate clean termination.
-         */
-        // case cs_HANDSHAKE:
-        // case cs_DATA:
-        // case cs_RENEGOTIATE:
-        default:
-            warning(Alerts.alert_close_notify);
-            writer.closeOutbound();
-            break;
-        }
-
-        // See comment in changeReadCiphers()
-        writeCipher.dispose();
-
-        connectionState = cs_CLOSED;
-    }
-
-    @Override
-    synchronized public void closeOutbound() {
-        /*
-         * Dump out a close_notify to the remote side
-         */
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                                    ", called closeOutbound()");
-        }
-
-        closeOutboundInternal();
-    }
-
-    /**
-     * Returns the outbound application data closure state
-     */
-    @Override
-    public boolean isOutboundDone() {
-        return writer.isOutboundDone();
-    }
-
-    /**
-     * Signals that no more inbound network data will be sent
-     * to this <code>SSLEngine</code>.
-     */
-    private void closeInboundInternal() {
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                                    ", closeInboundInternal()");
-        }
-
-        /*
-         * Already closed, ignore
-         */
-        if (inboundDone) {
-            return;
-        }
-
-        closeOutboundInternal();
-        inboundDone = true;
-
-        // See comment in changeReadCiphers()
-        readCipher.dispose();
-
-        connectionState = cs_CLOSED;
-    }
-
-    /*
-     * Close the inbound side of the connection.  We grab the
-     * lock here, and do the real work in the internal verison.
-     * We do check for truncation attacks.
-     */
-    @Override
-    synchronized public void closeInbound() throws SSLException {
-        /*
-         * Currently closes the outbound side as well.  The IETF TLS
-         * working group has expressed the opinion that 1/2 open
-         * connections are not allowed by the spec.  May change
-         * someday in the future.
-         */
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                                    ", called closeInbound()");
-        }
-
-        /*
-         * No need to throw an Exception if we haven't even started yet.
-         */
-        if ((connectionState != cs_START) && !recvCN) {
-            recvCN = true;  // Only receive the Exception once
-            fatal(Alerts.alert_internal_error,
-                "Inbound closed before receiving peer's close_notify: " +
-                "possible truncation attack?");
-        } else {
-            /*
-             * Currently, this is a no-op, but in case we change
-             * the close inbound code later.
-             */
-            closeInboundInternal();
-        }
-    }
-
-    /**
-     * Returns the network inbound data closure state
-     */
-    @Override
-    synchronized public boolean isInboundDone() {
-        return inboundDone;
-    }
-
-
-    //
-    // Misc stuff
-    //
-
-
-    /**
-     * Returns the current <code>SSLSession</code> for this
-     * <code>SSLEngine</code>
-     * <P>
-     * These can be long lived, and frequently correspond to an
-     * entire login session for some user.
-     */
-    @Override
-    synchronized public SSLSession getSession() {
-        return sess;
-    }
-
-    @Override
-    synchronized public SSLSession getHandshakeSession() {
-        return handshakeSession;
-    }
-
-    synchronized void setHandshakeSession(SSLSessionImpl session) {
-        handshakeSession = session;
-    }
-
-    /**
-     * Returns a delegated <code>Runnable</code> task for
-     * this <code>SSLEngine</code>.
-     */
-    @Override
-    synchronized public Runnable getDelegatedTask() {
-        if (handshaker != null) {
-            return handshaker.getTask();
-        }
-        return null;
-    }
-
-
-    //
-    // EXCEPTION AND ALERT HANDLING
-    //
-
-    /*
-     * Send a warning alert.
-     */
-    void warning(byte description) {
-        sendAlert(Alerts.alert_warning, description);
-    }
-
-    synchronized void fatal(byte description, String diagnostic)
-            throws SSLException {
-        fatal(description, diagnostic, null);
-    }
-
-    synchronized void fatal(byte description, Throwable cause)
-            throws SSLException {
-        fatal(description, null, cause);
-    }
-
-    /*
-     * We've got a fatal error here, so start the shutdown process.
-     *
-     * Because of the way the code was written, we have some code
-     * calling fatal directly when the "description" is known
-     * and some throwing Exceptions which are then caught by higher
-     * levels which then call here.  This code needs to determine
-     * if one of the lower levels has already started the process.
-     *
-     * We won't worry about Error's, if we have one of those,
-     * we're in worse trouble.  Note:  the networking code doesn't
-     * deal with Errors either.
-     */
-    synchronized void fatal(byte description, String diagnostic,
-            Throwable cause) throws SSLException {
-
-        /*
-         * If we have no further information, make a general-purpose
-         * message for folks to see.  We generally have one or the other.
-         */
-        if (diagnostic == null) {
-            diagnostic = "General SSLEngine problem";
-        }
-        if (cause == null) {
-            cause = Alerts.getSSLException(description, cause, diagnostic);
-        }
-
-        /*
-         * If we've already shutdown because of an error,
-         * there is nothing we can do except rethrow the exception.
-         *
-         * Most exceptions seen here will be SSLExceptions.
-         * We may find the occasional Exception which hasn't been
-         * converted to a SSLException, so we'll do it here.
-         */
-        if (closeReason != null) {
-            if ((debug != null) && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", fatal: engine already closed.  Rethrowing " +
-                    cause.toString());
-            }
-            if (cause instanceof RuntimeException) {
-                throw (RuntimeException)cause;
-            } else if (cause instanceof SSLException) {
-                throw (SSLException)cause;
-            } else if (cause instanceof Exception) {
-                throw new SSLException("fatal SSLEngine condition", cause);
-            }
-        }
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName()
-                        + ", fatal error: " + description +
-                        ": " + diagnostic + "\n" + cause.toString());
-        }
-
-        /*
-         * Ok, this engine's going down.
-         */
-        int oldState = connectionState;
-        connectionState = cs_ERROR;
-
-        inboundDone = true;
-
-        sess.invalidate();
-        if (handshakeSession != null) {
-            handshakeSession.invalidate();
-        }
-
-        /*
-         * If we haven't even started handshaking yet, no need
-         * to generate the fatal close alert.
-         */
-        if (oldState != cs_START) {
-            sendAlert(Alerts.alert_fatal, description);
-        }
-
-        if (cause instanceof SSLException) { // only true if != null
-            closeReason = (SSLException)cause;
-        } else {
-            /*
-             * Including RuntimeExceptions, but we'll throw those
-             * down below.  The closeReason isn't used again,
-             * except for null checks.
-             */
-            closeReason =
-                Alerts.getSSLException(description, cause, diagnostic);
-        }
-
-        writer.closeOutbound();
-
-        connectionState = cs_CLOSED;
-
-        // See comment in changeReadCiphers()
-        readCipher.dispose();
-        writeCipher.dispose();
-
-        if (cause instanceof RuntimeException) {
-            throw (RuntimeException)cause;
-        } else {
-            throw closeReason;
-        }
-    }
-
-    /*
-     * Process an incoming alert ... caller must already have synchronized
-     * access to "this".
-     */
-    private void recvAlert() throws IOException {
-        byte level = (byte)inputRecord.read();
-        byte description = (byte)inputRecord.read();
-        if (description == -1) { // check for short message
-            fatal(Alerts.alert_illegal_parameter, "Short alert message");
-        }
-
-        if (debug != null && (Debug.isOn("record") ||
-                Debug.isOn("handshake"))) {
-            synchronized (System.out) {
-                System.out.print(Thread.currentThread().getName());
-                System.out.print(", RECV " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level " + (0x0ff & level) + ">, ");
-                }
-                System.out.println(Alerts.alertDescription(description));
-            }
-        }
-
-        if (level == Alerts.alert_warning) {
-            if (description == Alerts.alert_close_notify) {
-                if (connectionState == cs_HANDSHAKE) {
-                    fatal(Alerts.alert_unexpected_message,
-                                "Received close_notify during handshake");
-                } else {
-                    recvCN = true;
-                    closeInboundInternal();  // reply to close
-                }
-            } else {
-
-                //
-                // The other legal warnings relate to certificates,
-                // e.g. no_certificate, bad_certificate, etc; these
-                // are important to the handshaking code, which can
-                // also handle illegal protocol alerts if needed.
-                //
-                if (handshaker != null) {
-                    handshaker.handshakeAlert(description);
-                }
-            }
-        } else { // fatal or unknown level
-            String reason = "Received fatal alert: "
-                + Alerts.alertDescription(description);
-            if (closeReason == null) {
-                closeReason = Alerts.getSSLException(description, reason);
-            }
-            fatal(Alerts.alert_unexpected_message, reason);
-        }
-    }
-
-
-    /*
-     * Emit alerts.  Caller must have synchronized with "this".
-     */
-    private void sendAlert(byte level, byte description) {
-        // the connectionState cannot be cs_START
-        if (connectionState >= cs_CLOSED) {
-            return;
-        }
-
-        // For initial handshaking, don't send alert message to peer if
-        // handshaker has not started.
-        if (connectionState == cs_HANDSHAKE &&
-            (handshaker == null || !handshaker.started())) {
-            return;
-        }
-
-        EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
-        r.setVersion(protocolVersion);
-
-        boolean useDebug = debug != null && Debug.isOn("ssl");
-        if (useDebug) {
-            synchronized (System.out) {
-                System.out.print(Thread.currentThread().getName());
-                System.out.print(", SEND " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level = " + (0x0ff & level) + ">, ");
-                }
-                System.out.println("description = "
-                        + Alerts.alertDescription(description));
-            }
-        }
-
-        r.write(level);
-        r.write(description);
-        try {
-            writeRecord(r);
-        } catch (IOException e) {
-            if (useDebug) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", Exception sending alert: " + e);
-            }
-        }
-    }
-
-
-    //
-    // VARIOUS OTHER METHODS (COMMON TO SSLSocket)
-    //
-
-
-    /**
-     * Controls whether new connections may cause creation of new SSL
-     * sessions.
-     *
-     * As long as handshaking has not started, we can change
-     * whether we enable session creations.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    @Override
-    synchronized public void setEnableSessionCreation(boolean flag) {
-        enableSessionCreation = flag;
-
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnableSessionCreation(enableSessionCreation);
-        }
-    }
-
-    /**
-     * Returns true if new connections may cause creation of new SSL
-     * sessions.
-     */
-    @Override
-    synchronized public boolean getEnableSessionCreation() {
-        return enableSessionCreation;
-    }
-
-
-    /**
-     * Sets the flag controlling whether a server mode engine
-     * *REQUIRES* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is needed.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    @Override
-    synchronized public void setNeedClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    @Override
-    synchronized public boolean getNeedClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_required);
-    }
-
-    /**
-     * Sets the flag controlling whether a server mode engine
-     * *REQUESTS* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is requested.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    @Override
-    synchronized public void setWantClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    @Override
-    synchronized public boolean getWantClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_requested);
-    }
-
-
-    /**
-     * Sets the flag controlling whether the engine is in SSL
-     * client or server mode.  Must be called before any SSL
-     * traffic has started.
-     */
-    @Override
-    @SuppressWarnings("fallthrough")
-    synchronized public void setUseClientMode(boolean flag) {
-        switch (connectionState) {
-
-        case cs_START:
-            /*
-             * If we need to change the socket mode and the enabled
-             * protocols and cipher suites haven't specifically been
-             * set by the user, change them to the corresponding
-             * default ones.
-             */
-            if (roleIsServer != (!flag)) {
-                if (sslContext.isDefaultProtocolList(enabledProtocols)) {
-                    enabledProtocols =
-                            sslContext.getDefaultProtocolList(!flag);
-                }
-
-                if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) {
-                    enabledCipherSuites =
-                            sslContext.getDefaultCipherSuiteList(!flag);
-                }
-            }
-
-            roleIsServer = !flag;
-            serverModeSet = true;
-            break;
-
-        case cs_HANDSHAKE:
-            /*
-             * If we have a handshaker, but haven't started
-             * SSL traffic, we can throw away our current
-             * handshaker, and start from scratch.  Don't
-             * need to call doneConnect() again, we already
-             * have the streams.
-             */
-            assert(handshaker != null);
-            if (!handshaker.activated()) {
-                /*
-                 * If we need to change the engine mode and the enabled
-                 * protocols haven't specifically been set by the user,
-                 * change them to the corresponding default ones.
-                 */
-                if (roleIsServer != (!flag) &&
-                        sslContext.isDefaultProtocolList(enabledProtocols)) {
-                    enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-                }
-
-                roleIsServer = !flag;
-                connectionState = cs_START;
-                initHandshaker();
-                break;
-            }
-
-            // If handshake has started, that's an error.  Fall through...
-
-        default:
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", setUseClientMode() invoked in state = " +
-                    connectionState);
-            }
-
-            /*
-             * We can let them continue if they catch this correctly,
-             * we don't need to shut this down.
-             */
-            throw new IllegalArgumentException(
-                "Cannot change mode after SSL traffic has started");
-        }
-    }
-
-    @Override
-    synchronized public boolean getUseClientMode() {
-        return !roleIsServer;
-    }
-
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    @Override
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSupportedCipherSuiteList().toStringArray();
-    }
-
-    /**
-     * Controls which particular cipher suites are enabled for use on
-     * this connection.  The cipher suites must have been listed by
-     * getCipherSuites() as being supported.  Even if a suite has been
-     * enabled, it might never be used if no peer supports it or the
-     * requisite certificates (and private keys) are not available.
-     *
-     * @param suites Names of all the cipher suites to enable.
-     */
-    @Override
-    synchronized public void setEnabledCipherSuites(String[] suites) {
-        enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        }
-    }
-
-    /**
-     * Returns the names of the SSL cipher suites which are currently enabled
-     * for use on this connection.  When an SSL engine is first created,
-     * all enabled cipher suites <em>(a)</em> protect data confidentiality,
-     * by traffic encryption, and <em>(b)</em> can mutually authenticate
-     * both clients and servers.  Thus, in some environments, this value
-     * might be empty.
-     *
-     * @return an array of cipher suite names
-     */
-    @Override
-    synchronized public String[] getEnabledCipherSuites() {
-        return enabledCipherSuites.toStringArray();
-    }
-
-
-    /**
-     * Returns the protocols that are supported by this implementation.
-     * A subset of the supported protocols may be enabled for this connection
-     * @return an array of protocol names.
-     */
-    @Override
-    public String[] getSupportedProtocols() {
-        return sslContext.getSuportedProtocolList().toStringArray();
-    }
-
-    /**
-     * Controls which protocols are enabled for use on
-     * this connection.  The protocols must have been listed by
-     * getSupportedProtocols() as being supported.
-     *
-     * @param protocols protocols to enable.
-     * @exception IllegalArgumentException when one of the protocols
-     *  named by the parameter is not supported.
-     */
-    @Override
-    synchronized public void setEnabledProtocols(String[] protocols) {
-        enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledProtocols(enabledProtocols);
-        }
-    }
-
-    @Override
-    synchronized public String[] getEnabledProtocols() {
-        return enabledProtocols.toStringArray();
-    }
-
-    /**
-     * Returns the SSLParameters in effect for this SSLEngine.
-     */
-    @Override
-    synchronized public SSLParameters getSSLParameters() {
-        SSLParameters params = super.getSSLParameters();
-
-        // the super implementation does not handle the following parameters
-        params.setEndpointIdentificationAlgorithm(identificationProtocol);
-        params.setAlgorithmConstraints(algorithmConstraints);
-        params.setSNIMatchers(sniMatchers);
-        params.setServerNames(serverNames);
-        params.setUseCipherSuitesOrder(preferLocalCipherSuites);
-        params.setApplicationProtocols(applicationProtocols);
-
-        return params;
-    }
-
-    /**
-     * Applies SSLParameters to this engine.
-     */
-    @Override
-    synchronized public void setSSLParameters(SSLParameters params) {
-        super.setSSLParameters(params);
-
-        // the super implementation does not handle the following parameters
-        identificationProtocol = params.getEndpointIdentificationAlgorithm();
-        algorithmConstraints = params.getAlgorithmConstraints();
-        preferLocalCipherSuites = params.getUseCipherSuitesOrder();
-
-        List<SNIServerName> sniNames = params.getServerNames();
-        if (sniNames != null) {
-            serverNames = sniNames;
-        }
-
-        Collection<SNIMatcher> matchers = params.getSNIMatchers();
-        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);
-            } else {
-                handshaker.setSNIServerNames(serverNames);
-            }
-        }
-    }
-
-    @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.
-     */
-    @Override
-    public String toString() {
-        StringBuilder retval = new StringBuilder(80);
-
-        retval.append(Integer.toHexString(hashCode()));
-        retval.append("[");
-        retval.append("SSLEngine[hostname=");
-        String host = getPeerHost();
-        retval.append((host == null) ? "null" : host);
-        retval.append(" port=");
-        retval.append(Integer.toString(getPeerPort()));
-        retval.append("] ");
-        retval.append(getSession().getCipherSuite());
-        retval.append("]");
-
-        return retval.toString();
-    }
-}
--- a/src/share/classes/sun/security/ssl/SSLServerSocketFactoryImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.net.InetAddress;
-import java.net.ServerSocket;
-
-import javax.net.ssl.SSLServerSocketFactory;
-
-/**
- * This class creates SSL server sockets.
- *
- * @author David Brownell
- */
-final
-public class SSLServerSocketFactoryImpl extends SSLServerSocketFactory
-{
-    private static final int DEFAULT_BACKLOG = 50;
-    private SSLContextImpl context;
-
-
-    /**
-     * Constructor used to instantiate the default factory. This method is
-     * only called if the old "ssl.ServerSocketFactory.provider" property in the
-     * java.security file is set.
-     */
-    public SSLServerSocketFactoryImpl() throws Exception {
-        this.context = SSLContextImpl.DefaultSSLContext.getDefaultImpl();
-    }
-
-    /**
-     * Called from SSLContextImpl's getSSLServerSocketFactory().
-     */
-    SSLServerSocketFactoryImpl (SSLContextImpl context)
-    {
-        this.context = context;
-    }
-
-    /**
-     * Returns an unbound server socket.
-     *
-     * @return the unbound socket
-     * @throws IOException if the socket cannot be created
-     * @see java.net.Socket#bind(java.net.SocketAddress)
-     */
-    @Override
-    public ServerSocket createServerSocket() throws IOException {
-        return new SSLServerSocketImpl(context);
-    }
-
-    @Override
-    public ServerSocket createServerSocket (int port)
-    throws IOException
-    {
-        return new SSLServerSocketImpl (port, DEFAULT_BACKLOG, context);
-    }
-
-
-    @Override
-    public ServerSocket createServerSocket (int port, int backlog)
-    throws IOException
-    {
-        return new SSLServerSocketImpl (port, backlog, context);
-    }
-
-    @Override
-    public ServerSocket
-    createServerSocket (int port, int backlog, InetAddress ifAddress)
-    throws IOException
-    {
-        return new SSLServerSocketImpl (port, backlog, ifAddress, context);
-    }
-
-    /**
-     * Returns the subset of the supported cipher suites which are
-     * enabled by default.  These cipher suites all provide a minimum
-     * quality of service whereby the server authenticates itself
-     * (preventing person-in-the-middle attacks) and where traffic
-     * is encrypted to provide confidentiality.
-     */
-    @Override
-    public String[] getDefaultCipherSuites() {
-        return context.getDefaultCipherSuiteList(true).toStringArray();
-    }
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    @Override
-    public String[] getSupportedCipherSuites() {
-        return context.getSupportedCipherSuiteList().toStringArray();
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 1996, 2020, 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.net.InetAddress;
-import java.net.Socket;
-
-import java.security.AlgorithmConstraints;
-
-import java.util.*;
-
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SNIMatcher;
-
-
-/**
- * This class provides a simple way for servers to support conventional
- * use of the Secure Sockets Layer (SSL).  Application code uses an
- * SSLServerSocketImpl exactly like it uses a regular TCP ServerSocket; the
- * difference is that the connections established are secured using SSL.
- *
- * <P> Also, the constructors take an explicit authentication context
- * parameter, giving flexibility with respect to how the server socket
- * authenticates itself.  That policy flexibility is not exposed through
- * the standard SSLServerSocketFactory API.
- *
- * <P> System security defaults prevent server sockets from accepting
- * connections if they the authentication context has not been given
- * a certificate chain and its matching private key.  If the clients
- * of your application support "anonymous" cipher suites, you may be
- * able to configure a server socket to accept those suites.
- *
- * @see SSLSocketImpl
- * @see SSLServerSocketFactoryImpl
- *
- * @author David Brownell
- */
-final
-class SSLServerSocketImpl extends SSLServerSocket
-{
-    private SSLContextImpl      sslContext;
-
-    /* Do newly accepted connections require clients to authenticate? */
-    private byte                doClientAuth = SSLEngineImpl.clauth_none;
-
-    /* Do new connections created here use the "server" mode of SSL? */
-    private boolean             useServerMode = true;
-
-    /* Can new connections created establish new sessions? */
-    private boolean             enableSessionCreation = true;
-
-    /* what cipher suites to use by default */
-    private CipherSuiteList     enabledCipherSuites = null;
-
-    /* which protocol to use by default */
-    private ProtocolList        enabledProtocols = null;
-
-    // the endpoint identification protocol to use by default
-    private String              identificationProtocol = null;
-
-    // The cryptographic algorithm constraints
-    private AlgorithmConstraints    algorithmConstraints = null;
-
-    // The server name indication
-    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?
-     */
-    private boolean             preferLocalCipherSuites = false;
-
-    /**
-     * Create an SSL server socket on a port, using a non-default
-     * authentication context and a specified connection backlog.
-     *
-     * @param port the port on which to listen
-     * @param backlog how many connections may be pending before
-     *          the system should start rejecting new requests
-     * @param context authentication context for this server
-     */
-    SSLServerSocketImpl(int port, int backlog, SSLContextImpl context)
-    throws IOException, SSLException
-    {
-        super(port, backlog);
-        initServer(context);
-    }
-
-
-    /**
-     * Create an SSL server socket on a port, using a specified
-     * authentication context and a specified backlog of connections
-     * as well as a particular specified network interface.  This
-     * constructor is used on multihomed hosts, such as those used
-     * for firewalls or as routers, to control through which interface
-     * a network service is provided.
-     *
-     * @param port the port on which to listen
-     * @param backlog how many connections may be pending before
-     *          the system should start rejecting new requests
-     * @param address the address of the network interface through
-     *          which connections will be accepted
-     * @param context authentication context for this server
-     */
-    SSLServerSocketImpl(
-        int             port,
-        int             backlog,
-        InetAddress     address,
-        SSLContextImpl  context)
-        throws IOException
-    {
-        super(port, backlog, address);
-        initServer(context);
-    }
-
-
-    /**
-     * Creates an unbound server socket.
-     */
-    SSLServerSocketImpl(SSLContextImpl context) throws IOException {
-        super();
-        initServer(context);
-    }
-
-
-    /**
-     * Initializes the server socket.
-     */
-    private void initServer(SSLContextImpl context) throws SSLException {
-        if (context == null) {
-            throw new SSLException("No Authentication context given");
-        }
-        sslContext = context;
-        enabledCipherSuites = sslContext.getDefaultCipherSuiteList(true);
-        enabledProtocols = sslContext.getDefaultProtocolList(true);
-    }
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    @Override
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSupportedCipherSuiteList().toStringArray();
-    }
-
-    /**
-     * Returns the list of cipher suites which are currently enabled
-     * for use by newly accepted connections.  A null return indicates
-     * that the system defaults are in effect.
-     */
-    @Override
-    synchronized public String[] getEnabledCipherSuites() {
-        return enabledCipherSuites.toStringArray();
-    }
-
-    /**
-     * Controls which particular SSL cipher suites are enabled for use
-     * by accepted connections.
-     *
-     * @param suites Names of all the cipher suites to enable; null
-     *  means to accept system defaults.
-     */
-    @Override
-    synchronized public void setEnabledCipherSuites(String[] suites) {
-        enabledCipherSuites = new CipherSuiteList(suites);
-    }
-
-    @Override
-    public String[] getSupportedProtocols() {
-        return sslContext.getSuportedProtocolList().toStringArray();
-    }
-
-    /**
-     * Controls which protocols are enabled for use.
-     * The protocols must have been listed by
-     * getSupportedProtocols() as being supported.
-     *
-     * @param protocols protocols to enable.
-     * @exception IllegalArgumentException when one of the protocols
-     *  named by the parameter is not supported.
-     */
-    @Override
-    synchronized public void setEnabledProtocols(String[] protocols) {
-        enabledProtocols = new ProtocolList(protocols);
-    }
-
-    @Override
-    synchronized public String[] getEnabledProtocols() {
-        return enabledProtocols.toStringArray();
-    }
-
-    /**
-     * Controls whether the connections which are accepted must include
-     * client authentication.
-     */
-    @Override
-    public void setNeedClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-    }
-
-    @Override
-    public boolean getNeedClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_required);
-    }
-
-    /**
-     * Controls whether the connections which are accepted should request
-     * client authentication.
-     */
-    @Override
-    public void setWantClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-    }
-
-    @Override
-    public boolean getWantClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_requested);
-    }
-
-    /**
-     * Makes the returned sockets act in SSL "client" mode, not the usual
-     * server mode.  The canonical example of why this is needed is for
-     * FTP clients, which accept connections from servers and should be
-     * rejoining the already-negotiated SSL connection.
-     */
-    @Override
-    public void setUseClientMode(boolean flag) {
-        /*
-         * If we need to change the socket mode and the enabled
-         * protocols haven't specifically been set by the user,
-         * change them to the corresponding default ones.
-         */
-        if (useServerMode != (!flag) &&
-                sslContext.isDefaultProtocolList(enabledProtocols)) {
-            enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-        }
-
-        useServerMode = !flag;
-    }
-
-    @Override
-    public boolean getUseClientMode() {
-        return !useServerMode;
-    }
-
-
-    /**
-     * Controls whether new connections may cause creation of new SSL
-     * sessions.
-     */
-    @Override
-    public void setEnableSessionCreation(boolean flag) {
-        enableSessionCreation = flag;
-    }
-
-    /**
-     * Returns true if new connections may cause creation of new SSL
-     * sessions.
-     */
-    @Override
-    public boolean getEnableSessionCreation() {
-        return enableSessionCreation;
-    }
-
-    /**
-     * Returns the SSLParameters in effect for newly accepted connections.
-     */
-    @Override
-    synchronized public SSLParameters getSSLParameters() {
-        SSLParameters params = super.getSSLParameters();
-
-        // the super implementation does not handle the following parameters
-        params.setEndpointIdentificationAlgorithm(identificationProtocol);
-        params.setAlgorithmConstraints(algorithmConstraints);
-        params.setSNIMatchers(sniMatchers);
-        params.setUseCipherSuitesOrder(preferLocalCipherSuites);
-        params.setApplicationProtocols(applicationProtocols);
-
-        return params;
-    }
-
-    /**
-     * Applies SSLParameters to newly accepted connections.
-     */
-    @Override
-    synchronized public void setSSLParameters(SSLParameters params) {
-        super.setSSLParameters(params);
-
-        // the super implementation does not handle the following parameters
-        identificationProtocol = params.getEndpointIdentificationAlgorithm();
-        algorithmConstraints = params.getAlgorithmConstraints();
-        preferLocalCipherSuites = params.getUseCipherSuitesOrder();
-        Collection<SNIMatcher> matchers = params.getSNIMatchers();
-        if (matchers != null) {
-            sniMatchers = params.getSNIMatchers();
-        }
-        applicationProtocols = params.getApplicationProtocols();
-    }
-
-    /**
-     * Accept a new SSL connection.  This server identifies itself with
-     * information provided in the authentication context which was
-     * presented during construction.
-     */
-    @Override
-    public Socket accept() throws IOException {
-        SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
-            enabledCipherSuites, doClientAuth, enableSessionCreation,
-            enabledProtocols, identificationProtocol, algorithmConstraints,
-            sniMatchers, preferLocalCipherSuites, applicationProtocols);
-
-        implAccept(s);
-        s.doneConnect();
-        return s;
-    }
-
-    /**
-     * Provides a brief description of this SSL socket.
-     */
-    @Override
-    public String toString() {
-        return "[SSL: "+ super.toString() + "]";
-    }
-}
--- a/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.Enumeration;
-import java.util.Vector;
-import java.util.Locale;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-
-import sun.security.action.GetIntegerAction;
-import sun.security.util.Cache;
-
-
-final class SSLSessionContextImpl implements SSLSessionContext {
-    private final static int DEFAULT_MAX_CACHE_SIZE = 20480;
-
-    private Cache<SessionId, SSLSessionImpl> sessionCache;
-                                        // session cache, session id as key
-    private Cache<String, SSLSessionImpl> sessionHostPortCache;
-                                        // session cache, "host:port" as key
-    private int cacheLimit;             // the max cache size
-    private int timeout;                // timeout in seconds
-
-    // package private
-    SSLSessionContextImpl() {
-        cacheLimit = getDefaultCacheLimit();    // default cache size
-        timeout = 86400;                        // default, 24 hours
-
-        // use soft reference
-        sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
-        sessionHostPortCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
-    }
-
-    /**
-     * Returns the <code>SSLSession</code> bound to the specified session id.
-     */
-    @Override
-    public SSLSession getSession(byte[] sessionId) {
-        if (sessionId == null) {
-            throw new NullPointerException("session id cannot be null");
-        }
-
-        SSLSessionImpl sess = sessionCache.get(new SessionId(sessionId));
-        if (!isTimedout(sess)) {
-            return sess;
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns an enumeration of the active SSL sessions.
-     */
-    @Override
-    public Enumeration<byte[]> getIds() {
-        SessionCacheVisitor scVisitor = new SessionCacheVisitor();
-        sessionCache.accept(scVisitor);
-
-        return scVisitor.getSessionIds();
-    }
-
-    /**
-     * Sets the timeout limit for cached <code>SSLSession</code> objects
-     *
-     * Note that after reset the timeout, the cached session before
-     * should be timed within the shorter one of the old timeout and the
-     * new timeout.
-     */
-    @Override
-    public void setSessionTimeout(int seconds)
-                 throws IllegalArgumentException {
-        if (seconds < 0) {
-            throw new IllegalArgumentException();
-        }
-
-        if (timeout != seconds) {
-            sessionCache.setTimeout(seconds);
-            sessionHostPortCache.setTimeout(seconds);
-            timeout = seconds;
-        }
-    }
-
-    /**
-     * Gets the timeout limit for cached <code>SSLSession</code> objects
-     */
-    @Override
-    public int getSessionTimeout() {
-        return timeout;
-    }
-
-    /**
-     * Sets the size of the cache used for storing
-     * <code>SSLSession</code> objects.
-     */
-    @Override
-    public void setSessionCacheSize(int size)
-                 throws IllegalArgumentException {
-        if (size < 0)
-            throw new IllegalArgumentException();
-
-        if (cacheLimit != size) {
-            sessionCache.setCapacity(size);
-            sessionHostPortCache.setCapacity(size);
-            cacheLimit = size;
-        }
-    }
-
-    /**
-     * Gets the size of the cache used for storing
-     * <code>SSLSession</code> objects.
-     */
-    @Override
-    public int getSessionCacheSize() {
-        return cacheLimit;
-    }
-
-
-    // package-private method, used ONLY by ServerHandshaker
-    SSLSessionImpl get(byte[] id) {
-        return (SSLSessionImpl)getSession(id);
-    }
-
-    // package-private method, used ONLY by ClientHandshaker
-    SSLSessionImpl get(String hostname, int port) {
-        /*
-         * If no session caching info is available, we won't
-         * get one, so exit before doing a lookup.
-         */
-        if (hostname == null && port == -1) {
-            return null;
-        }
-
-        SSLSessionImpl sess = sessionHostPortCache.get(getKey(hostname, port));
-        if (!isTimedout(sess)) {
-            return sess;
-        }
-
-        return null;
-    }
-
-    private String getKey(String hostname, int port) {
-        return (hostname + ":" +
-            String.valueOf(port)).toLowerCase(Locale.ENGLISH);
-    }
-
-    // cache a SSLSession
-    //
-    // In SunJSSE implementation, a session is created while getting a
-    // client hello or a server hello message, and cached while the
-    // handshaking finished.
-    // Here we time the session from the time it cached instead of the
-    // time it created, which is a little longer than the expected. So
-    // please do check isTimedout() while getting entry from the cache.
-    void put(SSLSessionImpl s) {
-        sessionCache.put(s.getSessionId(), s);
-
-        // If no hostname/port info is available, don't add this one.
-        if ((s.getPeerHost() != null) && (s.getPeerPort() != -1)) {
-            sessionHostPortCache.put(
-                getKey(s.getPeerHost(), s.getPeerPort()), s);
-        }
-
-        s.setContext(this);
-    }
-
-    // package-private method, remove a cached SSLSession
-    void remove(SessionId key) {
-        SSLSessionImpl s = sessionCache.get(key);
-        if (s != null) {
-            sessionCache.remove(key);
-            sessionHostPortCache.remove(
-                        getKey(s.getPeerHost(), s.getPeerPort()));
-        }
-    }
-
-    private int getDefaultCacheLimit() {
-        try {
-            int defaultCacheLimit =
-                java.security.AccessController.doPrivileged(
-                    new GetIntegerAction("javax.net.ssl.sessionCacheSize",
-                                         DEFAULT_MAX_CACHE_SIZE)).intValue();
-
-            if (defaultCacheLimit >= 0) {
-                return defaultCacheLimit;
-            }
-        } catch (Exception e) {
-        }
-
-        return DEFAULT_MAX_CACHE_SIZE;
-    }
-
-    boolean isTimedout(SSLSession sess) {
-        if (timeout == 0) {
-            return false;
-        }
-
-        if ((sess != null) && ((sess.getCreationTime() + timeout * 1000L)
-                                        <= (System.currentTimeMillis()))) {
-            sess.invalidate();
-            return true;
-        }
-
-        return false;
-    }
-
-    final class SessionCacheVisitor
-            implements Cache.CacheVisitor<SessionId, SSLSessionImpl> {
-        Vector<byte[]> ids = null;
-
-        // public void visit(java.util.Map<K,V> map) {}
-        @Override
-        public void visit(java.util.Map<SessionId, SSLSessionImpl> map) {
-            ids = new Vector<>(map.size());
-
-            for (SessionId key : map.keySet()) {
-                SSLSessionImpl value = map.get(key);
-                if (!isTimedout(value)) {
-                    ids.addElement(key.getId());
-                }
-            }
-        }
-
-        public Enumeration<byte[]> getSessionIds() {
-            return  ids != null ? ids.elements() :
-                                  new Vector<byte[]>().elements();
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/SSLSessionImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,907 +0,0 @@
-/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.net.*;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.ArrayList;
-
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateEncodingException;
-
-import javax.crypto.SecretKey;
-
-import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.SSLSessionBindingListener;
-import javax.net.ssl.SSLSessionBindingEvent;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLPermission;
-import javax.net.ssl.ExtendedSSLSession;
-import javax.net.ssl.SNIServerName;
-
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * Implements the SSL session interface, and exposes the session context
- * which is maintained by SSL servers.
- *
- * <P> Servers have the ability to manage the sessions associated with
- * their authentication context(s).  They can do this by enumerating the
- * IDs of the sessions which are cached, examining those sessions, and then
- * perhaps invalidating a given session so that it can't be used again.
- * If servers do not explicitly manage the cache, sessions will linger
- * until memory is low enough that the runtime environment purges cache
- * entries automatically to reclaim space.
- *
- * <P><em> The only reason this class is not package-private is that
- * there's no other public way to get at the server session context which
- * is associated with any given authentication context. </em>
- *
- * @author David Brownell
- */
-final class SSLSessionImpl extends ExtendedSSLSession {
-
-    // compression methods
-    private static final byte           compression_null = 0;
-
-    /*
-     * The state of a single session, as described in section 7.1
-     * of the SSLv3 spec.
-     */
-    private final ProtocolVersion       protocolVersion;
-    private final SessionId             sessionId;
-    private X509Certificate[]   peerCerts;
-    private byte                compressionMethod;
-    private CipherSuite         cipherSuite;
-    private SecretKey           masterSecret;
-    private final boolean       useExtendedMasterSecret;
-
-    /*
-     * Information not part of the SSLv3 protocol spec, but used
-     * to support session management policies.
-     */
-    private final long          creationTime = System.currentTimeMillis();
-    private long                lastUsedTime = 0;
-    private final String        host;
-    private final int           port;
-    private SSLSessionContextImpl       context;
-    private int                 sessionCount;
-    private boolean             invalidated;
-    private X509Certificate[]   localCerts;
-    private PrivateKey          localPrivateKey;
-    private String[]            localSupportedSignAlgs;
-    private String[]            peerSupportedSignAlgs;
-    private List<SNIServerName>    requestedServerNames;
-
-
-    // Principals for non-certificate based cipher suites
-    private Principal peerPrincipal;
-    private Principal localPrincipal;
-
-    // The endpoint identification algorithm used to check certificates
-    // in this session.
-    private final String              endpointIdentificationAlgorithm;
-
-    /*
-     * Is the session currently re-established with a session-resumption
-     * abbreviated initial handshake?
-     *
-     * Note that currently we only set this variable in client side.
-     */
-    private boolean isSessionResumption = false;
-
-    /*
-     * We count session creations, eventually for statistical data but
-     * also since counters make shorter debugging IDs than the big ones
-     * we use in the protocol for uniqueness-over-time.
-     */
-    private static volatile int counter = 0;
-
-    /*
-     * Use of session caches is globally enabled/disabled.
-     */
-    private static boolean      defaultRejoinable = true;
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    /*
-     * Create a new non-rejoinable session, using the default (null)
-     * cipher spec.  This constructor returns a session which could
-     * be used either by a client or by a server, as a connection is
-     * first opened and before handshaking begins.
-     */
-    SSLSessionImpl() {
-        this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
-            new SessionId(false, null), null, -1, false, null);
-    }
-
-    /*
-     * Create a new session, using a given cipher spec.  This will
-     * be rejoinable if session caching is enabled; the constructor
-     * is intended mostly for use by serves.
-     */
-    SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
-            Collection<SignatureAndHashAlgorithm> algorithms,
-            SecureRandom generator, String host, int port,
-            boolean useExtendedMasterSecret, String endpointIdAlgorithm) {
-        this(protocolVersion, cipherSuite, algorithms,
-             new SessionId(defaultRejoinable, generator), host, port,
-             useExtendedMasterSecret, endpointIdAlgorithm);
-    }
-
-    /*
-     * Record a new session, using a given cipher spec and session ID.
-     */
-    SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
-            Collection<SignatureAndHashAlgorithm> algorithms,
-            SessionId id, String host, int port,
-            boolean useExtendedMasterSecret,
-            String endpointIdAlgorithm){
-        this.protocolVersion = protocolVersion;
-        sessionId = id;
-        peerCerts = null;
-        compressionMethod = compression_null;
-        this.cipherSuite = cipherSuite;
-        masterSecret = null;
-        this.host = host;
-        this.port = port;
-        sessionCount = ++counter;
-        localSupportedSignAlgs =
-            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
-        this.useExtendedMasterSecret = useExtendedMasterSecret;
-        this.endpointIdentificationAlgorithm = endpointIdAlgorithm;
-
-        if (debug != null && Debug.isOn("session")) {
-            System.out.println("%% Initialized:  " + this);
-        }
-    }
-
-    void setMasterSecret(SecretKey secret) {
-        if (masterSecret == null) {
-            masterSecret = secret;
-        } else {
-            throw new RuntimeException("setMasterSecret() error");
-        }
-    }
-
-    /**
-     * Returns the master secret ... treat with extreme caution!
-     */
-    SecretKey getMasterSecret() {
-        return masterSecret;
-    }
-
-    boolean getUseExtendedMasterSecret() {
-        return useExtendedMasterSecret;
-    }
-
-    void setPeerCertificates(X509Certificate[] peer) {
-        if (peerCerts == null) {
-            peerCerts = peer;
-        }
-    }
-
-    void setLocalCertificates(X509Certificate[] local) {
-        localCerts = local;
-    }
-
-    void setLocalPrivateKey(PrivateKey privateKey) {
-        localPrivateKey = privateKey;
-    }
-
-    void setPeerSupportedSignatureAlgorithms(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        peerSupportedSignAlgs =
-            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
-    }
-
-    void setRequestedServerNames(List<SNIServerName> requestedServerNames) {
-        this.requestedServerNames = new ArrayList<>(requestedServerNames);
-    }
-
-    /**
-     * Set the peer principal.
-     */
-    void setPeerPrincipal(Principal principal) {
-        if (peerPrincipal == null) {
-            peerPrincipal = principal;
-        }
-    }
-
-    /**
-     * Set the local principal.
-     */
-    void setLocalPrincipal(Principal principal) {
-        localPrincipal = principal;
-    }
-
-    String getEndpointIdentificationAlgorithm() {
-        return this.endpointIdentificationAlgorithm;
-    }
-
-    /**
-     * Returns true iff this session may be resumed ... sessions are
-     * usually resumable.  Security policies may suggest otherwise,
-     * for example sessions that haven't been used for a while (say,
-     * a working day) won't be resumable, and sessions might have a
-     * maximum lifetime in any case.
-     */
-    boolean isRejoinable() {
-        return sessionId != null && sessionId.length() != 0 &&
-            !invalidated && isLocalAuthenticationValid();
-    }
-
-    @Override
-    public synchronized boolean isValid() {
-        return isRejoinable();
-    }
-
-    /**
-     * Check if the authentication used when establishing this session
-     * is still valid. Returns true if no authentication was used
-     */
-    boolean isLocalAuthenticationValid() {
-        if (localPrivateKey != null) {
-            try {
-                // if the private key is no longer valid, getAlgorithm()
-                // should throw an exception
-                // (e.g. Smartcard has been removed from the reader)
-                localPrivateKey.getAlgorithm();
-            } catch (Exception e) {
-                invalidate();
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns the ID for this session.  The ID is fixed for the
-     * duration of the session; neither it, nor its value, changes.
-     */
-    @Override
-    public byte[] getId() {
-        return sessionId.getId();
-    }
-
-    /**
-     * For server sessions, this returns the set of sessions which
-     * are currently valid in this process.  For client sessions,
-     * this returns null.
-     */
-    @Override
-    public SSLSessionContext getSessionContext() {
-        /*
-         * An interim security policy until we can do something
-         * more specific in 1.2. Only allow trusted code (code which
-         * can set system properties) to get an
-         * SSLSessionContext. This is to limit the ability of code to
-         * look up specific sessions or enumerate over them. Otherwise,
-         * code can only get session objects from successful SSL
-         * connections which implies that they must have had permission
-         * to make the network connection in the first place.
-         */
-        SecurityManager sm;
-        if ((sm = System.getSecurityManager()) != null) {
-            sm.checkPermission(new SSLPermission("getSSLSessionContext"));
-        }
-
-        return context;
-    }
-
-
-    SessionId getSessionId() {
-        return sessionId;
-    }
-
-
-    /**
-     * Returns the cipher spec in use on this session
-     */
-    CipherSuite getSuite() {
-        return cipherSuite;
-    }
-
-    /**
-     * Resets the cipher spec in use on this session
-     */
-    void setSuite(CipherSuite suite) {
-       cipherSuite = suite;
-
-       if (debug != null && Debug.isOn("session")) {
-           System.out.println("%% Negotiating:  " + this);
-       }
-    }
-
-    /**
-     * Return true if the session is currently re-established with a
-     * session-resumption abbreviated initial handshake.
-     */
-    boolean isSessionResumption() {
-        return isSessionResumption;
-    }
-
-    /**
-     * Resets whether the session is re-established with a session-resumption
-     * abbreviated initial handshake.
-     */
-    void setAsSessionResumption(boolean flag) {
-        isSessionResumption = flag;
-    }
-
-    /**
-     * Returns the name of the cipher suite in use on this session
-     */
-    @Override
-    public String getCipherSuite() {
-        return getSuite().name;
-    }
-
-    ProtocolVersion getProtocolVersion() {
-        return protocolVersion;
-    }
-
-    /**
-     * Returns the standard name of the protocol in use on this session
-     */
-    @Override
-    public String getProtocol() {
-        return getProtocolVersion().name;
-    }
-
-    /**
-     * Returns the compression technique used in this session
-     */
-    byte getCompression() {
-        return compressionMethod;
-    }
-
-    /**
-     * Returns the hashcode for this session
-     */
-    @Override
-    public int hashCode() {
-        return sessionId.hashCode();
-    }
-
-
-    /**
-     * Returns true if sessions have same ids, false otherwise.
-     */
-    @Override
-    public boolean equals(Object obj) {
-
-        if (obj == this) {
-            return true;
-        }
-
-        if (obj instanceof SSLSessionImpl) {
-            SSLSessionImpl sess = (SSLSessionImpl) obj;
-            return (sessionId != null) && (sessionId.equals(
-                        sess.getSessionId()));
-        }
-
-        return false;
-    }
-
-
-    /**
-     * Return the cert chain presented by the peer in the
-     * java.security.cert format.
-     * Note: This method can be used only when using certificate-based
-     * cipher suites; using it with non-certificate-based cipher suites,
-     * such as Kerberos, will throw an SSLPeerUnverifiedException.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    @Override
-    public java.security.cert.Certificate[] getPeerCertificates()
-            throws SSLPeerUnverifiedException {
-        //
-        // clone to preserve integrity of session ... caller can't
-        // change record of peer identity even by accident, much
-        // less do it intentionally.
-        //
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            throw new SSLPeerUnverifiedException("no certificates expected"
-                        + " for Kerberos cipher suites");
-        }
-        if (peerCerts == null) {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-        // Certs are immutable objects, therefore we don't clone them.
-        // But do need to clone the array, so that nothing is inserted
-        // into peerCerts.
-        return (java.security.cert.Certificate[])peerCerts.clone();
-    }
-
-    /**
-     * Return the cert chain presented to the peer in the
-     * java.security.cert format.
-     * Note: This method is useful only when using certificate-based
-     * cipher suites.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    @Override
-    public java.security.cert.Certificate[] getLocalCertificates() {
-        //
-        // clone to preserve integrity of session ... caller can't
-        // change record of peer identity even by accident, much
-        // less do it intentionally.
-        return (localCerts == null ? null :
-            (java.security.cert.Certificate[])localCerts.clone());
-    }
-
-    /**
-     * Return the cert chain presented by the peer in the
-     * javax.security.cert format.
-     * Note: This method can be used only when using certificate-based
-     * cipher suites; using it with non-certificate-based cipher suites,
-     * such as Kerberos, will throw an SSLPeerUnverifiedException.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    @Override
-    public javax.security.cert.X509Certificate[] getPeerCertificateChain()
-            throws SSLPeerUnverifiedException {
-        //
-        // clone to preserve integrity of session ... caller can't
-        // change record of peer identity even by accident, much
-        // less do it intentionally.
-        //
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            throw new SSLPeerUnverifiedException("no certificates expected"
-                        + " for Kerberos cipher suites");
-        }
-        if (peerCerts == null) {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-        javax.security.cert.X509Certificate[] certs;
-        certs = new javax.security.cert.X509Certificate[peerCerts.length];
-        for (int i = 0; i < peerCerts.length; i++) {
-            byte[] der = null;
-            try {
-                der = peerCerts[i].getEncoded();
-                certs[i] = javax.security.cert.X509Certificate.getInstance(der);
-            } catch (CertificateEncodingException e) {
-                throw new SSLPeerUnverifiedException(e.getMessage());
-            } catch (javax.security.cert.CertificateException e) {
-                throw new SSLPeerUnverifiedException(e.getMessage());
-            }
-        }
-
-        return certs;
-    }
-
-    /**
-     * Return the cert chain presented by the peer.
-     * Note: This method can be used only when using certificate-based
-     * cipher suites; using it with non-certificate-based cipher suites,
-     * such as Kerberos, will throw an SSLPeerUnverifiedException.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    public X509Certificate[] getCertificateChain()
-            throws SSLPeerUnverifiedException {
-        /*
-         * clone to preserve integrity of session ... caller can't
-         * change record of peer identity even by accident, much
-         * less do it intentionally.
-         */
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            throw new SSLPeerUnverifiedException("no certificates expected"
-                        + " for Kerberos cipher suites");
-        }
-        if (peerCerts != null) {
-            return peerCerts.clone();
-        } else {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-    }
-
-    /**
-     * Returns the identity of the peer which was established as part of
-     * defining the session.
-     *
-     * @return the peer's principal. Returns an X500Principal of the
-     * end-entity certificate for X509-based cipher suites, and
-     * Principal for Kerberos cipher suites.
-     *
-     * @throws SSLPeerUnverifiedException if the peer's identity has not
-     *          been verified
-     */
-    @Override
-    public Principal getPeerPrincipal()
-                throws SSLPeerUnverifiedException
-    {
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            if (peerPrincipal == null) {
-                throw new SSLPeerUnverifiedException("peer not authenticated");
-            } else {
-                // Eliminate dependency on KerberosPrincipal
-                return peerPrincipal;
-            }
-        }
-        if (peerCerts == null) {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-        return peerCerts[0].getSubjectX500Principal();
-    }
-
-    /**
-     * Returns the principal that was sent to the peer during handshaking.
-     *
-     * @return the principal sent to the peer. Returns an X500Principal
-     * of the end-entity certificate for X509-based cipher suites, and
-     * Principal for Kerberos cipher suites. If no principal was
-     * sent, then null is returned.
-     */
-    @Override
-    public Principal getLocalPrincipal() {
-
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-                // Eliminate dependency on KerberosPrincipal
-                return (localPrincipal == null ? null : localPrincipal);
-        }
-        return (localCerts == null ? null :
-                localCerts[0].getSubjectX500Principal());
-    }
-
-    /**
-     * Returns the time this session was created.
-     */
-    @Override
-    public long getCreationTime() {
-        return creationTime;
-    }
-
-    /**
-     * Returns the last time this session was used to initialize
-     * a connection.
-     */
-    @Override
-    public long getLastAccessedTime() {
-        return (lastUsedTime != 0) ? lastUsedTime : creationTime;
-    }
-
-    void setLastAccessedTime(long time) {
-        lastUsedTime = time;
-    }
-
-
-    /**
-     * Returns the network address of the session's peer.  This
-     * implementation does not insist that connections between
-     * different ports on the same host must necessarily belong
-     * to different sessions, though that is of course allowed.
-     */
-    public InetAddress getPeerAddress() {
-        try {
-            return InetAddress.getByName(host);
-        } catch (java.net.UnknownHostException e) {
-            return null;
-        }
-    }
-
-    @Override
-    public String getPeerHost() {
-        return host;
-    }
-
-    /**
-     * Need to provide the port info for caching sessions based on
-     * host and port. Accessed by SSLSessionContextImpl
-     */
-    @Override
-    public int getPeerPort() {
-        return port;
-    }
-
-    void setContext(SSLSessionContextImpl ctx) {
-        if (context == null) {
-            context = ctx;
-        }
-    }
-
-    /**
-     * Invalidate a session.  Active connections may still exist, but
-     * no connections will be able to rejoin this session.
-     */
-    @Override
-    synchronized public void invalidate() {
-        invalidated = true;
-        if (debug != null && Debug.isOn("session")) {
-            System.out.println("%% Invalidated:  " + this);
-        }
-        if (context != null) {
-            context.remove(sessionId);
-            context = null;
-        }
-    }
-
-    /*
-     * Table of application-specific session data indexed by an application
-     * key and the calling security context. This is important since
-     * sessions can be shared across different protection domains.
-     */
-    private Hashtable<SecureKey, Object> table = new Hashtable<>();
-
-    /**
-     * Assigns a session value.  Session change events are given if
-     * appropriate, to any original value as well as the new value.
-     */
-    @Override
-    public void putValue(String key, Object value) {
-        if ((key == null) || (value == null)) {
-            throw new IllegalArgumentException("arguments can not be null");
-        }
-
-        SecureKey secureKey = new SecureKey(key);
-        Object oldValue = table.put(secureKey, value);
-
-        if (oldValue instanceof SSLSessionBindingListener) {
-            SSLSessionBindingEvent e;
-
-            e = new SSLSessionBindingEvent(this, key);
-            ((SSLSessionBindingListener)oldValue).valueUnbound(e);
-        }
-        if (value instanceof SSLSessionBindingListener) {
-            SSLSessionBindingEvent e;
-
-            e = new SSLSessionBindingEvent(this, key);
-            ((SSLSessionBindingListener)value).valueBound(e);
-        }
-    }
-
-
-    /**
-     * Returns the specified session value.
-     */
-    @Override
-    public Object getValue(String key) {
-        if (key == null) {
-            throw new IllegalArgumentException("argument can not be null");
-        }
-
-        SecureKey secureKey = new SecureKey(key);
-        return table.get(secureKey);
-    }
-
-
-    /**
-     * Removes the specified session value, delivering a session changed
-     * event as appropriate.
-     */
-    @Override
-    public void removeValue(String key) {
-        if (key == null) {
-            throw new IllegalArgumentException("argument can not be null");
-        }
-
-        SecureKey secureKey = new SecureKey(key);
-        Object value = table.remove(secureKey);
-
-        if (value instanceof SSLSessionBindingListener) {
-            SSLSessionBindingEvent e;
-
-            e = new SSLSessionBindingEvent(this, key);
-            ((SSLSessionBindingListener)value).valueUnbound(e);
-        }
-    }
-
-
-    /**
-     * Lists the names of the session values.
-     */
-    @Override
-    public String[] getValueNames() {
-        Enumeration<SecureKey> e;
-        Vector<Object> v = new Vector<>();
-        SecureKey key;
-        Object securityCtx = SecureKey.getCurrentSecurityContext();
-
-        for (e = table.keys(); e.hasMoreElements(); ) {
-            key = e.nextElement();
-
-            if (securityCtx.equals(key.getSecurityContext())) {
-                v.addElement(key.getAppKey());
-            }
-        }
-        String[] names = new String[v.size()];
-        v.copyInto(names);
-
-        return names;
-    }
-
-    /**
-     * Use large packet sizes now or follow RFC 2246 packet sizes (2^14)
-     * until changed.
-     *
-     * In the TLS specification (section 6.2.1, RFC2246), it is not
-     * recommended that the plaintext has more than 2^14 bytes.
-     * However, some TLS implementations violate the specification.
-     * This is a workaround for interoperability with these stacks.
-     *
-     * Application could accept large fragments up to 2^15 bytes by
-     * setting the system property jsse.SSLEngine.acceptLargeFragments
-     * to "true".
-     */
-    private boolean acceptLargeFragments =
-        Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false);
-
-    /**
-     * Expand the buffer size of both SSL/TLS network packet and
-     * application data.
-     */
-    protected synchronized void expandBufferSizes() {
-        acceptLargeFragments = true;
-    }
-
-    /**
-     * Gets the current size of the largest SSL/TLS packet that is expected
-     * when using this session.
-     */
-    @Override
-    public synchronized int getPacketBufferSize() {
-        return acceptLargeFragments ?
-                Record.maxLargeRecordSize : Record.maxRecordSize;
-    }
-
-    /**
-     * Gets the current size of the largest application data that is
-     * expected when using this session.
-     */
-    @Override
-    public synchronized int getApplicationBufferSize() {
-        return getPacketBufferSize() - Record.headerSize;
-    }
-
-    /**
-     * Gets an array of supported signature algorithms that the local side is
-     * willing to verify.
-     */
-    @Override
-    public String[] getLocalSupportedSignatureAlgorithms() {
-        if (localSupportedSignAlgs != null) {
-            return localSupportedSignAlgs.clone();
-        }
-
-        return new String[0];
-    }
-
-    /**
-     * Gets an array of supported signature algorithms that the peer is
-     * able to verify.
-     */
-    @Override
-    public String[] getPeerSupportedSignatureAlgorithms() {
-        if (peerSupportedSignAlgs != null) {
-            return peerSupportedSignAlgs.clone();
-        }
-
-        return new String[0];
-    }
-
-    /**
-     * Obtains a <code>List</code> containing all {@link SNIServerName}s
-     * of the requested Server Name Indication (SNI) extension.
-     */
-    @Override
-    public List<SNIServerName> getRequestedServerNames() {
-        if (requestedServerNames != null && !requestedServerNames.isEmpty()) {
-            return Collections.<SNIServerName>unmodifiableList(
-                                                requestedServerNames);
-        }
-
-        return Collections.<SNIServerName>emptyList();
-    }
-
-    /** Returns a string representation of this SSL session */
-    @Override
-    public String toString() {
-        return "[Session-" + sessionCount
-            + ", " + getCipherSuite()
-            + "]";
-    }
-
-    /**
-     * When SSL sessions are finalized, all values bound to
-     * them are removed.
-     */
-    @Override
-    protected void finalize() throws Throwable {
-        String[] names = getValueNames();
-        for (int i = 0; i < names.length; i++) {
-            removeValue(names[i]);
-        }
-    }
-}
-
-
-/**
- * This "struct" class serves as a Hash Key that combines an
- * application-specific key and a security context.
- */
-class SecureKey {
-    private static Object       nullObject = new Object();
-    private Object        appKey;
-    private Object      securityCtx;
-
-    static Object getCurrentSecurityContext() {
-        SecurityManager sm = System.getSecurityManager();
-        Object context = null;
-
-        if (sm != null)
-            context = sm.getSecurityContext();
-        if (context == null)
-            context = nullObject;
-        return context;
-    }
-
-    SecureKey(Object key) {
-        this.appKey = key;
-        this.securityCtx = getCurrentSecurityContext();
-    }
-
-    Object getAppKey() {
-        return appKey;
-    }
-
-    Object getSecurityContext() {
-        return securityCtx;
-    }
-
-    @Override
-    public int hashCode() {
-        return appKey.hashCode() ^ securityCtx.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey)
-                        && ((SecureKey)o).securityCtx.equals(securityCtx);
-    }
-}
--- a/src/share/classes/sun/security/ssl/SSLSocketFactoryImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.*;
-import java.net.*;
-import javax.net.ssl.SSLSocketFactory;
-
-
-/**
- * Implementation of an SSL socket factory.  This provides the public
- * hooks to create SSL sockets, using a "high level" programming
- * interface which encapsulates system security policy defaults rather than
- * offering application flexibility.  In particular, it uses a configurable
- * authentication context (and the keys held there) rather than offering
- * any flexibility about which keys to use; that context defaults to the
- * process-default context, but may be explicitly specified.
- *
- * @author David Brownell
- */
-final public class SSLSocketFactoryImpl extends SSLSocketFactory {
-
-    private SSLContextImpl context;
-
-    /**
-     * Constructor used to instantiate the default factory. This method is
-     * only called if the old "ssl.SocketFactory.provider" property in the
-     * java.security file is set.
-     */
-    public SSLSocketFactoryImpl() throws Exception {
-        this.context = SSLContextImpl.DefaultSSLContext.getDefaultImpl();
-    }
-
-    /**
-     * Constructs an SSL socket factory.
-     */
-    SSLSocketFactoryImpl(SSLContextImpl context) {
-        this.context = context;
-    }
-
-    /**
-     * Creates an unconnected socket.
-     *
-     * @return the unconnected socket
-     * @see java.net.Socket#connect(java.net.SocketAddress, int)
-     */
-    @Override
-    public Socket createSocket() {
-        return new SSLSocketImpl(context);
-    }
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port.
-     * This acts as the SSL client, and may authenticate itself or rejoin
-     * existing SSL sessions allowed by the authentication context which
-     * has been configured.
-     *
-     * @param host name of the host with which to connect
-     * @param port number of the server's port
-     */
-    @Override
-    public Socket createSocket(String host, int port)
-    throws IOException, UnknownHostException
-    {
-        return new SSLSocketImpl(context, host, port);
-    }
-
-    /**
-     * Returns a socket layered over an existing socket to a
-     * ServerSocket on the named host, at the given port.  This
-     * constructor can be used when tunneling SSL through a proxy. The
-     * host and port refer to the logical destination server.  This
-     * socket is configured using the socket options established for
-     * this factory.
-     *
-     * @param s the existing socket
-     * @param host the server host
-     * @param port the server port
-     * @param autoClose close the underlying socket when this socket is closed
-     *
-     * @exception IOException if the connection can't be established
-     * @exception UnknownHostException if the host is not known
-     */
-    @Override
-    public Socket createSocket(Socket s, String host, int port,
-            boolean autoClose) throws IOException {
-        return new SSLSocketImpl(context, s, host, port, autoClose);
-    }
-
-    @Override
-    public Socket createSocket(Socket s, InputStream consumed,
-            boolean autoClose) throws IOException {
-        if (s == null) {
-            throw new NullPointerException(
-                    "the existing socket cannot be null");
-        }
-
-        return new SSLSocketImpl(context, s, consumed, autoClose);
-    }
-
-    /**
-     * Constructs an SSL connection to a server at a specified address
-     * and TCP port.  This acts as the SSL client, and may authenticate
-     * itself or rejoin existing SSL sessions allowed by the authentication
-     * context which has been configured.
-     *
-     * @param address the server's host
-     * @param port its port
-     */
-    @Override
-    public Socket createSocket(InetAddress address, int port)
-    throws IOException
-    {
-        return new SSLSocketImpl(context, address, port);
-    }
-
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port.
-     * This acts as the SSL client, and may authenticate itself or rejoin
-     * existing SSL sessions allowed by the authentication context which
-     * has been configured. The socket will also bind() to the local
-     * address and port supplied.
-     */
-    @Override
-    public Socket createSocket(String host, int port,
-        InetAddress clientAddress, int clientPort)
-    throws IOException
-    {
-        return new SSLSocketImpl(context, host, port,
-                clientAddress, clientPort);
-    }
-
-    /**
-     * Constructs an SSL connection to a server at a specified address
-     * and TCP port.  This acts as the SSL client, and may authenticate
-     * itself or rejoin existing SSL sessions allowed by the authentication
-     * context which has been configured. The socket will also bind() to
-     * the local address and port supplied.
-     */
-    @Override
-    public Socket createSocket(InetAddress address, int port,
-        InetAddress clientAddress, int clientPort)
-    throws IOException
-    {
-        return new SSLSocketImpl(context, address, port,
-                clientAddress, clientPort);
-    }
-
-
-    /**
-     * Returns the subset of the supported cipher suites which are
-     * enabled by default.  These cipher suites all provide a minimum
-     * quality of service whereby the server authenticates itself
-     * (preventing person-in-the-middle attacks) and where traffic
-     * is encrypted to provide confidentiality.
-     */
-    @Override
-    public String[] getDefaultCipherSuites() {
-        return context.getDefaultCipherSuiteList(false).toStringArray();
-    }
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     */
-    @Override
-    public String[] getSupportedCipherSuites() {
-        return context.getSupportedCipherSuiteList().toStringArray();
-    }
-}
--- a/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2769 +0,0 @@
-/*
- * Copyright (c) 1996, 2020, 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.*;
-import java.net.*;
-import java.security.GeneralSecurityException;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.PrivilegedAction;
-import java.security.AlgorithmConstraints;
-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.*;
-
-import sun.misc.JavaNetAccess;
-import sun.misc.SharedSecrets;
-
-/**
- * Implementation of an SSL socket.  This is a normal connection type
- * socket, implementing SSL over some lower level socket, such as TCP.
- * Because it is layered over some lower level socket, it MUST override
- * all default socket methods.
- *
- * <P> This API offers a non-traditional option for establishing SSL
- * connections.  You may first establish the connection directly, then pass
- * that connection to the SSL socket constructor with a flag saying which
- * role should be taken in the handshake protocol.  (The two ends of the
- * connection must not choose the same role!)  This allows setup of SSL
- * proxying or tunneling, and also allows the kind of "role reversal"
- * that is required for most FTP data transfers.
- *
- * @see javax.net.ssl.SSLSocket
- * @see SSLServerSocket
- *
- * @author David Brownell
- */
-final public class SSLSocketImpl extends BaseSSLSocketImpl {
-
-    /*
-     * ERROR HANDLING GUIDELINES
-     * (which exceptions to throw and catch and which not to throw and catch)
-     *
-     * . if there is an IOException (SocketException) when accessing the
-     *   underlying Socket, pass it through
-     *
-     * . do not throw IOExceptions, throw SSLExceptions (or a subclass)
-     *
-     * . for internal errors (things that indicate a bug in JSSE or a
-     *   grossly misconfigured J2RE), throw either an SSLException or
-     *   a RuntimeException at your convenience.
-     *
-     * . handshaking code (Handshaker or HandshakeMessage) should generally
-     *   pass through exceptions, but can handle them if they know what to
-     *   do.
-     *
-     * . exception chaining should be used for all new code. If you happen
-     *   to touch old code that does not use chaining, you should change it.
-     *
-     * . there is a top level exception handler that sits at all entry
-     *   points from application code to SSLSocket read/write code. It
-     *   makes sure that all errors are handled (see handleException()).
-     *
-     * . JSSE internal code should generally not call close(), call
-     *   closeInternal().
-     */
-
-    /*
-     * There's a state machine associated with each connection, which
-     * among other roles serves to negotiate session changes.
-     *
-     * - START with constructor, until the TCP connection's around.
-     * - HANDSHAKE picks session parameters before allowing traffic.
-     *          There are many substates due to sequencing requirements
-     *          for handshake messages.
-     * - DATA may be transmitted.
-     * - RENEGOTIATE state allows concurrent data and handshaking
-     *          traffic ("same" substates as HANDSHAKE), and terminates
-     *          in selection of new session (and connection) parameters
-     * - ERROR state immediately precedes abortive disconnect.
-     * - SENT_CLOSE sent a close_notify to the peer. For layered,
-     *          non-autoclose socket, must now read close_notify
-     *          from peer before closing the connection. For nonlayered or
-     *          non-autoclose socket, close connection and go onto
-     *          cs_CLOSED state.
-     * - CLOSED after sending close_notify alert, & socket is closed.
-     *          SSL connection objects are not reused.
-     * - APP_CLOSED once the application calls close(). Then it behaves like
-     *          a closed socket, e.g.. getInputStream() throws an Exception.
-     *
-     * State affects what SSL record types may legally be sent:
-     *
-     * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
-     * - App Data ... only in DATA and RENEGOTIATE states
-     * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
-     *
-     * Re what may be received:  same as what may be sent, except that
-     * HandshakeRequest handshaking messages can come from servers even
-     * in the application data state, to request entry to RENEGOTIATE.
-     *
-     * The state machine within HANDSHAKE and RENEGOTIATE states controls
-     * the pending session, not the connection state, until the change
-     * cipher spec and "Finished" handshake messages are processed and
-     * make the "new" session become the current one.
-     *
-     * NOTE: details of the SMs always need to be nailed down better.
-     * The text above illustrates the core ideas.
-     *
-     *                +---->-------+------>--------->-------+
-     *                |            |                        |
-     *     <-----<    ^            ^  <-----<               v
-     *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE  SENT_CLOSE
-     *                v            v               v        |   |
-     *                |            |               |        |   v
-     *                +------------+---------------+        v ERROR
-     *                |                                     |   |
-     *                v                                     |   |
-     *               ERROR>------>----->CLOSED<--------<----+-- +
-     *                                     |
-     *                                     v
-     *                                 APP_CLOSED
-     *
-     * ALSO, note that the the purpose of handshaking (renegotiation is
-     * included) is to assign a different, and perhaps new, session to
-     * the connection.  The SSLv3 spec is a bit confusing on that new
-     * protocol feature.
-     */
-    private static final int    cs_START = 0;
-    private static final int    cs_HANDSHAKE = 1;
-    private static final int    cs_DATA = 2;
-    private static final int    cs_RENEGOTIATE = 3;
-    private static final int    cs_ERROR = 4;
-    private static final int   cs_SENT_CLOSE = 5;
-    private static final int    cs_CLOSED = 6;
-    private static final int    cs_APP_CLOSED = 7;
-
-
-    /*
-     * Client authentication be off, requested, or required.
-     *
-     * Migrated to SSLEngineImpl:
-     *    clauth_none/cl_auth_requested/clauth_required
-     */
-
-    /*
-     * Drives the protocol state machine.
-     */
-    private volatile int        connectionState;
-
-    /*
-     * Flag indicating if the next record we receive MUST be a Finished
-     * message. Temporarily set during the handshake to ensure that
-     * a change cipher spec message is followed by a finished message.
-     */
-    private boolean             expectingFinished;
-
-    /*
-     * For improved diagnostics, we detail connection closure
-     * If the socket is closed (connectionState >= cs_ERROR),
-     * closeReason != null indicates if the socket was closed
-     * because of an error or because or normal shutdown.
-     */
-    private SSLException        closeReason;
-
-    /*
-     * Per-connection private state that doesn't change when the
-     * session is changed.
-     */
-    private byte                doClientAuth;
-    private boolean             roleIsServer;
-    private boolean             enableSessionCreation = true;
-    private String              host;
-    private boolean             autoClose = true;
-    private AccessControlContext acc;
-
-    // The cipher suites enabled for use on this connection.
-    private CipherSuiteList     enabledCipherSuites;
-
-    // The endpoint identification protocol
-    private String              identificationProtocol = null;
-
-    // The cryptographic algorithm constraints
-    private AlgorithmConstraints    algorithmConstraints = null;
-
-    // The server name indication and matchers
-    List<SNIServerName>         serverNames =
-                                    Collections.<SNIServerName>emptyList();
-    Collection<SNIMatcher>      sniMatchers =
-                                    Collections.<SNIMatcher>emptyList();
-    // Is the serverNames set to empty with SSLParameters.setServerNames()?
-    private boolean             noSniExtension = false;
-
-    // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()?
-    private boolean             noSniMatcher = false;
-
-    // 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.
-     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
-     *
-     * There are several locks here.
-     *
-     * The primary lock is the per-instance lock used by
-     * synchronized(this) and the synchronized methods.  It controls all
-     * access to things such as the connection state and variables which
-     * affect handshaking.  If we are inside a synchronized method, we
-     * can access the state directly, otherwise, we must use the
-     * synchronized equivalents.
-     *
-     * The handshakeLock is used to ensure that only one thread performs
-     * the *complete initial* handshake.  If someone is handshaking, any
-     * stray application or startHandshake() requests who find the
-     * connection state is cs_HANDSHAKE will stall on handshakeLock
-     * until handshaking is done.  Once the handshake is done, we either
-     * succeeded or failed, but we can never go back to the cs_HANDSHAKE
-     * or cs_START state again.
-     *
-     * Note that the read/write() calls here in SSLSocketImpl are not
-     * obviously synchronized.  In fact, it's very nonintuitive, and
-     * requires careful examination of code paths.  Grab some coffee,
-     * and be careful with any code changes.
-     *
-     * There can be only three threads active at a time in the I/O
-     * subsection of this class.
-     *    1.  startHandshake
-     *    2.  AppInputStream
-     *    3.  AppOutputStream
-     * One thread could call startHandshake().
-     * AppInputStream/AppOutputStream read() and write() calls are each
-     * synchronized on 'this' in their respective classes, so only one
-     * app. thread will be doing a SSLSocketImpl.read() or .write()'s at
-     * a time.
-     *
-     * If handshaking is required (state cs_HANDSHAKE), and
-     * getConnectionState() for some/all threads returns cs_HANDSHAKE,
-     * only one can grab the handshakeLock, and the rest will stall
-     * either on getConnectionState(), or on the handshakeLock if they
-     * happen to successfully race through the getConnectionState().
-     *
-     * If a writer is doing the initial handshaking, it must create a
-     * temporary reader to read the responses from the other side.  As a
-     * side-effect, the writer's reader will have priority over any
-     * other reader.  However, the writer's reader is not allowed to
-     * consume any application data.  When handshakeLock is finally
-     * released, we either have a cs_DATA connection, or a
-     * cs_CLOSED/cs_ERROR socket.
-     *
-     * The writeLock is held while writing on a socket connection and
-     * also to protect the MAC and cipher for their direction.  The
-     * writeLock is package private for Handshaker which holds it while
-     * writing the ChangeCipherSpec message.
-     *
-     * To avoid the problem of a thread trying to change operational
-     * modes on a socket while handshaking is going on, we synchronize
-     * on 'this'.  If handshaking has not started yet, we tell the
-     * handshaker to change its mode.  If handshaking has started,
-     * we simply store that request until the next pending session
-     * is created, at which time the new handshaker's state is set.
-     *
-     * The readLock is held during readRecord(), which is responsible
-     * for reading an InputRecord, decrypting it, and processing it.
-     * The readLock ensures that these three steps are done atomically
-     * and that once started, no other thread can block on InputRecord.read.
-     * This is necessary so that processing of close_notify alerts
-     * from the peer are handled properly.
-     */
-    final private Object        handshakeLock = new Object();
-    final ReentrantLock         writeLock = new ReentrantLock();
-    final private Object        readLock = new Object();
-
-    private InputRecord         inrec;
-
-    /*
-     * Crypto state that's reinitialized when the session changes.
-     */
-    private Authenticator       readAuthenticator, writeAuthenticator;
-    private CipherBox           readCipher, writeCipher;
-    // NOTE: compression state would be saved here
-
-    /*
-     * security parameters for secure renegotiation.
-     */
-    private boolean             secureRenegotiation;
-    private byte[]              clientVerifyData;
-    private byte[]              serverVerifyData;
-
-    /*
-     * The authentication context holds all information used to establish
-     * who this end of the connection is (certificate chains, private keys,
-     * etc) and who is trusted (e.g. as CAs or websites).
-     */
-    private SSLContextImpl      sslContext;
-
-
-    /*
-     * This connection is one of (potentially) many associated with
-     * any given session.  The output of the handshake protocol is a
-     * new session ... although all the protocol description talks
-     * about changing the cipher spec (and it does change), in fact
-     * that's incidental since it's done by changing everything that
-     * is associated with a session at the same time.  (TLS/IETF may
-     * change that to add client authentication w/o new key exchg.)
-     */
-    private Handshaker                  handshaker;
-    private SSLSessionImpl              sess;
-    private volatile SSLSessionImpl     handshakeSession;
-
-
-    /*
-     * If anyone wants to get notified about handshake completions,
-     * they'll show up on this list.
-     */
-    private HashMap<HandshakeCompletedListener, AccessControlContext>
-                                                        handshakeListeners;
-
-    /*
-     * Reuse the same internal input/output streams.
-     */
-    private InputStream         sockInput;
-    private OutputStream        sockOutput;
-
-
-    /*
-     * These input and output streams block their data in SSL records,
-     * and usually arrange integrity and privacy protection for those
-     * records.  The guts of the SSL protocol are wrapped up in these
-     * streams, and in the handshaking that establishes the details of
-     * that integrity and privacy protection.
-     */
-    private AppInputStream      input;
-    private AppOutputStream     output;
-
-    /*
-     * The protocol versions enabled for use on this connection.
-     *
-     * Note: we support a pseudo protocol called SSLv2Hello which when
-     * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
-     * or TLS (version 3.1, 3.2, etc.) version info.
-     */
-    private ProtocolList enabledProtocols;
-
-    /*
-     * The SSL version associated with this connection.
-     */
-    private ProtocolVersion     protocolVersion = ProtocolVersion.DEFAULT;
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    /*
-     * Is it the first application record to write?
-     */
-    private boolean isFirstAppOutputRecord = true;
-
-    /*
-     * If AppOutputStream needs to delay writes of small packets, we
-     * will use this to store the data until we actually do the write.
-     */
-    private ByteArrayOutputStream heldRecordBuffer = null;
-
-    /*
-     * Whether local cipher suites preference in server side should be
-     * honored during handshaking?
-     */
-    private boolean preferLocalCipherSuites = false;
-
-    /*
-     * Is the local name service trustworthy?
-     *
-     * If the local name service is not trustworthy, reverse host name
-     * resolution should not be performed for endpoint identification.
-     */
-    static final boolean trustNameService =
-            Debug.getBooleanProperty("jdk.tls.trustNameService", false);
-
-    //
-    // CONSTRUCTORS AND INITIALIZATION CODE
-    //
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port,
-     * using the authentication context provided.  This endpoint acts as
-     * the client, and may rejoin an existing SSL session if appropriate.
-     *
-     * @param context authentication context to use
-     * @param host name of the host with which to connect
-     * @param port number of the server's port
-     */
-    SSLSocketImpl(SSLContextImpl context, String host, int port)
-            throws IOException, UnknownHostException {
-        super();
-        this.host = host;
-        this.serverNames =
-            Utilities.addToSNIServerNameList(this.serverNames, this.host);
-        init(context, false);
-        SocketAddress socketAddress =
-               host != null ? new InetSocketAddress(host, port) :
-               new InetSocketAddress(InetAddress.getByName(null), port);
-        connect(socketAddress, 0);
-    }
-
-
-    /**
-     * Constructs an SSL connection to a server at a specified address.
-     * and TCP port, using the authentication context provided.  This
-     * endpoint acts as the client, and may rejoin an existing SSL session
-     * if appropriate.
-     *
-     * @param context authentication context to use
-     * @param address the server's host
-     * @param port its port
-     */
-    SSLSocketImpl(SSLContextImpl context, InetAddress host, int port)
-            throws IOException {
-        super();
-        init(context, false);
-        SocketAddress socketAddress = new InetSocketAddress(host, port);
-        connect(socketAddress, 0);
-    }
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port,
-     * using the authentication context provided.  This endpoint acts as
-     * the client, and may rejoin an existing SSL session if appropriate.
-     *
-     * @param context authentication context to use
-     * @param host name of the host with which to connect
-     * @param port number of the server's port
-     * @param localAddr the local address the socket is bound to
-     * @param localPort the local port the socket is bound to
-     */
-    SSLSocketImpl(SSLContextImpl context, String host, int port,
-            InetAddress localAddr, int localPort)
-            throws IOException, UnknownHostException {
-        super();
-        this.host = host;
-        this.serverNames =
-            Utilities.addToSNIServerNameList(this.serverNames, this.host);
-        init(context, false);
-        bind(new InetSocketAddress(localAddr, localPort));
-        SocketAddress socketAddress =
-               host != null ? new InetSocketAddress(host, port) :
-               new InetSocketAddress(InetAddress.getByName(null), port);
-        connect(socketAddress, 0);
-    }
-
-
-    /**
-     * Constructs an SSL connection to a server at a specified address.
-     * and TCP port, using the authentication context provided.  This
-     * endpoint acts as the client, and may rejoin an existing SSL session
-     * if appropriate.
-     *
-     * @param context authentication context to use
-     * @param address the server's host
-     * @param port its port
-     * @param localAddr the local address the socket is bound to
-     * @param localPort the local port the socket is bound to
-     */
-    SSLSocketImpl(SSLContextImpl context, InetAddress host, int port,
-            InetAddress localAddr, int localPort)
-            throws IOException {
-        super();
-        init(context, false);
-        bind(new InetSocketAddress(localAddr, localPort));
-        SocketAddress socketAddress = new InetSocketAddress(host, port);
-        connect(socketAddress, 0);
-    }
-
-    /*
-     * Package-private constructor used ONLY by SSLServerSocket.  The
-     * java.net package accepts the TCP connection after this call is
-     * made.  This just initializes handshake state to use "server mode",
-     * giving control over the use of SSL client authentication.
-     */
-    SSLSocketImpl(SSLContextImpl context, boolean serverMode,
-            CipherSuiteList suites, byte clientAuth,
-            boolean sessionCreation, ProtocolList protocols,
-            String identificationProtocol,
-            AlgorithmConstraints algorithmConstraints,
-            Collection<SNIMatcher> sniMatchers,
-            boolean preferLocalCipherSuites,
-            String[] applicationProtocols) throws IOException {
-
-        super();
-        doClientAuth = clientAuth;
-        enableSessionCreation = sessionCreation;
-        this.identificationProtocol = identificationProtocol;
-        this.algorithmConstraints = algorithmConstraints;
-        this.sniMatchers = sniMatchers;
-        this.preferLocalCipherSuites = preferLocalCipherSuites;
-        this.applicationProtocols = applicationProtocols;
-        init(context, serverMode);
-
-        /*
-         * Override what was picked out for us.
-         */
-        enabledCipherSuites = suites;
-        enabledProtocols = protocols;
-    }
-
-
-    /**
-     * Package-private constructor used to instantiate an unconnected
-     * socket. The java.net package will connect it, either when the
-     * connect() call is made by the application.  This instance is
-     * meant to set handshake state to use "client mode".
-     */
-    SSLSocketImpl(SSLContextImpl context) {
-        super();
-        init(context, false);
-    }
-
-
-    /**
-     * Layer SSL traffic over an existing connection, rather than creating
-     * a new connection.  The existing connection may be used only for SSL
-     * traffic (using this SSLSocket) until the SSLSocket.close() call
-     * returns. However, if a protocol error is detected, that existing
-     * connection is automatically closed.
-     *
-     * <P> This particular constructor always uses the socket in the
-     * role of an SSL client. It may be useful in cases which start
-     * using SSL after some initial data transfers, for example in some
-     * SSL tunneling applications or as part of some kinds of application
-     * protocols which negotiate use of a SSL based security.
-     *
-     * @param sock the existing connection
-     * @param context the authentication context to use
-     */
-    SSLSocketImpl(SSLContextImpl context, Socket sock, String host,
-            int port, boolean autoClose) throws IOException {
-        super(sock);
-        // We always layer over a connected socket
-        if (!sock.isConnected()) {
-            throw new SocketException("Underlying socket is not connected");
-        }
-        this.host = host;
-        this.serverNames =
-            Utilities.addToSNIServerNameList(this.serverNames, this.host);
-        init(context, false);
-        this.autoClose = autoClose;
-        doneConnect();
-    }
-
-    /**
-     * Creates a server mode {@link Socket} layered over an
-     * existing connected socket, and is able to read data which has
-     * already been consumed/removed from the {@link Socket}'s
-     * underlying {@link InputStream}.
-     */
-    SSLSocketImpl(SSLContextImpl context, Socket sock,
-            InputStream consumed, boolean autoClose) throws IOException {
-        super(sock, consumed);
-        // We always layer over a connected socket
-        if (!sock.isConnected()) {
-            throw new SocketException("Underlying socket is not connected");
-        }
-
-        // In server mode, it is not necessary to set host and serverNames.
-        // Otherwise, would require a reverse DNS lookup to get the hostname.
-
-        init(context, true);
-        this.autoClose = autoClose;
-        doneConnect();
-    }
-
-    /**
-     * Initializes the client socket.
-     */
-    private void init(SSLContextImpl context, boolean isServer) {
-        sslContext = context;
-        sess = new SSLSessionImpl();
-        handshakeSession = null;
-
-        /*
-         * role is as specified, state is START until after
-         * the low level connection's established.
-         */
-        roleIsServer = isServer;
-        connectionState = cs_START;
-
-        /*
-         * default read and write side cipher and MAC support
-         *
-         * Note:  compression support would go here too
-         */
-        readCipher = CipherBox.NULL;
-        readAuthenticator = MAC.NULL;
-        writeCipher = CipherBox.NULL;
-        writeAuthenticator = MAC.NULL;
-
-        // initial security parameters for secure renegotiation
-        secureRenegotiation = false;
-        clientVerifyData = new byte[0];
-        serverVerifyData = new byte[0];
-
-        enabledCipherSuites =
-                sslContext.getDefaultCipherSuiteList(roleIsServer);
-        enabledProtocols =
-                sslContext.getDefaultProtocolList(roleIsServer);
-
-        inrec = null;
-
-        // save the acc
-        acc = AccessController.getContext();
-
-        input = new AppInputStream(this);
-        output = new AppOutputStream(this);
-    }
-
-    /**
-     * Connects this socket to the server with a specified timeout
-     * value.
-     *
-     * This method is either called on an unconnected SSLSocketImpl by the
-     * application, or it is called in the constructor of a regular
-     * SSLSocketImpl. If we are layering on top on another socket, then
-     * this method should not be called, because we assume that the
-     * underlying socket is already connected by the time it is passed to
-     * us.
-     *
-     * @param   endpoint the <code>SocketAddress</code>
-     * @param   timeout  the timeout value to be used, 0 is no timeout
-     * @throws  IOException if an error occurs during the connection
-     * @throws  SocketTimeoutException if timeout expires before connecting
-     */
-    @Override
-    public void connect(SocketAddress endpoint, int timeout)
-            throws IOException {
-
-        if (isLayered()) {
-            throw new SocketException("Already connected");
-        }
-
-        if (!(endpoint instanceof InetSocketAddress)) {
-            throw new SocketException(
-                                  "Cannot handle non-Inet socket addresses.");
-        }
-
-        super.connect(endpoint, timeout);
-
-        if (host == null || host.length() == 0) {
-            useImplicitHost(false);
-        }
-
-        doneConnect();
-    }
-
-    /**
-     * Initialize the handshaker and socket streams.
-     *
-     * Called by connect, the layered constructor, and SSLServerSocket.
-     */
-    void doneConnect() throws IOException {
-        /*
-         * Save the input and output streams.  May be done only after
-         * java.net actually connects using the socket "self", else
-         * we get some pretty bizarre failure modes.
-         */
-        sockInput = super.getInputStream();
-        sockOutput = super.getOutputStream();
-
-        /*
-         * Move to handshaking state, with pending session initialized
-         * to defaults and the appropriate kind of handshaker set up.
-         */
-        initHandshaker();
-    }
-
-    synchronized private int getConnectionState() {
-        return connectionState;
-    }
-
-    synchronized private void setConnectionState(int state) {
-        connectionState = state;
-    }
-
-    AccessControlContext getAcc() {
-        return acc;
-    }
-
-    //
-    // READING AND WRITING RECORDS
-    //
-
-    /*
-     * AppOutputStream calls may need to buffer multiple outbound
-     * application packets.
-     *
-     * All other writeRecord() calls will not buffer, so do not hold
-     * these records.
-     */
-    void writeRecord(OutputRecord r) throws IOException {
-        writeRecord(r, false);
-    }
-
-    /*
-     * Record Output. Application data can't be sent until the first
-     * handshake establishes a session.
-     *
-     * NOTE:  we let empty records be written as a hook to force some
-     * TCP-level activity, notably handshaking, to occur.
-     */
-    void writeRecord(OutputRecord r, boolean holdRecord) throws IOException {
-        /*
-         * The loop is in case of HANDSHAKE --> ERROR transitions, etc
-         */
-    loop:
-        while (r.contentType() == Record.ct_application_data) {
-            /*
-             * Not all states support passing application data.  We
-             * synchronize access to the connection state, so that
-             * synchronous handshakes can complete cleanly.
-             */
-            switch (getConnectionState()) {
-
-            /*
-             * We've deferred the initial handshaking till just now,
-             * when presumably a thread's decided it's OK to block for
-             * longish periods of time for I/O purposes (as well as
-             * configured the cipher suites it wants to use).
-             */
-            case cs_HANDSHAKE:
-                performInitialHandshake();
-                break;
-
-            case cs_DATA:
-            case cs_RENEGOTIATE:
-                break loop;
-
-            case cs_ERROR:
-                fatal(Alerts.alert_close_notify,
-                    "error while writing to socket");
-                break; // dummy
-
-            case cs_SENT_CLOSE:
-            case cs_CLOSED:
-            case cs_APP_CLOSED:
-                // we should never get here (check in AppOutputStream)
-                // this is just a fallback
-                if (closeReason != null) {
-                    throw closeReason;
-                } else {
-                    throw new SocketException("Socket closed");
-                }
-
-            /*
-             * Else something's goofy in this state machine's use.
-             */
-            default:
-                throw new SSLProtocolException("State error, send app data");
-            }
-        }
-
-        //
-        // Don't bother to really write empty records.  We went this
-        // far to drive the handshake machinery, for correctness; not
-        // writing empty records improves performance by cutting CPU
-        // time and network resource usage.  However, some protocol
-        // implementations are fragile and don't like to see empty
-        // records, so this also increases robustness.
-        //
-        if (!r.isEmpty()) {
-
-            // If the record is a close notify alert, we need to honor
-            // socket option SO_LINGER. Note that we will try to send
-            // the close notify even if the SO_LINGER set to zero.
-            if (r.isAlert(Alerts.alert_close_notify) && getSoLinger() >= 0) {
-
-                // keep and clear the current thread interruption status.
-                boolean interrupted = Thread.interrupted();
-                try {
-                    if (writeLock.tryLock(getSoLinger(), TimeUnit.SECONDS)) {
-                        try {
-                            writeRecordInternal(r, holdRecord);
-                        } finally {
-                            writeLock.unlock();
-                        }
-                    } else {
-                        SSLException ssle = new SSLException(
-                                "SO_LINGER timeout," +
-                                " close_notify message cannot be sent.");
-
-
-                        // For layered, non-autoclose sockets, we are not
-                        // able to bring them into a usable state, so we
-                        // treat it as fatal error.
-                        if (isLayered() && !autoClose) {
-                            // Note that the alert description is
-                            // specified as -1, so no message will be send
-                            // to peer anymore.
-                            fatal((byte)(-1), ssle);
-                        } else if ((debug != null) && Debug.isOn("ssl")) {
-                            System.out.println(
-                                Thread.currentThread().getName() +
-                                ", received Exception: " + ssle);
-                        }
-
-                        // RFC2246 requires that the session becomes
-                        // unresumable if any connection is terminated
-                        // without proper close_notify messages with
-                        // level equal to warning.
-                        //
-                        // RFC4346 no longer requires that a session not be
-                        // resumed if failure to properly close a connection.
-                        //
-                        // We choose to make the session unresumable if
-                        // failed to send the close_notify message.
-                        //
-                        sess.invalidate();
-                    }
-                } catch (InterruptedException ie) {
-                    // keep interrupted status
-                    interrupted = true;
-                }
-
-                // restore the interrupted status
-                if (interrupted) {
-                    Thread.currentThread().interrupt();
-                }
-            } else {
-                writeLock.lock();
-                try {
-                    writeRecordInternal(r, holdRecord);
-                } finally {
-                    writeLock.unlock();
-                }
-            }
-        }
-    }
-
-    private void writeRecordInternal(OutputRecord r,
-            boolean holdRecord) throws IOException {
-
-        // r.compress(c);
-        r.encrypt(writeAuthenticator, writeCipher);
-
-        if (holdRecord) {
-            // If we were requested to delay the record due to possibility
-            // of Nagle's being active when finally got to writing, and
-            // it's actually not, we don't really need to delay it.
-            if (getTcpNoDelay()) {
-                holdRecord = false;
-            } else {
-                // We need to hold the record, so let's provide
-                // a per-socket place to do it.
-                if (heldRecordBuffer == null) {
-                    // Likely only need 37 bytes.
-                    heldRecordBuffer = new ByteArrayOutputStream(40);
-                }
-            }
-        }
-        r.write(sockOutput, holdRecord, heldRecordBuffer);
-
-        /*
-         * Check the sequence number state
-         *
-         * Note that in order to maintain the connection I/O
-         * properly, we check the sequence number after the last
-         * record writing process. As we request renegotiation
-         * or close the connection for wrapped sequence number
-         * when there is enough sequence number space left to
-         * handle a few more records, so the sequence number
-         * of the last record cannot be wrapped.
-         */
-        if (connectionState < cs_ERROR) {
-            checkSequenceNumber(writeAuthenticator, r.contentType());
-        }
-
-        // turn off the flag of the first application record
-        if (isFirstAppOutputRecord &&
-                r.contentType() == Record.ct_application_data) {
-            isFirstAppOutputRecord = false;
-        }
-    }
-
-    /*
-     * Need to split the payload except the following cases:
-     *
-     * 1. protocol version is TLS 1.1 or later;
-     * 2. bulk cipher does not use CBC mode, including null bulk cipher suites.
-     * 3. the payload is the first application record of a freshly
-     *    negotiated TLS session.
-     * 4. the CBC protection is disabled;
-     *
-     * More details, please refer to AppOutputStream.write(byte[], int, int).
-     */
-    boolean needToSplitPayload() {
-        writeLock.lock();
-        try {
-            return (protocolVersion.v <= ProtocolVersion.TLS10.v) &&
-                    writeCipher.isCBCMode() && !isFirstAppOutputRecord &&
-                    Record.enableCBCProtection;
-        } finally {
-            writeLock.unlock();
-        }
-    }
-
-    /*
-     * Read an application data record.  Alerts and handshake
-     * messages are handled directly.
-     */
-    void readDataRecord(InputRecord r) throws IOException {
-        if (getConnectionState() == cs_HANDSHAKE) {
-            performInitialHandshake();
-        }
-        readRecord(r, true);
-    }
-
-    /*
-     * Clear the pipeline of records from the peer, optionally returning
-     * application data.   Caller is responsible for knowing that it's
-     * possible to do this kind of clearing, if they don't want app
-     * data -- e.g. since it's the initial SSL handshake.
-     *
-     * Don't synchronize (this) during a blocking read() since it
-     * protects data which is accessed on the write side as well.
-     */
-    private void readRecord(InputRecord r, boolean needAppData)
-            throws IOException {
-        int state;
-
-        // readLock protects reading and processing of an InputRecord.
-        // It keeps the reading from sockInput and processing of the record
-        // atomic so that no two threads can be blocked on the
-        // read from the same input stream at the same time.
-        // This is required for example when a reader thread is
-        // blocked on the read and another thread is trying to
-        // close the socket. For a non-autoclose, layered socket,
-        // the thread performing the close needs to read the close_notify.
-        //
-        // Use readLock instead of 'this' for locking because
-        // 'this' also protects data accessed during writing.
-      synchronized (readLock) {
-        /*
-         * Read and handle records ... return application data
-         * ONLY if it's needed.
-         */
-
-        while (((state = getConnectionState()) != cs_CLOSED) &&
-                (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
-            /*
-             * Read a record ... maybe emitting an alert if we get a
-             * comprehensible but unsupported "hello" message during
-             * format checking (e.g. V2).
-             */
-            try {
-                r.setAppDataValid(false);
-                r.read(sockInput, sockOutput);
-            } catch (SSLProtocolException e) {
-                try {
-                    fatal(Alerts.alert_unexpected_message, e);
-                } catch (IOException x) {
-                    // discard this exception
-                }
-                throw e;
-            } catch (EOFException eof) {
-                boolean handshaking = (getConnectionState() <= cs_HANDSHAKE);
-                boolean rethrow = requireCloseNotify || handshaking;
-                if ((debug != null) && Debug.isOn("ssl")) {
-                    System.out.println(Thread.currentThread().getName() +
-                        ", received EOFException: "
-                        + (rethrow ? "error" : "ignored"));
-                }
-                if (rethrow) {
-                    SSLException e;
-                    if (handshaking) {
-                        e = new SSLHandshakeException
-                            ("Remote host closed connection during handshake");
-                    } else {
-                        e = new SSLProtocolException
-                            ("Remote host closed connection incorrectly");
-                    }
-                    e.initCause(eof);
-                    throw e;
-                } else {
-                    // treat as if we had received a close_notify
-                    closeInternal(false);
-                    continue;
-                }
-            }
-
-
-            /*
-             * The basic SSLv3 record protection involves (optional)
-             * encryption for privacy, and an integrity check ensuring
-             * data origin authentication.  We do them both here, and
-             * throw a fatal alert if the integrity check fails.
-             */
-            try {
-                r.decrypt(readAuthenticator, readCipher);
-            } catch (BadPaddingException e) {
-                byte alertType = (r.contentType() == Record.ct_handshake)
-                                        ? Alerts.alert_handshake_failure
-                                        : Alerts.alert_bad_record_mac;
-                fatal(alertType, e.getMessage(), e);
-            }
-
-            // if (!r.decompress(c))
-            //     fatal(Alerts.alert_decompression_failure,
-            //         "decompression failure");
-
-            /*
-             * Process the record.
-             */
-            synchronized (this) {
-              switch (r.contentType()) {
-                case Record.ct_handshake:
-                    /*
-                     * Handshake messages always go to a pending session
-                     * handshaker ... if there isn't one, create one.  This
-                     * must work asynchronously, for renegotiation.
-                     *
-                     * NOTE that handshaking will either resume a session
-                     * which was in the cache (and which might have other
-                     * connections in it already), or else will start a new
-                     * session (new keys exchanged) with just this connection
-                     * in it.
-                     */
-                    initHandshaker();
-                    if (!handshaker.activated()) {
-                        // prior to handshaking, activate the handshake
-                        if (connectionState == cs_RENEGOTIATE) {
-                            // don't use SSLv2Hello when renegotiating
-                            handshaker.activate(protocolVersion);
-                        } else {
-                            handshaker.activate(null);
-                        }
-                    }
-
-                    /*
-                     * process the handshake record ... may contain just
-                     * a partial handshake message or multiple messages.
-                     *
-                     * The handshaker state machine will ensure that it's
-                     * a finished message.
-                     */
-                    handshaker.process_record(r, expectingFinished);
-                    expectingFinished = false;
-
-                    if (handshaker.invalidated) {
-                        handshaker = null;
-                        inrec.setHandshakeHash(null);
-
-                        // if state is cs_RENEGOTIATE, revert it to cs_DATA
-                        if (connectionState == cs_RENEGOTIATE) {
-                            connectionState = cs_DATA;
-                        }
-                    } else if (handshaker.isDone()) {
-                        // reset the parameters for secure renegotiation.
-                        secureRenegotiation =
-                                        handshaker.isSecureRenegotiation();
-                        clientVerifyData = handshaker.getClientVerifyData();
-                        serverVerifyData = handshaker.getServerVerifyData();
-                        // set connection ALPN value
-                        applicationProtocol =
-                            handshaker.getHandshakeApplicationProtocol();
-
-                        sess = handshaker.getSession();
-                        handshakeSession = null;
-                        handshaker = null;
-                        connectionState = cs_DATA;
-
-                        //
-                        // Tell folk about handshake completion, but do
-                        // it in a separate thread.
-                        //
-                        if (handshakeListeners != null) {
-                            HandshakeCompletedEvent event =
-                                new HandshakeCompletedEvent(this, sess);
-
-                            Thread t = new NotifyHandshakeThread(
-                                handshakeListeners.entrySet(), event);
-                            t.start();
-                        }
-                    }
-
-                    if (needAppData || connectionState != cs_DATA) {
-                        continue;
-                    }
-                    break;
-
-                case Record.ct_application_data:
-                    // Pass this right back up to the application.
-                    if (connectionState != cs_DATA
-                            && connectionState != cs_RENEGOTIATE
-                            && connectionState != cs_SENT_CLOSE) {
-                        throw new SSLProtocolException(
-                            "Data received in non-data state: " +
-                            connectionState);
-                    }
-                    if (expectingFinished) {
-                        throw new SSLProtocolException
-                                ("Expecting finished message, received data");
-                    }
-                    if (!needAppData) {
-                        throw new SSLException("Discarding app data");
-                    }
-
-                    r.setAppDataValid(true);
-                    break;
-
-                case Record.ct_alert:
-                    recvAlert(r);
-                    continue;
-
-                case Record.ct_change_cipher_spec:
-                    if ((connectionState != cs_HANDSHAKE
-                                && connectionState != cs_RENEGOTIATE)) {
-                        // For the CCS message arriving in the wrong state
-                        fatal(Alerts.alert_unexpected_message,
-                                "illegal change cipher spec msg, conn state = "
-                                + connectionState);
-                    } else if (r.available() != 1 || r.read() != 1) {
-                        // For structural/content issues with the CCS
-                        fatal(Alerts.alert_unexpected_message,
-                                "Malformed change cipher spec msg");
-                    }
-
-                    //
-                    // The first message after a change_cipher_spec
-                    // record MUST be a "Finished" handshake record,
-                    // else it's a protocol violation.  We force this
-                    // to be checked by a minor tweak to the state
-                    // machine.
-                    //
-                    handshaker.receiveChangeCipherSpec();
-                    changeReadCiphers();
-                    // next message MUST be a finished message
-                    expectingFinished = true;
-                    continue;
-
-                default:
-                    //
-                    // TLS requires that unrecognized records be ignored.
-                    //
-                    if (debug != null && Debug.isOn("ssl")) {
-                        System.out.println(Thread.currentThread().getName() +
-                            ", Received record type: "
-                            + r.contentType());
-                    }
-                    continue;
-              } // switch
-
-              /*
-               * Check the sequence number state
-               *
-               * Note that in order to maintain the connection I/O
-               * properly, we check the sequence number after the last
-               * record reading process. As we request renegotiation
-               * or close the connection for wrapped sequence number
-               * when there is enough sequence number space left to
-               * handle a few more records, so the sequence number
-               * of the last record cannot be wrapped.
-               */
-              if (connectionState < cs_ERROR) {
-                  checkSequenceNumber(readAuthenticator, r.contentType());
-              }
-
-              return;
-            } // synchronized (this)
-        }
-
-        //
-        // couldn't read, due to some kind of error
-        //
-        r.close();
-        return;
-      }  // synchronized (readLock)
-    }
-
-    /**
-     * Check the sequence number state
-     *
-     * RFC 4346 states that, "Sequence numbers are of type uint64 and
-     * may not exceed 2^64-1.  Sequence numbers do not wrap. If a TLS
-     * implementation would need to wrap a sequence number, it must
-     * renegotiate instead."
-     */
-    private void checkSequenceNumber(Authenticator authenticator, byte type)
-            throws IOException {
-
-        /*
-         * Don't bother to check the sequence number for error or
-         * closed connections, or NULL MAC.
-         */
-        if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
-            return;
-        }
-
-        /*
-         * Conservatively, close the connection immediately when the
-         * sequence number is close to overflow
-         */
-        if (authenticator.seqNumOverflow()) {
-            /*
-             * TLS protocols do not define a error alert for sequence
-             * number overflow. We use handshake_failure error alert
-             * for handshaking and bad_record_mac for other records.
-             */
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", sequence number extremely close to overflow " +
-                    "(2^64-1 packets). Closing connection.");
-
-            }
-
-            fatal(Alerts.alert_handshake_failure, "sequence number overflow");
-        }
-
-        /*
-         * Ask for renegotiation when need to renew sequence number.
-         *
-         * Don't bother to kickstart the renegotiation when the local is
-         * asking for it.
-         */
-        if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                        ", request renegotiation " +
-                        "to avoid sequence number overflow");
-            }
-
-            startHandshake();
-        }
-    }
-
-    //
-    // HANDSHAKE RELATED CODE
-    //
-
-    /**
-     * Return the AppInputStream. For use by Handshaker only.
-     */
-    AppInputStream getAppInputStream() {
-        return input;
-    }
-
-    /**
-     * Return the AppOutputStream. For use by Handshaker only.
-     */
-    AppOutputStream getAppOutputStream() {
-        return output;
-    }
-
-    /**
-     * Initialize the handshaker object. This means:
-     *
-     *  . if a handshake is already in progress (state is cs_HANDSHAKE
-     *    or cs_RENEGOTIATE), do nothing and return
-     *
-     *  . if the socket is already closed, throw an Exception (internal error)
-     *
-     *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object, and advance the connection state (to cs_HANDSHAKE or
-     *    cs_RENEGOTIATE, respectively).
-     *
-     * This method is called right after a new socket is created, when
-     * starting renegotiation, or when changing client/ server mode of the
-     * socket.
-     */
-    private void initHandshaker() {
-        switch (connectionState) {
-
-        //
-        // Starting a new handshake.
-        //
-        case cs_START:
-        case cs_DATA:
-            break;
-
-        //
-        // We're already in the middle of a handshake.
-        //
-        case cs_HANDSHAKE:
-        case cs_RENEGOTIATE:
-            return;
-
-        //
-        // Anyone allowed to call this routine is required to
-        // do so ONLY if the connection state is reasonable...
-        //
-        default:
-            throw new IllegalStateException("Internal error");
-        }
-
-        // state is either cs_START or cs_DATA
-        if (connectionState == cs_START) {
-            connectionState = cs_HANDSHAKE;
-        } else { // cs_DATA
-            connectionState = cs_RENEGOTIATE;
-        }
-        if (roleIsServer) {
-            handshaker = new ServerHandshaker(this, sslContext,
-                    enabledProtocols, doClientAuth,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-            handshaker.setSNIMatchers(sniMatchers);
-            handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
-        } else {
-            handshaker = new ClientHandshaker(this, sslContext,
-                    enabledProtocols,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-            handshaker.setSNIServerNames(serverNames);
-        }
-        handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        handshaker.setEnableSessionCreation(enableSessionCreation);
-        handshaker.setApplicationProtocols(applicationProtocols);
-        handshaker.setApplicationProtocolSelectorSSLSocket(
-            applicationProtocolSelector);
-    }
-
-    /**
-     * Synchronously perform the initial handshake.
-     *
-     * If the handshake is already in progress, this method blocks until it
-     * is completed. If the initial handshake has already been completed,
-     * it returns immediately.
-     */
-    private void performInitialHandshake() throws IOException {
-        // use handshakeLock and the state check to make sure only
-        // one thread performs the handshake
-        synchronized (handshakeLock) {
-            if (getConnectionState() == cs_HANDSHAKE) {
-                kickstartHandshake();
-
-                /*
-                 * All initial handshaking goes through this operation
-                 * until we have a valid SSL connection.
-                 *
-                 * Handle handshake messages only, need no application data.
-                 */
-                if (inrec == null) {
-                    inrec = new InputRecord();
-
-                    /*
-                     * Grab the characteristics already assigned to
-                     * AppInputStream's InputRecord.  Enable checking for
-                     * SSLv2 hellos on this first handshake.
-                     */
-                    inrec.setHandshakeHash(input.r.getHandshakeHash());
-                    inrec.setHelloVersion(input.r.getHelloVersion());
-                    inrec.enableFormatChecks();
-                }
-
-                readRecord(inrec, false);
-                inrec = null;
-            }
-        }
-    }
-
-    /**
-     * Starts an SSL handshake on this connection.
-     */
-    @Override
-    public void startHandshake() throws IOException {
-        // start an ssl handshake that could be resumed from timeout exception
-        startHandshake(true);
-    }
-
-    /**
-     * Starts an ssl handshake on this connection.
-     *
-     * @param resumable indicates the handshake process is resumable from a
-     *          certain exception. If <code>resumable</code>, the socket will
-     *          be reserved for exceptions like timeout; otherwise, the socket
-     *          will be closed, no further communications could be done.
-     */
-    private void startHandshake(boolean resumable) throws IOException {
-        checkWrite();
-        try {
-            if (getConnectionState() == cs_HANDSHAKE) {
-                // do initial handshake
-                performInitialHandshake();
-            } else {
-                // start renegotiation
-                kickstartHandshake();
-            }
-        } catch (Exception e) {
-            // shutdown and rethrow (wrapped) exception as appropriate
-            handleException(e, resumable);
-        }
-    }
-
-    /**
-     * Kickstart the handshake if it is not already in progress.
-     * This means:
-     *
-     *  . if handshaking is already underway, do nothing and return
-     *
-     *  . if the socket is not connected or already closed, throw an
-     *    Exception.
-     *
-     *  . otherwise, call initHandshake() to initialize the handshaker
-     *    object and progress the state. Then, send the initial
-     *    handshaking message if appropriate (always on clients and
-     *    on servers when renegotiating).
-     */
-    private synchronized void kickstartHandshake() throws IOException {
-
-        switch (connectionState) {
-
-        case cs_HANDSHAKE:
-            // handshaker already setup, proceed
-            break;
-
-        case cs_DATA:
-            if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
-                throw new SSLHandshakeException(
-                        "Insecure renegotiation is not allowed");
-            }
-
-            if (!secureRenegotiation) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "Warning: Using insecure renegotiation");
-                }
-            }
-
-            // initialize the handshaker, move to cs_RENEGOTIATE
-            initHandshaker();
-            break;
-
-        case cs_RENEGOTIATE:
-            // handshaking already in progress, return
-            return;
-
-        /*
-         * The only way to get a socket in the state is when
-         * you have an unconnected socket.
-         */
-        case cs_START:
-            throw new SocketException(
-                "handshaking attempted on unconnected socket");
-
-        default:
-            throw new SocketException("connection is closed");
-        }
-
-        //
-        // Kickstart handshake state machine if we need to ...
-        //
-        // Note that handshaker.kickstart() writes the message
-        // to its HandshakeOutStream, which calls back into
-        // SSLSocketImpl.writeRecord() to send it.
-        //
-        if (!handshaker.activated()) {
-             // prior to handshaking, activate the handshake
-            if (connectionState == cs_RENEGOTIATE) {
-                // don't use SSLv2Hello when renegotiating
-                handshaker.activate(protocolVersion);
-            } else {
-                handshaker.activate(null);
-            }
-
-            if (handshaker instanceof ClientHandshaker) {
-                // send client hello
-                handshaker.kickstart();
-            } else {
-                if (connectionState == cs_HANDSHAKE) {
-                    // initial handshake, no kickstart message to send
-                } else {
-                    // we want to renegotiate, send hello request
-                    handshaker.kickstart();
-                    // hello request is not included in the handshake
-                    // hashes, reset them
-                    handshaker.handshakeHash.reset();
-                }
-            }
-        }
-    }
-
-    //
-    // CLOSURE RELATED CALLS
-    //
-
-    /**
-     * Return whether the socket has been explicitly closed by the application.
-     */
-    @Override
-    public boolean isClosed() {
-        return connectionState == cs_APP_CLOSED;
-    }
-
-    /**
-     * Return whether we have reached end-of-file.
-     *
-     * If the socket is not connected, has been shutdown because of an error
-     * or has been closed, throw an Exception.
-     */
-    boolean checkEOF() throws IOException {
-        switch (getConnectionState()) {
-        case cs_START:
-            throw new SocketException("Socket is not connected");
-
-        case cs_HANDSHAKE:
-        case cs_DATA:
-        case cs_RENEGOTIATE:
-        case cs_SENT_CLOSE:
-            return false;
-
-        case cs_APP_CLOSED:
-            throw new SocketException("Socket is closed");
-
-        case cs_ERROR:
-        case cs_CLOSED:
-        default:
-            // either closed because of error, or normal EOF
-            if (closeReason == null) {
-                return true;
-            }
-            IOException e = new SSLException
-                        ("Connection has been shutdown: " + closeReason);
-            e.initCause(closeReason);
-            throw e;
-
-        }
-    }
-
-    /**
-     * Check if we can write data to this socket. If not, throw an IOException.
-     */
-    void checkWrite() throws IOException {
-        if (checkEOF() || (getConnectionState() == cs_SENT_CLOSE)) {
-            // we are at EOF, write must throw Exception
-            throw new SocketException("Connection closed by remote host");
-        }
-    }
-
-    protected void closeSocket() throws IOException {
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                                                ", called closeSocket()");
-        }
-
-        super.close();
-    }
-
-    private void closeSocket(boolean selfInitiated) throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                ", called closeSocket(" + selfInitiated + ")");
-        }
-        if (!isLayered() || autoClose) {
-            super.close();
-        } else if (selfInitiated) {
-            // layered && non-autoclose
-            // read close_notify alert to clear input stream
-            waitForClose(false);
-        }
-    }
-
-    /*
-     * Closing the connection is tricky ... we can't officially close the
-     * connection until we know the other end is ready to go away too,
-     * and if ever the connection gets aborted we must forget session
-     * state (it becomes invalid).
-     */
-
-    /**
-     * Closes the SSL connection.  SSL includes an application level
-     * shutdown handshake; you should close SSL sockets explicitly
-     * rather than leaving it for finalization, so that your remote
-     * peer does not experience a protocol error.
-     */
-    @Override
-    public void close() throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                                                    ", called close()");
-        }
-        closeInternal(true);  // caller is initiating close
-        setConnectionState(cs_APP_CLOSED);
-    }
-
-    /**
-     * Don't synchronize the whole method because waitForClose()
-     * (which calls readRecord()) might be called.
-     *
-     * @param selfInitiated Indicates which party initiated the close.
-     * If selfInitiated, this side is initiating a close; for layered and
-     * non-autoclose socket, wait for close_notify response.
-     * If !selfInitiated, peer sent close_notify; we reciprocate but
-     * no need to wait for response.
-     */
-    private void closeInternal(boolean selfInitiated) throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                        ", called closeInternal(" + selfInitiated + ")");
-        }
-
-        int state = getConnectionState();
-        boolean closeSocketCalled = false;
-        Throwable cachedThrowable = null;
-        try {
-            switch (state) {
-            case cs_START:
-                // unconnected socket or handshaking has not been initialized
-                closeSocket(selfInitiated);
-                break;
-
-            /*
-             * If we're closing down due to error, we already sent (or else
-             * received) the fatal alert ... no niceties, blow the connection
-             * away as quickly as possible (even if we didn't allocate the
-             * socket ourselves; it's unusable, regardless).
-             */
-            case cs_ERROR:
-                closeSocket();
-                break;
-
-            /*
-             * Sometimes close() gets called more than once.
-             */
-            case cs_CLOSED:
-            case cs_APP_CLOSED:
-                 break;
-
-            /*
-             * Otherwise we indicate clean termination.
-             */
-            // case cs_HANDSHAKE:
-            // case cs_DATA:
-            // case cs_RENEGOTIATE:
-            // case cs_SENT_CLOSE:
-            default:
-                synchronized (this) {
-                    if (((state = getConnectionState()) == cs_CLOSED) ||
-                       (state == cs_ERROR) || (state == cs_APP_CLOSED)) {
-                        return;  // connection was closed while we waited
-                    }
-                    if (state != cs_SENT_CLOSE) {
-                        try {
-                            warning(Alerts.alert_close_notify);
-                            connectionState = cs_SENT_CLOSE;
-                        } catch (Throwable th) {
-                            // we need to ensure socket is closed out
-                            // if we encounter any errors.
-                            connectionState = cs_ERROR;
-                            // cache this for later use
-                            cachedThrowable = th;
-                            closeSocketCalled = true;
-                            closeSocket(selfInitiated);
-                        }
-                    }
-                }
-                // If state was cs_SENT_CLOSE before, we don't do the actual
-                // closing since it is already in progress.
-                if (state == cs_SENT_CLOSE) {
-                    if (debug != null && Debug.isOn("ssl")) {
-                        System.out.println(Thread.currentThread().getName() +
-                            ", close invoked again; state = " +
-                            getConnectionState());
-                    }
-                    if (selfInitiated == false) {
-                        // We were called because a close_notify message was
-                        // received. This may be due to another thread calling
-                        // read() or due to our call to waitForClose() below.
-                        // In either case, just return.
-                        return;
-                    }
-                    // Another thread explicitly called close(). We need to
-                    // wait for the closing to complete before returning.
-                    synchronized (this) {
-                        while (connectionState < cs_CLOSED) {
-                            try {
-                                this.wait();
-                            } catch (InterruptedException e) {
-                                // ignore
-                            }
-                        }
-                    }
-                    if ((debug != null) && Debug.isOn("ssl")) {
-                        System.out.println(Thread.currentThread().getName() +
-                            ", after primary close; state = " +
-                            getConnectionState());
-                    }
-                    return;
-                }
-
-                if (!closeSocketCalled)  {
-                    closeSocketCalled = true;
-                    closeSocket(selfInitiated);
-                }
-
-                break;
-            }
-        } finally {
-            synchronized (this) {
-                // Upon exit from this method, the state is always >= cs_CLOSED
-                connectionState = (connectionState == cs_APP_CLOSED)
-                                ? cs_APP_CLOSED : cs_CLOSED;
-                // notify any threads waiting for the closing to finish
-                this.notifyAll();
-            }
-            if (closeSocketCalled) {
-                // Dispose of ciphers since we've closed socket
-                disposeCiphers();
-            }
-            if (cachedThrowable != null) {
-               /*
-                * Rethrow the error to the calling method
-                * The Throwable caught can only be an Error or RuntimeException
-                */
-                if (cachedThrowable instanceof Error)
-                    throw (Error) cachedThrowable;
-                if (cachedThrowable instanceof RuntimeException)
-                    throw (RuntimeException) cachedThrowable;
-            }
-        }
-    }
-
-    /**
-     * Reads a close_notify or a fatal alert from the input stream.
-     * Keep reading records until we get a close_notify or until
-     * the connection is otherwise closed.  The close_notify or alert
-     * might be read by another reader,
-     * which will then process the close and set the connection state.
-     */
-    void waitForClose(boolean rethrow) throws IOException {
-        if (debug != null && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                ", waiting for close_notify or alert: state "
-                + getConnectionState());
-        }
-
-        try {
-            int state;
-
-            while (((state = getConnectionState()) != cs_CLOSED) &&
-                   (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
-                // create the InputRecord if it isn't initialized.
-                if (inrec == null) {
-                    inrec = new InputRecord();
-                }
-
-                // Ask for app data and then throw it away
-                try {
-                    readRecord(inrec, true);
-                } catch (SocketTimeoutException e) {
-                    if ((debug != null) && Debug.isOn("ssl")) {
-                        System.out.println(
-                            Thread.currentThread().getName() +
-                            ", received Exception: " + e);
-                    }
-                    fatal((byte)(-1), "Did not receive close_notify from peer", e);
-                }
-            }
-            inrec = null;
-        } catch (IOException e) {
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", Exception while waiting for close " +e);
-            }
-            if (rethrow) {
-                throw e; // pass exception up
-            }
-        }
-    }
-
-    /**
-     * Called by closeInternal() only. Be sure to consider the
-     * synchronization locks carefully before calling it elsewhere.
-     */
-    private void disposeCiphers() {
-        // See comment in changeReadCiphers()
-        synchronized (readLock) {
-            readCipher.dispose();
-        }
-        // See comment in changeReadCiphers()
-        writeLock.lock();
-        try {
-            writeCipher.dispose();
-        } finally {
-            writeLock.unlock();
-        }
-    }
-
-    //
-    // EXCEPTION AND ALERT HANDLING
-    //
-
-    /**
-     * Handle an exception. This method is called by top level exception
-     * handlers (in read(), write()) to make sure we always shutdown the
-     * connection correctly and do not pass runtime exception to the
-     * application.
-     */
-    void handleException(Exception e) throws IOException {
-        handleException(e, true);
-    }
-
-    /**
-     * Handle an exception. This method is called by top level exception
-     * handlers (in read(), write(), startHandshake()) to make sure we
-     * always shutdown the connection correctly and do not pass runtime
-     * exception to the application.
-     *
-     * This method never returns normally, it always throws an IOException.
-     *
-     * We first check if the socket has already been shutdown because of an
-     * error. If so, we just rethrow the exception. If the socket has not
-     * been shutdown, we sent a fatal alert and remember the exception.
-     *
-     * @param e the Exception
-     * @param resumable indicates the caller process is resumable from the
-     *          exception. If <code>resumable</code>, the socket will be
-     *          reserved for exceptions like timeout; otherwise, the socket
-     *          will be closed, no further communications could be done.
-     */
-    synchronized private void handleException(Exception e, boolean resumable)
-        throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                        ", handling exception: " + e.toString());
-        }
-
-        // don't close the Socket in case of timeouts or interrupts if
-        // the process is resumable.
-        if (e instanceof InterruptedIOException && resumable) {
-            throw (IOException)e;
-        }
-
-        // if we've already shutdown because of an error,
-        // there is nothing to do except rethrow the exception
-        if (closeReason != null) {
-            if (e instanceof IOException) { // includes SSLException
-                throw (IOException)e;
-            } else {
-                // this is odd, not an IOException.
-                // normally, this should not happen
-                // if closeReason has been already been set
-                throw Alerts.getSSLException(Alerts.alert_internal_error, e,
-                                      "Unexpected exception");
-            }
-        }
-
-        // need to perform error shutdown
-        boolean isSSLException = (e instanceof SSLException);
-        if ((isSSLException == false) && (e instanceof IOException)) {
-            // IOException from the socket
-            // this means the TCP connection is already dead
-            // we call fatal just to set the error status
-            try {
-                fatal(Alerts.alert_unexpected_message, e);
-            } catch (IOException ee) {
-                // ignore (IOException wrapped in SSLException)
-            }
-            // rethrow original IOException
-            throw (IOException)e;
-        }
-
-        // must be SSLException or RuntimeException
-        byte alertType;
-        if (isSSLException) {
-            if (e instanceof SSLHandshakeException) {
-                alertType = Alerts.alert_handshake_failure;
-            } else {
-                alertType = Alerts.alert_unexpected_message;
-            }
-        } else {
-            alertType = Alerts.alert_internal_error;
-        }
-        fatal(alertType, e);
-    }
-
-    /*
-     * Send a warning alert.
-     */
-    void warning(byte description) {
-        sendAlert(Alerts.alert_warning, description);
-    }
-
-    synchronized void fatal(byte description, String diagnostic)
-            throws IOException {
-        fatal(description, diagnostic, null);
-    }
-
-    synchronized void fatal(byte description, Throwable cause)
-            throws IOException {
-        fatal(description, null, cause);
-    }
-
-    /*
-     * Send a fatal alert, and throw an exception so that callers will
-     * need to stand on their heads to accidentally continue processing.
-     */
-    synchronized void fatal(byte description, String diagnostic,
-            Throwable cause) throws IOException {
-        if ((input != null) && (input.r != null)) {
-            input.r.close();
-        }
-        sess.invalidate();
-        if (handshakeSession != null) {
-            handshakeSession.invalidate();
-        }
-
-        int oldState = connectionState;
-        if (connectionState < cs_ERROR) {
-            connectionState = cs_ERROR;
-        }
-
-        /*
-         * Has there been an error received yet?  If not, remember it.
-         * By RFC 2246, we don't bother waiting for a response.
-         * Fatal errors require immediate shutdown.
-         */
-        if (closeReason == null) {
-            /*
-             * Try to clear the kernel buffer to avoid TCP connection resets.
-             */
-            if (oldState == cs_HANDSHAKE) {
-                sockInput.skip(sockInput.available());
-            }
-
-            // If the description equals -1, the alert won't be sent to peer.
-            if (description != -1) {
-                sendAlert(Alerts.alert_fatal, description);
-            }
-            if (cause instanceof SSLException) { // only true if != null
-                closeReason = (SSLException)cause;
-            } else {
-                closeReason =
-                    Alerts.getSSLException(description, cause, diagnostic);
-            }
-        }
-
-        /*
-         * Clean up our side.
-         */
-        closeSocket();
-        // Another thread may have disposed the ciphers during closing
-        if (connectionState < cs_CLOSED) {
-            connectionState = (oldState == cs_APP_CLOSED) ? cs_APP_CLOSED
-                                                              : cs_CLOSED;
-
-            // We should lock readLock and writeLock if no deadlock risks.
-            // See comment in changeReadCiphers()
-            readCipher.dispose();
-            writeCipher.dispose();
-        }
-
-        throw closeReason;
-    }
-
-
-    /*
-     * Process an incoming alert ... caller must already have synchronized
-     * access to "this".
-     */
-    private void recvAlert(InputRecord r) throws IOException {
-        byte level = (byte)r.read();
-        byte description = (byte)r.read();
-        if (description == -1) { // check for short message
-            fatal(Alerts.alert_illegal_parameter, "Short alert message");
-        }
-
-        if (debug != null && (Debug.isOn("record") ||
-                Debug.isOn("handshake"))) {
-            synchronized (System.out) {
-                System.out.print(Thread.currentThread().getName());
-                System.out.print(", RECV " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level " + (0x0ff & level) + ">, ");
-                }
-                System.out.println(Alerts.alertDescription(description));
-            }
-        }
-
-        if (level == Alerts.alert_warning) {
-            if (description == Alerts.alert_close_notify) {
-                if (connectionState == cs_HANDSHAKE) {
-                    fatal(Alerts.alert_unexpected_message,
-                                "Received close_notify during handshake");
-                } else {
-                    closeInternal(false);  // reply to close
-                }
-            } else {
-
-                //
-                // The other legal warnings relate to certificates,
-                // e.g. no_certificate, bad_certificate, etc; these
-                // are important to the handshaking code, which can
-                // also handle illegal protocol alerts if needed.
-                //
-                if (handshaker != null) {
-                    handshaker.handshakeAlert(description);
-                }
-            }
-        } else { // fatal or unknown level
-            String reason = "Received fatal alert: "
-                + Alerts.alertDescription(description);
-            if (closeReason == null) {
-                closeReason = Alerts.getSSLException(description, reason);
-            }
-            fatal(Alerts.alert_unexpected_message, reason);
-        }
-    }
-
-
-    /*
-     * Emit alerts.  Caller must have synchronized with "this".
-     */
-    private void sendAlert(byte level, byte description) {
-        // the connectionState cannot be cs_START
-        if (connectionState >= cs_SENT_CLOSE) {
-            return;
-        }
-
-        // For initial handshaking, don't send alert message to peer if
-        // handshaker has not started.
-        if (connectionState == cs_HANDSHAKE &&
-            (handshaker == null || !handshaker.started())) {
-            return;
-        }
-
-        OutputRecord r = new OutputRecord(Record.ct_alert);
-        r.setVersion(protocolVersion);
-
-        boolean useDebug = debug != null && Debug.isOn("ssl");
-        if (useDebug) {
-            synchronized (System.out) {
-                System.out.print(Thread.currentThread().getName());
-                System.out.print(", SEND " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level = " + (0x0ff & level) + ">, ");
-                }
-                System.out.println("description = "
-                        + Alerts.alertDescription(description));
-            }
-        }
-
-        r.write(level);
-        r.write(description);
-        try {
-            writeRecord(r);
-        } catch (IOException e) {
-            if (useDebug) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", Exception sending alert: " + e);
-            }
-        }
-    }
-
-    //
-    // VARIOUS OTHER METHODS
-    //
-
-    /*
-     * When a connection finishes handshaking by enabling use of a newly
-     * negotiated session, each end learns about it in two halves (read,
-     * and write).  When both read and write ciphers have changed, and the
-     * last handshake message has been read, the connection has joined
-     * (rejoined) the new session.
-     *
-     * NOTE:  The SSLv3 spec is rather unclear on the concepts here.
-     * Sessions don't change once they're established (including cipher
-     * suite and master secret) but connections can join them (and leave
-     * them).  They're created by handshaking, though sometime handshaking
-     * causes connections to join up with pre-established sessions.
-     */
-    private void changeReadCiphers() throws SSLException {
-        if (connectionState != cs_HANDSHAKE
-                && connectionState != cs_RENEGOTIATE) {
-            throw new SSLProtocolException(
-                "State error, change cipher specs");
-        }
-
-        // ... create decompressor
-
-        CipherBox oldCipher = readCipher;
-
-        try {
-            readCipher = handshaker.newReadCipher();
-            readAuthenticator = handshaker.newReadAuthenticator();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw new SSLException("Algorithm missing:  ", e);
-        }
-
-        /*
-         * Dispose of any intermediate state in the underlying cipher.
-         * For PKCS11 ciphers, this will release any attached sessions,
-         * and thus make finalization faster.
-         *
-         * Since MAC's doFinal() is called for every SSL/TLS packet, it's
-         * not necessary to do the same with MAC's.
-         */
-        oldCipher.dispose();
-    }
-
-    // used by Handshaker
-    void changeWriteCiphers() throws SSLException {
-        if (connectionState != cs_HANDSHAKE
-                && connectionState != cs_RENEGOTIATE) {
-            throw new SSLProtocolException(
-                "State error, change cipher specs");
-        }
-
-        // ... create compressor
-
-        CipherBox oldCipher = writeCipher;
-
-        try {
-            writeCipher = handshaker.newWriteCipher();
-            writeAuthenticator = handshaker.newWriteAuthenticator();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw new SSLException("Algorithm missing:  ", e);
-        }
-
-        // See comment above.
-        oldCipher.dispose();
-
-        // reset the flag of the first application record
-        isFirstAppOutputRecord = true;
-    }
-
-    /*
-     * Updates the SSL version associated with this connection.
-     * Called from Handshaker once it has determined the negotiated version.
-     */
-    synchronized void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        output.r.setVersion(protocolVersion);
-    }
-
-    //
-    // ONLY used by ClientHandshaker for the server hostname during handshaking
-    //
-    synchronized String getHost() {
-        // Note that the host may be null or empty for localhost.
-        if (host == null || host.length() == 0) {
-            useImplicitHost(true);
-        }
-
-        return host;
-    }
-
-    /*
-     * Try to set and use the implicit specified hostname
-     */
-    private synchronized void useImplicitHost(boolean noSniUpdate) {
-
-        // Note: If the local name service is not trustworthy, reverse
-        // host name resolution should not be performed for endpoint
-        // identification.  Use the application original specified
-        // hostname or IP address instead.
-
-        // Get the original hostname via jdk.internal.misc.SharedSecrets
-        InetAddress inetAddress = getInetAddress();
-        if (inetAddress == null) {      // not connected
-            return;
-        }
-
-        JavaNetAccess jna = SharedSecrets.getJavaNetAccess();
-        String originalHostname = jna.getOriginalHostName(inetAddress);
-        if ((originalHostname != null) &&
-                (originalHostname.length() != 0)) {
-
-            host = originalHostname;
-            if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) {
-                serverNames =
-                        Utilities.addToSNIServerNameList(serverNames, host);
-
-                if (!roleIsServer &&
-                        (handshaker != null) && !handshaker.started()) {
-                    handshaker.setSNIServerNames(serverNames);
-                }
-            }
-
-            return;
-        }
-
-        // No explicitly specified hostname, no server name indication.
-        if (!trustNameService) {
-            // The local name service is not trustworthy, use IP address.
-            host = inetAddress.getHostAddress();
-        } else {
-            // Use the underlying reverse host name resolution service.
-            host = getInetAddress().getHostName();
-        }
-    }
-
-
-    // ONLY used by HttpsClient to setup the URI specified hostname
-    //
-    // Please NOTE that this method MUST be called before calling to
-    // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
-    // may override SNIHostName in the customized server name indication.
-    synchronized public void setHost(String host) {
-        this.host = host;
-        this.serverNames =
-            Utilities.addToSNIServerNameList(this.serverNames, this.host);
-
-        if (!roleIsServer && (handshaker != null) && !handshaker.started()) {
-            handshaker.setSNIServerNames(serverNames);
-        }
-    }
-
-    /**
-     * Gets an input stream to read from the peer on the other side.
-     * Data read from this stream was always integrity protected in
-     * transit, and will usually have been confidentiality protected.
-     */
-    @Override
-    synchronized public InputStream getInputStream() throws IOException {
-        if (isClosed()) {
-            throw new SocketException("Socket is closed");
-        }
-
-        /*
-         * Can't call isConnected() here, because the Handshakers
-         * do some initialization before we actually connect.
-         */
-        if (connectionState == cs_START) {
-            throw new SocketException("Socket is not connected");
-        }
-
-        return input;
-    }
-
-    /**
-     * Gets an output stream to write to the peer on the other side.
-     * Data written on this stream is always integrity protected, and
-     * will usually be confidentiality protected.
-     */
-    @Override
-    synchronized public OutputStream getOutputStream() throws IOException {
-        if (isClosed()) {
-            throw new SocketException("Socket is closed");
-        }
-
-        /*
-         * Can't call isConnected() here, because the Handshakers
-         * do some initialization before we actually connect.
-         */
-        if (connectionState == cs_START) {
-            throw new SocketException("Socket is not connected");
-        }
-
-        return output;
-    }
-
-    /**
-     * Returns the the SSL Session in use by this connection.  These can
-     * be long lived, and frequently correspond to an entire login session
-     * for some user.
-     */
-    @Override
-    public SSLSession getSession() {
-        /*
-         * Force a synchronous handshake, if appropriate.
-         */
-        if (getConnectionState() == cs_HANDSHAKE) {
-            try {
-                // start handshaking, if failed, the connection will be closed.
-                startHandshake(false);
-            } catch (IOException e) {
-                // handshake failed. log and return a nullSession
-                if (debug != null && Debug.isOn("handshake")) {
-                      System.out.println(Thread.currentThread().getName() +
-                          ", IOException in getSession():  " + e);
-                }
-            }
-        }
-        synchronized (this) {
-            return sess;
-        }
-    }
-
-    @Override
-    synchronized public SSLSession getHandshakeSession() {
-        return handshakeSession;
-    }
-
-    synchronized void setHandshakeSession(SSLSessionImpl session) {
-        handshakeSession = session;
-    }
-
-    /**
-     * Controls whether new connections may cause creation of new SSL
-     * sessions.
-     *
-     * As long as handshaking has not started, we can change
-     * whether we enable session creations.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    @Override
-    synchronized public void setEnableSessionCreation(boolean flag) {
-        enableSessionCreation = flag;
-
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnableSessionCreation(enableSessionCreation);
-        }
-    }
-
-    /**
-     * Returns true if new connections may cause creation of new SSL
-     * sessions.
-     */
-    @Override
-    synchronized public boolean getEnableSessionCreation() {
-        return enableSessionCreation;
-    }
-
-
-    /**
-     * Sets the flag controlling whether a server mode socket
-     * *REQUIRES* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is needed.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    @Override
-    synchronized public void setNeedClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    @Override
-    synchronized public boolean getNeedClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_required);
-    }
-
-    /**
-     * Sets the flag controlling whether a server mode socket
-     * *REQUESTS* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is requested.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    @Override
-    synchronized public void setWantClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    @Override
-    synchronized public boolean getWantClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_requested);
-    }
-
-
-    /**
-     * Sets the flag controlling whether the socket is in SSL
-     * client or server mode.  Must be called before any SSL
-     * traffic has started.
-     */
-    @Override
-    @SuppressWarnings("fallthrough")
-    synchronized public void setUseClientMode(boolean flag) {
-        switch (connectionState) {
-
-        case cs_START:
-            /*
-             * If we need to change the socket mode and the enabled
-             * protocols and cipher suites haven't specifically been
-             * set by the user, change them to the corresponding
-             * default ones.
-             */
-            if (roleIsServer != (!flag)) {
-                if (sslContext.isDefaultProtocolList(enabledProtocols)) {
-                    enabledProtocols =
-                            sslContext.getDefaultProtocolList(!flag);
-                }
-
-                if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) {
-                    enabledCipherSuites =
-                            sslContext.getDefaultCipherSuiteList(!flag);
-                }
-            }
-
-            roleIsServer = !flag;
-            break;
-
-        case cs_HANDSHAKE:
-            /*
-             * If we have a handshaker, but haven't started
-             * SSL traffic, we can throw away our current
-             * handshaker, and start from scratch.  Don't
-             * need to call doneConnect() again, we already
-             * have the streams.
-             */
-            assert(handshaker != null);
-            if (!handshaker.activated()) {
-                /*
-                 * If we need to change the socket mode and the enabled
-                 * protocols haven't specifically been set by the user,
-                 * change them to the corresponding default ones.
-                 */
-                if (roleIsServer != (!flag) &&
-                        sslContext.isDefaultProtocolList(enabledProtocols)) {
-                    enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-                }
-                roleIsServer = !flag;
-                connectionState = cs_START;
-                initHandshaker();
-                break;
-            }
-
-            // If handshake has started, that's an error.  Fall through...
-
-        default:
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(Thread.currentThread().getName() +
-                    ", setUseClientMode() invoked in state = " +
-                    connectionState);
-            }
-            throw new IllegalArgumentException(
-                "Cannot change mode after SSL traffic has started");
-        }
-    }
-
-    @Override
-    synchronized public boolean getUseClientMode() {
-        return !roleIsServer;
-    }
-
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    @Override
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSupportedCipherSuiteList().toStringArray();
-    }
-
-    /**
-     * Controls which particular cipher suites are enabled for use on
-     * this connection.  The cipher suites must have been listed by
-     * getCipherSuites() as being supported.  Even if a suite has been
-     * enabled, it might never be used if no peer supports it or the
-     * requisite certificates (and private keys) are not available.
-     *
-     * @param suites Names of all the cipher suites to enable.
-     */
-    @Override
-    synchronized public void setEnabledCipherSuites(String[] suites) {
-        enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        }
-    }
-
-    /**
-     * Returns the names of the SSL cipher suites which are currently enabled
-     * for use on this connection.  When an SSL socket is first created,
-     * all enabled cipher suites <em>(a)</em> protect data confidentiality,
-     * by traffic encryption, and <em>(b)</em> can mutually authenticate
-     * both clients and servers.  Thus, in some environments, this value
-     * might be empty.
-     *
-     * @return an array of cipher suite names
-     */
-    @Override
-    synchronized public String[] getEnabledCipherSuites() {
-        return enabledCipherSuites.toStringArray();
-    }
-
-
-    /**
-     * Returns the protocols that are supported by this implementation.
-     * A subset of the supported protocols may be enabled for this connection
-     * @return an array of protocol names.
-     */
-    @Override
-    public String[] getSupportedProtocols() {
-        return sslContext.getSuportedProtocolList().toStringArray();
-    }
-
-    /**
-     * Controls which protocols are enabled for use on
-     * this connection.  The protocols must have been listed by
-     * getSupportedProtocols() as being supported.
-     *
-     * @param protocols protocols to enable.
-     * @exception IllegalArgumentException when one of the protocols
-     *  named by the parameter is not supported.
-     */
-    @Override
-    synchronized public void setEnabledProtocols(String[] protocols) {
-        enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledProtocols(enabledProtocols);
-        }
-    }
-
-    @Override
-    synchronized public String[] getEnabledProtocols() {
-        return enabledProtocols.toStringArray();
-    }
-
-    /**
-     * Assigns the socket timeout.
-     * @see java.net.Socket#setSoTimeout
-     */
-    @Override
-    public void setSoTimeout(int timeout) throws SocketException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(Thread.currentThread().getName() +
-                ", setSoTimeout(" + timeout + ") called");
-        }
-
-        super.setSoTimeout(timeout);
-    }
-
-    /**
-     * Registers an event listener to receive notifications that an
-     * SSL handshake has completed on this connection.
-     */
-    @Override
-    public synchronized void addHandshakeCompletedListener(
-            HandshakeCompletedListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener is null");
-        }
-        if (handshakeListeners == null) {
-            handshakeListeners = new
-                HashMap<HandshakeCompletedListener, AccessControlContext>(4);
-        }
-        handshakeListeners.put(listener, AccessController.getContext());
-    }
-
-
-    /**
-     * Removes a previously registered handshake completion listener.
-     */
-    @Override
-    public synchronized void removeHandshakeCompletedListener(
-            HandshakeCompletedListener listener) {
-        if (handshakeListeners == null) {
-            throw new IllegalArgumentException("no listeners");
-        }
-        if (handshakeListeners.remove(listener) == null) {
-            throw new IllegalArgumentException("listener not registered");
-        }
-        if (handshakeListeners.isEmpty()) {
-            handshakeListeners = null;
-        }
-    }
-
-    /**
-     * Returns the SSLParameters in effect for this SSLSocket.
-     */
-    @Override
-    synchronized public SSLParameters getSSLParameters() {
-        SSLParameters params = super.getSSLParameters();
-
-        // the super implementation does not handle the following parameters
-        params.setEndpointIdentificationAlgorithm(identificationProtocol);
-        params.setAlgorithmConstraints(algorithmConstraints);
-
-        if (sniMatchers.isEmpty() && !noSniMatcher) {
-            // 'null' indicates none has been set
-            params.setSNIMatchers(null);
-        } else {
-            params.setSNIMatchers(sniMatchers);
-        }
-
-        if (serverNames.isEmpty() && !noSniExtension) {
-            // 'null' indicates none has been set
-            params.setServerNames(null);
-        } else {
-            params.setServerNames(serverNames);
-        }
-
-        params.setUseCipherSuitesOrder(preferLocalCipherSuites);
-        params.setApplicationProtocols(applicationProtocols);
-
-        return params;
-    }
-
-    /**
-     * Applies SSLParameters to this socket.
-     */
-    @Override
-    synchronized public void setSSLParameters(SSLParameters params) {
-        super.setSSLParameters(params);
-
-        // the super implementation does not handle the following parameters
-        identificationProtocol = params.getEndpointIdentificationAlgorithm();
-        algorithmConstraints = params.getAlgorithmConstraints();
-        preferLocalCipherSuites = params.getUseCipherSuitesOrder();
-
-        List<SNIServerName> sniNames = params.getServerNames();
-        if (sniNames != null) {
-            noSniExtension = sniNames.isEmpty();
-            serverNames = sniNames;
-        }
-
-        Collection<SNIMatcher> matchers = params.getSNIMatchers();
-        if (matchers != null) {
-            noSniMatcher = matchers.isEmpty();
-            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);
-            } else {
-                handshaker.setSNIServerNames(serverNames);
-            }
-        }
-    }
-
-    @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
-    // protocol state machine.
-    //
-    private static class NotifyHandshakeThread extends Thread {
-
-        private Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
-                targets;        // who gets notified
-        private HandshakeCompletedEvent event;          // the notification
-
-        NotifyHandshakeThread(
-            Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
-            entrySet, HandshakeCompletedEvent e) {
-
-            super("HandshakeCompletedNotify-Thread");
-            targets = new HashSet<>(entrySet);          // clone the entry set
-            event = e;
-        }
-
-        @Override
-        public void run() {
-            // Don't need to synchronize, as it only runs in one thread.
-            for (Map.Entry<HandshakeCompletedListener,AccessControlContext>
-                entry : targets) {
-
-                final HandshakeCompletedListener l = entry.getKey();
-                AccessControlContext acc = entry.getValue();
-                AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                    @Override
-                    public Void run() {
-                        l.handshakeCompleted(event);
-                        return null;
-                    }
-                }, acc);
-            }
-        }
-    }
-
-    /**
-     * Returns a printable representation of this end of the connection.
-     */
-    @Override
-    public String toString() {
-        StringBuffer retval = new StringBuffer(80);
-
-        retval.append(Integer.toHexString(hashCode()));
-        retval.append("[");
-        retval.append(sess.getCipherSuite());
-        retval.append(": ");
-
-        retval.append(super.toString());
-        retval.append("]");
-
-        return retval.toString();
-    }
-}
--- a/src/share/classes/sun/security/ssl/ServerHandshaker.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2062 +0,0 @@
-/*
- * Copyright (c) 1996, 2020, 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.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.interfaces.*;
-import java.security.spec.ECParameterSpec;
-import java.math.BigInteger;
-import java.util.function.BiFunction;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import javax.net.ssl.*;
-
-import javax.security.auth.Subject;
-
-import sun.security.util.KeyUtil;
-import sun.security.util.LegacyAlgorithmConstraints;
-import sun.security.action.GetPropertyAction;
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-import sun.security.ssl.SignatureAndHashAlgorithm.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * ServerHandshaker does the protocol handshaking from the point
- * of view of a server.  It is driven asychronously by handshake messages
- * as delivered by the parent Handshaker class, and also uses
- * common functionality (e.g. key generation) that is provided there.
- *
- * @author David Brownell
- */
-final class ServerHandshaker extends Handshaker {
-
-    // is the server going to require the client to authenticate?
-    private byte                doClientAuth;
-
-    // our authentication info
-    private X509Certificate[]   certs;
-    private PrivateKey          privateKey;
-
-    private Object              serviceCreds;
-
-    // flag to check for clientCertificateVerify message
-    private boolean             needClientVerify = false;
-
-    /*
-     * For exportable ciphersuites using non-exportable key sizes, we use
-     * ephemeral RSA keys. We could also do anonymous RSA in the same way
-     * but there are no such ciphersuites currently defined.
-     */
-    private PrivateKey          tempPrivateKey;
-    private PublicKey           tempPublicKey;
-
-    /*
-     * For anonymous and ephemeral Diffie-Hellman key exchange, we use
-     * ephemeral Diffie-Hellman keys.
-     */
-    private DHCrypt dh;
-
-    // Helper for ECDH based key exchanges
-    private ECDHCrypt ecdh;
-
-    // version request by the client in its ClientHello
-    // we remember it for the RSA premaster secret version check
-    private ProtocolVersion clientRequestedVersion;
-
-    // client supported elliptic curves
-    private EllipticCurvesExtension requestedCurves;
-
-    // the preferable signature algorithm used by ServerKeyExchange message
-    SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
-    // Flag to use smart ephemeral DH key which size matches the corresponding
-    // authentication key
-    private static final boolean useSmartEphemeralDHKeys;
-
-    // Flag to use legacy ephemeral DH key which size is 512 bits for
-    // exportable cipher suites, and 768 bits for others
-    private static final boolean useLegacyEphemeralDHKeys;
-
-    // The customized ephemeral DH key size for non-exportable cipher suites.
-    private static final int customizedDHKeySize;
-
-    // legacy algorithm constraints
-    private static final AlgorithmConstraints legacyAlgorithmConstraints =
-            new LegacyAlgorithmConstraints(
-                    LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS,
-                    new SSLAlgorithmDecomposer());
-
-    static {
-        String property = AccessController.doPrivileged(
-                    new GetPropertyAction("jdk.tls.ephemeralDHKeySize"));
-        if (property == null || property.length() == 0) {
-            useLegacyEphemeralDHKeys = false;
-            useSmartEphemeralDHKeys = false;
-            customizedDHKeySize = -1;
-        } else if ("matched".equals(property)) {
-            useLegacyEphemeralDHKeys = false;
-            useSmartEphemeralDHKeys = true;
-            customizedDHKeySize = -1;
-        } else if ("legacy".equals(property)) {
-            useLegacyEphemeralDHKeys = true;
-            useSmartEphemeralDHKeys = false;
-            customizedDHKeySize = -1;
-        } else {
-            useLegacyEphemeralDHKeys = false;
-            useSmartEphemeralDHKeys = false;
-
-            try {
-                // DH parameter generation can be extremely slow, best to
-                // use one of the supported pre-computed DH parameters
-                // (see DHCrypt class).
-                customizedDHKeySize = Integer.parseUnsignedInt(property);
-                if (customizedDHKeySize < 1024 || customizedDHKeySize > 8192 ||
-                        (customizedDHKeySize & 0x3f) != 0) {
-                    throw new IllegalArgumentException(
-                        "Unsupported customized DH key size: " +
-                        customizedDHKeySize + ". " +
-                        "The key size must be multiple of 64, " +
-                        "and can only range from 1024 to 8192 (inclusive)");
-                }
-            } catch (NumberFormatException nfe) {
-                throw new IllegalArgumentException(
-                        "Invalid system property jdk.tls.ephemeralDHKeySize");
-            }
-        }
-    }
-
-    /*
-     * Constructor ... use the keys found in the auth context.
-     */
-    ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
-            ProtocolList enabledProtocols, byte clientAuth,
-            ProtocolVersion activeProtocolVersion, boolean isInitialHandshake,
-            boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(socket, context, enabledProtocols,
-                (clientAuth != SSLEngineImpl.clauth_none), false,
-                activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-                clientVerifyData, serverVerifyData);
-        doClientAuth = clientAuth;
-    }
-
-    /*
-     * Constructor ... use the keys found in the auth context.
-     */
-    ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
-            ProtocolList enabledProtocols, byte clientAuth,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(engine, context, enabledProtocols,
-                (clientAuth != SSLEngineImpl.clauth_none), false,
-                activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-                clientVerifyData, serverVerifyData);
-        doClientAuth = clientAuth;
-    }
-
-    /*
-     * As long as handshaking has not started, we can change
-     * whether client authentication is required.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    void setClientAuth(byte clientAuth) {
-        doClientAuth = clientAuth;
-    }
-
-    /*
-     * This routine handles all the server side handshake messages, one at
-     * a time.  Given the message type (and in some cases the pending cipher
-     * spec) it parses the type-specific message.  Then it calls a function
-     * that handles that specific message.
-     *
-     * It updates the state machine as each message is processed, and writes
-     * responses as needed using the connection in the constructor.
-     */
-    @Override
-    void processMessage(byte type, int message_len)
-            throws IOException {
-
-        // check the handshake state
-        handshakeState.check(type);
-
-        switch (type) {
-            case HandshakeMessage.ht_client_hello:
-                ClientHello ch = new ClientHello(input, message_len);
-                handshakeState.update(ch, resumingSession);
-                /*
-                 * send it off for processing.
-                 */
-                this.clientHello(ch);
-                break;
-
-            case HandshakeMessage.ht_certificate:
-                if (doClientAuth == SSLEngineImpl.clauth_none) {
-                    fatalSE(Alerts.alert_unexpected_message,
-                                "client sent unsolicited cert chain");
-                    // NOTREACHED
-                }
-                CertificateMsg certificateMsg = new CertificateMsg(input);
-                handshakeState.update(certificateMsg, resumingSession);
-                this.clientCertificate(certificateMsg);
-                break;
-
-            case HandshakeMessage.ht_client_key_exchange:
-                SecretKey preMasterSecret;
-                switch (keyExchange) {
-                case K_RSA:
-                case K_RSA_EXPORT:
-                    /*
-                     * The client's pre-master secret is decrypted using
-                     * either the server's normal private RSA key, or the
-                     * temporary one used for non-export or signing-only
-                     * certificates/keys.
-                     */
-                    RSAClientKeyExchange pms = new RSAClientKeyExchange(
-                            protocolVersion, clientRequestedVersion,
-                            sslContext.getSecureRandom(), input,
-                            message_len, privateKey);
-                    handshakeState.update(pms, resumingSession);
-                    preMasterSecret = this.clientKeyExchange(pms);
-                    break;
-                case K_KRB5:
-                case K_KRB5_EXPORT:
-                    KerberosClientKeyExchange kke =
-                        new KerberosClientKeyExchange(protocolVersion,
-                            clientRequestedVersion,
-                            sslContext.getSecureRandom(),
-                            input,
-                            this.getAccSE(),
-                            serviceCreds);
-                    handshakeState.update(kke, resumingSession);
-                    preMasterSecret = this.clientKeyExchange(kke);
-                    break;
-                case K_DHE_RSA:
-                case K_DHE_DSS:
-                case K_DH_ANON:
-                    /*
-                     * The pre-master secret is derived using the normal
-                     * Diffie-Hellman calculation.   Note that the main
-                     * protocol difference in these five flavors is in how
-                     * the ServerKeyExchange message was constructed!
-                     */
-                    DHClientKeyExchange dhcke = new DHClientKeyExchange(input);
-                    handshakeState.update(dhcke, resumingSession);
-                    preMasterSecret = this.clientKeyExchange(dhcke);
-                    break;
-                case K_ECDH_RSA:
-                case K_ECDH_ECDSA:
-                case K_ECDHE_RSA:
-                case K_ECDHE_ECDSA:
-                case K_ECDH_ANON:
-                    ECDHClientKeyExchange ecdhcke =
-                        new ECDHClientKeyExchange(input);
-                    handshakeState.update(ecdhcke, resumingSession);
-                    preMasterSecret = this.clientKeyExchange(ecdhcke);
-                    break;
-                default:
-                    throw new SSLProtocolException
-                        ("Unrecognized key exchange: " + keyExchange);
-                }
-
-                // Need to add the hash for RFC 7627.
-                if (session.getUseExtendedMasterSecret()) {
-                    input.digestNow();
-                }
-
-                //
-                // All keys are calculated from the premaster secret
-                // and the exchanged nonces in the same way.
-                //
-                calculateKeys(preMasterSecret, clientRequestedVersion);
-                break;
-
-            case HandshakeMessage.ht_certificate_verify:
-                CertificateVerify cvm =
-                        new CertificateVerify(input,
-                            getLocalSupportedSignAlgs(), protocolVersion);
-                handshakeState.update(cvm, resumingSession);
-                this.clientCertificateVerify(cvm);
-                break;
-
-            case HandshakeMessage.ht_finished:
-                Finished cfm =
-                    new Finished(protocolVersion, input, cipherSuite);
-                handshakeState.update(cfm, resumingSession);
-                this.clientFinished(cfm);
-                break;
-
-            default:
-                throw new SSLProtocolException(
-                        "Illegal server handshake msg, " + type);
-        }
-    }
-
-
-    /*
-     * ClientHello presents the server with a bunch of options, to which the
-     * server replies with a ServerHello listing the ones which this session
-     * will use.  If needed, it also writes its Certificate plus in some cases
-     * a ServerKeyExchange message.  It may also write a CertificateRequest,
-     * to elicit a client certificate.
-     *
-     * All these messages are terminated by a ServerHelloDone message.  In
-     * most cases, all this can be sent in a single Record.
-     */
-    private void clientHello(ClientHello mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        // Reject client initiated renegotiation?
-        //
-        // If server side should reject client-initiated renegotiation,
-        // send an alert_handshake_failure fatal alert, not a no_renegotiation
-        // warning alert (no_renegotiation must be a warning: RFC 2246).
-        // no_renegotiation might seem more natural at first, but warnings
-        // are not appropriate because the sending party does not know how
-        // the receiving party will behave.  This state must be treated as
-        // a fatal server condition.
-        //
-        // This will not have any impact on server initiated renegotiation.
-        if (rejectClientInitiatedRenego && !isInitialHandshake &&
-                !serverHelloRequested) {
-            fatalSE(Alerts.alert_handshake_failure,
-                "Client initiated renegotiation is not allowed");
-        }
-
-        // check the server name indication if required
-        ServerNameExtension clientHelloSNIExt = (ServerNameExtension)
-                    mesg.extensions.get(ExtensionType.EXT_SERVER_NAME);
-        if (!sniMatchers.isEmpty()) {
-            // we do not reject client without SNI extension
-            if (clientHelloSNIExt != null &&
-                        !clientHelloSNIExt.isMatched(sniMatchers)) {
-                fatalSE(Alerts.alert_unrecognized_name,
-                    "Unrecognized server name indication");
-            }
-        }
-
-        // Does the message include security renegotiation indication?
-        boolean renegotiationIndicated = false;
-
-        // check the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
-        CipherSuiteList cipherSuites = mesg.getCipherSuites();
-        if (cipherSuites.contains(CipherSuite.C_SCSV)) {
-            renegotiationIndicated = true;
-            if (isInitialHandshake) {
-                secureRenegotiation = true;
-            } else {
-                // abort the handshake with a fatal handshake_failure alert
-                if (secureRenegotiation) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The SCSV is present in a secure renegotiation");
-                } else {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The SCSV is present in a insecure renegotiation");
-                }
-            }
-        }
-
-        // check the "renegotiation_info" extension
-        RenegotiationInfoExtension clientHelloRI = (RenegotiationInfoExtension)
-                    mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
-        if (clientHelloRI != null) {
-            renegotiationIndicated = true;
-            if (isInitialHandshake) {
-                // verify the length of the "renegotiated_connection" field
-                if (!clientHelloRI.isEmpty()) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The renegotiation_info field is not empty");
-                }
-
-                secureRenegotiation = true;
-            } else {
-                if (!secureRenegotiation) {
-                    // unexpected RI extension for insecure renegotiation,
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The renegotiation_info is present in a insecure " +
-                        "renegotiation");
-                }
-
-                // verify the client_verify_data value
-                if (!MessageDigest.isEqual(clientVerifyData,
-                                clientHelloRI.getRenegotiatedConnection())) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Incorrect verify data in ClientHello " +
-                        "renegotiation_info message");
-                }
-            }
-        } else if (!isInitialHandshake && secureRenegotiation) {
-           // if the connection's "secure_renegotiation" flag is set to TRUE
-           // and the "renegotiation_info" extension is not present, abort
-           // the handshake.
-            fatalSE(Alerts.alert_handshake_failure,
-                        "Inconsistent secure renegotiation indication");
-        }
-
-        // if there is no security renegotiation indication or the previous
-        // handshake is insecure.
-        if (!renegotiationIndicated || !secureRenegotiation) {
-            if (isInitialHandshake) {
-                if (!allowLegacyHelloMessages) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Failed to negotiate the use of secure renegotiation");
-                }
-
-                // continue with legacy ClientHello
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("Warning: No renegotiation " +
-                        "indication in ClientHello, allow legacy ClientHello");
-                }
-            } else if (!allowUnsafeRenegotiation) {
-                // abort the handshake
-                if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
-                    // respond with a no_renegotiation warning
-                    warningSE(Alerts.alert_no_renegotiation);
-
-                    // invalidate the handshake so that the caller can
-                    // dispose this object.
-                    invalidated = true;
-
-                    // If there is still unread block in the handshake
-                    // input stream, it would be truncated with the disposal
-                    // and the next handshake message will become incomplete.
-                    //
-                    // However, according to SSL/TLS specifications, no more
-                    // handshake message could immediately follow ClientHello
-                    // or HelloRequest. But in case of any improper messages,
-                    // we'd better check to ensure there is no remaining bytes
-                    // in the handshake input stream.
-                    if (input.available() > 0) {
-                        fatalSE(Alerts.alert_unexpected_message,
-                            "ClientHello followed by an unexpected  " +
-                            "handshake message");
-                    }
-
-                    return;
-                } else {
-                    // For SSLv3, send the handshake_failure fatal error.
-                    // Note that SSLv3 does not define a no_renegotiation
-                    // alert like TLSv1. However we cannot ignore the message
-                    // simply, otherwise the other side was waiting for a
-                    // response that would never come.
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Renegotiation is not allowed");
-                }
-            } else {   // !isInitialHandshake && allowUnsafeRenegotiation
-                // continue with unsafe renegotiation.
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                            "Warning: continue with insecure renegotiation");
-                }
-            }
-        }
-
-        // check out the "extended_master_secret" extension
-        if (useExtendedMasterSecret) {
-            ExtendedMasterSecretExtension extendedMasterSecretExtension =
-                    (ExtendedMasterSecretExtension)mesg.extensions.get(
-                            ExtensionType.EXT_EXTENDED_MASTER_SECRET);
-            if (extendedMasterSecretExtension != null) {
-                requestedToUseEMS = true;
-            } else if (mesg.protocolVersion.v >= ProtocolVersion.TLS10.v) {
-                if (!allowLegacyMasterSecret) {
-                    // For full handshake, if the server receives a ClientHello
-                    // without the extension, it SHOULD abort the handshake if
-                    // it does not wish to interoperate with legacy clients.
-                    //
-                    // As if extended master extension is required for full
-                    // handshake, it MUST be used in abbreviated handshake too.
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Extended Master Secret extension is required");
-                }
-            }
-        }
-
-        // 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.
-         */
-        input.digestNow();
-
-        /*
-         * FIRST, construct the ServerHello using the options and priorities
-         * from the ClientHello.  Update the (pending) cipher spec as we do
-         * so, and save the client's version to protect against rollback
-         * attacks.
-         *
-         * There are a bunch of minor tasks here, and one major one: deciding
-         * if the short or the full handshake sequence will be used.
-         */
-        ServerHello m1 = new ServerHello();
-
-        clientRequestedVersion = mesg.protocolVersion;
-
-        // select a proper protocol version.
-        ProtocolVersion selectedVersion =
-               selectProtocolVersion(clientRequestedVersion);
-        if (selectedVersion == null ||
-                selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
-            fatalSE(Alerts.alert_handshake_failure,
-                "Client requested protocol " + clientRequestedVersion +
-                " not enabled or not supported");
-        }
-
-        handshakeHash.protocolDetermined(selectedVersion);
-        setVersion(selectedVersion);
-
-        m1.protocolVersion = protocolVersion;
-
-        //
-        // random ... save client and server values for later use
-        // in computing the master secret (from pre-master secret)
-        // and thence the other crypto keys.
-        //
-        // NOTE:  this use of three inputs to generating _each_ set
-        // of ciphers slows things down, but it does increase the
-        // security since each connection in the session can hold
-        // its own authenticated (and strong) keys.  One could make
-        // creation of a session a rare thing...
-        //
-        clnt_random = mesg.clnt_random;
-        svr_random = new RandomCookie(sslContext.getSecureRandom());
-        m1.svr_random = svr_random;
-
-        session = null; // forget about the current session
-        //
-        // Here we go down either of two paths:  (a) the fast one, where
-        // the client's asked to rejoin an existing session, and the server
-        // permits this; (b) the other one, where a new session is created.
-        //
-        if (mesg.sessionId.length() != 0) {
-            // client is trying to resume a session, let's see...
-
-            SSLSessionImpl previous = ((SSLSessionContextImpl)sslContext
-                        .engineGetServerSessionContext())
-                        .get(mesg.sessionId.getId());
-            //
-            // Check if we can use the fast path, resuming a session.  We
-            // can do so iff we have a valid record for that session, and
-            // the cipher suite for that session was on the list which the
-            // client requested, and if we're not forgetting any needed
-            // authentication on the part of the client.
-            //
-            if (previous != null) {
-                resumingSession = previous.isRejoinable();
-
-                if (resumingSession) {
-                    ProtocolVersion oldVersion = previous.getProtocolVersion();
-                    // cannot resume session with different version
-                    if (oldVersion != mesg.protocolVersion) {
-                        resumingSession = false;
-                    }
-                }
-
-                if (resumingSession && useExtendedMasterSecret) {
-                    if (requestedToUseEMS &&
-                            !previous.getUseExtendedMasterSecret()) {
-                        // For abbreviated handshake request, If the original
-                        // session did not use the "extended_master_secret"
-                        // extension but the new ClientHello contains the
-                        // extension, then the server MUST NOT perform the
-                        // abbreviated handshake.  Instead, it SHOULD continue
-                        // with a full handshake.
-                        resumingSession = false;
-                    } else if (!requestedToUseEMS &&
-                            previous.getUseExtendedMasterSecret()) {
-                        // For abbreviated handshake request, if the original
-                        // session used the "extended_master_secret" extension
-                        // but the new ClientHello does not contain it, the
-                        // server MUST abort the abbreviated handshake.
-                        fatalSE(Alerts.alert_handshake_failure,
-                                "Missing Extended Master Secret extension " +
-                                "on session resumption");
-                    } else if (!requestedToUseEMS &&
-                            !previous.getUseExtendedMasterSecret()) {
-                        // For abbreviated handshake request, if neither the
-                        // original session nor the new ClientHello uses the
-                        // extension, the server SHOULD abort the handshake.
-                        if (!allowLegacyResumption) {
-                            fatalSE(Alerts.alert_handshake_failure,
-                                "Missing Extended Master Secret extension " +
-                                "on session resumption");
-                        } else {  // Otherwise, continue with a full handshake.
-                            resumingSession = false;
-                        }
-                    }
-                }
-
-                // cannot resume session with different server name indication
-                if (resumingSession) {
-                    List<SNIServerName> oldServerNames =
-                            previous.getRequestedServerNames();
-                    if (clientHelloSNIExt != null) {
-                        if (!clientHelloSNIExt.isIdentical(oldServerNames)) {
-                            resumingSession = false;
-                        }
-                    } else if (!oldServerNames.isEmpty()) {
-                        resumingSession = false;
-                    }
-
-                    if (!resumingSession &&
-                            debug != null && Debug.isOn("handshake")) {
-                        System.out.println(
-                            "The requested server name indication " +
-                            "is not identical to the previous one");
-                    }
-                }
-
-                if (resumingSession &&
-                        (doClientAuth == SSLEngineImpl.clauth_required)) {
-                    try {
-                        previous.getPeerPrincipal();
-                    } catch (SSLPeerUnverifiedException e) {
-                        resumingSession = false;
-                    }
-                }
-
-                // validate subject identity
-                if (resumingSession) {
-                    CipherSuite suite = previous.getSuite();
-                    if (suite.keyExchange == K_KRB5 ||
-                        suite.keyExchange == K_KRB5_EXPORT) {
-                        Principal localPrincipal = previous.getLocalPrincipal();
-
-                        Subject subject = null;
-                        try {
-                            subject = AccessController.doPrivileged(
-                                new PrivilegedExceptionAction<Subject>() {
-                                @Override
-                                public Subject run() throws Exception {
-                                    return
-                                        Krb5Helper.getServerSubject(getAccSE());
-                            }});
-                        } catch (PrivilegedActionException e) {
-                            subject = null;
-                            if (debug != null && Debug.isOn("session")) {
-                                System.out.println("Attempt to obtain" +
-                                                " subject failed!");
-                            }
-                        }
-
-                        if (subject != null) {
-                            // Eliminate dependency on KerberosPrincipal
-                            if (Krb5Helper.isRelated(subject, localPrincipal)) {
-                                if (debug != null && Debug.isOn("session"))
-                                    System.out.println("Subject can" +
-                                            " provide creds for princ");
-                            } else {
-                                resumingSession = false;
-                                if (debug != null && Debug.isOn("session"))
-                                    System.out.println("Subject cannot" +
-                                            " provide creds for princ");
-                            }
-                        } else {
-                            resumingSession = false;
-                            if (debug != null && Debug.isOn("session"))
-                                System.out.println("Kerberos credentials are" +
-                                    " not present in the current Subject;" +
-                                    " check if " +
-                                    " javax.security.auth.useSubjectAsCreds" +
-                                    " system property has been set to false");
-                        }
-                    }
-                }
-
-                // ensure that the endpoint identification algorithm matches the
-                // one in the session
-                String identityAlg = getEndpointIdentificationAlgorithmSE();
-                if (resumingSession && identityAlg != null) {
-
-                    String sessionIdentityAlg =
-                    previous.getEndpointIdentificationAlgorithm();
-                    if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
-
-                        if (debug != null && Debug.isOn("session")) {
-                            System.out.println("%% can't resume, endpoint id"
-                                + " algorithm does not match, requested: " +
-                                identityAlg + ", cached: " +
-                                sessionIdentityAlg);
-                        }
-                        resumingSession = false;
-                    }
-                }
-
-                if (resumingSession) {
-                    CipherSuite suite = previous.getSuite();
-                    // verify that the ciphersuite from the cached session
-                    // is in the list of client requested ciphersuites and
-                    // we have it enabled
-                    if ((isNegotiable(suite) == false) ||
-                            (mesg.getCipherSuites().contains(suite) == false)) {
-                        resumingSession = false;
-                    } else {
-                        // everything looks ok, set the ciphersuite
-                        // this should be done last when we are sure we
-                        // will resume
-                        setCipherSuite(suite);
-                    }
-                }
-
-                if (resumingSession) {
-                    session = previous;
-                    if (debug != null &&
-                        (Debug.isOn("handshake") || Debug.isOn("session"))) {
-                        System.out.println("%% Resuming " + session);
-                    }
-                }
-            }
-        } // else client did not try to resume
-
-        //
-        // If client hasn't specified a session we can resume, start a
-        // new one and choose its cipher suite and compression options.
-        // Unless new session creation is disabled for this connection!
-        //
-        if (session == null) {
-            if (!enableNewSession) {
-                throw new SSLException("Client did not resume a session");
-            }
-
-            requestedCurves = (EllipticCurvesExtension)
-                        mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
-
-            // We only need to handle the "signature_algorithm" extension
-            // for full handshakes and TLS 1.2 or later.
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                SignatureAlgorithmsExtension signAlgs =
-                    (SignatureAlgorithmsExtension)mesg.extensions.get(
-                                    ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-                if (signAlgs != null) {
-                    Collection<SignatureAndHashAlgorithm> peerSignAlgs =
-                                            signAlgs.getSignAlgorithms();
-                    if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
-                        throw new SSLHandshakeException(
-                            "No peer supported signature algorithms");
-                    }
-
-                    Collection<SignatureAndHashAlgorithm>
-                        supportedPeerSignAlgs =
-                            SignatureAndHashAlgorithm.getSupportedAlgorithms(
-                                algorithmConstraints, peerSignAlgs);
-                    if (supportedPeerSignAlgs.isEmpty()) {
-                        throw new SSLHandshakeException(
-                            "No signature and hash algorithm in common");
-                    }
-
-                    setPeerSupportedSignAlgs(supportedPeerSignAlgs);
-                } // else, need to use peer implicit supported signature algs
-            }
-
-            session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,
-                        getLocalSupportedSignAlgs(),
-                        sslContext.getSecureRandom(),
-                        getHostAddressSE(), getPortSE(),
-                        (requestedToUseEMS &&
-                                (protocolVersion.v >= ProtocolVersion.TLS10.v)),
-                        getEndpointIdentificationAlgorithmSE());
-
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (peerSupportedSignAlgs != null) {
-                    session.setPeerSupportedSignatureAlgorithms(
-                            peerSupportedSignAlgs);
-                }   // else, we will set the implicit peer supported signature
-                    // algorithms in chooseCipherSuite()
-            }
-
-            // set the server name indication in the session
-            List<SNIServerName> clientHelloSNI =
-                    Collections.<SNIServerName>emptyList();
-            if (clientHelloSNIExt != null) {
-                clientHelloSNI = clientHelloSNIExt.getServerNames();
-            }
-            session.setRequestedServerNames(clientHelloSNI);
-
-            // set the handshake session
-            setHandshakeSessionSE(session);
-
-            // choose cipher suite and corresponding private key
-            chooseCipherSuite(mesg);
-
-            session.setSuite(cipherSuite);
-            session.setLocalPrivateKey(privateKey);
-
-            // chooseCompression(mesg);
-        } else {
-            // set the handshake session
-            setHandshakeSessionSE(session);
-        }
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
-        }
-
-        m1.cipherSuite = cipherSuite;
-        m1.sessionId = session.getSessionId();
-        m1.compression_method = session.getCompression();
-
-        if (secureRenegotiation) {
-            // For ServerHellos that are initial handshakes, then the
-            // "renegotiated_connection" field in "renegotiation_info"
-            // extension is of zero length.
-            //
-            // For ServerHellos that are renegotiating, this field contains
-            // the concatenation of client_verify_data and server_verify_data.
-            //
-            // Note that for initial handshakes, both the clientVerifyData
-            // variable and serverVerifyData variable are of zero length.
-            HelloExtension serverHelloRI = new RenegotiationInfoExtension(
-                                        clientVerifyData, serverVerifyData);
-            m1.extensions.add(serverHelloRI);
-        }
-
-        if (!sniMatchers.isEmpty() && clientHelloSNIExt != null) {
-            // When resuming a session, the server MUST NOT include a
-            // server_name extension in the server hello.
-            if (!resumingSession) {
-                ServerNameExtension serverHelloSNI = new ServerNameExtension();
-                m1.extensions.add(serverHelloSNI);
-            }
-        }
-
-        if (session.getUseExtendedMasterSecret()) {
-            m1.extensions.add(new ExtendedMasterSecretExtension());
-        }
-
-        // 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());
-        }
-        m1.write(output);
-        handshakeState.update(m1, resumingSession);
-
-        //
-        // If we are resuming a session, we finish writing handshake
-        // messages right now and then finish.
-        //
-        if (resumingSession) {
-            calculateConnectionKeys(session.getMasterSecret());
-            sendChangeCipherAndFinish(false);
-            return;
-        }
-
-
-        /*
-         * SECOND, write the server Certificate(s) if we need to.
-         *
-         * NOTE:  while an "anonymous RSA" mode is explicitly allowed by
-         * the protocol, we can't support it since all of the SSL flavors
-         * defined in the protocol spec are explicitly stated to require
-         * using RSA certificates.
-         */
-        if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-            // Server certificates are omitted for Kerberos ciphers
-
-        } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
-            if (certs == null) {
-                throw new RuntimeException("no certificates");
-            }
-
-            CertificateMsg m2 = new CertificateMsg(certs);
-
-            /*
-             * Set local certs in the SSLSession, output
-             * debug info, and then actually write to the client.
-             */
-            session.setLocalCertificates(certs);
-            if (debug != null && Debug.isOn("handshake")) {
-                m2.print(System.out);
-            }
-            m2.write(output);
-            handshakeState.update(m2, resumingSession);
-
-            // XXX has some side effects with OS TCP buffering,
-            // leave it out for now
-
-            // let client verify chain in the meantime...
-            // output.flush();
-        } else {
-            if (certs != null) {
-                throw new RuntimeException("anonymous keyexchange with certs");
-            }
-        }
-
-        /*
-         * THIRD, the ServerKeyExchange message ... iff it's needed.
-         *
-         * It's usually needed unless there's an encryption-capable
-         * RSA cert, or a D-H cert.  The notable exception is that
-         * exportable ciphers used with big RSA keys need to downgrade
-         * to use short RSA keys, even when the key/cert encrypts OK.
-         */
-
-        ServerKeyExchange m3;
-        switch (keyExchange) {
-        case K_RSA:
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            // no server key exchange for RSA or KRB5 ciphersuites
-            m3 = null;
-            break;
-        case K_RSA_EXPORT:
-            if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
-                try {
-                    m3 = new RSA_ServerKeyExchange(
-                        tempPublicKey, privateKey,
-                        clnt_random, svr_random,
-                        sslContext.getSecureRandom());
-                    privateKey = tempPrivateKey;
-                } catch (GeneralSecurityException e) {
-                    throwSSLException
-                        ("Error generating RSA server key exchange", e);
-                    m3 = null; // make compiler happy
-                }
-            } else {
-                // RSA_EXPORT with short key, don't need ServerKeyExchange
-                m3 = null;
-            }
-            break;
-        case K_DHE_RSA:
-        case K_DHE_DSS:
-            try {
-                m3 = new DH_ServerKeyExchange(dh,
-                    privateKey,
-                    clnt_random.random_bytes,
-                    svr_random.random_bytes,
-                    sslContext.getSecureRandom(),
-                    preferableSignatureAlgorithm,
-                    protocolVersion);
-            } catch (GeneralSecurityException e) {
-                throwSSLException("Error generating DH server key exchange", e);
-                m3 = null; // make compiler happy
-            }
-            break;
-        case K_DH_ANON:
-            m3 = new DH_ServerKeyExchange(dh, protocolVersion);
-            break;
-        case K_ECDHE_RSA:
-        case K_ECDHE_ECDSA:
-        case K_ECDH_ANON:
-            try {
-                m3 = new ECDH_ServerKeyExchange(ecdh,
-                    privateKey,
-                    clnt_random.random_bytes,
-                    svr_random.random_bytes,
-                    sslContext.getSecureRandom(),
-                    preferableSignatureAlgorithm,
-                    protocolVersion);
-            } catch (GeneralSecurityException e) {
-                throwSSLException(
-                    "Error generating ECDH server key exchange", e);
-                m3 = null; // make compiler happy
-            }
-            break;
-        case K_ECDH_RSA:
-        case K_ECDH_ECDSA:
-            // ServerKeyExchange not used for fixed ECDH
-            m3 = null;
-            break;
-        default:
-            throw new RuntimeException("internal error: " + keyExchange);
-        }
-        if (m3 != null) {
-            if (debug != null && Debug.isOn("handshake")) {
-                m3.print(System.out);
-            }
-            m3.write(output);
-            handshakeState.update(m3, resumingSession);
-        }
-
-        //
-        // FOURTH, the CertificateRequest message.  The details of
-        // the message can be affected by the key exchange algorithm
-        // in use.  For example, certs with fixed Diffie-Hellman keys
-        // are only useful with the DH_DSS and DH_RSA key exchange
-        // algorithms.
-        //
-        // Needed only if server requires client to authenticate self.
-        // Illegal for anonymous flavors, so we need to check that.
-        //
-        // CertificateRequest is omitted for Kerberos ciphers
-        if (doClientAuth != SSLEngineImpl.clauth_none &&
-                keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON &&
-                keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) {
-
-            CertificateRequest m4;
-            X509Certificate caCerts[];
-
-            Collection<SignatureAndHashAlgorithm> localSignAlgs = null;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                // We currently use all local upported signature and hash
-                // algorithms. However, to minimize the computation cost
-                // of requested hash algorithms, we may use a restricted
-                // set of signature algorithms in the future.
-                localSignAlgs = getLocalSupportedSignAlgs();
-                if (localSignAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-                }
-
-                Set<String> localHashAlgs =
-                    SignatureAndHashAlgorithm.getHashAlgorithmNames(
-                        localSignAlgs);
-                if (localHashAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-                }
-            }
-
-            caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();
-            m4 = new CertificateRequest(caCerts, keyExchange,
-                                            localSignAlgs, protocolVersion);
-
-            if (debug != null && Debug.isOn("handshake")) {
-                m4.print(System.out);
-            }
-            m4.write(output);
-            handshakeState.update(m4, resumingSession);
-        }
-
-        /*
-         * FIFTH, say ServerHelloDone.
-         */
-        ServerHelloDone m5 = new ServerHelloDone();
-
-        if (debug != null && Debug.isOn("handshake")) {
-            m5.print(System.out);
-        }
-        m5.write(output);
-        handshakeState.update(m5, resumingSession);
-
-        /*
-         * Flush any buffered messages so the client will see them.
-         * Ideally, all the messages above go in a single network level
-         * message to the client.  Without big Certificate chains, it's
-         * going to be the common case.
-         */
-        output.flush();
-    }
-
-    /*
-     * Choose cipher suite from among those supported by client. Sets
-     * the cipherSuite and keyExchange variables.
-     */
-    private void chooseCipherSuite(ClientHello mesg) throws IOException {
-        CipherSuiteList prefered;
-        CipherSuiteList proposed;
-        if (preferLocalCipherSuites) {
-            prefered = getActiveCipherSuites();
-            proposed = mesg.getCipherSuites();
-        } else {
-            prefered = mesg.getCipherSuites();
-            proposed = getActiveCipherSuites();
-        }
-
-        List<CipherSuite> legacySuites = new ArrayList<>();
-        for (CipherSuite suite : prefered.collection()) {
-            if (isNegotiable(proposed, suite) == false) {
-                continue;
-            }
-
-            if (doClientAuth == SSLEngineImpl.clauth_required) {
-                if ((suite.keyExchange == K_DH_ANON) ||
-                    (suite.keyExchange == K_ECDH_ANON)) {
-                    continue;
-                }
-            }
-
-            if (!legacyAlgorithmConstraints.permits(null, suite.name, null)) {
-                legacySuites.add(suite);
-                continue;
-            }
-
-            if (trySetCipherSuite(suite) == false) {
-                continue;
-            }
-
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("Standard ciphersuite chosen: " + suite);
-            }
-            return;
-        }
-
-        for (CipherSuite suite : legacySuites) {
-            if (trySetCipherSuite(suite)) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("Legacy ciphersuite chosen: " + suite);
-                }
-                return;
-            }
-        }
-
-        fatalSE(Alerts.alert_handshake_failure, "no cipher suites in common");
-    }
-
-    /**
-     * Set the given CipherSuite, if possible. Return the result.
-     * The call succeeds if the CipherSuite is available and we have
-     * the necessary certificates to complete the handshake. We don't
-     * check if the CipherSuite is actually enabled.
-     *
-     * If successful, this method also generates ephemeral keys if
-     * required for this ciphersuite. This may take some time, so this
-     * method should only be called if you really want to use the
-     * CipherSuite.
-     *
-     * This method is called from chooseCipherSuite() in this class.
-     */
-    boolean trySetCipherSuite(CipherSuite suite) {
-        /*
-         * If we're resuming a session we know we can
-         * support this key exchange algorithm and in fact
-         * have already cached the result of it in
-         * the session state.
-         */
-        if (resumingSession) {
-            return true;
-        }
-
-        if (suite.isNegotiable() == false) {
-            return false;
-        }
-
-        // must not negotiate the obsoleted weak cipher suites.
-        if (protocolVersion.v >= suite.obsoleted) {
-            return false;
-        }
-
-        // must not negotiate unsupported cipher suites.
-        if (protocolVersion.v < suite.supported) {
-            return false;
-        }
-
-        KeyExchange keyExchange = suite.keyExchange;
-
-        // null out any existing references
-        privateKey = null;
-        certs = null;
-        dh = null;
-        tempPrivateKey = null;
-        tempPublicKey = null;
-
-        Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            if (peerSupportedSignAlgs != null) {
-                supportedSignAlgs = peerSupportedSignAlgs;
-            } else {
-                SignatureAndHashAlgorithm algorithm = null;
-
-                // we may optimize the performance
-                switch (keyExchange) {
-                    // If the negotiated key exchange algorithm is one of
-                    // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA),
-                    // behave as if client had sent the value {sha1,rsa}.
-                    case K_RSA:
-                    case K_DHE_RSA:
-                    case K_DH_RSA:
-                    // case K_RSA_PSK:
-                    case K_ECDH_RSA:
-                    case K_ECDHE_RSA:
-                        algorithm = SignatureAndHashAlgorithm.valueOf(
-                                HashAlgorithm.SHA1.value,
-                                SignatureAlgorithm.RSA.value, 0);
-                        break;
-                    // If the negotiated key exchange algorithm is one of
-                    // (DHE_DSS, DH_DSS), behave as if the client had
-                    // sent the value {sha1,dsa}.
-                    case K_DHE_DSS:
-                    case K_DH_DSS:
-                        algorithm = SignatureAndHashAlgorithm.valueOf(
-                                HashAlgorithm.SHA1.value,
-                                SignatureAlgorithm.DSA.value, 0);
-                        break;
-                    // If the negotiated key exchange algorithm is one of
-                    // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client
-                    // had sent value {sha1,ecdsa}.
-                    case K_ECDH_ECDSA:
-                    case K_ECDHE_ECDSA:
-                        algorithm = SignatureAndHashAlgorithm.valueOf(
-                                HashAlgorithm.SHA1.value,
-                                SignatureAlgorithm.ECDSA.value, 0);
-                        break;
-                    default:
-                        // no peer supported signature algorithms
-                }
-
-                if (algorithm == null) {
-                    supportedSignAlgs =
-                        Collections.<SignatureAndHashAlgorithm>emptySet();
-                } else {
-                    supportedSignAlgs =
-                        new ArrayList<SignatureAndHashAlgorithm>(1);
-                    supportedSignAlgs.add(algorithm);
-
-                    supportedSignAlgs =
-                            SignatureAndHashAlgorithm.getSupportedAlgorithms(
-                                algorithmConstraints, supportedSignAlgs);
-
-                    // May be no default activated signature algorithm, but
-                    // let the following process make the final decision.
-                }
-
-                // Sets the peer supported signature algorithm to use in KM
-                // temporarily.
-                session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);
-            }
-        }
-
-        switch (keyExchange) {
-        case K_RSA:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-            break;
-        case K_RSA_EXPORT:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-
-            try {
-               if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
-                    if (!setupEphemeralRSAKeys(suite.exportable)) {
-                        return false;
-                    }
-               }
-            } catch (RuntimeException e) {
-                // could not determine keylength, ignore key
-                return false;
-            }
-            break;
-        case K_DHE_RSA:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                        supportedSignAlgs, "RSA", privateKey);
-                if (preferableSignatureAlgorithm == null) {
-                    if ((debug != null) && Debug.isOn("handshake")) {
-                        System.out.println(
-                                "No signature and hash algorithm for cipher " +
-                                suite);
-                    }
-                    return false;
-                }
-            }
-
-            setupEphemeralDHKeys(suite.exportable, privateKey);
-            break;
-        case K_ECDHE_RSA:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                        supportedSignAlgs, "RSA", privateKey);
-                if (preferableSignatureAlgorithm == null) {
-                    if ((debug != null) && Debug.isOn("handshake")) {
-                        System.out.println(
-                                "No signature and hash algorithm for cipher " +
-                                suite);
-                    }
-                    return false;
-                }
-            }
-
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
-            break;
-        case K_DHE_DSS:
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                                supportedSignAlgs, "DSA");
-                if (preferableSignatureAlgorithm == null) {
-                    if ((debug != null) && Debug.isOn("handshake")) {
-                        System.out.println(
-                                "No signature and hash algorithm for cipher " +
-                                suite);
-                    }
-                    return false;
-                }
-            }
-
-            // need DSS certs for authentication
-            if (setupPrivateKeyAndChain("DSA") == false) {
-                return false;
-            }
-
-            setupEphemeralDHKeys(suite.exportable, privateKey);
-            break;
-        case K_ECDHE_ECDSA:
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                            supportedSignAlgs, "ECDSA");
-                if (preferableSignatureAlgorithm == null) {
-                    if ((debug != null) && Debug.isOn("handshake")) {
-                        System.out.println(
-                                "No signature and hash algorithm for cipher " +
-                                suite);
-                    }
-                    return false;
-                }
-            }
-
-            // need EC cert
-            if (setupPrivateKeyAndChain("EC") == false) {
-                return false;
-            }
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
-            break;
-        case K_ECDH_RSA:
-            // need EC cert
-            if (setupPrivateKeyAndChain("EC") == false) {
-                return false;
-            }
-            setupStaticECDHKeys();
-            break;
-        case K_ECDH_ECDSA:
-            // need EC cert
-            if (setupPrivateKeyAndChain("EC") == false) {
-                return false;
-            }
-            setupStaticECDHKeys();
-            break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            // need Kerberos Key
-            if (!setupKerberosKeys()) {
-                return false;
-            }
-            break;
-        case K_DH_ANON:
-            // no certs needed for anonymous
-            setupEphemeralDHKeys(suite.exportable, null);
-            break;
-        case K_ECDH_ANON:
-            // no certs needed for anonymous
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
-            break;
-        default:
-            // internal error, unknown key exchange
-            throw new RuntimeException(
-                    "Unrecognized cipherSuite: " + suite);
-        }
-        setCipherSuite(suite);
-
-        // set the peer implicit supported signature algorithms
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            if (peerSupportedSignAlgs == null) {
-                setPeerSupportedSignAlgs(supportedSignAlgs);
-                // we had alreay update the session
-            }
-        }
-        return true;
-    }
-
-    /*
-     * Get some "ephemeral" RSA keys for this context. This means
-     * generating them if it's not already been done.
-     *
-     * Note that we currently do not implement any ciphersuites that use
-     * strong ephemeral RSA. (We do not support the EXPORT1024 ciphersuites
-     * and standard RSA ciphersuites prohibit ephemeral mode for some reason)
-     * This means that export is always true and 512 bit keys are generated.
-     */
-    private boolean setupEphemeralRSAKeys(boolean export) {
-        KeyPair kp = sslContext.getEphemeralKeyManager().
-                        getRSAKeyPair(export, sslContext.getSecureRandom());
-        if (kp == null) {
-            return false;
-        } else {
-            tempPublicKey = kp.getPublic();
-            tempPrivateKey = kp.getPrivate();
-            return true;
-        }
-    }
-
-    /*
-     * Acquire some "ephemeral" Diffie-Hellman  keys for this handshake.
-     * We don't reuse these, for improved forward secrecy.
-     */
-    private void setupEphemeralDHKeys(boolean export, Key key) {
-        /*
-         * 768 bits ephemeral DH private keys were used to be used in
-         * ServerKeyExchange except that exportable ciphers max out at 512
-         * bits modulus values. We still adhere to this behavior in legacy
-         * mode (system property "jdk.tls.ephemeralDHKeySize" is defined
-         * as "legacy").
-         *
-         * Old JDK (JDK 7 and previous) releases don't support DH keys bigger
-         * than 1024 bits. We have to consider the compatibility requirement.
-         * 1024 bits DH key is always used for non-exportable cipher suites
-         * in default mode (system property "jdk.tls.ephemeralDHKeySize"
-         * is not defined).
-         *
-         * However, if applications want more stronger strength, setting
-         * system property "jdk.tls.ephemeralDHKeySize" to "matched"
-         * is a workaround to use ephemeral DH key which size matches the
-         * corresponding authentication key. For example, if the public key
-         * size of an authentication certificate is 2048 bits, then the
-         * ephemeral DH key size should be 2048 bits accordingly unless
-         * the cipher suite is exportable.  This key sizing scheme keeps
-         * the cryptographic strength consistent between authentication
-         * keys and key-exchange keys.
-         *
-         * Applications may also want to customize the ephemeral DH key size
-         * to a fixed length for non-exportable cipher suites. This can be
-         * approached by setting system property "jdk.tls.ephemeralDHKeySize"
-         * to a valid positive integer between 1024 and 8192 bits, inclusive.
-         *
-         * Note that the minimum acceptable key size is 1024 bits except
-         * exportable cipher suites or legacy mode.
-         *
-         * Note that per RFC 2246, the key size limit of DH is 512 bits for
-         * exportable cipher suites.  Because of the weakness, exportable
-         * cipher suites are deprecated since TLS v1.1 and they are not
-         * enabled by default in Oracle provider. The legacy behavior is
-         * reserved and 512 bits DH key is always used for exportable
-         * cipher suites.
-         */
-        int keySize = export ? 512 : 1024;           // default mode
-        if (!export) {
-            if (useLegacyEphemeralDHKeys) {          // legacy mode
-                keySize = 768;
-            } else if (useSmartEphemeralDHKeys) {    // matched mode
-                if (key != null) {
-                    int ks = KeyUtil.getKeySize(key);
-
-                    // DH parameter generation can be extremely slow, make
-                    // sure to use one of the supported pre-computed DH
-                    // parameters (see DHCrypt class).
-                    //
-                    // Old deployed applications may not be ready to support
-                    // DH key sizes bigger than 2048 bits.  Please DON'T use
-                    // value other than 1024 and 2048 at present.  May improve
-                    // the underlying providers and key size limit in the
-                    // future when the compatibility and interoperability
-                    // impact is limited.
-                    //
-                    // keySize = ks <= 1024 ? 1024 : (ks >= 2048 ? 2048 : ks);
-                    keySize = ks <= 1024 ? 1024 : 2048;
-                } // Otherwise, anonymous cipher suites, 1024-bit is used.
-            } else if (customizedDHKeySize > 0) {    // customized mode
-                keySize = customizedDHKeySize;
-            }
-        }
-
-        dh = new DHCrypt(keySize, sslContext.getSecureRandom());
-    }
-
-    // Setup the ephemeral ECDH parameters.
-    // If we cannot continue because we do not support any of the curves that
-    // the client requested, return false. Otherwise (all is well), return true.
-    private boolean setupEphemeralECDHKeys() {
-        int index = (requestedCurves != null) ?
-                requestedCurves.getPreferredCurve(algorithmConstraints) :
-                EllipticCurvesExtension.getActiveCurves(algorithmConstraints);
-        if (index < 0) {
-            // no match found, cannot use this ciphersuite
-            return false;
-        }
-
-        ecdh = new ECDHCrypt(index, sslContext.getSecureRandom());
-        return true;
-    }
-
-    private void setupStaticECDHKeys() {
-        // don't need to check whether the curve is supported, already done
-        // in setupPrivateKeyAndChain().
-        ecdh = new ECDHCrypt(privateKey, certs[0].getPublicKey());
-    }
-
-    /**
-     * Retrieve the server key and certificate for the specified algorithm
-     * from the KeyManager and set the instance variables.
-     *
-     * @return true if successful, false if not available or invalid
-     */
-    private boolean setupPrivateKeyAndChain(String algorithm) {
-        X509ExtendedKeyManager km = sslContext.getX509KeyManager();
-        String alias;
-        if (conn != null) {
-            alias = km.chooseServerAlias(algorithm, null, conn);
-        } else {
-            alias = km.chooseEngineServerAlias(algorithm, null, engine);
-        }
-        if (alias == null) {
-            return false;
-        }
-        PrivateKey tempPrivateKey = km.getPrivateKey(alias);
-        if (tempPrivateKey == null) {
-            return false;
-        }
-        X509Certificate[] tempCerts = km.getCertificateChain(alias);
-        if ((tempCerts == null) || (tempCerts.length == 0)) {
-            return false;
-        }
-        String keyAlgorithm = algorithm.split("_")[0];
-        PublicKey publicKey = tempCerts[0].getPublicKey();
-        if ((tempPrivateKey.getAlgorithm().equals(keyAlgorithm) == false)
-                || (publicKey.getAlgorithm().equals(keyAlgorithm) == false)) {
-            return false;
-        }
-        // For ECC certs, check whether we support the EC domain parameters.
-        // If the client sent a SupportedEllipticCurves ClientHello extension,
-        // check against that too.
-        if (keyAlgorithm.equals("EC")) {
-            if (publicKey instanceof ECPublicKey == false) {
-                return false;
-            }
-            ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
-            int id = EllipticCurvesExtension.getCurveIndex(params);
-            if ((id <= 0) || !EllipticCurvesExtension.isSupported(id) ||
-                ((requestedCurves != null) && !requestedCurves.contains(id))) {
-                return false;
-            }
-        }
-        this.privateKey = tempPrivateKey;
-        this.certs = tempCerts;
-        return true;
-    }
-
-    /**
-     * Retrieve the Kerberos key for the specified server principal
-     * from the JAAS configuration file.
-     *
-     * @return true if successful, false if not available or invalid
-     */
-    private boolean setupKerberosKeys() {
-        if (serviceCreds != null) {
-            return true;
-        }
-        try {
-            final AccessControlContext acc = getAccSE();
-            serviceCreds = AccessController.doPrivileged(
-                // Eliminate dependency on KerberosKey
-                new PrivilegedExceptionAction<Object>() {
-                @Override
-                public Object run() throws Exception {
-                    // get kerberos key for the default principal
-                    return Krb5Helper.getServiceCreds(acc);
-                        }});
-
-            // check permission to access and use the secret key of the
-            // Kerberized "host" service
-            if (serviceCreds != null) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("Using Kerberos creds");
-                }
-                String serverPrincipal =
-                        Krb5Helper.getServerPrincipalName(serviceCreds);
-                if (serverPrincipal != null) {
-                    // When service is bound, we check ASAP. Otherwise,
-                    // will check after client request is received
-                    // in in Kerberos ClientKeyExchange
-                    SecurityManager sm = System.getSecurityManager();
-                    try {
-                        if (sm != null) {
-                            // Eliminate dependency on ServicePermission
-                            sm.checkPermission(Krb5Helper.getServicePermission(
-                                    serverPrincipal, "accept"), acc);
-                        }
-                    } catch (SecurityException se) {
-                        serviceCreds = null;
-                        // Do not destroy keys. Will affect Subject
-                        if (debug != null && Debug.isOn("handshake")) {
-                            System.out.println("Permission to access Kerberos"
-                                    + " secret key denied");
-                        }
-                        return false;
-                    }
-                }
-            }
-            return serviceCreds != null;
-        } catch (PrivilegedActionException e) {
-            // Likely exception here is LoginExceptin
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("Attempt to obtain Kerberos key failed: "
-                                + e.toString());
-            }
-            return false;
-        }
-    }
-
-    /*
-     * For Kerberos ciphers, the premaster secret is encrypted using
-     * the session key. See RFC 2712.
-     */
-    private SecretKey clientKeyExchange(KerberosClientKeyExchange mesg)
-        throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        // Record the principals involved in exchange
-        session.setPeerPrincipal(mesg.getPeerPrincipal());
-        session.setLocalPrincipal(mesg.getLocalPrincipal());
-
-        byte[] b = mesg.getUnencryptedPreMasterSecret();
-        return new SecretKeySpec(b, "TlsPremasterSecret");
-    }
-
-    /*
-     * Diffie Hellman key exchange is used when the server presented
-     * D-H parameters in its certificate (signed using RSA or DSS/DSA),
-     * or else the server presented no certificate but sent D-H params
-     * in a ServerKeyExchange message.  Use of D-H is specified by the
-     * cipher suite chosen.
-     *
-     * The message optionally contains the client's D-H public key (if
-     * it wasn't not sent in a client certificate).  As always with D-H,
-     * if a client and a server have each other's D-H public keys and
-     * they use common algorithm parameters, they have a shared key
-     * that's derived via the D-H calculation.  That key becomes the
-     * pre-master secret.
-     */
-    private SecretKey clientKeyExchange(DHClientKeyExchange mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        BigInteger publicKeyValue = mesg.getClientPublicKey();
-
-        // check algorithm constraints
-        dh.checkConstraints(algorithmConstraints, publicKeyValue);
-
-        return dh.getAgreedSecret(publicKeyValue, false);
-    }
-
-    private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        byte[] publicPoint = mesg.getEncodedPoint();
-
-        // check algorithm constraints
-        ecdh.checkConstraints(algorithmConstraints, publicPoint);
-
-        return ecdh.getAgreedSecret(publicPoint);
-    }
-
-    /*
-     * Client wrote a message to verify the certificate it sent earlier.
-     *
-     * Note that this certificate isn't involved in key exchange.  Client
-     * authentication messages are included in the checksums used to
-     * validate the handshake (e.g. Finished messages).  Other than that,
-     * the _exact_ identity of the client is less fundamental to protocol
-     * security than its role in selecting keys via the pre-master secret.
-     */
-    private void clientCertificateVerify(CertificateVerify mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            SignatureAndHashAlgorithm signAlg =
-                mesg.getPreferableSignatureAlgorithm();
-            if (signAlg == null) {
-                throw new SSLHandshakeException(
-                        "Illegal CertificateVerify message");
-            }
-
-            String hashAlg =
-                SignatureAndHashAlgorithm.getHashAlgorithmName(signAlg);
-            if (hashAlg == null || hashAlg.length() == 0) {
-                throw new SSLHandshakeException(
-                        "No supported hash algorithm");
-            }
-        }
-
-        try {
-            PublicKey publicKey =
-                session.getPeerCertificates()[0].getPublicKey();
-
-            boolean valid = mesg.verify(protocolVersion, handshakeHash,
-                                        publicKey, session.getMasterSecret());
-            if (valid == false) {
-                fatalSE(Alerts.alert_bad_certificate,
-                            "certificate verify message signature error");
-            }
-        } catch (GeneralSecurityException e) {
-            fatalSE(Alerts.alert_bad_certificate,
-                "certificate verify format error", e);
-        }
-
-        // reset the flag for clientCertificateVerify message
-        needClientVerify = false;
-    }
-
-
-    /*
-     * Client writes "finished" at the end of its handshake, after cipher
-     * spec is changed.   We verify it and then send ours.
-     *
-     * When we're resuming a session, we'll have already sent our own
-     * Finished message so just the verification is needed.
-     */
-    private void clientFinished(Finished mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        /*
-         * Verify if client did send the certificate when client
-         * authentication was required, otherwise server should not proceed
-         */
-        if (doClientAuth == SSLEngineImpl.clauth_required) {
-           // get X500Principal of the end-entity certificate for X509-based
-           // ciphersuites, or Kerberos principal for Kerberos ciphersuites
-           session.getPeerPrincipal();
-        }
-
-        /*
-         * Verify if client did send clientCertificateVerify message following
-         * the client Certificate, otherwise server should not proceed
-         */
-        if (needClientVerify) {
-                fatalSE(Alerts.alert_handshake_failure,
-                        "client did not send certificate verify message");
-        }
-
-        /*
-         * Verify the client's message with the "before" digest of messages,
-         * and forget about continuing to use that digest.
-         */
-        boolean verified = mesg.verify(handshakeHash, Finished.CLIENT,
-            session.getMasterSecret());
-
-        if (!verified) {
-            fatalSE(Alerts.alert_handshake_failure,
-                        "client 'finished' message doesn't verify");
-            // NOTREACHED
-        }
-
-        /*
-         * save client verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            clientVerifyData = mesg.getVerifyData();
-        }
-
-        /*
-         * OK, it verified.  If we're doing the full handshake, add that
-         * "Finished" message to the hash of handshake messages, then send
-         * the change_cipher_spec and Finished message.
-         */
-        if (!resumingSession) {
-            input.digestNow();
-            sendChangeCipherAndFinish(true);
-        } else {
-            handshakeFinished = true;
-        }
-
-        /*
-         * Update the session cache only after the handshake completed, else
-         * we're open to an attack against a partially completed handshake.
-         */
-        session.setLastAccessedTime(System.currentTimeMillis());
-        if (!resumingSession && session.isRejoinable()) {
-            ((SSLSessionContextImpl)sslContext.engineGetServerSessionContext())
-                .put(session);
-            if (debug != null && Debug.isOn("session")) {
-                System.out.println(
-                    "%% Cached server session: " + session);
-            }
-        } else if (!resumingSession &&
-                debug != null && Debug.isOn("session")) {
-            System.out.println(
-                "%% Didn't cache non-resumable server session: "
-                + session);
-        }
-    }
-
-    /*
-     * Compute finished message with the "server" digest (and then forget
-     * about that digest, it can't be used again).
-     */
-    private void sendChangeCipherAndFinish(boolean finishedTag)
-            throws IOException {
-
-        output.flush();
-
-        Finished mesg = new Finished(protocolVersion, handshakeHash,
-            Finished.SERVER, session.getMasterSecret(), cipherSuite);
-
-        /*
-         * Send the change_cipher_spec record; then our Finished handshake
-         * message will be the last handshake message.  Flush, and now we
-         * are ready for application data!!
-         */
-        sendChangeCipherSpec(mesg, finishedTag);
-
-        /*
-         * save server verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            serverVerifyData = mesg.getVerifyData();
-        }
-    }
-
-
-    /*
-     * Returns a HelloRequest message to kickstart renegotiations
-     */
-    @Override
-    HandshakeMessage getKickstartMessage() {
-        return new HelloRequest();
-    }
-
-
-    /*
-     * Fault detected during handshake.
-     */
-    @Override
-    void handshakeAlert(byte description) throws SSLProtocolException {
-
-        String message = Alerts.alertDescription(description);
-
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("SSL -- handshake alert:  "
-                + message);
-        }
-
-        /*
-         * It's ok to get a no_certificate alert from a client of which
-         * we *requested* authentication information.
-         * However, if we *required* it, then this is not acceptable.
-         *
-         * Anyone calling getPeerCertificates() on the
-         * session will get an SSLPeerUnverifiedException.
-         */
-        if ((description == Alerts.alert_no_certificate) &&
-                (doClientAuth == SSLEngineImpl.clauth_requested)) {
-            return;
-        }
-
-        throw new SSLProtocolException("handshake alert: " + message);
-    }
-
-    /*
-     * RSA key exchange is normally used.  The client encrypts a "pre-master
-     * secret" with the server's public key, from the Certificate (or else
-     * ServerKeyExchange) message that was sent to it by the server.  That's
-     * decrypted using the private key before we get here.
-     */
-    private SecretKey clientKeyExchange(RSAClientKeyExchange mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        return mesg.preMaster;
-    }
-
-    /*
-     * Verify the certificate sent by the client. We'll only get one if we
-     * sent a CertificateRequest to request client authentication. If we
-     * are in TLS mode, the client may send a message with no certificates
-     * to indicate it does not have an appropriate chain. (In SSLv3 mode,
-     * it would send a no certificate alert).
-     */
-    private void clientCertificate(CertificateMsg mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        X509Certificate[] peerCerts = mesg.getCertificateChain();
-
-        if (peerCerts.length == 0) {
-            /*
-             * If the client authentication is only *REQUESTED* (e.g.
-             * not *REQUIRED*, this is an acceptable condition.)
-             */
-            if (doClientAuth == SSLEngineImpl.clauth_requested) {
-                return;
-            } else {
-                fatalSE(Alerts.alert_bad_certificate,
-                    "null cert chain");
-            }
-        }
-
-        // ask the trust manager to verify the chain
-        X509TrustManager tm = sslContext.getX509TrustManager();
-
-        try {
-            // find out the types of client authentication used
-            PublicKey key = peerCerts[0].getPublicKey();
-            String keyAlgorithm = key.getAlgorithm();
-            String authType;
-            if (keyAlgorithm.equals("RSA")) {
-                authType = "RSA";
-            } else if (keyAlgorithm.equals("DSA")) {
-                authType = "DSA";
-            } else if (keyAlgorithm.equals("EC")) {
-                authType = "EC";
-            } else {
-                // unknown public key type
-                authType = "UNKNOWN";
-            }
-
-            if (tm instanceof X509ExtendedTrustManager) {
-                if (conn != null) {
-                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
-                        peerCerts.clone(),
-                        authType,
-                        conn);
-                } else {
-                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
-                        peerCerts.clone(),
-                        authType,
-                        engine);
-                }
-            } else {
-                // Unlikely to happen, because we have wrapped the old
-                // X509TrustManager with the new X509ExtendedTrustManager.
-                throw new CertificateException(
-                    "Improper X509TrustManager implementation");
-            }
-        } catch (CertificateException e) {
-            // This will throw an exception, so include the original error.
-            fatalSE(Alerts.alert_certificate_unknown, e);
-        }
-        // set the flag for clientCertificateVerify message
-        needClientVerify = true;
-
-        session.setPeerCertificates(peerCerts);
-    }
-}
--- a/src/share/classes/sun/security/ssl/ServerNameExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,283 +0,0 @@
-/*
- * Copyright (c) 2006, 2012, 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.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.net.ssl.SNIHostName;
-import javax.net.ssl.SNIMatcher;
-import javax.net.ssl.SNIServerName;
-import javax.net.ssl.SSLProtocolException;
-import javax.net.ssl.StandardConstants;
-
-/*
- * [RFC 4366/6066] To facilitate secure connections to servers that host
- * multiple 'virtual' servers at a single underlying network address, clients
- * MAY include an extension of type "server_name" in the (extended) client
- * hello.  The "extension_data" field of this extension SHALL contain
- * "ServerNameList" where:
- *
- *     struct {
- *         NameType name_type;
- *         select (name_type) {
- *             case host_name: HostName;
- *         } name;
- *     } ServerName;
- *
- *     enum {
- *         host_name(0), (255)
- *     } NameType;
- *
- *     opaque HostName<1..2^16-1>;
- *
- *     struct {
- *         ServerName server_name_list<1..2^16-1>
- *     } ServerNameList;
- */
-final class ServerNameExtension extends HelloExtension {
-
-    // For backward compatibility, all future data structures associated with
-    // new NameTypes MUST begin with a 16-bit length field.
-    final static int NAME_HEADER_LENGTH = 3;    // NameType: 1 byte
-                                                // Name length: 2 bytes
-    private Map<Integer, SNIServerName> sniMap;
-    private int listLength;     // ServerNameList length
-
-    // constructor for ServerHello
-    ServerNameExtension() throws IOException {
-        super(ExtensionType.EXT_SERVER_NAME);
-
-        listLength = 0;
-        sniMap = Collections.<Integer, SNIServerName>emptyMap();
-    }
-
-    // constructor for ClientHello
-    ServerNameExtension(List<SNIServerName> serverNames)
-            throws IOException {
-        super(ExtensionType.EXT_SERVER_NAME);
-
-        listLength = 0;
-        sniMap = new LinkedHashMap<>();
-        for (SNIServerName serverName : serverNames) {
-            // check for duplicated server name type
-            if (sniMap.put(serverName.getType(), serverName) != null) {
-                // unlikely to happen, but in case ...
-                throw new RuntimeException(
-                    "Duplicated server name of type " + serverName.getType());
-            }
-
-            listLength += serverName.getEncoded().length + NAME_HEADER_LENGTH;
-        }
-
-        // This constructor is used for ClientHello only.  Empty list is
-        // not allowed in client mode.
-        if (listLength == 0) {
-            throw new RuntimeException("The ServerNameList cannot be empty");
-        }
-    }
-
-    // constructor for ServerHello for parsing SNI extension
-    ServerNameExtension(HandshakeInStream s, int len)
-            throws IOException {
-        super(ExtensionType.EXT_SERVER_NAME);
-
-        int remains = len;
-        if (len >= 2) {    // "server_name" extension in ClientHello
-            listLength = s.getInt16();     // ServerNameList length
-            if (listLength == 0 || listLength + 2 != len) {
-                throw new SSLProtocolException(
-                        "Invalid " + type + " extension");
-            }
-
-            remains -= 2;
-            sniMap = new LinkedHashMap<>();
-            while (remains > 0) {
-                int code = s.getInt8();       // NameType
-
-                // HostName (length read in getBytes16);
-                byte[] encoded = s.getBytes16();
-                SNIServerName serverName;
-                switch (code) {
-                    case StandardConstants.SNI_HOST_NAME:
-                        if (encoded.length == 0) {
-                            throw new SSLProtocolException(
-                                "Empty HostName in server name indication");
-                        }
-                        try {
-                            serverName = new SNIHostName(encoded);
-                        } catch (IllegalArgumentException iae) {
-                            SSLProtocolException spe = new SSLProtocolException(
-                                "Illegal server name, type=host_name(" +
-                                code + "), name=" +
-                                (new String(encoded, StandardCharsets.UTF_8)) +
-                                ", value=" + Debug.toString(encoded));
-                            spe.initCause(iae);
-                            throw spe;
-                        }
-                        break;
-                    default:
-                        try {
-                            serverName = new UnknownServerName(code, encoded);
-                        } catch (IllegalArgumentException iae) {
-                            SSLProtocolException spe = new SSLProtocolException(
-                                "Illegal server name, type=(" + code +
-                                "), value=" + Debug.toString(encoded));
-                            spe.initCause(iae);
-                            throw spe;
-                        }
-                }
-                // check for duplicated server name type
-                if (sniMap.put(serverName.getType(), serverName) != null) {
-                    throw new SSLProtocolException(
-                            "Duplicated server name of type " +
-                            serverName.getType());
-                }
-
-                remains -= encoded.length + NAME_HEADER_LENGTH;
-            }
-        } else if (len == 0) {     // "server_name" extension in ServerHello
-            listLength = 0;
-            sniMap = Collections.<Integer, SNIServerName>emptyMap();
-        }
-
-        if (remains != 0) {
-            throw new SSLProtocolException("Invalid server_name extension");
-        }
-    }
-
-    List<SNIServerName> getServerNames() {
-        if (sniMap != null && !sniMap.isEmpty()) {
-            return Collections.<SNIServerName>unmodifiableList(
-                                        new ArrayList<>(sniMap.values()));
-        }
-
-        return Collections.<SNIServerName>emptyList();
-    }
-
-    /*
-     * Is the extension recognized by the corresponding matcher?
-     *
-     * This method is used to check whether the server name indication can
-     * be recognized by the server name matchers.
-     *
-     * Per RFC 6066, if the server understood the ClientHello extension but
-     * does not recognize the server name, the server SHOULD take one of two
-     * actions: either abort the handshake by sending a fatal-level
-     * unrecognized_name(112) alert or continue the handshake.
-     *
-     * If there is an instance of SNIMatcher defined for a particular name
-     * type, it must be used to perform match operations on the server name.
-     */
-    boolean isMatched(Collection<SNIMatcher> matchers) {
-        if (sniMap != null && !sniMap.isEmpty()) {
-            for (SNIMatcher matcher : matchers) {
-                SNIServerName sniName = sniMap.get(matcher.getType());
-                if (sniName != null && (!matcher.matches(sniName))) {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    /*
-     * Is the extension is identical to a server name list?
-     *
-     * This method is used to check the server name indication during session
-     * resumption.
-     *
-     * Per RFC 6066, when the server is deciding whether or not to accept a
-     * request to resume a session, the contents of a server_name extension
-     * MAY be used in the lookup of the session in the session cache.  The
-     * client SHOULD include the same server_name extension in the session
-     * resumption request as it did in the full handshake that established
-     * the session.  A server that implements this extension MUST NOT accept
-     * the request to resume the session if the server_name extension contains
-     * a different name.  Instead, it proceeds with a full handshake to
-     * establish a new session.  When resuming a session, the server MUST NOT
-     * include a server_name extension in the server hello.
-     */
-    boolean isIdentical(List<SNIServerName> other) {
-        if (other.size() == sniMap.size()) {
-            for(SNIServerName sniInOther : other) {
-                SNIServerName sniName = sniMap.get(sniInOther.getType());
-                if (sniName == null || !sniInOther.equals(sniName)) {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    int length() {
-        return listLength == 0 ? 4 : 6 + listLength;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        if (listLength == 0) {
-            s.putInt16(listLength);     // in ServerHello, empty extension_data
-        } else {
-            s.putInt16(listLength + 2); // length of extension_data
-            s.putInt16(listLength);     // length of ServerNameList
-
-            for (SNIServerName sniName : sniMap.values()) {
-                s.putInt8(sniName.getType());         // server name type
-                s.putBytes16(sniName.getEncoded());   // server name value
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-        for (SNIServerName sniName : sniMap.values()) {
-            buffer.append("[" + sniName + "]");
-        }
-
-        return "Extension " + type + ", server_name: " + buffer;
-    }
-
-    private static class UnknownServerName extends SNIServerName {
-        UnknownServerName(int code, byte[] encoded) {
-            super(code, encoded);
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/SessionId.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, 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.security.SecureRandom;
-import java.util.Arrays;
-import javax.net.ssl.SSLProtocolException;
-
-/**
- * Encapsulates an SSL session ID.  SSL Session IDs are not reused by
- * servers during the lifetime of any sessions it created.  Sessions may
- * be used by many connections, either concurrently (for example, two
- * connections to a web server at the same time) or sequentially (over as
- * long a time period as is allowed by a given server).
- *
- * @author Satish Dharmaraj
- * @author David Brownell
- */
-final
-class SessionId
-{
-    static int MAX_LENGTH = 32;
-    private byte sessionId [];          // max 32 bytes
-
-    /** Constructs a new session ID ... perhaps for a rejoinable session */
-    SessionId (boolean isRejoinable, SecureRandom generator)
-    {
-        if (isRejoinable)
-            // this will be unique, it's a timestamp plus much randomness
-            sessionId = new RandomCookie (generator).random_bytes;
-        else
-            sessionId = new byte [0];
-    }
-
-    /** Constructs a session ID from a byte array (max size 32 bytes) */
-    SessionId (byte sessionId [])
-        { this.sessionId = sessionId; }
-
-    /** Returns the length of the ID, in bytes */
-    int length ()
-        { return sessionId.length; }
-
-    /** Returns the bytes in the ID.  May be an empty array.  */
-    byte [] getId ()
-    {
-        return sessionId.clone ();
-    }
-
-    /** Returns the ID as a string */
-    @Override
-    public String toString ()
-    {
-        int             len = sessionId.length;
-        StringBuffer    s = new StringBuffer (10 + 2 * len);
-
-        s.append ("{");
-        for (int i = 0; i < len; i++) {
-            s.append (0x0ff & sessionId [i]);
-            if (i != (len - 1))
-                s.append (", ");
-        }
-        s.append ("}");
-        return s.toString ();
-    }
-
-
-    /** Returns a value which is the same for session IDs which are equal */
-    @Override
-    public int hashCode ()
-    {
-        return Arrays.hashCode(sessionId);
-    }
-
-    /** Returns true if the parameter is the same session ID */
-    @Override
-    public boolean equals (Object obj)
-    {
-        if (!(obj instanceof SessionId))
-            return false;
-
-        SessionId s = (SessionId) obj;
-        byte b [] = s.getId ();
-
-        if (b.length != sessionId.length)
-            return false;
-        for (int i = 0; i < sessionId.length; i++) {
-            if (b [i] != sessionId [i])
-                return false;
-        }
-        return true;
-    }
-
-    /**
-     * Checks the length of the session ID to make sure it sits within
-     * the range called out in the specification
-     */
-    void checkLength(ProtocolVersion pv) throws SSLProtocolException {
-        // As of today all versions of TLS have a 32-byte maximum length.
-        // In the future we can do more here to support protocol versions
-        // that may have longer max lengths.
-        if (sessionId.length > MAX_LENGTH) {
-            throw new SSLProtocolException("Invalid session ID length (" +
-                    sessionId.length + " bytes)");
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2006, 2012, 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.util.ArrayList;
-import java.util.Collection;
-
-import javax.net.ssl.SSLProtocolException;
-
-/*
- * [RFC5246] The client uses the "signature_algorithms" extension to
- * indicate to the server which signature/hash algorithm pairs may be
- * used in digital signatures.  The "extension_data" field of this
- * extension contains a "supported_signature_algorithms" value.
- *
- *     enum {
- *         none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- *         sha512(6), (255)
- *     } HashAlgorithm;
- *
- *     enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- *       SignatureAlgorithm;
- *
- *     struct {
- *           HashAlgorithm hash;
- *           SignatureAlgorithm signature;
- *     } SignatureAndHashAlgorithm;
- *
- *     SignatureAndHashAlgorithm
- *       supported_signature_algorithms<2..2^16-2>;
- */
-final class SignatureAlgorithmsExtension extends HelloExtension {
-
-    private Collection<SignatureAndHashAlgorithm> algorithms;
-    private int algorithmsLen;  // length of supported_signature_algorithms
-
-    SignatureAlgorithmsExtension(
-            Collection<SignatureAndHashAlgorithm> signAlgs) {
-
-        super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-
-        algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
-        algorithmsLen =
-            SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
-    }
-
-    SignatureAlgorithmsExtension(HandshakeInStream s, int len)
-                throws IOException {
-        super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-
-        algorithmsLen = s.getInt16();
-        if (algorithmsLen == 0 || algorithmsLen + 2 != len) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-        int remains = algorithmsLen;
-        int sequence = 0;
-        while (remains > 1) {   // needs at least two bytes
-            int hash = s.getInt8();         // hash algorithm
-            int signature = s.getInt8();    // signature algorithm
-
-            SignatureAndHashAlgorithm algorithm =
-                SignatureAndHashAlgorithm.valueOf(hash, signature, ++sequence);
-            algorithms.add(algorithm);
-            remains -= 2;  // one byte for hash, one byte for signature
-        }
-
-        if (remains != 0) {
-            throw new SSLProtocolException("Invalid server_name extension");
-        }
-    }
-
-    Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
-        return algorithms;
-    }
-
-    @Override
-    int length() {
-        return 6 + algorithmsLen;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putInt16(algorithmsLen + 2);
-        s.putInt16(algorithmsLen);
-
-        for (SignatureAndHashAlgorithm algorithm : algorithms) {
-            s.putInt8(algorithm.getHashValue());      // HashAlgorithm
-            s.putInt8(algorithm.getSignatureValue()); // SignatureAlgorithm
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-        boolean opened = false;
-        for (SignatureAndHashAlgorithm signAlg : algorithms) {
-            if (opened) {
-                buffer.append(", " + signAlg.getAlgorithmName());
-            } else {
-                buffer.append(signAlg.getAlgorithmName());
-                opened = true;
-            }
-        }
-
-        return "Extension " + type + ", signature_algorithms: " + buffer;
-    }
-}
-
--- a/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,441 +0,0 @@
-/*
- * Copyright (c) 2010, 2016, 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.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.PrivateKey;
-import java.security.Security;
-
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.EnumSet;
-import java.util.TreeMap;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ArrayList;
-
-import sun.security.util.KeyUtil;
-
-/**
- * Signature and hash algorithm.
- *
- * [RFC5246] The client uses the "signature_algorithms" extension to
- * indicate to the server which signature/hash algorithm pairs may be
- * used in digital signatures.  The "extension_data" field of this
- * extension contains a "supported_signature_algorithms" value.
- *
- *     enum {
- *         none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- *         sha512(6), (255)
- *     } HashAlgorithm;
- *
- *     enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- *       SignatureAlgorithm;
- *
- *     struct {
- *           HashAlgorithm hash;
- *           SignatureAlgorithm signature;
- *     } SignatureAndHashAlgorithm;
- */
-final class SignatureAndHashAlgorithm {
-
-    // minimum priority for default enabled algorithms
-    final static int SUPPORTED_ALG_PRIORITY_MAX_NUM = 0x00F0;
-
-    // performance optimization
-    private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
-        Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
-
-    // supported pairs of signature and hash algorithm
-    private final static Map<Integer, SignatureAndHashAlgorithm> supportedMap;
-    private final static Map<Integer, SignatureAndHashAlgorithm> priorityMap;
-
-    // the hash algorithm
-    private HashAlgorithm hash;
-
-    // id in 16 bit MSB format, i.e. 0x0603 for SHA512withECDSA
-    private int id;
-
-    // the standard algorithm name, for example "SHA512withECDSA"
-    private String algorithm;
-
-    // Priority for the preference order. The lower the better.
-    //
-    // If the algorithm is unsupported, its priority should be bigger
-    // than SUPPORTED_ALG_PRIORITY_MAX_NUM.
-    private int priority;
-
-    // constructor for supported algorithm
-    private SignatureAndHashAlgorithm(HashAlgorithm hash,
-            SignatureAlgorithm signature, String algorithm, int priority) {
-        this.hash = hash;
-        this.algorithm = algorithm;
-        this.id = ((hash.value & 0xFF) << 8) | (signature.value & 0xFF);
-        this.priority = priority;
-    }
-
-    // constructor for unsupported algorithm
-    private SignatureAndHashAlgorithm(String algorithm, int id, int sequence) {
-        this.hash = HashAlgorithm.valueOf((id >> 8) & 0xFF);
-        this.algorithm = algorithm;
-        this.id = id;
-
-        // add one more to the sequence number, in case that the number is zero
-        this.priority = SUPPORTED_ALG_PRIORITY_MAX_NUM + sequence + 1;
-    }
-
-    // Note that we do not use the sequence argument for supported algorithms,
-    // so please don't sort by comparing the objects read from handshake
-    // messages.
-    static SignatureAndHashAlgorithm valueOf(int hash,
-            int signature, int sequence) {
-        hash &= 0xFF;
-        signature &= 0xFF;
-
-        int id = (hash << 8) | signature;
-        SignatureAndHashAlgorithm signAlg = supportedMap.get(id);
-        if (signAlg == null) {
-            // unsupported algorithm
-            signAlg = new SignatureAndHashAlgorithm(
-                "Unknown (hash:0x" + Integer.toString(hash, 16) +
-                ", signature:0x" + Integer.toString(signature, 16) + ")",
-                id, sequence);
-        }
-
-        return signAlg;
-    }
-
-    int getHashValue() {
-        return (id >> 8) & 0xFF;
-    }
-
-    int getSignatureValue() {
-        return id & 0xFF;
-    }
-
-    String getAlgorithmName() {
-        return algorithm;
-    }
-
-    // return the size of a SignatureAndHashAlgorithm structure in TLS record
-    static int sizeInRecord() {
-        return 2;
-    }
-
-    // Get local supported algorithm collection complying to
-    // algorithm constraints
-    static Collection<SignatureAndHashAlgorithm>
-            getSupportedAlgorithms(AlgorithmConstraints constraints) {
-
-        Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
-        for (SignatureAndHashAlgorithm sigAlg : priorityMap.values()) {
-            if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
-                    constraints.permits(SIGNATURE_PRIMITIVE_SET,
-                            sigAlg.algorithm, null)) {
-                supported.add(sigAlg);
-            }
-        }
-
-        return supported;
-    }
-
-    // Get supported algorithm collection from an untrusted collection
-    static Collection<SignatureAndHashAlgorithm> getSupportedAlgorithms(
-            AlgorithmConstraints constraints,
-            Collection<SignatureAndHashAlgorithm> algorithms ) {
-        Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
-        for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-            if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
-                    constraints.permits(SIGNATURE_PRIMITIVE_SET,
-                                sigAlg.algorithm, null)) {
-                supported.add(sigAlg);
-            }
-        }
-
-        return supported;
-    }
-
-    static String[] getAlgorithmNames(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        ArrayList<String> algorithmNames = new ArrayList<>();
-        if (algorithms != null) {
-            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-                algorithmNames.add(sigAlg.algorithm);
-            }
-        }
-
-        String[] array = new String[algorithmNames.size()];
-        return algorithmNames.toArray(array);
-    }
-
-    static Set<String> getHashAlgorithmNames(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        Set<String> algorithmNames = new HashSet<>();
-        if (algorithms != null) {
-            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-                if (sigAlg.hash.value > 0) {
-                    algorithmNames.add(sigAlg.hash.standardName);
-                }
-            }
-        }
-
-        return algorithmNames;
-    }
-
-    static String getHashAlgorithmName(SignatureAndHashAlgorithm algorithm) {
-        return algorithm.hash.standardName;
-    }
-
-    private static void supports(HashAlgorithm hash,
-            SignatureAlgorithm signature, String algorithm, int priority) {
-
-        SignatureAndHashAlgorithm pair =
-            new SignatureAndHashAlgorithm(hash, signature, algorithm, priority);
-        if (supportedMap.put(pair.id, pair) != null) {
-            throw new RuntimeException(
-                "Duplicate SignatureAndHashAlgorithm definition, id: " +
-                pair.id);
-        }
-        if (priorityMap.put(pair.priority, pair) != null) {
-            throw new RuntimeException(
-                "Duplicate SignatureAndHashAlgorithm definition, priority: " +
-                pair.priority);
-        }
-    }
-
-    static SignatureAndHashAlgorithm getPreferableAlgorithm(
-        Collection<SignatureAndHashAlgorithm> algorithms, String expected) {
-
-        return SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                algorithms, expected, null);
-    }
-
-    static SignatureAndHashAlgorithm getPreferableAlgorithm(
-            Collection<SignatureAndHashAlgorithm> algorithms,
-            String expected, PrivateKey signingKey) {
-
-        int maxDigestLength = getMaxDigestLength(signingKey);
-        for (SignatureAndHashAlgorithm algorithm : algorithms) {
-            int signValue = algorithm.id & 0xFF;
-            if ((expected == null) ||
-                    (expected.equalsIgnoreCase("rsa") &&
-                            signValue == SignatureAlgorithm.RSA.value) ||
-                    (expected.equalsIgnoreCase("dsa") &&
-                            signValue == SignatureAlgorithm.DSA.value) ||
-                    (expected.equalsIgnoreCase("ecdsa") &&
-                            signValue == SignatureAlgorithm.ECDSA.value) ||
-                    (expected.equalsIgnoreCase("ec") &&
-                            signValue == SignatureAlgorithm.ECDSA.value)) {
-
-                if (algorithm.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
-                        algorithm.hash.length <= maxDigestLength) {
-
-                    return algorithm;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /*
-     * Need to check key length to match the length of hash value
-     */
-    private static int getMaxDigestLength(PrivateKey signingKey) {
-        int maxDigestLength = Integer.MAX_VALUE;
-
-        // only need to check RSA algorithm at present.
-        if (signingKey != null &&
-                "rsa".equalsIgnoreCase(signingKey.getAlgorithm())) {
-            /*
-             * RSA keys of 512 bits have been shown to be practically
-             * breakable, it does not make much sense to use the strong
-             * hash algorithm for keys whose key size less than 512 bits.
-             * So it is not necessary to caculate the required max digest
-             * length exactly.
-             *
-             * If key size is greater than or equals to 768, there is no max
-             * digest length limitation in currect implementation.
-             *
-             * If key size is greater than or equals to 512, but less than
-             * 768, the digest length should be less than or equal to 32 bytes.
-             *
-             * If key size is less than 512, the  digest length should be
-             * less than or equal to 20 bytes.
-             */
-            int keySize = KeyUtil.getKeySize(signingKey);
-            if (keySize >= 768) {
-                maxDigestLength = HashAlgorithm.SHA512.length;
-            } else if ((keySize >= 512) && (keySize < 768)) {
-                maxDigestLength = HashAlgorithm.SHA256.length;
-            } else if ((keySize > 0) && (keySize < 512)) {
-                maxDigestLength = HashAlgorithm.SHA1.length;
-            }   // Otherwise, cannot determine the key size, prefer the most
-                // preferable hash algorithm.
-        }
-
-        return maxDigestLength;
-    }
-
-    static enum HashAlgorithm {
-        UNDEFINED("undefined",        "", -1, -1),
-        NONE(          "none",    "NONE",  0, -1),
-        MD5(            "md5",     "MD5",  1, 16),
-        SHA1(          "sha1",   "SHA-1",  2, 20),
-        SHA224(      "sha224", "SHA-224",  3, 28),
-        SHA256(      "sha256", "SHA-256",  4, 32),
-        SHA384(      "sha384", "SHA-384",  5, 48),
-        SHA512(      "sha512", "SHA-512",  6, 64);
-
-        final String name;  // not the standard signature algorithm name
-                            // except the UNDEFINED, other names are defined
-                            // by TLS 1.2 protocol
-        final String standardName; // the standard MessageDigest algorithm name
-        final int value;
-        final int length;   // digest length in bytes, -1 means not applicable
-
-        private HashAlgorithm(String name, String standardName,
-                int value, int length) {
-            this.name = name;
-            this.standardName = standardName;
-            this.value = value;
-            this.length = length;
-        }
-
-        static HashAlgorithm valueOf(int value) {
-            HashAlgorithm algorithm = UNDEFINED;
-            switch (value) {
-                case 0:
-                    algorithm = NONE;
-                    break;
-                case 1:
-                    algorithm = MD5;
-                    break;
-                case 2:
-                    algorithm = SHA1;
-                    break;
-                case 3:
-                    algorithm = SHA224;
-                    break;
-                case 4:
-                    algorithm = SHA256;
-                    break;
-                case 5:
-                    algorithm = SHA384;
-                    break;
-                case 6:
-                    algorithm = SHA512;
-                    break;
-            }
-
-            return algorithm;
-        }
-    }
-
-    static enum SignatureAlgorithm {
-        UNDEFINED("undefined", -1),
-        ANONYMOUS("anonymous",  0),
-        RSA(            "rsa",  1),
-        DSA(            "dsa",  2),
-        ECDSA(        "ecdsa",  3);
-
-        final String name;  // not the standard signature algorithm name
-                            // except the UNDEFINED, other names are defined
-                            // by TLS 1.2 protocol
-        final int value;
-
-        private SignatureAlgorithm(String name, int value) {
-            this.name = name;
-            this.value = value;
-        }
-
-        static SignatureAlgorithm valueOf(int value) {
-            SignatureAlgorithm algorithm = UNDEFINED;
-            switch (value) {
-                case 0:
-                    algorithm = ANONYMOUS;
-                    break;
-                case 1:
-                    algorithm = RSA;
-                    break;
-                case 2:
-                    algorithm = DSA;
-                    break;
-                case 3:
-                    algorithm = ECDSA;
-                    break;
-            }
-
-            return algorithm;
-        }
-    }
-
-    static {
-        supportedMap = Collections.synchronizedSortedMap(
-            new TreeMap<Integer, SignatureAndHashAlgorithm>());
-        priorityMap = Collections.synchronizedSortedMap(
-            new TreeMap<Integer, SignatureAndHashAlgorithm>());
-
-        synchronized (supportedMap) {
-            int p = SUPPORTED_ALG_PRIORITY_MAX_NUM;
-            supports(HashAlgorithm.MD5,         SignatureAlgorithm.RSA,
-                    "MD5withRSA",           --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.DSA,
-                    "SHA1withDSA",          --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.RSA,
-                    "SHA1withRSA",          --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.ECDSA,
-                    "SHA1withECDSA",        --p);
-
-            if (Security.getProvider("SunMSCAPI") == null) {
-                supports(HashAlgorithm.SHA224,      SignatureAlgorithm.DSA,
-                        "SHA224withDSA",        --p);
-                supports(HashAlgorithm.SHA224,      SignatureAlgorithm.RSA,
-                        "SHA224withRSA",        --p);
-                supports(HashAlgorithm.SHA224,      SignatureAlgorithm.ECDSA,
-                        "SHA224withECDSA",      --p);
-            }
-
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.DSA,
-                    "SHA256withDSA",        --p);
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.RSA,
-                    "SHA256withRSA",        --p);
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.ECDSA,
-                    "SHA256withECDSA",      --p);
-            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.RSA,
-                    "SHA384withRSA",        --p);
-            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.ECDSA,
-                    "SHA384withECDSA",      --p);
-            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.RSA,
-                    "SHA512withRSA",        --p);
-            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.ECDSA,
-                    "SHA512withECDSA",      --p);
-        }
-    }
-}
-
--- a/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,427 +0,0 @@
-/*
- * Copyright (c) 1999, 2013, 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 javax.net.ssl.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.*;
-import java.net.Socket;
-
-import javax.security.auth.x500.X500Principal;
-
-
-/**
- * An implementation of X509KeyManager backed by a KeyStore.
- *
- * The backing KeyStore is inspected when this object is constructed.
- * All key entries containing a PrivateKey and a non-empty chain of
- * X509Certificate are then copied into an internal store. This means
- * that subsequent modifications of the KeyStore have no effect on the
- * X509KeyManagerImpl object.
- *
- * Note that this class assumes that all keys are protected by the same
- * password.
- *
- * The JSSE handshake code currently calls into this class via
- * chooseClientAlias() and chooseServerAlias() to find the certificates to
- * use. As implemented here, both always return the first alias returned by
- * getClientAliases() and getServerAliases(). In turn, these methods are
- * implemented by calling getAliases(), which performs the actual lookup.
- *
- * Note that this class currently implements no checking of the local
- * certificates. In particular, it is *not* guaranteed that:
- *  . the certificates are within their validity period and not revoked
- *  . the signatures verify
- *  . they form a PKIX compliant chain.
- *  . the certificate extensions allow the certificate to be used for
- *    the desired purpose.
- *
- * Chains that fail any of these criteria will probably be rejected by
- * the remote peer.
- *
- */
-final class SunX509KeyManagerImpl extends X509ExtendedKeyManager {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private static final String[] STRING0 = new String[0];
-
-    /*
-     * The credentials from the KeyStore as
-     * Map: String(alias) -> X509Credentials(credentials)
-     */
-    private Map<String,X509Credentials> credentialsMap;
-
-    /*
-     * Cached server aliases for the case issuers == null.
-     * (in the current JSSE implementation, issuers are always null for
-     * server certs). See chooseServerAlias() for details.
-     *
-     * Map: String(keyType) -> String[](alias)
-     */
-    private final Map<String,String[]> serverAliasCache;
-
-    /*
-     * Basic container for credentials implemented as an inner class.
-     */
-    private static class X509Credentials {
-        PrivateKey privateKey;
-        X509Certificate[] certificates;
-        private Set<X500Principal> issuerX500Principals;
-
-        X509Credentials(PrivateKey privateKey, X509Certificate[] certificates) {
-            // assert privateKey and certificates != null
-            this.privateKey = privateKey;
-            this.certificates = certificates;
-        }
-
-        synchronized Set<X500Principal> getIssuerX500Principals() {
-            // lazy initialization
-            if (issuerX500Principals == null) {
-                issuerX500Principals = new HashSet<X500Principal>();
-                for (int i = 0; i < certificates.length; i++) {
-                    issuerX500Principals.add(
-                                certificates[i].getIssuerX500Principal());
-                }
-            }
-            return issuerX500Principals;
-        }
-    }
-
-    SunX509KeyManagerImpl(KeyStore ks, char[] password)
-            throws KeyStoreException,
-            NoSuchAlgorithmException, UnrecoverableKeyException {
-
-        credentialsMap = new HashMap<String,X509Credentials>();
-        serverAliasCache = Collections.synchronizedMap(
-                            new HashMap<String,String[]>());
-        if (ks == null) {
-            return;
-        }
-
-        for (Enumeration<String> aliases = ks.aliases();
-                                        aliases.hasMoreElements(); ) {
-            String alias = aliases.nextElement();
-            if (!ks.isKeyEntry(alias)) {
-                continue;
-            }
-            Key key = ks.getKey(alias, password);
-            if (key instanceof PrivateKey == false) {
-                continue;
-            }
-            Certificate[] certs = ks.getCertificateChain(alias);
-            if ((certs == null) || (certs.length == 0) ||
-                    !(certs[0] instanceof X509Certificate)) {
-                continue;
-            }
-            if (!(certs instanceof X509Certificate[])) {
-                Certificate[] tmp = new X509Certificate[certs.length];
-                System.arraycopy(certs, 0, tmp, 0, certs.length);
-                certs = tmp;
-            }
-
-            X509Credentials cred = new X509Credentials((PrivateKey)key,
-                (X509Certificate[])certs);
-            credentialsMap.put(alias, cred);
-            if (debug != null && Debug.isOn("keymanager")) {
-                System.out.println("***");
-                System.out.println("found key for : " + alias);
-                for (int i = 0; i < certs.length; i++) {
-                    System.out.println("chain [" + i + "] = "
-                    + certs[i]);
-                }
-                System.out.println("***");
-            }
-        }
-    }
-
-    /*
-     * Returns the certificate chain associated with the given alias.
-     *
-     * @return the certificate chain (ordered with the user's certificate first
-     * and the root certificate authority last)
-     */
-    @Override
-    public X509Certificate[] getCertificateChain(String alias) {
-        if (alias == null) {
-            return null;
-        }
-        X509Credentials cred = credentialsMap.get(alias);
-        if (cred == null) {
-            return null;
-        } else {
-            return cred.certificates.clone();
-        }
-    }
-
-    /*
-     * Returns the key associated with the given alias
-     */
-    @Override
-    public PrivateKey getPrivateKey(String alias) {
-        if (alias == null) {
-            return null;
-        }
-        X509Credentials cred = credentialsMap.get(alias);
-        if (cred == null) {
-            return null;
-        } else {
-            return cred.privateKey;
-        }
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
-            Socket socket) {
-        /*
-         * We currently don't do anything with socket, but
-         * someday we might.  It might be a useful hint for
-         * selecting one of the aliases we get back from
-         * getClientAliases().
-         */
-
-        if (keyTypes == null) {
-            return null;
-        }
-
-        for (int i = 0; i < keyTypes.length; i++) {
-            String[] aliases = getClientAliases(keyTypes[i], issuers);
-            if ((aliases != null) && (aliases.length > 0)) {
-                return aliases[0];
-            }
-        }
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of an
-     * <code>SSLEngine</code> connection given the public key type
-     * and the list of certificate issuer authorities recognized by
-     * the peer (if any).
-     *
-     * @since 1.5
-     */
-    @Override
-    public String chooseEngineClientAlias(String[] keyType,
-            Principal[] issuers, SSLEngine engine) {
-        /*
-         * If we ever start using socket as a selection criteria,
-         * we'll need to adjust this.
-         */
-        return chooseClientAlias(keyType, issuers, null);
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String chooseServerAlias(String keyType,
-            Principal[] issuers, Socket socket) {
-        /*
-         * We currently don't do anything with socket, but
-         * someday we might.  It might be a useful hint for
-         * selecting one of the aliases we get back from
-         * getServerAliases().
-         */
-        if (keyType == null) {
-            return null;
-        }
-
-        String[] aliases;
-
-        if (issuers == null || issuers.length == 0) {
-            aliases = serverAliasCache.get(keyType);
-            if (aliases == null) {
-                aliases = getServerAliases(keyType, issuers);
-                // Cache the result (positive and negative lookups)
-                if (aliases == null) {
-                    aliases = STRING0;
-                }
-                serverAliasCache.put(keyType, aliases);
-            }
-        } else {
-            aliases = getServerAliases(keyType, issuers);
-        }
-        if ((aliases != null) && (aliases.length > 0)) {
-            return aliases[0];
-        }
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of an
-     * <code>SSLEngine</code> connection given the public key type
-     * and the list of certificate issuer authorities recognized by
-     * the peer (if any).
-     *
-     * @since 1.5
-     */
-    @Override
-    public String chooseEngineServerAlias(String keyType,
-            Principal[] issuers, SSLEngine engine) {
-        /*
-         * If we ever start using socket as a selection criteria,
-         * we'll need to adjust this.
-         */
-        return chooseServerAlias(keyType, issuers, null);
-    }
-
-    /*
-     * Get the matching aliases for authenticating the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers);
-    }
-
-    /*
-     * Get the matching aliases for authenticating the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    @Override
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers);
-    }
-
-    /*
-     * Get the matching aliases for authenticating the either side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     *
-     * Issuers comes to us in the form of X500Principal[].
-     */
-    private String[] getAliases(String keyType, Principal[] issuers) {
-        if (keyType == null) {
-            return null;
-        }
-        if (issuers == null) {
-            issuers = new X500Principal[0];
-        }
-        if (issuers instanceof X500Principal[] == false) {
-            // normally, this will never happen but try to recover if it does
-            issuers = convertPrincipals(issuers);
-        }
-        String sigType;
-        if (keyType.contains("_")) {
-            int k = keyType.indexOf("_");
-            sigType = keyType.substring(k + 1);
-            keyType = keyType.substring(0, k);
-        } else {
-            sigType = null;
-        }
-
-        X500Principal[] x500Issuers = (X500Principal[])issuers;
-        // the algorithm below does not produce duplicates, so avoid Set
-        List<String> aliases = new ArrayList<>();
-
-        for (Map.Entry<String,X509Credentials> entry :
-                                                credentialsMap.entrySet()) {
-
-            String alias = entry.getKey();
-            X509Credentials credentials = entry.getValue();
-            X509Certificate[] certs = credentials.certificates;
-
-            if (!keyType.equals(certs[0].getPublicKey().getAlgorithm())) {
-                continue;
-            }
-            if (sigType != null) {
-                if (certs.length > 1) {
-                    // if possible, check the public key in the issuer cert
-                    if (!sigType.equals(
-                            certs[1].getPublicKey().getAlgorithm())) {
-                        continue;
-                    }
-                } else {
-                    // Check the signature algorithm of the certificate itself.
-                    // Look for the "withRSA" in "SHA1withRSA", etc.
-                    String sigAlgName =
-                        certs[0].getSigAlgName().toUpperCase(Locale.ENGLISH);
-                    String pattern = "WITH" +
-                        sigType.toUpperCase(Locale.ENGLISH);
-                    if (sigAlgName.contains(pattern) == false) {
-                        continue;
-                    }
-                }
-            }
-
-            if (issuers.length == 0) {
-                // no issuer specified, match all
-                aliases.add(alias);
-                if (debug != null && Debug.isOn("keymanager")) {
-                    System.out.println("matching alias: " + alias);
-                }
-            } else {
-                Set<X500Principal> certIssuers =
-                                        credentials.getIssuerX500Principals();
-                for (int i = 0; i < x500Issuers.length; i++) {
-                    if (certIssuers.contains(issuers[i])) {
-                        aliases.add(alias);
-                        if (debug != null && Debug.isOn("keymanager")) {
-                            System.out.println("matching alias: " + alias);
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-
-        String[] aliasStrings = aliases.toArray(STRING0);
-        return ((aliasStrings.length == 0) ? null : aliasStrings);
-    }
-
-    /*
-     * Convert an array of Principals to an array of X500Principals, if
-     * possible. Principals that cannot be converted are ignored.
-     */
-    private static X500Principal[] convertPrincipals(Principal[] principals) {
-        List<X500Principal> list = new ArrayList<>(principals.length);
-        for (int i = 0; i < principals.length; i++) {
-            Principal p = principals[i];
-            if (p instanceof X500Principal) {
-                list.add((X500Principal)p);
-            } else {
-                try {
-                    list.add(new X500Principal(p.getName()));
-                } catch (IllegalArgumentException e) {
-                    // ignore
-                }
-            }
-        }
-        return list.toArray(new X500Principal[list.size()]);
-    }
-}
--- a/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-import java.io.*;
-import java.security.*;
-import java.security.cert.*;
-import javax.net.ssl.*;
-
-import sun.security.validator.Validator;
-import sun.security.validator.TrustStoreUtil;
-
-abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-    private X509TrustManager trustManager = null;
-    private boolean isInitialized = false;
-
-    TrustManagerFactoryImpl() {
-        // empty
-    }
-
-    @Override
-    protected void engineInit(KeyStore ks) throws KeyStoreException {
-        if (ks == null) {
-            try {
-                trustManager = getInstance(TrustStoreManager.getTrustedCerts());
-            } catch (SecurityException se) {
-                // eat security exceptions but report other throwables
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + se);
-                }
-            } catch (Error err) {
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + err);
-                }
-                throw err;
-            } catch (RuntimeException re) {
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + re);
-                }
-                throw re;
-            } catch (Exception e) {
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + e);
-                }
-                throw new KeyStoreException(
-                    "problem accessing trust store", e);
-            }
-        } else {
-            trustManager = getInstance(TrustStoreUtil.getTrustedCerts(ks));
-        }
-
-        isInitialized = true;
-    }
-
-    abstract X509TrustManager getInstance(
-            Collection<X509Certificate> trustedCerts);
-
-    abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
-            throws InvalidAlgorithmParameterException;
-
-    @Override
-    protected void engineInit(ManagerFactoryParameters spec) throws
-            InvalidAlgorithmParameterException {
-        trustManager = getInstance(spec);
-        isInitialized = true;
-    }
-
-    /**
-     * Returns one trust manager for each type of trust material.
-     */
-    @Override
-    protected TrustManager[] engineGetTrustManagers() {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                        "TrustManagerFactoryImpl is not initialized");
-        }
-        return new TrustManager[] { trustManager };
-    }
-
-    /*
-     * Try to get an InputStream based on the file we pass in.
-     */
-    private static FileInputStream getFileInputStream(final File file)
-            throws Exception {
-        return AccessController.doPrivileged(
-                new PrivilegedExceptionAction<FileInputStream>() {
-                    @Override
-                    public FileInputStream run() throws Exception {
-                        try {
-                            if (file.exists()) {
-                                return new FileInputStream(file);
-                            } else {
-                                return null;
-                            }
-                        } catch (FileNotFoundException e) {
-                            // couldn't find it, oh well.
-                            return null;
-                        }
-                    }
-                });
-    }
-
-    public static final class SimpleFactory extends TrustManagerFactoryImpl {
-        @Override
-        X509TrustManager getInstance(
-                Collection<X509Certificate> trustedCerts) {
-            return new X509TrustManagerImpl(
-                    Validator.TYPE_SIMPLE, trustedCerts);
-        }
-
-        @Override
-        X509TrustManager getInstance(ManagerFactoryParameters spec)
-                throws InvalidAlgorithmParameterException {
-            throw new InvalidAlgorithmParameterException
-                ("SunX509 TrustManagerFactory does not use "
-                + "ManagerFactoryParameters");
-        }
-    }
-
-    public static final class PKIXFactory extends TrustManagerFactoryImpl {
-        @Override
-        X509TrustManager getInstance(
-                Collection<X509Certificate> trustedCerts) {
-            return new X509TrustManagerImpl(Validator.TYPE_PKIX, trustedCerts);
-        }
-
-        @Override
-        X509TrustManager getInstance(ManagerFactoryParameters spec)
-                throws InvalidAlgorithmParameterException {
-            if (spec instanceof CertPathTrustManagerParameters == false) {
-                throw new InvalidAlgorithmParameterException
-                    ("Parameters must be CertPathTrustManagerParameters");
-            }
-            CertPathParameters params =
-                ((CertPathTrustManagerParameters)spec).getParameters();
-            if (params instanceof PKIXBuilderParameters == false) {
-                throw new InvalidAlgorithmParameterException
-                    ("Encapsulated parameters must be PKIXBuilderParameters");
-            }
-            PKIXBuilderParameters pkixParams = (PKIXBuilderParameters)params;
-            return new X509TrustManagerImpl(Validator.TYPE_PKIX, pkixParams);
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/TrustStoreManager.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,395 +0,0 @@
-/*
- * Copyright (c) 2016, 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.lang.ref.WeakReference;
-import java.io.*;
-import java.util.*;
-
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import sun.security.action.*;
-import sun.security.validator.TrustStoreUtil;
-
-/**
- * Collection of static utility methods to manage the default trusted KeyStores
- * effectively.
- */
-final class TrustStoreManager {
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    // A singleton service to manage the default trusted KeyStores effectively.
-    private static final TrustAnchorManager tam = new TrustAnchorManager();
-
-    // Restrict instantiation of this class.
-    private TrustStoreManager() {
-        // empty
-    }
-
-    /**
-     * Return an unmodifiable set of all trusted X509Certificates contained
-     * in the default trusted KeyStore.
-     */
-    public static Set<X509Certificate> getTrustedCerts() throws Exception {
-        return tam.getTrustedCerts(TrustStoreDescriptor.createInstance());
-    }
-
-    /**
-     * Return an instance of the default trusted KeyStore.
-     */
-    public static KeyStore getTrustedKeyStore() throws Exception {
-        return tam.getKeyStore(TrustStoreDescriptor.createInstance());
-    }
-
-    /**
-     * A descriptor of the default trusted KeyStore.
-     *
-     * The preference of the default trusted KeyStore is:
-     *    javax.net.ssl.trustStore
-     *    jssecacerts
-     *    cacerts
-     */
-    private static final class TrustStoreDescriptor {
-        private static final String fileSep = File.separator;
-        private static final String defaultStorePath =
-                GetPropertyAction.privilegedGetProperty("java.home") +
-                fileSep + "lib" + fileSep + "security";
-        private static final String defaultStore =
-                defaultStorePath + fileSep + "cacerts";
-        private static final String jsseDefaultStore =
-                defaultStorePath + fileSep + "jssecacerts";
-
-        // the trust store name
-        private final String storeName;
-
-        // the trust store type, JKS/PKCS12
-        private final String storeType;
-
-        // the provider of the trust store
-        private final String storeProvider;
-
-        // the password used for the trust store
-        private final String storePassword;
-
-        // the File object of the trust store
-        private final File storeFile;
-
-        // the last modified time of the store
-        private final long lastModified;
-
-        private TrustStoreDescriptor(String storeName, String storeType,
-                String storeProvider, String storePassword,
-                File storeFile, long lastModified) {
-            this.storeName = storeName;
-            this.storeType = storeType;
-            this.storeProvider = storeProvider;
-            this.storePassword = storePassword;
-            this.storeFile = storeFile;
-            this.lastModified = lastModified;
-
-            if (debug != null && Debug.isOn("trustmanager")) {
-                System.out.println(
-                    "trustStore is: " + storeName + "\n" +
-                    "trustStore type is: " + storeType + "\n" +
-                    "trustStore provider is: " + storeProvider + "\n" +
-                    "the last modified time is: " + (new Date(lastModified)));
-            }
-        }
-
-        /**
-         * Create an instance of TrustStoreDescriptor for the default
-         * trusted KeyStore.
-         */
-        static TrustStoreDescriptor createInstance() {
-             return AccessController.doPrivileged(new PrivilegedAction<TrustStoreDescriptor>() {
-
-                @Override
-                public TrustStoreDescriptor run() {
-                    // Get the system properties for trust store.
-                    String storePropName = System.getProperty(
-                            "javax.net.ssl.trustStore", jsseDefaultStore);
-                    String storePropType = System.getProperty(
-                            "javax.net.ssl.trustStoreType",
-                            KeyStore.getDefaultType());
-                    String storePropProvider = System.getProperty(
-                            "javax.net.ssl.trustStoreProvider", "");
-                    String storePropPassword = System.getProperty(
-                            "javax.net.ssl.trustStorePassword", "");
-
-                    String temporaryName = "";
-                    File temporaryFile = null;
-                    long temporaryTime = 0L;
-                    if (!"NONE".equals(storePropName)) {
-                        String[] fileNames =
-                                new String[] {storePropName, defaultStore};
-                        for (String fileName : fileNames) {
-                            File f = new File(fileName);
-                            if (f.isFile() && f.canRead()) {
-                                temporaryName = fileName;;
-                                temporaryFile = f;
-                                temporaryTime = f.lastModified();
-
-                                break;
-                            }
-
-                            // Not break, the file is inaccessible.
-                            if (debug != null &&
-                                    Debug.isOn("trustmanager")) {
-                                System.out.println(
-                                    "Inaccessible trust store: " +
-                                    storePropName);
-                            }
-                        }
-                    } else {
-                        temporaryName = storePropName;
-                    }
-
-                    return new TrustStoreDescriptor(
-                            temporaryName, storePropType, storePropProvider,
-                            storePropPassword, temporaryFile, temporaryTime);
-                }
-            });
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == this) {
-                return true;
-            }
-
-            if (obj instanceof TrustStoreDescriptor) {
-                TrustStoreDescriptor that = (TrustStoreDescriptor)obj;
-                return ((this.lastModified == that.lastModified) &&
-                    Objects.equals(this.storeName, that.storeName) &&
-                    Objects.equals(this.storeType, that.storeType) &&
-                    Objects.equals(this.storeProvider, that.storeProvider));
-            }
-
-            return false;
-        }
-
-
-        // Please be careful if computing security-sensitive attributes'
-        // hash code.  For example the storePassword should not be computed.
-        @Override
-        public int hashCode() {
-            int result = 17;
-
-            if (storeName != null && !storeName.isEmpty()) {
-                result = 31 * result + storeName.hashCode();
-            }
-
-            if (storeType != null && !storeType.isEmpty()) {
-                result = 31 * result + storeType.hashCode();
-            }
-
-            if (storeProvider != null && !storeProvider.isEmpty()) {
-                result = 31 * result + storeProvider.hashCode();
-            }
-
-            if (storeFile != null) {
-                result = 31 * result + storeFile.hashCode();
-            }
-
-            if (lastModified != 0L) {
-                result = (int)(31 * result + lastModified);
-            }
-
-            return result;
-        }
-    }
-
-    /**
-     * The trust anchors manager used to expedite the performance.
-     *
-     * This class can be used to provide singleton services to access default
-     * trust KeyStore more effectively.
-     */
-    private static final class TrustAnchorManager {
-        // Last trust store descriptor.
-        private TrustStoreDescriptor descriptor;
-
-        // The key store used for the trust anchors.
-        //
-        // Use weak reference so that the heavy loaded KeyStore object can
-        // be atomically cleared, and reloaded if needed.
-        private WeakReference<KeyStore> ksRef;
-
-        // The trusted X.509 certificates in the key store.
-        //
-        // Use weak reference so that the heavy loaded certificates collection
-        // objects can be atomically cleared, and reloaded if needed.
-        private WeakReference<Set<X509Certificate>> csRef;
-
-        private TrustAnchorManager() {
-            this.descriptor = null;
-            this.ksRef = new WeakReference<>(null);
-            this.csRef = new WeakReference<>(null);
-        }
-
-        /**
-         * Get the default trusted KeyStore with the specified descriptor.
-         *
-         * @return null if the underlying KeyStore is not available.
-         */
-        synchronized KeyStore getKeyStore(
-                TrustStoreDescriptor descriptor) throws Exception {
-
-            TrustStoreDescriptor temporaryDesc = this.descriptor;
-            KeyStore ks = ksRef.get();
-            if ((ks != null) && descriptor.equals(temporaryDesc)) {
-                return ks;
-            }
-
-            // Reload a new key store.
-            if ((debug != null) && Debug.isOn("trustmanager")) {
-                System.out.println("Reload the trust store");
-            }
-
-            ks = loadKeyStore(descriptor);
-            this.descriptor = descriptor;
-            this.ksRef = new WeakReference<>(ks);
-
-            return ks;
-        }
-
-        /**
-         * Get trusted certificates in the default trusted KeyStore with
-         * the specified descriptor.
-         *
-         * @return empty collection if the underlying KeyStore is not available.
-         */
-        synchronized Set<X509Certificate> getTrustedCerts(
-                TrustStoreDescriptor descriptor) throws Exception {
-
-            KeyStore ks = null;
-            TrustStoreDescriptor temporaryDesc = this.descriptor;
-            Set<X509Certificate> certs = csRef.get();
-            if (certs != null) {
-                if (descriptor.equals(temporaryDesc)) {
-                    return certs;
-                } else {
-                    // Use the new descriptor.
-                    this.descriptor = descriptor;
-                }
-            } else {
-                // Try to use the cached store at first.
-                if (descriptor.equals(temporaryDesc)) {
-                    ks = ksRef.get();
-                } else {
-                    // Use the new descriptor.
-                    this.descriptor = descriptor;
-                }
-            }
-
-            // Reload the trust store if needed.
-            if (ks == null) {
-                if ((debug != null) && Debug.isOn("trustmanager")) {
-                    System.out.println("Reload the trust store");
-                }
-                ks = loadKeyStore(descriptor);
-            }
-
-            // Reload trust certs from the key store.
-            if ((debug != null) && Debug.isOn("trustmanager")) {
-                System.out.println("Reload trust certs");
-            }
-
-            certs = loadTrustedCerts(ks);
-            if ((debug != null) && Debug.isOn("trustmanager")) {
-                System.out.println("Reloaded " + certs.size() + " trust certs");
-            }
-
-            // Note that as ks is a local variable, it is not
-            // necessary to add it to the ksRef weak reference.
-            this.csRef = new WeakReference<>(certs);
-
-            return certs;
-        }
-
-        /**
-         * Load the the KeyStore as described in the specified descriptor.
-         */
-        private static KeyStore loadKeyStore(
-                TrustStoreDescriptor descriptor) throws Exception {
-            if (!"NONE".equals(descriptor.storeName) &&
-                    descriptor.storeFile == null) {
-
-                // No file available, no KeyStore available.
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println("No available key store");
-                }
-
-                return null;
-            }
-
-            KeyStore ks;
-            if (descriptor.storeProvider.isEmpty()) {
-                ks = KeyStore.getInstance(descriptor.storeType);
-            } else {
-                ks = KeyStore.getInstance(
-                        descriptor.storeType, descriptor.storeProvider);
-            }
-
-            char[] password = null;
-            if (!descriptor.storePassword.isEmpty()) {
-                password = descriptor.storePassword.toCharArray();
-            }
-
-            if (!"NONE".equals(descriptor.storeName)) {
-                try (FileInputStream fis = AccessController.doPrivileged(
-                        new OpenFileInputStreamAction(descriptor.storeFile))) {
-                    ks.load(fis, password);
-                } catch (FileNotFoundException fnfe) {
-                    // No file available, no KeyStore available.
-                    if (debug != null && Debug.isOn("trustmanager")) {
-                        System.out.println(
-                            "Not available key store: " + descriptor.storeName);
-                    }
-
-                    return null;
-                }
-            } else {
-                ks.load(null, password);
-            }
-
-            return ks;
-        }
-
-        /**
-         * Load trusted certificates from the specified KeyStore.
-         */
-        private static Set<X509Certificate> loadTrustedCerts(KeyStore ks) {
-            if (ks == null) {
-                return Collections.<X509Certificate>emptySet();
-            }
-
-            return TrustStoreUtil.getTrustedCerts(ks);
-        }
-    }
-}
--- a/src/share/classes/sun/security/ssl/UnknownExtension.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2006, 2012, 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;
-
-final class UnknownExtension extends HelloExtension {
-
-    private final byte[] data;
-
-    UnknownExtension(HandshakeInStream s, int len, ExtensionType type)
-            throws IOException {
-        super(type);
-        data = new byte[len];
-        // s.read() does not handle 0-length arrays.
-        if (len != 0) {
-            s.read(data);
-        }
-    }
-
-    @Override
-    int length() {
-        return 4 + data.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putBytes16(data);
-    }
-
-    @Override
-    public String toString() {
-        return "Unsupported extension " + type + ", data: " +
-            Debug.toString(data);
-    }
-}
--- a/src/share/classes/sun/security/ssl/Utilities.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2012, 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 javax.net.ssl.*;
-import java.util.*;
-import sun.net.util.IPAddressUtil;
-
-/**
- * A utility class to share the static methods.
- */
-final class Utilities {
-    /**
-     * Puts {@code hostname} into the {@code serverNames} list.
-     * <P>
-     * If the {@code serverNames} does not look like a legal FQDN, it will
-     * not be put into the returned list.
-     * <P>
-     * Note that the returned list does not allow duplicated name type.
-     *
-     * @return a list of {@link SNIServerName}
-     */
-    static List<SNIServerName> addToSNIServerNameList(
-            List<SNIServerName> serverNames, String hostname) {
-
-        SNIHostName sniHostName = rawToSNIHostName(hostname);
-        if (sniHostName == null) {
-            return serverNames;
-        }
-
-        int size = serverNames.size();
-        List<SNIServerName> sniList = (size != 0) ?
-                new ArrayList<SNIServerName>(serverNames) :
-                new ArrayList<SNIServerName>(1);
-
-        boolean reset = false;
-        for (int i = 0; i < size; i++) {
-            SNIServerName serverName = sniList.get(i);
-            if (serverName.getType() == StandardConstants.SNI_HOST_NAME) {
-                sniList.set(i, sniHostName);
-                if (Debug.isOn("ssl")) {
-                    System.out.println(Thread.currentThread().getName() +
-                        ", the previous server name in SNI (" + serverName +
-                        ") was replaced with (" + sniHostName + ")");
-                }
-                reset = true;
-                break;
-            }
-        }
-
-        if (!reset) {
-            sniList.add(sniHostName);
-        }
-
-        return Collections.<SNIServerName>unmodifiableList(sniList);
-    }
-
-    /**
-     * Converts string hostname to {@code SNIHostName}.
-     * <P>
-     * Note that to check whether a hostname is a valid domain name, we cannot
-     * use the hostname resolved from name services.  For virtual hosting,
-     * multiple hostnames may be bound to the same IP address, so the hostname
-     * resolved from name services is not always reliable.
-     *
-     * @param  hostname
-     *         the raw hostname
-     * @return an instance of {@link SNIHostName}, or null if the hostname does
-     *         not look like a FQDN
-     */
-    private static SNIHostName rawToSNIHostName(String hostname) {
-        SNIHostName sniHostName = null;
-        if (hostname != null && hostname.indexOf('.') > 0 &&
-                !hostname.endsWith(".") &&
-                !IPAddressUtil.isIPv4LiteralAddress(hostname) &&
-                !IPAddressUtil.isIPv6LiteralAddress(hostname)) {
-
-            try {
-                sniHostName = new SNIHostName(hostname);
-            } catch (IllegalArgumentException iae) {
-                // don't bother to handle illegal host_name
-                if (Debug.isOn("ssl")) {
-                    System.out.println(Thread.currentThread().getName() +
-                        ", \"" + hostname + "\" " +
-                        "is not a legal HostName for  server name indication");
-                }
-            }
-        }
-
-        return sniHostName;
-    }
-}
--- a/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,860 +0,0 @@
-/*
- * Copyright (c) 2004, 2017, 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.lang.ref.*;
-import java.util.*;
-import static java.util.Locale.ENGLISH;
-import java.util.concurrent.atomic.AtomicLong;
-import java.net.Socket;
-
-import java.security.*;
-import java.security.KeyStore.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import javax.net.ssl.*;
-
-import sun.security.provider.certpath.AlgorithmChecker;
-import sun.security.validator.Validator;
-
-/**
- * The new X509 key manager implementation. The main differences to the
- * old SunX509 key manager are:
- *  . it is based around the KeyStore.Builder API. This allows it to use
- *    other forms of KeyStore protection or password input (e.g. a
- *    CallbackHandler) or to have keys within one KeyStore protected by
- *    different keys.
- *  . it can use multiple KeyStores at the same time.
- *  . it is explicitly designed to accommodate KeyStores that change over
- *    the lifetime of the process.
- *  . it makes an effort to choose the key that matches best, i.e. one that
- *    is not expired and has the appropriate certificate extensions.
- *
- * Note that this code is not explicitly performance optimzied yet.
- *
- * @author  Andreas Sterbenz
- */
-final class X509KeyManagerImpl extends X509ExtendedKeyManager
-        implements X509KeyManager {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private static final boolean useDebug =
-                            (debug != null) && Debug.isOn("keymanager");
-
-    // for unit testing only, set via privileged reflection
-    private static Date verificationDate;
-
-    // list of the builders
-    private final List<Builder> builders;
-
-    // counter to generate unique ids for the aliases
-    private final AtomicLong uidCounter;
-
-    // cached entries
-    private final Map<String,Reference<PrivateKeyEntry>> entryCacheMap;
-
-    X509KeyManagerImpl(Builder builder) {
-        this(Collections.singletonList(builder));
-    }
-
-    X509KeyManagerImpl(List<Builder> builders) {
-        this.builders = builders;
-        uidCounter = new AtomicLong();
-        entryCacheMap = Collections.synchronizedMap
-                        (new SizedMap<String,Reference<PrivateKeyEntry>>());
-    }
-
-    // LinkedHashMap with a max size of 10
-    // see LinkedHashMap JavaDocs
-    private static class SizedMap<K,V> extends LinkedHashMap<K,V> {
-        private static final long serialVersionUID = -8211222668790986062L;
-
-        @Override protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
-            return size() > 10;
-        }
-    }
-
-    //
-    // public methods
-    //
-
-    @Override
-    public X509Certificate[] getCertificateChain(String alias) {
-        PrivateKeyEntry entry = getEntry(alias);
-        return entry == null ? null :
-                (X509Certificate[])entry.getCertificateChain();
-    }
-
-    @Override
-    public PrivateKey getPrivateKey(String alias) {
-        PrivateKeyEntry entry = getEntry(alias);
-        return entry == null ? null : entry.getPrivateKey();
-    }
-
-    @Override
-    public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
-            Socket socket) {
-        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
-                        getAlgorithmConstraints(socket));
-    }
-
-    @Override
-    public String chooseEngineClientAlias(String[] keyTypes,
-            Principal[] issuers, SSLEngine engine) {
-        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
-                        getAlgorithmConstraints(engine));
-    }
-
-    @Override
-    public String chooseServerAlias(String keyType,
-            Principal[] issuers, Socket socket) {
-        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
-            getAlgorithmConstraints(socket),
-            X509TrustManagerImpl.getRequestedServerNames(socket),
-            "HTTPS");    // The SNI HostName is a fully qualified domain name.
-                         // The certificate selection scheme for SNI HostName
-                         // is similar to HTTPS endpoint identification scheme
-                         // implemented in this provider.
-                         //
-                         // Using HTTPS endpoint identification scheme to guide
-                         // the selection of an appropriate authentication
-                         // certificate according to requested SNI extension.
-                         //
-                         // It is not a really HTTPS endpoint identification.
-    }
-
-    @Override
-    public String chooseEngineServerAlias(String keyType,
-            Principal[] issuers, SSLEngine engine) {
-        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
-            getAlgorithmConstraints(engine),
-            X509TrustManagerImpl.getRequestedServerNames(engine),
-            "HTTPS");    // The SNI HostName is a fully qualified domain name.
-                         // The certificate selection scheme for SNI HostName
-                         // is similar to HTTPS endpoint identification scheme
-                         // implemented in this provider.
-                         //
-                         // Using HTTPS endpoint identification scheme to guide
-                         // the selection of an appropriate authentication
-                         // certificate according to requested SNI extension.
-                         //
-                         // It is not a really HTTPS endpoint identification.
-    }
-
-    @Override
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.CLIENT, null);
-    }
-
-    @Override
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.SERVER, null);
-    }
-
-    //
-    // implementation private methods
-    //
-
-    // Gets algorithm constraints of the socket.
-    private AlgorithmConstraints getAlgorithmConstraints(Socket socket) {
-        if (socket != null && socket.isConnected() &&
-                                        socket instanceof SSLSocket) {
-
-            SSLSocket sslSocket = (SSLSocket)socket;
-            SSLSession session = sslSocket.getHandshakeSession();
-
-            if (session != null) {
-                ProtocolVersion protocolVersion =
-                    ProtocolVersion.valueOf(session.getProtocol());
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    String[] peerSupportedSignAlgs = null;
-
-                    if (session instanceof ExtendedSSLSession) {
-                        ExtendedSSLSession extSession =
-                            (ExtendedSSLSession)session;
-                        peerSupportedSignAlgs =
-                            extSession.getPeerSupportedSignatureAlgorithms();
-                    }
-
-                    return new SSLAlgorithmConstraints(
-                        sslSocket, peerSupportedSignAlgs, true);
-                }
-            }
-
-            return new SSLAlgorithmConstraints(sslSocket, true);
-        }
-
-        return new SSLAlgorithmConstraints((SSLSocket)null, true);
-    }
-
-    // Gets algorithm constraints of the engine.
-    private AlgorithmConstraints getAlgorithmConstraints(SSLEngine engine) {
-        if (engine != null) {
-            SSLSession session = engine.getHandshakeSession();
-            if (session != null) {
-                ProtocolVersion protocolVersion =
-                    ProtocolVersion.valueOf(session.getProtocol());
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    String[] peerSupportedSignAlgs = null;
-
-                    if (session instanceof ExtendedSSLSession) {
-                        ExtendedSSLSession extSession =
-                            (ExtendedSSLSession)session;
-                        peerSupportedSignAlgs =
-                            extSession.getPeerSupportedSignatureAlgorithms();
-                    }
-
-                    return new SSLAlgorithmConstraints(
-                        engine, peerSupportedSignAlgs, true);
-                }
-            }
-        }
-
-        return new SSLAlgorithmConstraints(engine, true);
-    }
-
-    // we construct the alias we return to JSSE as seen in the code below
-    // a unique id is included to allow us to reliably cache entries
-    // between the calls to getCertificateChain() and getPrivateKey()
-    // even if tokens are inserted or removed
-    private String makeAlias(EntryStatus entry) {
-        return uidCounter.incrementAndGet() + "." + entry.builderIndex + "."
-                + entry.alias;
-    }
-
-    private PrivateKeyEntry getEntry(String alias) {
-        // if the alias is null, return immediately
-        if (alias == null) {
-            return null;
-        }
-
-        // try to get the entry from cache
-        Reference<PrivateKeyEntry> ref = entryCacheMap.get(alias);
-        PrivateKeyEntry entry = (ref != null) ? ref.get() : null;
-        if (entry != null) {
-            return entry;
-        }
-
-        // parse the alias
-        int firstDot = alias.indexOf('.');
-        int secondDot = alias.indexOf('.', firstDot + 1);
-        if ((firstDot == -1) || (secondDot == firstDot)) {
-            // invalid alias
-            return null;
-        }
-        try {
-            int builderIndex = Integer.parseInt
-                                (alias.substring(firstDot + 1, secondDot));
-            String keyStoreAlias = alias.substring(secondDot + 1);
-            Builder builder = builders.get(builderIndex);
-            KeyStore ks = builder.getKeyStore();
-            Entry newEntry = ks.getEntry
-                    (keyStoreAlias, builder.getProtectionParameter(alias));
-            if (newEntry instanceof PrivateKeyEntry == false) {
-                // unexpected type of entry
-                return null;
-            }
-            entry = (PrivateKeyEntry)newEntry;
-            entryCacheMap.put(alias, new SoftReference<PrivateKeyEntry>(entry));
-            return entry;
-        } catch (Exception e) {
-            // ignore
-            return null;
-        }
-    }
-
-    // Class to help verify that the public key algorithm (and optionally
-    // the signature algorithm) of a certificate matches what we need.
-    private static class KeyType {
-
-        final String keyAlgorithm;
-
-        // In TLS 1.2, the signature algorithm  has been obsoleted by the
-        // supported_signature_algorithms, and the certificate type no longer
-        // restricts the algorithm used to sign the certificate.
-        // However, because we don't support certificate type checking other
-        // than rsa_sign, dss_sign and ecdsa_sign, we don't have to check the
-        // protocol version here.
-        final String sigKeyAlgorithm;
-
-        KeyType(String algorithm) {
-            int k = algorithm.indexOf("_");
-            if (k == -1) {
-                keyAlgorithm = algorithm;
-                sigKeyAlgorithm = null;
-            } else {
-                keyAlgorithm = algorithm.substring(0, k);
-                sigKeyAlgorithm = algorithm.substring(k + 1);
-            }
-        }
-
-        boolean matches(Certificate[] chain) {
-            if (!chain[0].getPublicKey().getAlgorithm().equals(keyAlgorithm)) {
-                return false;
-            }
-            if (sigKeyAlgorithm == null) {
-                return true;
-            }
-            if (chain.length > 1) {
-                // if possible, check the public key in the issuer cert
-                return sigKeyAlgorithm.equals(
-                        chain[1].getPublicKey().getAlgorithm());
-            } else {
-                // Check the signature algorithm of the certificate itself.
-                // Look for the "withRSA" in "SHA1withRSA", etc.
-                X509Certificate issuer = (X509Certificate)chain[0];
-                String sigAlgName = issuer.getSigAlgName().toUpperCase(ENGLISH);
-                String pattern = "WITH" + sigKeyAlgorithm.toUpperCase(ENGLISH);
-                return sigAlgName.contains(pattern);
-            }
-        }
-    }
-
-    private static List<KeyType> getKeyTypes(String ... keyTypes) {
-        if ((keyTypes == null) ||
-                (keyTypes.length == 0) || (keyTypes[0] == null)) {
-            return null;
-        }
-        List<KeyType> list = new ArrayList<>(keyTypes.length);
-        for (String keyType : keyTypes) {
-            list.add(new KeyType(keyType));
-        }
-        return list;
-    }
-
-    /*
-     * Return the best alias that fits the given parameters.
-     * The algorithm we use is:
-     *   . scan through all the aliases in all builders in order
-     *   . as soon as we find a perfect match, return
-     *     (i.e. a match with a cert that has appropriate key usage,
-     *      qualified endpoint identity, and is not expired).
-     *   . if we do not find a perfect match, keep looping and remember
-     *     the imperfect matches
-     *   . at the end, sort the imperfect matches. we prefer expired certs
-     *     with appropriate key usage to certs with the wrong key usage.
-     *     return the first one of them.
-     */
-    private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
-            CheckType checkType, AlgorithmConstraints constraints) {
-
-        return chooseAlias(keyTypeList, issuers,
-                                    checkType, constraints, null, null);
-    }
-
-    private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
-            CheckType checkType, AlgorithmConstraints constraints,
-            List<SNIServerName> requestedServerNames, String idAlgorithm) {
-
-        if (keyTypeList == null || keyTypeList.isEmpty()) {
-            return null;
-        }
-
-        Set<Principal> issuerSet = getIssuerSet(issuers);
-        List<EntryStatus> allResults = null;
-        for (int i = 0, n = builders.size(); i < n; i++) {
-            try {
-                List<EntryStatus> results = getAliases(i, keyTypeList,
-                            issuerSet, false, checkType, constraints,
-                            requestedServerNames, idAlgorithm);
-                if (results != null) {
-                    // the results will either be a single perfect match
-                    // or 1 or more imperfect matches
-                    // if it's a perfect match, return immediately
-                    EntryStatus status = results.get(0);
-                    if (status.checkResult == CheckResult.OK) {
-                        if (useDebug) {
-                            debug.println("KeyMgr: choosing key: " + status);
-                        }
-                        return makeAlias(status);
-                    }
-                    if (allResults == null) {
-                        allResults = new ArrayList<EntryStatus>();
-                    }
-                    allResults.addAll(results);
-                }
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-        if (allResults == null) {
-            if (useDebug) {
-                debug.println("KeyMgr: no matching key found");
-            }
-            return null;
-        }
-        Collections.sort(allResults);
-        if (useDebug) {
-            debug.println("KeyMgr: no good matching key found, "
-                        + "returning best match out of:");
-            debug.println(allResults.toString());
-        }
-        return makeAlias(allResults.get(0));
-    }
-
-    /*
-     * Return all aliases that (approximately) fit the parameters.
-     * These are perfect matches plus imperfect matches (expired certificates
-     * and certificates with the wrong extensions).
-     * The perfect matches will be first in the array.
-     */
-    public String[] getAliases(String keyType, Principal[] issuers,
-            CheckType checkType, AlgorithmConstraints constraints) {
-        if (keyType == null) {
-            return null;
-        }
-
-        Set<Principal> issuerSet = getIssuerSet(issuers);
-        List<KeyType> keyTypeList = getKeyTypes(keyType);
-        List<EntryStatus> allResults = null;
-        for (int i = 0, n = builders.size(); i < n; i++) {
-            try {
-                List<EntryStatus> results = getAliases(i, keyTypeList,
-                                    issuerSet, true, checkType, constraints,
-                                    null, null);
-                if (results != null) {
-                    if (allResults == null) {
-                        allResults = new ArrayList<EntryStatus>();
-                    }
-                    allResults.addAll(results);
-                }
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-        if (allResults == null || allResults.isEmpty()) {
-            if (useDebug) {
-                debug.println("KeyMgr: no matching alias found");
-            }
-            return null;
-        }
-        Collections.sort(allResults);
-        if (useDebug) {
-            debug.println("KeyMgr: getting aliases: " + allResults);
-        }
-        return toAliases(allResults);
-    }
-
-    // turn candidate entries into unique aliases we can return to JSSE
-    private String[] toAliases(List<EntryStatus> results) {
-        String[] s = new String[results.size()];
-        int i = 0;
-        for (EntryStatus result : results) {
-            s[i++] = makeAlias(result);
-        }
-        return s;
-    }
-
-    // make a Set out of the array
-    private Set<Principal> getIssuerSet(Principal[] issuers) {
-        if ((issuers != null) && (issuers.length != 0)) {
-            return new HashSet<>(Arrays.asList(issuers));
-        } else {
-            return null;
-        }
-    }
-
-    // a candidate match
-    // identifies the entry by builder and alias
-    // and includes the result of the certificate check
-    private static class EntryStatus implements Comparable<EntryStatus> {
-
-        final int builderIndex;
-        final int keyIndex;
-        final String alias;
-        final CheckResult checkResult;
-
-        EntryStatus(int builderIndex, int keyIndex, String alias,
-                Certificate[] chain, CheckResult checkResult) {
-            this.builderIndex = builderIndex;
-            this.keyIndex = keyIndex;
-            this.alias = alias;
-            this.checkResult = checkResult;
-        }
-
-        @Override
-        public int compareTo(EntryStatus other) {
-            int result = this.checkResult.compareTo(other.checkResult);
-            return (result == 0) ? (this.keyIndex - other.keyIndex) : result;
-        }
-
-        @Override
-        public String toString() {
-            String s = alias + " (verified: " + checkResult + ")";
-            if (builderIndex == 0) {
-                return s;
-            } else {
-                return "Builder #" + builderIndex + ", alias: " + s;
-            }
-        }
-    }
-
-    // enum for the type of certificate check we want to perform
-    // (client or server)
-    // also includes the check code itself
-    private static enum CheckType {
-
-        // enum constant for "no check" (currently not used)
-        NONE(Collections.<String>emptySet()),
-
-        // enum constant for "tls client" check
-        // valid EKU for TLS client: any, tls_client
-        CLIENT(new HashSet<String>(Arrays.asList(new String[] {
-            "2.5.29.37.0", "1.3.6.1.5.5.7.3.2" }))),
-
-        // enum constant for "tls server" check
-        // valid EKU for TLS server: any, tls_server, ns_sgc, ms_sgc
-        SERVER(new HashSet<String>(Arrays.asList(new String[] {
-            "2.5.29.37.0", "1.3.6.1.5.5.7.3.1", "2.16.840.1.113730.4.1",
-            "1.3.6.1.4.1.311.10.3.3" })));
-
-        // set of valid EKU values for this type
-        final Set<String> validEku;
-
-        CheckType(Set<String> validEku) {
-            this.validEku = validEku;
-        }
-
-        private static boolean getBit(boolean[] keyUsage, int bit) {
-            return (bit < keyUsage.length) && keyUsage[bit];
-        }
-
-        // check if this certificate is appropriate for this type of use
-        // first check extensions, if they match, check expiration
-        // note: we may want to move this code into the sun.security.validator
-        // package
-        CheckResult check(X509Certificate cert, Date date,
-                List<SNIServerName> serverNames, String idAlgorithm) {
-
-            if (this == NONE) {
-                return CheckResult.OK;
-            }
-
-            // check extensions
-            try {
-                // check extended key usage
-                List<String> certEku = cert.getExtendedKeyUsage();
-                if ((certEku != null) &&
-                        Collections.disjoint(validEku, certEku)) {
-                    // if extension present and it does not contain any of
-                    // the valid EKU OIDs, return extension_mismatch
-                    return CheckResult.EXTENSION_MISMATCH;
-                }
-
-                // check key usage
-                boolean[] ku = cert.getKeyUsage();
-                if (ku != null) {
-                    String algorithm = cert.getPublicKey().getAlgorithm();
-                    boolean kuSignature = getBit(ku, 0);
-                    switch (algorithm) {
-                        case "RSA":
-                            // require either signature bit
-                            // or if server also allow key encipherment bit
-                            if (kuSignature == false) {
-                                if ((this == CLIENT) || (getBit(ku, 2) == false)) {
-                                    return CheckResult.EXTENSION_MISMATCH;
-                                }
-                            }
-                            break;
-                        case "DSA":
-                            // require signature bit
-                            if (kuSignature == false) {
-                                return CheckResult.EXTENSION_MISMATCH;
-                            }
-                            break;
-                        case "DH":
-                            // require keyagreement bit
-                            if (getBit(ku, 4) == false) {
-                                return CheckResult.EXTENSION_MISMATCH;
-                            }
-                            break;
-                        case "EC":
-                            // require signature bit
-                            if (kuSignature == false) {
-                                return CheckResult.EXTENSION_MISMATCH;
-                            }
-                            // For servers, also require key agreement.
-                            // This is not totally accurate as the keyAgreement
-                            // bit is only necessary for static ECDH key
-                            // exchange and not ephemeral ECDH. We leave it in
-                            // for now until there are signs that this check
-                            // causes problems for real world EC certificates.
-                            if ((this == SERVER) && (getBit(ku, 4) == false)) {
-                                return CheckResult.EXTENSION_MISMATCH;
-                            }
-                            break;
-                    }
-                }
-            } catch (CertificateException e) {
-                // extensions unparseable, return failure
-                return CheckResult.EXTENSION_MISMATCH;
-            }
-
-            try {
-                cert.checkValidity(date);
-            } catch (CertificateException e) {
-                return CheckResult.EXPIRED;
-            }
-
-            if (serverNames != null && !serverNames.isEmpty()) {
-                for (SNIServerName serverName : serverNames) {
-                    if (serverName.getType() ==
-                                StandardConstants.SNI_HOST_NAME) {
-                        if (!(serverName instanceof SNIHostName)) {
-                            try {
-                                serverName =
-                                    new SNIHostName(serverName.getEncoded());
-                            } catch (IllegalArgumentException iae) {
-                                // unlikely to happen, just in case ...
-                                if (useDebug) {
-                                    debug.println(
-                                       "Illegal server name: " + serverName);
-                                }
-
-                                return CheckResult.INSENSITIVE;
-                            }
-                        }
-                        String hostname =
-                                ((SNIHostName)serverName).getAsciiName();
-
-                        try {
-                            X509TrustManagerImpl.checkIdentity(hostname,
-                                                        cert, idAlgorithm);
-                        } catch (CertificateException e) {
-                            if (useDebug) {
-                                debug.println(
-                                   "Certificate identity does not match " +
-                                   "Server Name Inidication (SNI): " +
-                                   hostname);
-                            }
-                            return CheckResult.INSENSITIVE;
-                        }
-
-                        break;
-                    }
-                }
-            }
-
-            return CheckResult.OK;
-        }
-
-        public String getValidator() {
-            if (this == CLIENT) {
-                return Validator.VAR_TLS_CLIENT;
-            } else if (this == SERVER) {
-                return Validator.VAR_TLS_SERVER;
-            }
-            return Validator.VAR_GENERIC;
-        }
-    }
-
-    // enum for the result of the extension check
-    // NOTE: the order of the constants is important as they are used
-    // for sorting, i.e. OK is best, followed by EXPIRED and EXTENSION_MISMATCH
-    private static enum CheckResult {
-        OK,                     // ok or not checked
-        INSENSITIVE,            // server name indication insensitive
-        EXPIRED,                // extensions valid but cert expired
-        EXTENSION_MISMATCH,     // extensions invalid (expiration not checked)
-    }
-
-    /*
-     * Return a List of all candidate matches in the specified builder
-     * that fit the parameters.
-     * We exclude entries in the KeyStore if they are not:
-     *  . private key entries
-     *  . the certificates are not X509 certificates
-     *  . the algorithm of the key in the EE cert doesn't match one of keyTypes
-     *  . none of the certs is issued by a Principal in issuerSet
-     * Using those entries would not be possible or they would almost
-     * certainly be rejected by the peer.
-     *
-     * In addition to those checks, we also check the extensions in the EE
-     * cert and its expiration. Even if there is a mismatch, we include
-     * such certificates because they technically work and might be accepted
-     * by the peer. This leads to more graceful failure and better error
-     * messages if the cert expires from one day to the next.
-     *
-     * The return values are:
-     *   . null, if there are no matching entries at all
-     *   . if 'findAll' is 'false' and there is a perfect match, a List
-     *     with a single element (early return)
-     *   . if 'findAll' is 'false' and there is NO perfect match, a List
-     *     with all the imperfect matches (expired, wrong extensions)
-     *   . if 'findAll' is 'true', a List with all perfect and imperfect
-     *     matches
-     */
-    private List<EntryStatus> getAliases(int builderIndex,
-            List<KeyType> keyTypes, Set<Principal> issuerSet,
-            boolean findAll, CheckType checkType,
-            AlgorithmConstraints constraints,
-            List<SNIServerName> requestedServerNames,
-            String idAlgorithm) throws Exception {
-
-        Builder builder = builders.get(builderIndex);
-        KeyStore ks = builder.getKeyStore();
-        List<EntryStatus> results = null;
-        Date date = verificationDate;
-        boolean preferred = false;
-        for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
-            String alias = e.nextElement();
-            // check if it is a key entry (private key or secret key)
-            if (ks.isKeyEntry(alias) == false) {
-                continue;
-            }
-
-            Certificate[] chain = ks.getCertificateChain(alias);
-            if ((chain == null) || (chain.length == 0)) {
-                // must be secret key entry, ignore
-                continue;
-            }
-
-            boolean incompatible = false;
-            for (Certificate cert : chain) {
-                if (cert instanceof X509Certificate == false) {
-                    // not an X509Certificate, ignore this alias
-                    incompatible = true;
-                    break;
-                }
-            }
-            if (incompatible) {
-                continue;
-            }
-
-            // check keytype
-            int keyIndex = -1;
-            int j = 0;
-            for (KeyType keyType : keyTypes) {
-                if (keyType.matches(chain)) {
-                    keyIndex = j;
-                    break;
-                }
-                j++;
-            }
-            if (keyIndex == -1) {
-                if (useDebug) {
-                    debug.println("Ignoring alias " + alias
-                                + ": key algorithm does not match");
-                }
-                continue;
-            }
-            // check issuers
-            if (issuerSet != null) {
-                boolean found = false;
-                for (Certificate cert : chain) {
-                    X509Certificate xcert = (X509Certificate)cert;
-                    if (issuerSet.contains(xcert.getIssuerX500Principal())) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (found == false) {
-                    if (useDebug) {
-                        debug.println("Ignoring alias " + alias
-                                    + ": issuers do not match");
-                    }
-                    continue;
-                }
-            }
-
-            // check the algorithm constraints
-            if (constraints != null &&
-                    !conformsToAlgorithmConstraints(constraints, chain,
-                            checkType.getValidator())) {
-
-                if (useDebug) {
-                    debug.println("Ignoring alias " + alias +
-                            ": certificate list does not conform to " +
-                            "algorithm constraints");
-                }
-                continue;
-            }
-
-            if (date == null) {
-                date = new Date();
-            }
-            CheckResult checkResult =
-                    checkType.check((X509Certificate)chain[0], date,
-                                    requestedServerNames, idAlgorithm);
-            EntryStatus status =
-                    new EntryStatus(builderIndex, keyIndex,
-                                        alias, chain, checkResult);
-            if (!preferred && checkResult == CheckResult.OK && keyIndex == 0) {
-                preferred = true;
-            }
-            if (preferred && (findAll == false)) {
-                // if we have a good match and do not need all matches,
-                // return immediately
-                return Collections.singletonList(status);
-            } else {
-                if (results == null) {
-                    results = new ArrayList<EntryStatus>();
-                }
-                results.add(status);
-            }
-        }
-        return results;
-    }
-
-    private static boolean conformsToAlgorithmConstraints(
-            AlgorithmConstraints constraints, Certificate[] chain,
-            String variant) {
-
-        AlgorithmChecker checker = new AlgorithmChecker(constraints, null, variant);
-        try {
-            checker.init(false);
-        } catch (CertPathValidatorException cpve) {
-            // unlikely to happen
-            if (useDebug) {
-                debug.println(
-                    "Cannot initialize algorithm constraints checker: " + cpve);
-            }
-
-            return false;
-        }
-
-        // It is a forward checker, so we need to check from trust to target.
-        for (int i = chain.length - 1; i >= 0; i--) {
-            Certificate cert = chain[i];
-            try {
-                // We don't care about the unresolved critical extensions.
-                checker.check(cert, Collections.<String>emptySet());
-            } catch (CertPathValidatorException cpve) {
-                if (useDebug) {
-                    debug.println("Certificate (" + cert +
-                        ") does not conform to algorithm constraints: " + cpve);
-                }
-
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-}
--- a/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java	Sat Aug 01 03:20:01 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,474 +0,0 @@
-/*
- * Copyright (c) 1997, 2016, 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.net.Socket;
-import javax.net.ssl.SSLSession;
-
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-import javax.net.ssl.*;
-
-import sun.security.validator.*;
-import sun.security.util.HostnameChecker;
-
-/**
- * This class implements the SunJSSE X.509 trust manager using the internal
- * validator API in J2SE core. The logic in this class is minimal.<p>
- * <p>
- * This class supports both the Simple validation algorithm from previous
- * JSSE versions and PKIX validation. Currently, it is not possible for the
- * application to specify PKIX parameters other than trust anchors. This will
- * be fixed in a future release using new APIs. When that happens, it may also
- * make sense to separate the Simple and PKIX trust managers into separate
- * classes.
- *
- * @author Andreas Sterbenz
- */
-final class X509TrustManagerImpl extends X509ExtendedTrustManager
-        implements X509TrustManager {
-
-    private final String validatorType;
-
-    /**
-     * The Set of trusted X509Certificates.
-     */
-    private final Collection<X509Certificate> trustedCerts;
-
-    private final PKIXBuilderParameters pkixParams;
-
-    // note that we need separate validator for client and server due to
-    // the different extension checks. They are initialized lazily on demand.
-    private volatile Validator clientValidator, serverValidator;
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    X509TrustManagerImpl(String validatorType,
-            Collection<X509Certificate> trustedCerts) {
-
-        this.validatorType = validatorType;
-        this.pkixParams = null;
-
-        if (trustedCerts == null) {
-            trustedCerts = Collections.<X509Certificate>emptySet();
-        }
-
-        this.trustedCerts = trustedCerts;
-
-        if (debug != null && Debug.isOn("trustmanager")) {
-            showTrustedCerts();
-        }
-    }
-
-    X509TrustManagerImpl(String validatorType, PKIXBuilderParameters params) {
-        this.validatorType = validatorType;
-        this.pkixParams = params;
-        // create server validator eagerly so that we can conveniently
-        // get the trusted certificates
-        // clients need it anyway eventually, and servers will not mind
-        // the little extra footprint
-        Validator v = getValidator(Validator.VAR_TLS_SERVER);
-        trustedCerts = v.getTrustedCertificates();
-        serverValidator = v;
-
-        if (debug != null && Debug.isOn("trustmanager")) {
-            showTrustedCerts();
-        }
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        checkTrusted(chain, authType, (Socket)null, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        checkTrusted(chain, authType, (Socket)null, false);
-    }
-
-    @Override
-    public X509Certificate[] getAcceptedIssuers() {
-        X509Certificate[] certsArray = new X509Certificate[trustedCerts.size()];
-        trustedCerts.toArray(certsArray);
-        return certsArray;
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-                Socket socket) throws CertificateException {
-        checkTrusted(chain, authType, socket, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            Socket socket) throws CertificateException {
-        checkTrusted(chain, authType, socket, false);
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        checkTrusted(chain, authType, engine, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        checkTrusted(chain, authType, engine, false);
-    }
-
-    private Validator checkTrustedInit(X509Certificate[] chain,
-            String authType, boolean checkClientTrusted) {
-        if (chain == null || chain.length == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length certificate chain");
-        }
-
-        if (authType == null || authType.length() == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length authentication type");
-        }
-
-        Validator v = null;
-        if (checkClientTrusted) {
-            v = clientValidator;
-            if (v == null) {
-                synchronized (this) {
-                    v = clientValidator;
-                    if (v == null) {
-                        v = getValidator(Validator.VAR_TLS_CLIENT);
-                        clientValidator = v;
-                    }
-                }
-            }
-        } else {
-            // assume double checked locking with a volatile flag works
-            // (guaranteed under the new Tiger memory model)
-            v = serverValidator;
-            if (v == null) {
-                synchronized (this) {
-                    v = serverValidator;
-                    if (v == null) {
-                        v = getValidator(Validator.VAR_TLS_SERVER);
-                        serverValidator = v;
-                    }
-                }
-            }
-        }
-
-        return v;
-    }
-
-
-    private void checkTrusted(X509Certificate[] chain,
-            String authType, Socket socket,
-            boolean checkClientTrusted) throws CertificateException {
-        Validator v = checkTrustedInit(chain, authType, checkClientTrusted);
-
-        AlgorithmConstraints constraints = null;
-        if ((socket != null) && socket.isConnected() &&
-                                        (socket instanceof SSLSocket)) {
-
-            SSLSocket sslSocket = (SSLSocket)socket;
-            SSLSession session = sslSocket.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = sslSocket.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                checkIdentity(session, chain, identityAlg, checkClientTrusted);
-            }
-
-            // create the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] localSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    sslSocket, localSupportedSignAlgs, false);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(sslSocket, false);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(sslSocket, false);
-            }
-        }
-
-        X509Certificate[] trustedChain = null;
-        if (checkClientTrusted) {
-            trustedChain = validate(v, chain, constraints, null);
-        } else {
-            trustedChain = validate(v, chain, constraints, authType);
-        }
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    private void checkTrusted(X509Certificate[] chain,
-            String authType, SSLEngine engine,
-            boolean checkClientTrusted) throws CertificateException {
-        Validator v = checkTrustedInit(chain, authType, checkClientTrusted);
-
-        AlgorithmConstraints constraints = null;
-        if (engine != null) {
-            SSLSession session = engine.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = engine.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                checkIdentity(session, chain, identityAlg, checkClientTrusted);
-            }
-
-            // create the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] localSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    engine, localSupportedSignAlgs, false);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(engine, false);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(engine, false);
-            }
-        }
-
-        X509Certificate[] trustedChain = null;
-        if (checkClientTrusted) {
-            trustedChain = validate(v, chain, constraints, null);
-        } else {
-            trustedChain = validate(v, chain, constraints, authType);
-        }
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    private void showTrustedCerts() {
-        for (X509Certificate cert : trustedCerts) {
-            System.out.println("adding as trusted cert:");
-            System.out.println("  Subject: "
-                                    + cert.getSubjectX500Principal());
-            System.out.println("  Issuer:  "
-                                    + cert.getIssuerX500Principal());
-            System.out.println("  Algorithm: "
-                                    + cert.getPublicKey().getAlgorithm()
-                                    + "; Serial number: 0x"
-                                    + cert.getSerialNumber().toString(16));
-            System.out.println("  Valid from "
-                                    + cert.getNotBefore() + " until "
-                                    + cert.getNotAfter());
-            System.out.println();
-        }
-    }
-
-    private Validator getValidator(String variant) {
-        Validator v;
-        if (pkixParams == null) {
-            v = Validator.getInstance(validatorType, variant, trustedCerts);
-        } else {
-            v = Validator.getInstance(validatorType, variant, pkixParams);
-        }
-        return v;
-    }
-
-    private static X509Certificate[] validate(Validator v,
-            X509Certificate[] chain, AlgorithmConstraints constraints,
-            String authType) throws CertificateException {
-        Object o = JsseJce.beginFipsProvider();
-        try {
-            return v.validate(chain, null, constraints, authType);
-        } finally {
-            JsseJce.endFipsProvider(o);
-        }
-    }
-
-    // Get string representation of HostName from a list of server names.
-    //
-    // We are only accepting host_name name type in the list.
-    private static String getHostNameInSNI(List<SNIServerName> sniNames) {
-
-        SNIHostName hostname = null;
-        for (SNIServerName sniName : sniNames) {
-            if (sniName.getType() != StandardConstants.SNI_HOST_NAME) {
-                continue;
-            }
-
-            if (sniName instanceof SNIHostName) {
-                hostname = (SNIHostName)sniName;
-            } else {
-                try {
-                    hostname = new SNIHostName(sniName.getEncoded());
-                } catch (IllegalArgumentException iae) {
-                    // unlikely to happen, just in case ...
-                    if ((debug != null) && Debug.isOn("trustmanager")) {
-                        System.out.println("Illegal server name: " + sniName);
-                    }
-                }
-            }
-
-            // no more than server name of the same name type
-            break;
-        }
-
-        if (hostname != null) {
-            return hostname.getAsciiName();
-        }
-
-        return null;
-    }
-
-    // Also used by X509KeyManagerImpl
-    static List<SNIServerName> getRequestedServerNames(Socket socket) {
-        if (socket != null && socket.isConnected() &&
-                                        socket instanceof SSLSocket) {
-
-            return getRequestedServerNames(
-                    ((SSLSocket)socket).getHandshakeSession());
-        }
-
-        return Collections.<SNIServerName>emptyList();
-    }
-
-    // Also used by X509KeyManagerImpl
-    static List<SNIServerName> getRequestedServerNames(SSLEngine engine) {
-        if (engine != null) {
-            return getRequestedServerNames(engine.getHandshakeSession());
-        }
-
-        return Collections.<SNIServerName>emptyList();
-    }
-
-    private static List<SNIServerName> getRequestedServerNames(
-            SSLSession session) {
-        if (session != null && (session instanceof ExtendedSSLSession)) {
-            return ((ExtendedSSLSession)session).getRequestedServerNames();
-        }
-
-        return Collections.<SNIServerName>emptyList();
-    }
-
-    /*
-     * Per RFC 6066, if an application negotiates a server name using an
-     * application protocol and then upgrades to TLS, and if a server_name
-     * extension is sent, then the extension SHOULD contain the same name
-     * that was negotiated in the application protocol.  If the server_name
-     * is established in the TLS session handshake, the client SHOULD NOT
-     * attempt to request a different server name at the application layer.
-     *
-     * According to the above spec, we only need to check either the identity
-     * in server_name extension or the peer host of the connection.  Peer host
-     * is not always a reliable fully qualified domain name. The HostName in
-     * server_name extension is more reliable than peer host. So we prefer
-     * the identity checking aginst the server_name extension if present, and
-     * may failove to peer host checking.
-     */
-    static void checkIdentity(SSLSession session,
-            X509Certificate [] trustedChain,
-            String algorithm,
-            boolean checkClientTrusted) throws CertificateException {
-
-        boolean identifiable = false;
-        String peerHost = session.getPeerHost();
-        if (!checkClientTrusted) {
-            List<SNIServerName> sniNames = getRequestedServerNames(session);
-            String sniHostName = getHostNameInSNI(sniNames);
-            if (sniHostName != null) {
-                try {
-                    checkIdentity(sniHostName,
-                            trustedChain[0], algorithm);
-                    identifiable = true;
-                } catch (CertificateException ce) {
-                    if (sniHostName.equalsIgnoreCase(peerHost)) {
-                        throw ce;
-                    }
-
-                    // otherwisw, failover to check peer host
-                }
-            }
-        }
-
-        if (!identifiable) {
-            checkIdentity(peerHost,
-                    trustedChain[0], algorithm);
-        }
-    }
-
-    /*
-     * Identify the peer by its certificate and hostname.
-     *
-     * Lifted from sun.net.www.protocol.https.HttpsClient.
-     */
-    static void checkIdentity(String hostname, X509Certificate cert,
-            String algorithm) throws CertificateException {
-        if (algorithm != null && algorithm.length() != 0) {
-            // if IPv6 strip off the "[]"
-            if ((hostname != null) && hostname.startsWith("[") &&
-                    hostname.endsWith("]")) {
-                hostname = hostname.substring(1, hostname.length() - 1);
-            }
-
-            if (algorithm.equalsIgnoreCase("HTTPS")) {
-                HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match(
-                        hostname, cert);
-            } else if (algorithm.equalsIgnoreCase("LDAP") ||
-                    algorithm.equalsIgnoreCase("LDAPS")) {
-                HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP).match(
-                        hostname, cert);
-            } else {
-                throw new CertificateException(
-                        "Unknown identification algorithm: " + algorithm);
-            }
-        }
-    }
-}