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