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.Collections; 29 import java.util.List; 30 import java.util.LinkedList; 31 import java.util.HashMap; 32 import javax.net.ssl.SSLProtocolException; 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 static final boolean debugIsOn; 222 223 private static final 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