HandshakeStateManager.java revision 12518:250b2eae3121
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
26package sun.security.ssl;
27
28import java.util.Collections;
29import java.util.List;
30import java.util.LinkedList;
31import java.util.HashMap;
32import javax.net.ssl.SSLProtocolException;
33
34import static sun.security.ssl.CipherSuite.KeyExchange;
35import static sun.security.ssl.CipherSuite.KeyExchange.*;
36import static sun.security.ssl.HandshakeStateManager.HandshakeState.*;
37import 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 */
214final 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_FINISHED(
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    List<Byte> check(byte handshakeType) throws SSLProtocolException {
347        List<Byte> ignoredOptional = new LinkedList<>();
348        String exceptionMsg =
349                 "Handshake message sequence violation, " + handshakeType;
350
351        if (debugIsOn) {
352            System.out.println(
353                    "check handshake state: " + toString(handshakeType));
354        }
355
356        if (upcomingStates.isEmpty()) {
357            // Is it a kickstart message?
358            if ((handshakeType != HandshakeMessage.ht_hello_request) &&
359                (handshakeType != HandshakeMessage.ht_client_hello)) {
360
361                throw new SSLProtocolException(
362                    "Handshake message sequence violation, " + handshakeType);
363            }
364
365            // It is a kickstart message.
366            return Collections.emptyList();
367        }
368
369        // Ignore the checking for HelloRequest messages as they
370        // may be sent by the server at any time.
371        if (handshakeType == HandshakeMessage.ht_hello_request) {
372            return Collections.emptyList();
373        }
374
375        for (HandshakeState handshakeState : upcomingStates) {
376            if (handshakeState.handshakeType == handshakeType) {
377                // It's the expected next handshake type.
378                return ignoredOptional;
379            }
380
381            if (handshakeState.isOptional) {
382                ignoredOptional.add(handshakeState.handshakeType);
383                continue;
384            } else {
385                for (HandshakeState alternative : alternatives) {
386                    if (alternative.handshakeType == handshakeType) {
387                        return ignoredOptional;
388                    }
389
390                    if (alternative.isOptional) {
391                        continue;
392                    } else {
393                        throw new SSLProtocolException(exceptionMsg);
394                    }
395                }
396            }
397
398            throw new SSLProtocolException(exceptionMsg);
399        }
400
401        // Not an expected Handshake message.
402        throw new SSLProtocolException(
403                "Handshake message sequence violation, " + handshakeType);
404    }
405
406    void update(HandshakeMessage handshakeMessage,
407            boolean isAbbreviated) throws SSLProtocolException {
408
409        byte handshakeType = (byte)handshakeMessage.messageType();
410        String exceptionMsg =
411                 "Handshake message sequence violation, " + handshakeType;
412
413        if (debugIsOn) {
414            System.out.println(
415                    "update handshake state: " + toString(handshakeType));
416        }
417
418        boolean hasPresentState = false;
419        switch (handshakeType) {
420        case HandshakeMessage.ht_hello_request:
421            //
422            // State machine:
423            //     PRESENT: START
424            //        TO  : ClientHello
425            //
426
427            // No old state to update.
428
429            // Add the upcoming states.
430            if (!upcomingStates.isEmpty()) {
431                // A ClientHello message should be followed.
432                upcomingStates.add(HS_CLIENT_HELLO);
433
434            }   // Otherwise, ignore this HelloRequest message.
435
436            break;
437
438        case HandshakeMessage.ht_client_hello:
439            //
440            // State machine:
441            //     PRESENT: START
442            //              HS_CLIENT_HELLO
443            //        TO  : HS_HELLO_VERIFY_REQUEST (DTLS)
444            //              HS_SERVER_HELLO
445            //
446
447            // Check and update the present state.
448            if (!upcomingStates.isEmpty()) {
449                // The current state should be HS_CLIENT_HELLO.
450                HandshakeState handshakeState = upcomingStates.pop();
451                if (handshakeState != HS_CLIENT_HELLO) {
452                    throw new SSLProtocolException(exceptionMsg);
453                }
454            }
455
456            // Add the upcoming states.
457            ClientHello clientHello = (ClientHello)handshakeMessage;
458            if (isDTLS) {
459                // Is it an initial ClientHello message?
460                if (clientHello.cookie == null ||
461                        clientHello.cookie.length == 0) {
462                    // Is it an abbreviated handshake?
463                    if (clientHello.sessionId.length() != 0) {
464                        // A HelloVerifyRequest message or a ServerHello
465                        // message may follow the abbreviated session
466                        // resuming handshake request.
467                        upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
468                        alternatives.add(HS_SERVER_HELLO);
469                    } else {
470                        // A HelloVerifyRequest message should follow
471                        // the initial ClientHello message.
472                        upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
473                    }
474                } else {
475                    // A HelloVerifyRequest may be followed if the cookie
476                    // cannot be verified.
477                    upcomingStates.add(HS_SERVER_HELLO);
478                    alternatives.add(HS_HELLO_VERIFY_REQUEST);
479                }
480            } else {
481                upcomingStates.add(HS_SERVER_HELLO);
482            }
483
484            break;
485
486        case HandshakeMessage.ht_hello_verify_request:
487            //
488            // State machine:
489            //     PRESENT: HS_HELLO_VERIFY_REQUEST
490            //        TO  : HS_CLIENT_HELLO
491            //
492            // Note that this state may have an alternative option.
493
494            // Check and update the present state.
495            if (!upcomingStates.isEmpty()) {
496                // The current state should be HS_HELLO_VERIFY_REQUEST.
497                HandshakeState handshakeState = upcomingStates.pop();
498                HandshakeState alternative = null;
499                if (!alternatives.isEmpty()) {
500                    alternative = alternatives.pop();
501                }
502
503                if ((handshakeState != HS_HELLO_VERIFY_REQUEST) &&
504                        (alternative != HS_HELLO_VERIFY_REQUEST)) {
505
506                    throw new SSLProtocolException(exceptionMsg);
507                }
508            } else {
509                // No present state.
510                throw new SSLProtocolException(exceptionMsg);
511            }
512
513            // Add the upcoming states.
514            upcomingStates.add(HS_CLIENT_HELLO);
515
516            break;
517
518        case HandshakeMessage.ht_server_hello:
519            //
520            // State machine:
521            //     PRESENT: HS_SERVER_HELLO
522            //        TO  :
523            //          Full handshake state stacks
524            //              (ServerHello Flight)
525            //              HS_SERVER_SUPPLEMENTAL_DATA [optional]
526            //          --> HS_SERVER_CERTIFICATE [optional]
527            //          --> HS_CERTIFICATE_STATUS [optional]
528            //          --> HS_SERVER_KEY_EXCHANGE [optional]
529            //          --> HS_CERTIFICATE_REQUEST [optional]
530            //          --> HS_SERVER_HELLO_DONE
531            //              (Client ClientKeyExchange Flight)
532            //          --> HS_CLIENT_SUPPLEMENTAL_DATA [optional]
533            //          --> HS_CLIENT_CERTIFICATE or
534            //              HS_CERTIFICATE_URL
535            //          --> HS_CLIENT_KEY_EXCHANGE
536            //          --> HS_CERTIFICATE_VERIFY [optional]
537            //          --> HS_CLIENT_CHANGE_CIPHER_SPEC
538            //          --> HS_CLEINT_FINISHED
539            //              (Server Finished Flight)
540            //          --> HS_CLIENT_SUPPLEMENTAL_DATA [optional]
541            //
542            //          Abbreviated handshake state stacks
543            //              (Server Finished Flight)
544            //              HS_NEW_SESSION_TICKET
545            //          --> HS_SERVER_CHANGE_CIPHER_SPEC
546            //          --> HS_SERVER_FINISHED
547            //              (Client Finished Flight)
548            //          --> HS_CLIENT_CHANGE_CIPHER_SPEC
549            //          --> HS_CLEINT_FINISHED
550            //
551            // Note that this state may have an alternative option.
552
553            // Check and update the present state.
554            if (!upcomingStates.isEmpty()) {
555                // The current state should be HS_SERVER_HELLO
556                HandshakeState handshakeState = upcomingStates.pop();
557                HandshakeState alternative = null;
558                if (!alternatives.isEmpty()) {
559                    alternative = alternatives.pop();
560                }
561
562                if ((handshakeState != HS_SERVER_HELLO) &&
563                        (alternative != HS_SERVER_HELLO)) {
564
565                    throw new SSLProtocolException(exceptionMsg);
566                }
567            } else {
568                // No present state.
569                throw new SSLProtocolException(exceptionMsg);
570            }
571
572            // Add the upcoming states.
573            ServerHello serverHello = (ServerHello)handshakeMessage;
574            HelloExtensions hes = serverHello.extensions;
575
576
577            // Not support SessionTicket extension yet.
578            //
579            // boolean hasSessionTicketExt =
580            //     (hes.get(HandshakeMessage.ht_new_session_ticket) != null);
581
582            if (isAbbreviated) {
583                // Not support SessionTicket extension yet.
584                //
585                // // Mandatory NewSessionTicket message
586                // if (hasSessionTicketExt) {
587                //     upcomingStates.add(HS_NEW_SESSION_TICKET);
588                // }
589
590                // Mandatory server ChangeCipherSpec and Finished messages
591                upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
592                upcomingStates.add(HS_SERVER_FINISHED);
593
594                // Mandatory client ChangeCipherSpec and Finished messages
595                upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
596                upcomingStates.add(HS_CLEINT_FINISHED);
597            } else {
598                // Not support SupplementalData extension yet.
599                //
600                // boolean hasSupplementalDataExt =
601                //     (hes.get(HandshakeMessage.ht_supplemental_data) != null);
602
603                // Not support CertificateURL extension yet.
604                //
605                // boolean hasCertificateUrlExt =
606                //     (hes.get(ExtensionType EXT_CLIENT_CERTIFICATE_URL)
607                //          != null);
608
609                // Not support SupplementalData extension yet.
610                //
611                // // Optional SupplementalData message
612                // if (hasSupplementalDataExt) {
613                //     upcomingStates.add(HS_SERVER_SUPPLEMENTAL_DATA);
614                // }
615
616                // Need server Certificate message or not?
617                KeyExchange keyExchange = serverHello.cipherSuite.keyExchange;
618                if ((keyExchange != K_KRB5) &&
619                        (keyExchange != K_KRB5_EXPORT) &&
620                        (keyExchange != K_DH_ANON) &&
621                        (keyExchange != K_ECDH_ANON)) {
622                    // Mandatory Certificate message
623                    upcomingStates.add(HS_SERVER_CERTIFICATE);
624                }
625
626                // Optional CertificateStatus message
627                if (hes.get(ExtensionType.EXT_STATUS_REQUEST) != null ||
628                        hes.get(ExtensionType.EXT_STATUS_REQUEST_V2) != null) {
629                    upcomingStates.add(HS_CERTIFICATE_STATUS);
630                }
631
632                // Need ServerKeyExchange message or not?
633                if ((keyExchange == K_RSA_EXPORT) ||
634                        (keyExchange == K_DHE_RSA) ||
635                        (keyExchange == K_DHE_DSS) ||
636                        (keyExchange == K_DH_ANON) ||
637                        (keyExchange == K_ECDHE_RSA) ||
638                        (keyExchange == K_ECDHE_ECDSA) ||
639                        (keyExchange == K_ECDH_ANON)) {
640                    // Optional ServerKeyExchange message
641                    upcomingStates.add(HS_SERVER_KEY_EXCHANGE);
642                }
643
644                // Optional CertificateRequest message
645                upcomingStates.add(HS_CERTIFICATE_REQUEST);
646
647                // Mandatory ServerHelloDone message
648                upcomingStates.add(HS_SERVER_HELLO_DONE);
649
650                // Not support SupplementalData extension yet.
651                //
652                // // Optional SupplementalData message
653                // if (hasSupplementalDataExt) {
654                //     upcomingStates.add(HS_CLIENT_SUPPLEMENTAL_DATA);
655                // }
656
657                // Optional client Certificate message
658                upcomingStates.add(HS_CLIENT_CERTIFICATE);
659
660                // Not support CertificateURL extension yet.
661                //
662                // // Alternative CertificateURL message, optional too.
663                // //
664                // // Please put CertificateURL rather than Certificate
665                // // message in the alternatives list.  So that we can
666                // // simplify the process of this alternative pair later.
667                // if (hasCertificateUrlExt) {
668                //     alternatives.add(HS_CERTIFICATE_URL);
669                // }
670
671                // Mandatory ClientKeyExchange message
672                upcomingStates.add(HS_CLIENT_KEY_EXCHANGE);
673
674                // Optional CertificateVerify message
675                upcomingStates.add(HS_CERTIFICATE_VERIFY);
676
677                // Mandatory client ChangeCipherSpec and Finished messages
678                upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
679                upcomingStates.add(HS_CLEINT_FINISHED);
680
681                // Not support SessionTicket extension yet.
682                //
683                // // Mandatory NewSessionTicket message
684                // if (hasSessionTicketExt) {
685                //     upcomingStates.add(HS_NEW_SESSION_TICKET);
686                // }
687
688                // Mandatory server ChangeCipherSpec and Finished messages
689                upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
690                upcomingStates.add(HS_SERVER_FINISHED);
691            }
692
693            break;
694
695        case HandshakeMessage.ht_certificate:
696            //
697            // State machine:
698            //     PRESENT: HS_CERTIFICATE_URL or
699            //              HS_CLIENT_CERTIFICATE
700            //        TO  : HS_CLIENT_KEY_EXCHANGE
701            //
702            //     Or
703            //
704            //     PRESENT: HS_SERVER_CERTIFICATE
705            //        TO  : HS_CERTIFICATE_STATUS [optional]
706            //              HS_SERVER_KEY_EXCHANGE [optional]
707            //              HS_CERTIFICATE_REQUEST [optional]
708            //              HS_SERVER_HELLO_DONE
709            //
710            // Note that this state may have an alternative option.
711
712            // Check and update the present state.
713            while (!upcomingStates.isEmpty()) {
714                HandshakeState handshakeState = upcomingStates.pop();
715                if (handshakeState.handshakeType == handshakeType) {
716                    hasPresentState = true;
717
718                    // The current state should be HS_CLIENT_CERTIFICATE or
719                    // HS_SERVER_CERTIFICATE.
720                    //
721                    // Note that we won't put HS_CLIENT_CERTIFICATE into
722                    // the alternative list.
723                    if ((handshakeState != HS_CLIENT_CERTIFICATE) &&
724                            (handshakeState != HS_SERVER_CERTIFICATE)) {
725                        throw new SSLProtocolException(exceptionMsg);
726                    }
727
728                    // Is it an expected client Certificate message?
729                    boolean isClientMessage = false;
730                    if (!upcomingStates.isEmpty()) {
731                        // If the next expected message is ClientKeyExchange,
732                        // this one should be an expected client Certificate
733                        // message.
734                        HandshakeState nextState = upcomingStates.getFirst();
735                        if (nextState == HS_CLIENT_KEY_EXCHANGE) {
736                            isClientMessage = true;
737                        }
738                    }
739
740                    if (isClientMessage) {
741                        if (handshakeState != HS_CLIENT_CERTIFICATE) {
742                            throw new SSLProtocolException(exceptionMsg);
743                        }
744
745                        // Not support CertificateURL extension yet.
746                        /*******************************************
747                        // clear up the alternatives list
748                        if (!alternatives.isEmpty()) {
749                            HandshakeState alternative = alternatives.pop();
750
751                            if (alternative != HS_CERTIFICATE_URL) {
752                                throw new SSLProtocolException(exceptionMsg);
753                            }
754                        }
755                        ********************************************/
756                    } else {
757                        if ((handshakeState != HS_SERVER_CERTIFICATE)) {
758                            throw new SSLProtocolException(exceptionMsg);
759                        }
760                    }
761
762                    break;
763                } else if (!handshakeState.isOptional) {
764                    throw new SSLProtocolException(exceptionMsg);
765                }   // Otherwise, looking for next state track.
766            }
767
768            // No present state.
769            if (!hasPresentState) {
770                throw new SSLProtocolException(exceptionMsg);
771            }
772
773            // no new upcoming states.
774
775            break;
776
777        // Not support CertificateURL extension yet.
778        /*************************************************/
779        case HandshakeMessage.ht_certificate_url:
780            //
781            // State machine:
782            //     PRESENT: HS_CERTIFICATE_URL or
783            //              HS_CLIENT_CERTIFICATE
784            //        TO  : HS_CLIENT_KEY_EXCHANGE
785            //
786            // Note that this state may have an alternative option.
787
788            // Check and update the present state.
789            while (!upcomingStates.isEmpty()) {
790                // The current state should be HS_CLIENT_CERTIFICATE.
791                //
792                // Note that we won't put HS_CLIENT_CERTIFICATE into
793                // the alternative list.
794                HandshakeState handshakeState = upcomingStates.pop();
795                if (handshakeState.handshakeType ==
796                        HS_CLIENT_CERTIFICATE.handshakeType) {
797                    hasPresentState = true;
798
799                    // Look for HS_CERTIFICATE_URL state track.
800                    if (!alternatives.isEmpty()) {
801                        HandshakeState alternative = alternatives.pop();
802
803                        if (alternative != HS_CERTIFICATE_URL) {
804                            throw new SSLProtocolException(exceptionMsg);
805                        }
806                    } else {
807                        // No alternative CertificateUR state track.
808                        throw new SSLProtocolException(exceptionMsg);
809                    }
810
811                    if ((handshakeState != HS_CLIENT_CERTIFICATE)) {
812                        throw new SSLProtocolException(exceptionMsg);
813                    }
814
815                    break;
816                } else if (!handshakeState.isOptional) {
817                    throw new SSLProtocolException(exceptionMsg);
818                }   // Otherwise, looking for next state track.
819
820            }
821
822            // No present state.
823            if (!hasPresentState) {
824                // No present state.
825                throw new SSLProtocolException(exceptionMsg);
826            }
827
828            // no new upcoming states.
829
830            break;
831        /*************************************************/
832
833        default:
834            // Check and update the present state.
835            while (!upcomingStates.isEmpty()) {
836                HandshakeState handshakeState = upcomingStates.pop();
837                if (handshakeState.handshakeType == handshakeType) {
838                    hasPresentState = true;
839                    break;
840                } else if (!handshakeState.isOptional) {
841                    throw new SSLProtocolException(exceptionMsg);
842                }   // Otherwise, looking for next state track.
843            }
844
845            // No present state.
846            if (!hasPresentState) {
847                throw new SSLProtocolException(exceptionMsg);
848            }
849
850            // no new upcoming states.
851        }
852
853        if (debugIsOn) {
854            for (HandshakeState handshakeState : upcomingStates) {
855                System.out.println(
856                    "upcoming handshake states: " + handshakeState);
857            }
858            for (HandshakeState handshakeState : alternatives) {
859                System.out.println(
860                    "upcoming handshake alternative state: " + handshakeState);
861            }
862        }
863    }
864
865    void changeCipherSpec(boolean isInput,
866            boolean isClient) throws SSLProtocolException {
867
868        if (debugIsOn) {
869            System.out.println(
870                    "update handshake state: change_cipher_spec");
871        }
872
873        String exceptionMsg = "ChangeCipherSpec message sequence violation";
874
875        HandshakeState expectedState;
876        if ((isClient && isInput) || (!isClient && !isInput)) {
877            expectedState = HS_SERVER_CHANGE_CIPHER_SPEC;
878        } else {
879            expectedState = HS_CLIENT_CHANGE_CIPHER_SPEC;
880        }
881
882        boolean hasPresentState = false;
883
884        // Check and update the present state.
885        while (!upcomingStates.isEmpty()) {
886            HandshakeState handshakeState = upcomingStates.pop();
887            if (handshakeState == expectedState) {
888                hasPresentState = true;
889                break;
890            } else if (!handshakeState.isOptional) {
891                throw new SSLProtocolException(exceptionMsg);
892            }   // Otherwise, looking for next state track.
893        }
894
895        // No present state.
896        if (!hasPresentState) {
897            throw new SSLProtocolException(exceptionMsg);
898        }
899
900        // no new upcoming states.
901
902        if (debugIsOn) {
903            for (HandshakeState handshakeState : upcomingStates) {
904                System.out.println(
905                    "upcoming handshake states: " + handshakeState);
906            }
907            for (HandshakeState handshakeState : alternatives) {
908                System.out.println(
909                    "upcoming handshake alternative state: " + handshakeState);
910            }
911        }
912    }
913
914    private static String toString(byte handshakeType) {
915        String s = handshakeTypes.get(handshakeType);
916        if (s == null) {
917            s = "unknown";
918        }
919        return (s + "[" + handshakeType + "]");
920    }
921}
922
923