HandshakeStateManager.java revision 12072:6721ff11d592
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.LinkedList;
29import java.util.HashMap;
30import javax.net.ssl.SSLProtocolException;
31
32import sun.security.ssl.HandshakeMessage.*;
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_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
926