src/java.base/share/classes/sun/security/ssl/HandshakeStateManager.java
changeset 50768 68fa3d4026ea
parent 50767 356eaea05bf0
child 50769 1bf8f9840705
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeStateManager.java	Mon Jun 25 21:22:16 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,922 +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)            |
- *      |     -------------------------------------------->       |
- *      |                                                         |
- *      |   -      HelloVerifyRequest (No.3, RFC 6347)      -     |
- *      | D | <-------------------------------------------- | D   |
- *      | T |                                               | T   |
- *      | L |      ClientHello        (No.1, RFC 5246)      | L   |
- *      | S | --------------------------------------------> | S   |
- *      |   -                                               -     |
- *      |                                                         |
- *   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 boolean isDTLS;
-
-    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<>(15);
-
-        handshakeTypes.put(ht_hello_request,            "hello_request");
-        handshakeTypes.put(ht_client_hello,             "client_hello");
-        handshakeTypes.put(ht_server_hello,             "server_hello");
-        handshakeTypes.put(ht_hello_verify_request,     "hello_verify_request");
-        handshakeTypes.put(ht_new_session_ticket,       "session_ticket");
-        handshakeTypes.put(ht_certificate,              "certificate");
-        handshakeTypes.put(ht_server_key_exchange,      "server_key_exchange");
-        handshakeTypes.put(ht_certificate_request,      "certificate_request");
-        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");
-        handshakeTypes.put(ht_certificate_url,          "certificate_url");
-        handshakeTypes.put(ht_certificate_status,       "certificate_status");
-        handshakeTypes.put(ht_supplemental_data,        "supplemental_data");
-    }
-
-    HandshakeStateManager(boolean isDTLS) {
-        this.upcomingStates = new LinkedList<>();
-        this.alternatives = new LinkedList<>();
-        this.isDTLS = isDTLS;
-    }
-
-    //
-    // 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_HELLO_VERIFY_REQUEST(
-                "hello_verify_request",
-                HandshakeMessage.ht_hello_verify_request),
-        HS_SERVER_HELLO(
-                "server_hello",
-                HandshakeMessage.ht_server_hello),
-        HS_SERVER_SUPPLEMENTAL_DATA(
-                "server supplemental_data",
-                HandshakeMessage.ht_supplemental_data, true),
-        HS_SERVER_CERTIFICATE(
-                "server certificate",
-                HandshakeMessage.ht_certificate),
-        HS_CERTIFICATE_STATUS(
-                "certificate_status",
-                HandshakeMessage.ht_certificate_status, true),
-        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_SUPPLEMENTAL_DATA(
-                "client supplemental_data",
-                HandshakeMessage.ht_supplemental_data, true),
-        HS_CLIENT_CERTIFICATE(
-                "client certificate",
-                HandshakeMessage.ht_certificate, true),
-        HS_CERTIFICATE_URL(
-                "certificate_url",
-                HandshakeMessage.ht_certificate_url, 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_CLEINT_FINISHED(
-                "client finished",
-                HandshakeMessage.ht_finished),
-        HS_NEW_SESSION_TICKET(
-                "session_ticket",
-                HandshakeMessage.ht_new_session_ticket),
-        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_HELLO_VERIFY_REQUEST (DTLS)
-            //              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;
-            if (isDTLS) {
-                // Is it an initial ClientHello message?
-                if (clientHello.cookie == null ||
-                        clientHello.cookie.length == 0) {
-                    // Is it an abbreviated handshake?
-                    if (clientHello.sessionId.length() != 0) {
-                        // A HelloVerifyRequest message or a ServerHello
-                        // message may follow the abbreviated session
-                        // resuming handshake request.
-                        upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
-                        alternatives.add(HS_SERVER_HELLO);
-                    } else {
-                        // A HelloVerifyRequest message should follow
-                        // the initial ClientHello message.
-                        upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
-                    }
-                } else {
-                    // A HelloVerifyRequest may be followed if the cookie
-                    // cannot be verified.
-                    upcomingStates.add(HS_SERVER_HELLO);
-                    alternatives.add(HS_HELLO_VERIFY_REQUEST);
-                }
-            } else {
-                upcomingStates.add(HS_SERVER_HELLO);
-            }
-
-            break;
-
-        case HandshakeMessage.ht_hello_verify_request:
-            //
-            // State machine:
-            //     PRESENT: HS_HELLO_VERIFY_REQUEST
-            //        TO  : HS_CLIENT_HELLO
-            //
-            // Note that this state may have an alternative option.
-
-            // Check and update the present state.
-            if (!upcomingStates.isEmpty()) {
-                // The current state should be HS_HELLO_VERIFY_REQUEST.
-                HandshakeState handshakeState = upcomingStates.pop();
-                HandshakeState alternative = null;
-                if (!alternatives.isEmpty()) {
-                    alternative = alternatives.pop();
-                }
-
-                if ((handshakeState != HS_HELLO_VERIFY_REQUEST) &&
-                        (alternative != HS_HELLO_VERIFY_REQUEST)) {
-
-                    throw new SSLProtocolException(exceptionMsg);
-                }
-            } else {
-                // No present state.
-                throw new SSLProtocolException(exceptionMsg);
-            }
-
-            // Add the upcoming states.
-            upcomingStates.add(HS_CLIENT_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_CLEINT_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_CLEINT_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_CLEINT_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);
-                }
-
-                // Optional CertificateStatus message
-                if (hes.get(ExtensionType.EXT_STATUS_REQUEST) != null ||
-                        hes.get(ExtensionType.EXT_STATUS_REQUEST_V2) != null) {
-                    upcomingStates.add(HS_CERTIFICATE_STATUS);
-                }
-
-                // 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_CLEINT_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;
-
-        // Not support CertificateURL extension yet.
-        /*************************************************/
-        case HandshakeMessage.ht_certificate_url:
-            //
-            // State machine:
-            //     PRESENT: HS_CERTIFICATE_URL or
-            //              HS_CLIENT_CERTIFICATE
-            //        TO  : HS_CLIENT_KEY_EXCHANGE
-            //
-            // Note that this state may have an alternative option.
-
-            // Check and update the present state.
-            while (!upcomingStates.isEmpty()) {
-                // The current state should be HS_CLIENT_CERTIFICATE.
-                //
-                // Note that we won't put HS_CLIENT_CERTIFICATE into
-                // the alternative list.
-                HandshakeState handshakeState = upcomingStates.pop();
-                if (handshakeState.handshakeType ==
-                        HS_CLIENT_CERTIFICATE.handshakeType) {
-                    hasPresentState = true;
-
-                    // Look for HS_CERTIFICATE_URL state track.
-                    if (!alternatives.isEmpty()) {
-                        HandshakeState alternative = alternatives.pop();
-
-                        if (alternative != HS_CERTIFICATE_URL) {
-                            throw new SSLProtocolException(exceptionMsg);
-                        }
-                    } else {
-                        // No alternative CertificateUR state track.
-                        throw new SSLProtocolException(exceptionMsg);
-                    }
-
-                    if ((handshakeState != HS_CLIENT_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) {
-                // No present state.
-                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 + "]");
-    }
-}
-