--- a/src/java.base/share/classes/sun/security/ssl/HandshakeStateManager.java Fri May 11 14:55:56 2018 -0700
+++ /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 + "]");
- }
-}
-