1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.util.LinkedList;
  29 import java.util.HashMap;
  30 import javax.net.ssl.SSLProtocolException;
  31 
  32 import sun.security.ssl.HandshakeMessage.*;
  33 
  34 import static sun.security.ssl.CipherSuite.KeyExchange;
  35 import static sun.security.ssl.CipherSuite.KeyExchange.*;
  36 import static sun.security.ssl.HandshakeStateManager.HandshakeState.*;
  37 import static sun.security.ssl.HandshakeMessage.*;
  38 
  39 /*
  40  * Handshake state manager.
  41  *
  42  * Messages flow for a full handshake:
  43  *
  44  *      -                                                         -
  45  *      |          HelloRequest       (No.0, RFC 5246) [*]        |
  46  *      |     <--------------------------------------------       |
  47  *      |                                                         |
  48  *      |          ClientHello        (No.1, RFC 5246)            |
  49  *      |     -------------------------------------------->       |
  50  *      |                                                         |
  51  *      |   -      HelloVerifyRequest (No.3, RFC 6347)      -     |
  52  *      | D | <-------------------------------------------- | D   |
  53  *      | T |                                               | T   |
  54  *      | L |      ClientHello        (No.1, RFC 5246)      | L   |
  55  *      | S | --------------------------------------------> | S   |
  56  *      |   -                                               -     |
  57  *      |                                                         |
  58  *   C  |          ServerHello        (No.2, RFC 5246)            |  S
  59  *   L  |          SupplementalData   (No.23, RFC4680) [*]        |  E
  60  *   I  |          Certificate        (No.11, RFC 5246) [*]       |  R
  61  *   E  |          CertificateStatus  (No.22, RFC 6066) [*]       |  V
  62  *   N  |          ServerKeyExchange  (No.12, RFC 5246) [*]       |  E
  63  *   T  |          CertificateRequest (No.13, RFC 5246) [*]       |  R
  64  *      |          ServerHelloDone    (No.14, RFC 5246)           |
  65  *      |     <--------------------------------------------       |
  66  *      |                                                         |
  67  *      |          SupplementalData   (No.23, RFC4680) [*]        |
  68  *      |          Certificate        (No.11, RFC 5246) [*] Or    |
  69  *      |              CertificateURL (No.21, RFC6066) [*]        |
  70  *      |          ClientKeyExchange  (No.16, RFC 5246)           |
  71  *      |          CertificateVerify  (No.15, RFC 5246) [*]       |
  72  *      |          [ChangeCipherSpec] (RFC 5246)                  |
  73  *      |          Finished           (No.20, RFC 5246)           |
  74  *      |     -------------------------------------------->       |
  75  *      |                                                         |
  76  *      |          NewSessionTicket   (No.4, RFC4507) [*]         |
  77  *      |          [ChangeCipherSpec] (RFC 5246)                  |
  78  *      |          Finished           (No.20, RFC 5246)           |
  79  *      |     <--------------------------------------------       |
  80  *      -                                                         -
  81  * [*] Indicates optional or situation-dependent messages that are not
  82  * always sent.
  83  *
  84  * Message flow for an abbreviated handshake:
  85  *      -                                                         -
  86  *      |          ClientHello        (No.1, RFC 5246)            |
  87  *      |     -------------------------------------------->       |
  88  *      |                                                         |
  89  *   C  |          ServerHello        (No.2, RFC 5246)            |  S
  90  *   L  |          NewSessionTicket   (No.4, RFC4507) [*]         |  E
  91  *   I  |          [ChangeCipherSpec] (RFC 5246)                  |  R
  92  *   E  |          Finished           (No.20, RFC 5246)           |  V
  93  *   N  |     <--------------------------------------------       |  E
  94  *   T  |                                                         |  R
  95  *      |          [ChangeCipherSpec] (RFC 5246)                  |
  96  *      |          Finished           (No.20, RFC 5246)           |
  97  *      |     -------------------------------------------->       |
  98  *      -                                                         -
  99  *
 100  *
 101  * State machine of handshake states:
 102  *
 103  *                   +--------------+
 104  *      START -----> | HelloRequest |
 105  *        |          +--------------+
 106  *        |               |
 107  *        v               v
 108  *     +---------------------+   -->  +---------------------+
 109  *     |    ClientHello      |        | HelloVerifyRequest  |
 110  *     +---------------------+   <--  +---------------------+
 111  *               |
 112  *               |
 113  * =========================================================================
 114  *               |
 115  *               v
 116  *     +---------------------+
 117  *     |    ServerHello      |  ----------------------------------+------+
 118  *     +---------------------+  -->  +-------------------------+  |      |
 119  *                    |              | Server SupplementalData |  |      |
 120  *                    |              +-------------------------+  |      |
 121  *                    |                |                          |      |
 122  *                    v                v                          |      |
 123  *                +---------------------+                         |      |
 124  *         +----  | Server Certificate  |                         |      |
 125  *         |      +---------------------+                         |      |
 126  *         |          |                                           |      |
 127  *         |          |   +--------------------+                  |      |
 128  *         |          +-> | CertificateStatus  |                  |      |
 129  *         |          |   +--------------------+                  v      |
 130  *         |          |      |          |     +--------------------+     |
 131  *         |          v      v          +-->  | ServerKeyExchange  |     |
 132  *         |  +---------------------+   |     +--------------------+     |
 133  *         |  | CertificateRequest  |   |         |                      |
 134  *         |  +---------------------+ <-+---------+                      |
 135  *         |            |               |         |                      |
 136  *         v            v               |         |                      |
 137  *     +---------------------+  <-------+         |                      |
 138  *     |  ServerHelloDone    |  <-----------------+                      |
 139  *     +---------------------+                                           |
 140  *       |         |                                                     |
 141  *       |         |                                                     |
 142  *       |         |                                                     |
 143  * =========================================================================
 144  *       |         |                                                     |
 145  *       |         v                                                     |
 146  *       |   +-------------------------+                                 |
 147  *       |   | Client SupplementalData | --------------+                 |
 148  *       |   +-------------------------+               |                 |
 149  *       |             |                               |                 |
 150  *       |             v                               |                 |
 151  *       |   +--------------------+                    |                 |
 152  *       +-> | Client Certificate | ALT.               |                 |
 153  *       |   +--------------------+----------------+   |                 |
 154  *       |                        | CertificateURL |   |                 |
 155  *       |                        +----------------+   |                 |
 156  *       v                                             |                 |
 157  *     +-------------------+  <------------------------+                 |
 158  *     | ClientKeyExchange |                                             |
 159  *     +-------------------+                                             |
 160  *          |           |                                                |
 161  *          |           v                                                |
 162  *          |      +-------------------+                                 |
 163  *          |      | CertificateVerify |                                 |
 164  *          |      +-------------------+                                 |
 165  *          |          |                                                 |
 166  *          v          v                                                 |
 167  *     +-------------------------+                                       |
 168  *     | Client ChangeCipherSpec |  <---------------+                    |
 169  *     +-------------------------+                  |                    |
 170  *               |                                  |                    |
 171  *               v                                  |                    |
 172  *     +-----------------+  (abbreviated)           |                    |
 173  *     | Client Finished |  -------------> END      |                    |
 174  *     +-----------------+  (Abbreviated handshake) |                    |
 175  *                      |                           |                    |
 176  *                      | (full)                    |                    |
 177  *                      |                           |                    |
 178  * ================================                 |                    |
 179  *                      |                           |                    |
 180  *                      |                   ================================
 181  *                      |                           |                    |
 182  *                      v                           |                    |
 183  *                 +------------------+             |    (abbreviated)   |
 184  *                 | NewSessionTicket | <--------------------------------+
 185  *                 +------------------+             |                    |
 186  *                      |                           |                    |
 187  *                      v                           |                    |
 188  *     +-------------------------+                  |    (abbreviated)   |
 189  *     | Server ChangeCipherSpec | <-------------------------------------+
 190  *     +-------------------------+                  |
 191  *               |                                  |
 192  *               v                                  |
 193  *     +-----------------+    (abbreviated)         |
 194  *     | Server Finished | -------------------------+
 195  *     +-----------------+
 196  *            | (full)
 197  *            v
 198  *        END (Full handshake)
 199  *
 200  *
 201  * The scenarios of the use of this class:
 202  * 1. Create an instance of HandshakeStateManager during the initializtion
 203  *    handshake.
 204  * 2. If receiving a handshake message, call HandshakeStateManager.check()
 205  *    to make sure that the message is of the expected handshake type.  And
 206  *    then call HandshakeStateManager.update() in case handshake states may
 207  *    be impacted by this new incoming handshake message.
 208  * 3. On delivering a handshake message, call HandshakeStateManager.update()
 209  *    in case handshake states may by thie new outgoing handshake message.
 210  * 4. On receiving and delivering ChangeCipherSpec message, call
 211  *    HandshakeStateManager.changeCipherSpec() to check the present sequence
 212  *    of this message, and update the states if necessary.
 213  */
 214 final class HandshakeStateManager {
 215     // upcoming handshake states.
 216     private LinkedList<HandshakeState> upcomingStates;
 217     private LinkedList<HandshakeState> alternatives;
 218 
 219     private boolean isDTLS;
 220 
 221     private final static boolean debugIsOn;
 222 
 223     private final static HashMap<Byte, String> handshakeTypes;
 224 
 225     static {
 226         debugIsOn = (Handshaker.debug != null) &&
 227                 Debug.isOn("handshake") && Debug.isOn("verbose");
 228         handshakeTypes = new HashMap<>(15);
 229 
 230         handshakeTypes.put(ht_hello_request,            "hello_request");
 231         handshakeTypes.put(ht_client_hello,             "client_hello");
 232         handshakeTypes.put(ht_server_hello,             "server_hello");
 233         handshakeTypes.put(ht_hello_verify_request,     "hello_verify_request");
 234         handshakeTypes.put(ht_new_session_ticket,       "session_ticket");
 235         handshakeTypes.put(ht_certificate,              "certificate");
 236         handshakeTypes.put(ht_server_key_exchange,      "server_key_exchange");
 237         handshakeTypes.put(ht_certificate_request,      "certificate_request");
 238         handshakeTypes.put(ht_server_hello_done,        "server_hello_done");
 239         handshakeTypes.put(ht_certificate_verify,       "certificate_verify");
 240         handshakeTypes.put(ht_client_key_exchange,      "client_key_exchange");
 241         handshakeTypes.put(ht_finished,                 "finished");
 242         handshakeTypes.put(ht_certificate_url,          "certificate_url");
 243         handshakeTypes.put(ht_certificate_status,       "certificate_status");
 244         handshakeTypes.put(ht_supplemental_data,        "supplemental_data");
 245     }
 246 
 247     HandshakeStateManager(boolean isDTLS) {
 248         this.upcomingStates = new LinkedList<>();
 249         this.alternatives = new LinkedList<>();
 250         this.isDTLS = isDTLS;
 251     }
 252 
 253     //
 254     // enumation of handshake type
 255     //
 256     static enum HandshakeState {
 257         HS_HELLO_REQUEST(
 258                 "hello_request",
 259                 HandshakeMessage.ht_hello_request),
 260         HS_CLIENT_HELLO(
 261                 "client_hello",
 262                 HandshakeMessage.ht_client_hello),
 263         HS_HELLO_VERIFY_REQUEST(
 264                 "hello_verify_request",
 265                 HandshakeMessage.ht_hello_verify_request),
 266         HS_SERVER_HELLO(
 267                 "server_hello",
 268                 HandshakeMessage.ht_server_hello),
 269         HS_SERVER_SUPPLEMENTAL_DATA(
 270                 "server supplemental_data",
 271                 HandshakeMessage.ht_supplemental_data, true),
 272         HS_SERVER_CERTIFICATE(
 273                 "server certificate",
 274                 HandshakeMessage.ht_certificate),
 275         HS_CERTIFICATE_STATUS(
 276                 "certificate_status",
 277                 HandshakeMessage.ht_certificate_status, true),
 278         HS_SERVER_KEY_EXCHANGE(
 279                 "server_key_exchange",
 280                 HandshakeMessage.ht_server_key_exchange, true),
 281         HS_CERTIFICATE_REQUEST(
 282                 "certificate_request",
 283                 HandshakeMessage.ht_certificate_request, true),
 284         HS_SERVER_HELLO_DONE(
 285                 "server_hello_done",
 286                 HandshakeMessage.ht_server_hello_done),
 287         HS_CLIENT_SUPPLEMENTAL_DATA(
 288                 "client supplemental_data",
 289                 HandshakeMessage.ht_supplemental_data, true),
 290         HS_CLIENT_CERTIFICATE(
 291                 "client certificate",
 292                 HandshakeMessage.ht_certificate, true),
 293         HS_CERTIFICATE_URL(
 294                 "certificate_url",
 295                 HandshakeMessage.ht_certificate_url, true),
 296         HS_CLIENT_KEY_EXCHANGE(
 297                 "client_key_exchange",
 298                 HandshakeMessage.ht_client_key_exchange),
 299         HS_CERTIFICATE_VERIFY(
 300                 "certificate_verify",
 301                 HandshakeMessage.ht_certificate_verify, true),
 302         HS_CLIENT_CHANGE_CIPHER_SPEC(
 303                 "client change_cipher_spec",
 304                 HandshakeMessage.ht_not_applicable),
 305         HS_CLEINT_FINISHED(
 306                 "client finished",
 307                 HandshakeMessage.ht_finished),
 308         HS_NEW_SESSION_TICKET(
 309                 "session_ticket",
 310                 HandshakeMessage.ht_new_session_ticket),
 311         HS_SERVER_CHANGE_CIPHER_SPEC(
 312                 "server change_cipher_spec",
 313                 HandshakeMessage.ht_not_applicable),
 314         HS_SERVER_FINISHDE(
 315                 "server finished",
 316                 HandshakeMessage.ht_finished);
 317 
 318         final String description;
 319         final byte handshakeType;
 320         final boolean isOptional;
 321 
 322         HandshakeState(String description, byte handshakeType) {
 323             this.description = description;
 324             this.handshakeType = handshakeType;
 325             this.isOptional = false;
 326         }
 327 
 328         HandshakeState(String description,
 329                 byte handshakeType, boolean isOptional) {
 330 
 331             this.description = description;
 332             this.handshakeType = handshakeType;
 333             this.isOptional = isOptional;
 334         }
 335 
 336         public String toString() {
 337             return description + "[" + handshakeType + "]" +
 338                     (isOptional ? "(optional)" : "");
 339         }
 340     }
 341 
 342     boolean isEmpty() {
 343         return upcomingStates.isEmpty();
 344     }
 345 
 346     void check(byte handshakeType) throws SSLProtocolException {
 347         String exceptionMsg =
 348                  "Handshake message sequence violation, " + handshakeType;
 349 
 350         if (debugIsOn) {
 351             System.out.println(
 352                     "check handshake state: " + toString(handshakeType));
 353         }
 354 
 355         if (upcomingStates.isEmpty()) {
 356             // Is it a kickstart message?
 357             if ((handshakeType != HandshakeMessage.ht_hello_request) &&
 358                 (handshakeType != HandshakeMessage.ht_client_hello)) {
 359 
 360                 throw new SSLProtocolException(
 361                     "Handshake message sequence violation, " + handshakeType);
 362             }
 363 
 364             // It is a kickstart message.
 365             return;
 366         }
 367 
 368         // Ignore the checking for HelloRequest messages as they are
 369         // may be sent by the server at any time.
 370         if (handshakeType == HandshakeMessage.ht_hello_request) {
 371             return;
 372         }
 373 
 374         for (HandshakeState handshakeState : upcomingStates) {
 375             if (handshakeState.handshakeType == handshakeType) {
 376                 // It's the expected next handshake type.
 377                 return;
 378             }
 379 
 380             if (handshakeState.isOptional) {
 381                 continue;
 382             } else {
 383                 for (HandshakeState alternative : alternatives) {
 384                     if (alternative.handshakeType == handshakeType) {
 385                         return;
 386                     }
 387 
 388                     if (alternative.isOptional) {
 389                         continue;
 390                     } else {
 391                         throw new SSLProtocolException(exceptionMsg);
 392                     }
 393                 }
 394             }
 395 
 396             throw new SSLProtocolException(exceptionMsg);
 397         }
 398 
 399         // Not an expected Handshake message.
 400         throw new SSLProtocolException(
 401                 "Handshake message sequence violation, " + handshakeType);
 402     }
 403 
 404     void update(HandshakeMessage handshakeMessage,
 405             boolean isAbbreviated) throws SSLProtocolException {
 406 
 407         byte handshakeType = (byte)handshakeMessage.messageType();
 408         String exceptionMsg =
 409                  "Handshake message sequence violation, " + handshakeType;
 410 
 411         if (debugIsOn) {
 412             System.out.println(
 413                     "update handshake state: " + toString(handshakeType));
 414         }
 415 
 416         boolean hasPresentState = false;
 417         switch (handshakeType) {
 418         case HandshakeMessage.ht_hello_request:
 419             //
 420             // State machine:
 421             //     PRESENT: START
 422             //        TO  : ClientHello
 423             //
 424 
 425             // No old state to update.
 426 
 427             // Add the upcoming states.
 428             if (!upcomingStates.isEmpty()) {
 429                 // A ClientHello message should be followed.
 430                 upcomingStates.add(HS_CLIENT_HELLO);
 431                 
 432             }   // Otherwise, ignore this HelloRequest message.
 433 
 434             break;
 435 
 436         case HandshakeMessage.ht_client_hello:
 437             //
 438             // State machine:
 439             //     PRESENT: START
 440             //              HS_CLIENT_HELLO
 441             //        TO  : HS_HELLO_VERIFY_REQUEST (DTLS)
 442             //              HS_SERVER_HELLO
 443             //
 444 
 445             // Check and update the present state.
 446             if (!upcomingStates.isEmpty()) {
 447                 // The current state should be HS_CLIENT_HELLO.
 448                 HandshakeState handshakeState = upcomingStates.pop();
 449                 if (handshakeState != HS_CLIENT_HELLO) {
 450                     throw new SSLProtocolException(exceptionMsg);
 451                 }
 452             }
 453 
 454             // Add the upcoming states.
 455             ClientHello clientHello = (ClientHello)handshakeMessage;
 456             if (isDTLS) {
 457                 // Is it an initial ClientHello message?
 458                 if (clientHello.cookie == null ||
 459                         clientHello.cookie.length == 0) {
 460                     // Is it an abbreviated handshake?
 461                     if (clientHello.sessionId.length() != 0) {
 462                         // A HelloVerifyRequest message or a ServerHello
 463                         // message may follow the abbreviated session
 464                         // resuming handshake request.
 465                         upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
 466                         alternatives.add(HS_SERVER_HELLO);
 467                     } else {
 468                         // A HelloVerifyRequest message should follow
 469                         // the initial ClientHello message.
 470                         upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
 471                     }
 472                 } else {
 473                     // A HelloVerifyRequest may be followed if the cookie
 474                     // cannot be verified.
 475                     upcomingStates.add(HS_SERVER_HELLO);
 476                     alternatives.add(HS_HELLO_VERIFY_REQUEST);
 477                 }
 478             } else {
 479                 upcomingStates.add(HS_SERVER_HELLO);
 480             }
 481 
 482             break;
 483 
 484         case HandshakeMessage.ht_hello_verify_request:
 485             //
 486             // State machine:
 487             //     PRESENT: HS_HELLO_VERIFY_REQUEST
 488             //        TO  : HS_CLIENT_HELLO
 489             //
 490             // Note that this state may have an alternative option.
 491 
 492             // Check and update the present state.
 493             if (!upcomingStates.isEmpty()) {
 494                 // The current state should be HS_HELLO_VERIFY_REQUEST.
 495                 HandshakeState handshakeState = upcomingStates.pop();
 496                 HandshakeState alternative = null;
 497                 if (!alternatives.isEmpty()) {
 498                     alternative = alternatives.pop();
 499                 }
 500 
 501                 if ((handshakeState != HS_HELLO_VERIFY_REQUEST) &&
 502                         (alternative != HS_HELLO_VERIFY_REQUEST)) {
 503 
 504                     throw new SSLProtocolException(exceptionMsg);
 505                 }
 506             } else {
 507                 // No present state.
 508                 throw new SSLProtocolException(exceptionMsg);
 509             }
 510 
 511             // Add the upcoming states.
 512             upcomingStates.add(HS_CLIENT_HELLO);
 513 
 514             break;
 515 
 516         case HandshakeMessage.ht_server_hello:
 517             //
 518             // State machine:
 519             //     PRESENT: HS_SERVER_HELLO
 520             //        TO  :
 521             //          Full handshake state stacks
 522             //              (ServerHello Flight)
 523             //              HS_SERVER_SUPPLEMENTAL_DATA [optional]
 524             //          --> HS_SERVER_CERTIFICATE [optional]
 525             //          --> HS_CERTIFICATE_STATUS [optional]
 526             //          --> HS_SERVER_KEY_EXCHANGE [optional]
 527             //          --> HS_CERTIFICATE_REQUEST [optional]
 528             //          --> HS_SERVER_HELLO_DONE
 529             //              (Client ClientKeyExchange Flight)
 530             //          --> HS_CLIENT_SUPPLEMENTAL_DATA [optional]
 531             //          --> HS_CLIENT_CERTIFICATE or
 532             //              HS_CERTIFICATE_URL
 533             //          --> HS_CLIENT_KEY_EXCHANGE
 534             //          --> HS_CERTIFICATE_VERIFY [optional]
 535             //          --> HS_CLIENT_CHANGE_CIPHER_SPEC
 536             //          --> HS_CLEINT_FINISHED
 537             //              (Server Finished Flight)
 538             //          --> HS_CLIENT_SUPPLEMENTAL_DATA [optional]
 539             //
 540             //          Abbreviated handshake state stacks
 541             //              (Server Finished Flight)
 542             //              HS_NEW_SESSION_TICKET
 543             //          --> HS_SERVER_CHANGE_CIPHER_SPEC
 544             //          --> HS_SERVER_FINISHDE
 545             //              (Client Finished Flight)
 546             //          --> HS_CLIENT_CHANGE_CIPHER_SPEC
 547             //          --> HS_CLEINT_FINISHED
 548             //
 549             // Note that this state may have an alternative option.
 550 
 551             // Check and update the present state.
 552             if (!upcomingStates.isEmpty()) {
 553                 // The current state should be HS_SERVER_HELLO
 554                 HandshakeState handshakeState = upcomingStates.pop();
 555                 HandshakeState alternative = null;
 556                 if (!alternatives.isEmpty()) {
 557                     alternative = alternatives.pop();
 558                 }
 559 
 560                 if ((handshakeState != HS_SERVER_HELLO) &&
 561                         (alternative != HS_SERVER_HELLO)) {
 562 
 563                     throw new SSLProtocolException(exceptionMsg);
 564                 }
 565             } else {
 566                 // No present state.
 567                 throw new SSLProtocolException(exceptionMsg);
 568             }
 569 
 570             // Add the upcoming states.
 571             ServerHello serverHello = (ServerHello)handshakeMessage;
 572             HelloExtensions hes = serverHello.extensions;
 573 
 574 
 575             // Not support SessionTicket extension yet.
 576             //
 577             // boolean hasSessionTicketExt =
 578             //     (hes.get(HandshakeMessage.ht_new_session_ticket) != null);
 579 
 580             if (isAbbreviated) {
 581                 // Not support SessionTicket extension yet.
 582                 //
 583                 // // Mandatory NewSessionTicket message
 584                 // if (hasSessionTicketExt) {
 585                 //     upcomingStates.add(HS_NEW_SESSION_TICKET);
 586                 // }
 587 
 588                 // Mandatory server ChangeCipherSpec and Finished messages
 589                 upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
 590                 upcomingStates.add(HS_SERVER_FINISHDE);
 591 
 592                 // Mandatory client ChangeCipherSpec and Finished messages
 593                 upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
 594                 upcomingStates.add(HS_CLEINT_FINISHED);
 595             } else {
 596                 // Not support SupplementalData extension yet.
 597                 //
 598                 // boolean hasSupplementalDataExt =
 599                 //     (hes.get(HandshakeMessage.ht_supplemental_data) != null);
 600 
 601                 // Not support CertificateStatus extension yet.
 602                 //
 603                 // boolean hasCertificateStatusExt =
 604                 //    (hes.get(HandshakeMessage.ht_certificate_status) != null);
 605 
 606                 // Not support CertificateURL extension yet.
 607                 //
 608                 // boolean hasCertificateUrlExt =
 609                 //     (hes.get(HandshakeMessage.ht_certificate_url) != null);
 610 
 611                 // Not support SupplementalData extension yet.
 612                 //
 613                 // // Optional SupplementalData message
 614                 // if (hasSupplementalDataExt) {
 615                 //     upcomingStates.add(HS_SERVER_SUPPLEMENTAL_DATA);
 616                 // }
 617 
 618                 // Need server Certificate message or not?
 619                 KeyExchange keyExchange = serverHello.cipherSuite.keyExchange;
 620                 if ((keyExchange != K_KRB5) &&
 621                         (keyExchange != K_KRB5_EXPORT) &&
 622                         (keyExchange != K_DH_ANON) &&
 623                         (keyExchange != K_ECDH_ANON)) {
 624                     // Mandatory Certificate message
 625                     upcomingStates.add(HS_SERVER_CERTIFICATE);
 626                 }
 627 
 628                 // Not support CertificateStatus extension yet.
 629                 //
 630                 // // Optional CertificateStatus message
 631                 // if (hasCertificateStatusExt) {
 632                 //     upcomingStates.add(HS_CERTIFICATE_STATUS);
 633                 // }
 634 
 635                 // Need ServerKeyExchange message or not?
 636                 if ((keyExchange == K_RSA_EXPORT) ||
 637                         (keyExchange == K_DHE_RSA) ||
 638                         (keyExchange == K_DHE_DSS) ||
 639                         (keyExchange == K_DH_ANON) ||
 640                         (keyExchange == K_ECDHE_RSA) ||
 641                         (keyExchange == K_ECDHE_ECDSA) ||
 642                         (keyExchange == K_ECDH_ANON)) {
 643                     // Optional ServerKeyExchange message
 644                     upcomingStates.add(HS_SERVER_KEY_EXCHANGE);
 645                 }
 646 
 647                 // Optional CertificateRequest message
 648                 upcomingStates.add(HS_CERTIFICATE_REQUEST);
 649 
 650                 // Mandatory ServerHelloDone message
 651                 upcomingStates.add(HS_SERVER_HELLO_DONE);
 652                 
 653                 // Not support SupplementalData extension yet.
 654                 //
 655                 // // Optional SupplementalData message
 656                 // if (hasSupplementalDataExt) {
 657                 //     upcomingStates.add(HS_CLIENT_SUPPLEMENTAL_DATA);
 658                 // }
 659 
 660                 // Optional client Certificate message
 661                 upcomingStates.add(HS_CLIENT_CERTIFICATE);
 662 
 663                 // Not support CertificateURL extension yet.
 664                 //
 665                 // // Alternative CertificateURL message, optional too.
 666                 // //
 667                 // // Please put CertificateURL rather than Certificate
 668                 // // message in the alternatives list.  So that we can
 669                 // // simplify the process of this alternative pair later.
 670                 // if (hasCertificateUrlExt) {
 671                 //     alternatives.add(HS_CERTIFICATE_URL);
 672                 // }
 673 
 674                 // Mandatory ClientKeyExchange message
 675                 upcomingStates.add(HS_CLIENT_KEY_EXCHANGE);
 676 
 677                 // Optional CertificateVerify message
 678                 upcomingStates.add(HS_CERTIFICATE_VERIFY);
 679 
 680                 // Mandatory client ChangeCipherSpec and Finished messages
 681                 upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
 682                 upcomingStates.add(HS_CLEINT_FINISHED);
 683 
 684                 // Not support SessionTicket extension yet.
 685                 //
 686                 // // Mandatory NewSessionTicket message
 687                 // if (hasSessionTicketExt) {
 688                 //     upcomingStates.add(HS_NEW_SESSION_TICKET);
 689                 // }
 690 
 691                 // Mandatory server ChangeCipherSpec and Finished messages
 692                 upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
 693                 upcomingStates.add(HS_SERVER_FINISHDE);
 694             }
 695 
 696             break;
 697 
 698         case HandshakeMessage.ht_certificate:
 699             //
 700             // State machine:
 701             //     PRESENT: HS_CERTIFICATE_URL or
 702             //              HS_CLIENT_CERTIFICATE
 703             //        TO  : HS_CLIENT_KEY_EXCHANGE
 704             //
 705             //     Or
 706             //
 707             //     PRESENT: HS_SERVER_CERTIFICATE
 708             //        TO  : HS_CERTIFICATE_STATUS [optional]
 709             //              HS_SERVER_KEY_EXCHANGE [optional]
 710             //              HS_CERTIFICATE_REQUEST [optional]
 711             //              HS_SERVER_HELLO_DONE
 712             //
 713             // Note that this state may have an alternative option.
 714 
 715             // Check and update the present state.
 716             while (!upcomingStates.isEmpty()) {
 717                 HandshakeState handshakeState = upcomingStates.pop();
 718                 if (handshakeState.handshakeType == handshakeType) {
 719                     hasPresentState = true;
 720 
 721                     // The current state should be HS_CLIENT_CERTIFICATE or
 722                     // HS_SERVER_CERTIFICATE.
 723                     //
 724                     // Note that we won't put HS_CLIENT_CERTIFICATE into
 725                     // the alternative list.
 726                     if ((handshakeState != HS_CLIENT_CERTIFICATE) &&
 727                             (handshakeState != HS_SERVER_CERTIFICATE)) {
 728                         throw new SSLProtocolException(exceptionMsg);
 729                     }
 730 
 731                     // Is it an expected client Certificate message?
 732                     boolean isClientMessage = false;
 733                     if (!upcomingStates.isEmpty()) {
 734                         // If the next expected message is ClientKeyExchange,
 735                         // this one should be an expected client Certificate
 736                         // message.
 737                         HandshakeState nextState = upcomingStates.getFirst();
 738                         if (nextState == HS_CLIENT_KEY_EXCHANGE) {
 739                             isClientMessage = true;
 740                         }
 741                     }
 742 
 743                     if (isClientMessage) {
 744                         if (handshakeState != HS_CLIENT_CERTIFICATE) {
 745                             throw new SSLProtocolException(exceptionMsg);
 746                         }
 747 
 748                         // Not support CertificateURL extension yet.
 749                         /*******************************************
 750                         // clear up the alternatives list
 751                         if (!alternatives.isEmpty()) {
 752                             HandshakeState alternative = alternatives.pop();
 753 
 754                             if (alternative != HS_CERTIFICATE_URL) {
 755                                 throw new SSLProtocolException(exceptionMsg);
 756                             }
 757                         }
 758                         ********************************************/
 759                     } else {
 760                         if ((handshakeState != HS_SERVER_CERTIFICATE)) {
 761                             throw new SSLProtocolException(exceptionMsg);
 762                         }
 763                     }
 764 
 765                     break;
 766                 } else if (!handshakeState.isOptional) {
 767                     throw new SSLProtocolException(exceptionMsg);
 768                 }   // Otherwise, looking for next state track.
 769             }
 770 
 771             // No present state.
 772             if (!hasPresentState) {
 773                 throw new SSLProtocolException(exceptionMsg);
 774             }
 775 
 776             // no new upcoming states.
 777 
 778             break;
 779 
 780         // Not support CertificateURL extension yet.
 781         /*************************************************/
 782         case HandshakeMessage.ht_certificate_url:
 783             //
 784             // State machine:
 785             //     PRESENT: HS_CERTIFICATE_URL or
 786             //              HS_CLIENT_CERTIFICATE
 787             //        TO  : HS_CLIENT_KEY_EXCHANGE
 788             //
 789             // Note that this state may have an alternative option.
 790 
 791             // Check and update the present state.
 792             while (!upcomingStates.isEmpty()) {
 793                 // The current state should be HS_CLIENT_CERTIFICATE.
 794                 //
 795                 // Note that we won't put HS_CLIENT_CERTIFICATE into
 796                 // the alternative list.
 797                 HandshakeState handshakeState = upcomingStates.pop();
 798                 if (handshakeState.handshakeType ==
 799                         HS_CLIENT_CERTIFICATE.handshakeType) {
 800                     hasPresentState = true;
 801 
 802                     // Look for HS_CERTIFICATE_URL state track. 
 803                     if (!alternatives.isEmpty()) {
 804                         HandshakeState alternative = alternatives.pop();
 805 
 806                         if (alternative != HS_CERTIFICATE_URL) {
 807                             throw new SSLProtocolException(exceptionMsg);
 808                         }
 809                     } else {
 810                         // No alternative CertificateUR state track.
 811                         throw new SSLProtocolException(exceptionMsg);
 812                     }
 813 
 814                     if ((handshakeState != HS_CLIENT_CERTIFICATE)) {
 815                         throw new SSLProtocolException(exceptionMsg);
 816                     }
 817 
 818                     break;
 819                 } else if (!handshakeState.isOptional) {
 820                     throw new SSLProtocolException(exceptionMsg);
 821                 }   // Otherwise, looking for next state track.
 822 
 823             }
 824 
 825             // No present state.
 826             if (!hasPresentState) {
 827                 // No present state.
 828                 throw new SSLProtocolException(exceptionMsg);
 829             }
 830 
 831             // no new upcoming states.
 832 
 833             break;
 834         /*************************************************/
 835 
 836         default:
 837             // Check and update the present state.
 838             while (!upcomingStates.isEmpty()) {
 839                 HandshakeState handshakeState = upcomingStates.pop();
 840                 if (handshakeState.handshakeType == handshakeType) {
 841                     hasPresentState = true;
 842                     break;
 843                 } else if (!handshakeState.isOptional) {
 844                     throw new SSLProtocolException(exceptionMsg);
 845                 }   // Otherwise, looking for next state track.
 846             }
 847 
 848             // No present state.
 849             if (!hasPresentState) {
 850                 throw new SSLProtocolException(exceptionMsg);
 851             }
 852 
 853             // no new upcoming states.
 854         }
 855 
 856         if (debugIsOn) {
 857             for (HandshakeState handshakeState : upcomingStates) {
 858                 System.out.println(
 859                     "upcoming handshake states: " + handshakeState);
 860             }
 861             for (HandshakeState handshakeState : alternatives) {
 862                 System.out.println(
 863                     "upcoming handshake alternative state: " + handshakeState);
 864             }
 865         }
 866     }
 867 
 868     void changeCipherSpec(boolean isInput,
 869             boolean isClient) throws SSLProtocolException {
 870 
 871         if (debugIsOn) {
 872             System.out.println(
 873                     "update handshake state: change_cipher_spec");
 874         }
 875 
 876         String exceptionMsg = "ChangeCipherSpec message sequence violation";
 877 
 878         HandshakeState expectedState;
 879         if ((isClient && isInput) || (!isClient && !isInput)) {
 880             expectedState = HS_SERVER_CHANGE_CIPHER_SPEC;
 881         } else {
 882             expectedState = HS_CLIENT_CHANGE_CIPHER_SPEC;
 883         }
 884 
 885         boolean hasPresentState = false;
 886 
 887         // Check and update the present state.
 888         while (!upcomingStates.isEmpty()) {
 889             HandshakeState handshakeState = upcomingStates.pop();
 890             if (handshakeState == expectedState) {
 891                 hasPresentState = true;
 892                 break;
 893             } else if (!handshakeState.isOptional) {
 894                 throw new SSLProtocolException(exceptionMsg);
 895             }   // Otherwise, looking for next state track.
 896         }
 897 
 898         // No present state.
 899         if (!hasPresentState) {
 900             throw new SSLProtocolException(exceptionMsg);
 901         }
 902 
 903         // no new upcoming states.
 904 
 905         if (debugIsOn) {
 906             for (HandshakeState handshakeState : upcomingStates) {
 907                 System.out.println(
 908                     "upcoming handshake states: " + handshakeState);
 909             }
 910             for (HandshakeState handshakeState : alternatives) {
 911                 System.out.println(
 912                     "upcoming handshake alternative state: " + handshakeState);
 913             }
 914         }
 915     }
 916 
 917     private static String toString(byte handshakeType) {
 918         String s = handshakeTypes.get(handshakeType);    
 919         if (s == null) {
 920             s = "unknown";
 921         }
 922         return (s + "[" + handshakeType + "]");
 923     }
 924 }
 925