1 /* 2 * Copyright (c) 2015, 2018, 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 9406+5 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.io.*; 29 import java.nio.*; 30 import java.security.GeneralSecurityException; 31 import java.util.*; 32 import javax.crypto.BadPaddingException; 33 import javax.net.ssl.*; 34 import sun.security.ssl.SSLCipher.SSLReadCipher; 35 36 /** 37 * DTLS {@code InputRecord} implementation for {@code SSLEngine}. 38 */ 39 final class DTLSInputRecord extends InputRecord implements DTLSRecord { 40 private DTLSReassembler reassembler = null; 41 private int readEpoch; 42 43 DTLSInputRecord(HandshakeHash handshakeHash) { 44 super(handshakeHash, SSLReadCipher.nullDTlsReadCipher()); 45 this.readEpoch = 0; 46 } 47 48 @Override 49 void changeReadCiphers(SSLReadCipher readCipher) { 50 this.readCipher = readCipher; 51 this.readEpoch++; 52 } 53 54 @Override 55 public synchronized void close() throws IOException { 56 if (!isClosed) { 57 super.close(); 58 } 59 } 60 61 @Override 62 boolean isEmpty() { 63 return ((reassembler == null) || reassembler.isEmpty()); 64 } 65 66 @Override 67 int estimateFragmentSize(int packetSize) { 68 if (packetSize > 0) { 69 return readCipher.estimateFragmentSize(packetSize, headerSize); 70 } else { 71 return Record.maxDataSize; 72 } 73 } 74 75 @Override 76 void expectingFinishFlight() { 77 if (reassembler != null) { 78 reassembler.expectingFinishFlight(); 79 } 80 } 81 82 @Override 83 void finishHandshake() { 84 reassembler = null; 85 } 86 87 @Override 88 Plaintext acquirePlaintext() { 89 if (reassembler != null) { 90 return reassembler.acquirePlaintext(); 91 } 92 93 return null; 94 } 95 96 @Override 97 Plaintext[] decode(ByteBuffer[] srcs, int srcsOffset, 98 int srcsLength) throws IOException, BadPaddingException { 99 if (srcs == null || srcs.length == 0 || srcsLength == 0) { 100 Plaintext pt = acquirePlaintext(); 101 return pt == null ? new Plaintext[0] : new Plaintext[] { pt }; 102 } else if (srcsLength == 1) { 103 return decode(srcs[srcsOffset]); 104 } else { 105 ByteBuffer packet = extract(srcs, 106 srcsOffset, srcsLength, DTLSRecord.headerSize); 107 return decode(packet); 108 } 109 } 110 111 Plaintext[] decode(ByteBuffer packet) { 112 if (isClosed) { 113 return null; 114 } 115 116 if (SSLLogger.isOn && SSLLogger.isOn("packet")) { 117 SSLLogger.fine("Raw read", packet); 118 } 119 120 // The caller should have validated the record. 121 int srcPos = packet.position(); 122 int srcLim = packet.limit(); 123 124 byte contentType = packet.get(); // pos: 0 125 byte majorVersion = packet.get(); // pos: 1 126 byte minorVersion = packet.get(); // pos: 2 127 byte[] recordEnS = new byte[8]; // epoch + seqence 128 packet.get(recordEnS); 129 int recordEpoch = ((recordEnS[0] & 0xFF) << 8) | 130 (recordEnS[1] & 0xFF); // pos: 3, 4 131 long recordSeq = ((recordEnS[2] & 0xFFL) << 40) | 132 ((recordEnS[3] & 0xFFL) << 32) | 133 ((recordEnS[4] & 0xFFL) << 24) | 134 ((recordEnS[5] & 0xFFL) << 16) | 135 ((recordEnS[6] & 0xFFL) << 8) | 136 (recordEnS[7] & 0xFFL); // pos: 5-10 137 138 int contentLen = ((packet.get() & 0xFF) << 8) | 139 (packet.get() & 0xFF); // pos: 11, 12 140 141 if (SSLLogger.isOn && SSLLogger.isOn("record")) { 142 SSLLogger.fine("READ: " + 143 ProtocolVersion.nameOf(majorVersion, minorVersion) + 144 " " + ContentType.nameOf(contentType) + ", length = " + 145 contentLen); 146 } 147 148 int recLim = srcPos + DTLSRecord.headerSize + contentLen; 149 150 if (this.readEpoch > recordEpoch) { 151 // Reset the position of the packet buffer. 152 packet.position(recLim); 153 if (SSLLogger.isOn && SSLLogger.isOn("record")) { 154 SSLLogger.fine("READ: discard this old record", recordEnS); 155 } 156 return null; 157 } 158 159 // Buffer next epoch message if necessary. 160 if (this.readEpoch < recordEpoch) { 161 // Discard the record younger than the current epcoh if: 162 // 1. it is not a handshake message, or 163 // 3. it is not of next epoch. 164 if ((contentType != ContentType.HANDSHAKE.id && 165 contentType != ContentType.CHANGE_CIPHER_SPEC.id) || 166 (reassembler == null && 167 contentType != ContentType.HANDSHAKE.id) || 168 (this.readEpoch < (recordEpoch - 1))) { 169 170 packet.position(recLim); 171 172 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 173 SSLLogger.fine("Premature record (epoch), discard it."); 174 } 175 176 return null; 177 } 178 179 180 // Not ready to decrypt this record, may be an encrypted Finished 181 // message, need to buffer it. 182 byte[] fragment = new byte[contentLen]; 183 packet.get(fragment); // copy the fragment 184 RecordFragment buffered = new RecordFragment(fragment, contentType, 185 majorVersion, minorVersion, 186 recordEnS, recordEpoch, recordSeq, true); 187 188 if (reassembler == null) { 189 reassembler = new DTLSReassembler(recordEpoch); 190 } 191 reassembler.queueUpFragment(buffered); 192 193 // consume the full record in the packet buffer. 194 packet.position(recLim); 195 196 Plaintext pt = reassembler.acquirePlaintext(); 197 return pt == null ? null : new Plaintext[] { pt }; 198 } 199 200 // 201 // Now, the message is of this epoch. 202 // 203 // decrypt the fragment 204 packet.limit(recLim); 205 packet.position(srcPos + DTLSRecord.headerSize); 206 207 ByteBuffer plaintextFragment; 208 try { 209 Plaintext plaintext = 210 readCipher.decrypt(contentType, packet, recordEnS); 211 plaintextFragment = plaintext.fragment; 212 contentType = plaintext.contentType; 213 } catch (GeneralSecurityException gse) { 214 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 215 SSLLogger.fine("Discard invalid record: " + gse); 216 } 217 218 // invalid, discard this record [section 4.1.2.7, RFC 6347] 219 return null; 220 } finally { 221 // comsume a complete record 222 packet.limit(srcLim); 223 packet.position(recLim); 224 } 225 226 if (contentType != ContentType.CHANGE_CIPHER_SPEC.id && 227 contentType != ContentType.HANDSHAKE.id) { // app data or alert 228 // no retransmission 229 // Cleanup the handshake reassembler if necessary. 230 if ((reassembler != null) && 231 (reassembler.handshakeEpoch < recordEpoch)) { 232 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 233 SSLLogger.fine("Cleanup the handshake reassembler"); 234 } 235 236 reassembler = null; 237 } 238 239 return new Plaintext[] { 240 new Plaintext(contentType, majorVersion, minorVersion, 241 recordEpoch, Authenticator.toLong(recordEnS), 242 plaintextFragment)}; 243 } 244 245 if (contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 246 if (reassembler == null) { 247 reassembler = new DTLSReassembler(recordEpoch); 248 } 249 250 reassembler.queueUpChangeCipherSpec( 251 new RecordFragment(plaintextFragment, contentType, 252 majorVersion, minorVersion, 253 recordEnS, recordEpoch, recordSeq, false)); 254 } else { // handshake record 255 // One record may contain 1+ more handshake messages. 256 while (plaintextFragment.remaining() > 0) { 257 258 HandshakeFragment hsFrag = parseHandshakeMessage( 259 contentType, majorVersion, minorVersion, 260 recordEnS, recordEpoch, recordSeq, plaintextFragment); 261 262 if (hsFrag == null) { 263 // invalid, discard this record 264 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 265 SSLLogger.fine( 266 "Invalid handshake message, discard it."); 267 } 268 269 return null; 270 } 271 272 if (reassembler == null) { 273 reassembler = new DTLSReassembler(recordEpoch); 274 } 275 276 reassembler.queueUpHandshake(hsFrag); 277 } 278 } 279 280 // Completed the read of the full record. Acquire the reassembled 281 // messages. 282 if (reassembler != null) { 283 Plaintext pt = reassembler.acquirePlaintext(); 284 return pt == null ? null : new Plaintext[] { pt }; 285 } 286 287 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 288 SSLLogger.fine("The reassembler is not initialized yet."); 289 } 290 291 return null; 292 } 293 294 @Override 295 int bytesInCompletePacket( 296 ByteBuffer[] srcs, int srcsOffset, int srcsLength) throws IOException { 297 298 return bytesInCompletePacket(srcs[srcsOffset]); 299 } 300 301 private int bytesInCompletePacket(ByteBuffer packet) throws SSLException { 302 303 // DTLS length field is in bytes 11/12 304 if (packet.remaining() < headerSize) { 305 return -1; 306 } 307 308 // Last sanity check that it's not a wild record 309 int pos = packet.position(); 310 311 // Check the content type of the record. 312 byte contentType = packet.get(pos); 313 if (ContentType.valueOf(contentType) == null) { 314 throw new SSLException( 315 "Unrecognized SSL message, plaintext connection?"); 316 } 317 318 // Check the protocol version of the record. 319 byte majorVersion = packet.get(pos + 1); 320 byte minorVersion = packet.get(pos + 2); 321 if (!ProtocolVersion.isNegotiable( 322 majorVersion, minorVersion, true, false)) { 323 throw new SSLException("Unrecognized record version " + 324 ProtocolVersion.nameOf(majorVersion, minorVersion) + 325 " , plaintext connection?"); 326 } 327 328 // Get the fragment length of the record. 329 int fragLen = ((packet.get(pos + 11) & 0xFF) << 8) + 330 (packet.get(pos + 12) & 0xFF) + headerSize; 331 if (fragLen > Record.maxFragmentSize) { 332 throw new SSLException( 333 "Record overflow, fragment length (" + fragLen + 334 ") MUST not exceed " + Record.maxFragmentSize); 335 } 336 337 return fragLen; 338 } 339 340 private static HandshakeFragment parseHandshakeMessage( 341 byte contentType, byte majorVersion, byte minorVersion, 342 byte[] recordEnS, int recordEpoch, long recordSeq, 343 ByteBuffer plaintextFragment) { 344 345 int remaining = plaintextFragment.remaining(); 346 if (remaining < handshakeHeaderSize) { 347 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 348 SSLLogger.fine("Discard invalid record: " + 349 "too small record to hold a handshake fragment"); 350 } 351 352 // invalid, discard this record [section 4.1.2.7, RFC 6347] 353 return null; 354 } 355 356 byte handshakeType = plaintextFragment.get(); // pos: 0 357 int messageLength = 358 ((plaintextFragment.get() & 0xFF) << 16) | 359 ((plaintextFragment.get() & 0xFF) << 8) | 360 (plaintextFragment.get() & 0xFF); // pos: 1-3 361 int messageSeq = 362 ((plaintextFragment.get() & 0xFF) << 8) | 363 (plaintextFragment.get() & 0xFF); // pos: 4/5 364 int fragmentOffset = 365 ((plaintextFragment.get() & 0xFF) << 16) | 366 ((plaintextFragment.get() & 0xFF) << 8) | 367 (plaintextFragment.get() & 0xFF); // pos: 6-8 368 int fragmentLength = 369 ((plaintextFragment.get() & 0xFF) << 16) | 370 ((plaintextFragment.get() & 0xFF) << 8) | 371 (plaintextFragment.get() & 0xFF); // pos: 9-11 372 if ((remaining - handshakeHeaderSize) < fragmentLength) { 373 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 374 SSLLogger.fine("Discard invalid record: " + 375 "not a complete handshake fragment in the record"); 376 } 377 378 // invalid, discard this record [section 4.1.2.7, RFC 6347] 379 return null; 380 } 381 382 byte[] fragment = new byte[fragmentLength]; 383 plaintextFragment.get(fragment); 384 385 return new HandshakeFragment(fragment, contentType, 386 majorVersion, minorVersion, 387 recordEnS, recordEpoch, recordSeq, 388 handshakeType, messageLength, 389 messageSeq, fragmentOffset, fragmentLength); 390 } 391 392 // buffered record fragment 393 private static class RecordFragment implements Comparable<RecordFragment> { 394 boolean isCiphertext; 395 396 byte contentType; 397 byte majorVersion; 398 byte minorVersion; 399 int recordEpoch; 400 long recordSeq; 401 byte[] recordEnS; 402 byte[] fragment; 403 404 RecordFragment(ByteBuffer fragBuf, byte contentType, 405 byte majorVersion, byte minorVersion, byte[] recordEnS, 406 int recordEpoch, long recordSeq, boolean isCiphertext) { 407 this((byte[])null, contentType, majorVersion, minorVersion, 408 recordEnS, recordEpoch, recordSeq, isCiphertext); 409 410 this.fragment = new byte[fragBuf.remaining()]; 411 fragBuf.get(this.fragment); 412 } 413 414 RecordFragment(byte[] fragment, byte contentType, 415 byte majorVersion, byte minorVersion, byte[] recordEnS, 416 int recordEpoch, long recordSeq, boolean isCiphertext) { 417 this.isCiphertext = isCiphertext; 418 419 this.contentType = contentType; 420 this.majorVersion = majorVersion; 421 this.minorVersion = minorVersion; 422 this.recordEpoch = recordEpoch; 423 this.recordSeq = recordSeq; 424 this.recordEnS = recordEnS; 425 this.fragment = fragment; // The caller should have cloned 426 // the buffer if necessary. 427 } 428 429 @Override 430 public int compareTo(RecordFragment o) { 431 if (this.contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 432 if (o.contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 433 // Only one incoming ChangeCipherSpec message for an epoch. 434 // 435 // Ignore duplicated ChangeCipherSpec messages. 436 return Integer.compare(this.recordEpoch, o.recordEpoch); 437 } else if ((this.recordEpoch == o.recordEpoch) && 438 (o.contentType == ContentType.HANDSHAKE.id)) { 439 // ChangeCipherSpec is the latest message of an epoch. 440 return 1; 441 } 442 } else if (o.contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 443 if ((this.recordEpoch == o.recordEpoch) && 444 (this.contentType == ContentType.HANDSHAKE.id)) { 445 // ChangeCipherSpec is the latest message of an epoch. 446 return -1; 447 } else { 448 // different epoch or this is not a handshake message 449 return compareToSequence(o.recordEpoch, o.recordSeq); 450 } 451 } 452 453 return compareToSequence(o.recordEpoch, o.recordSeq); 454 } 455 456 int compareToSequence(int epoch, long seq) { 457 if (this.recordEpoch > epoch) { 458 return 1; 459 } else if (this.recordEpoch == epoch) { 460 return Long.compare(this.recordSeq, seq); 461 } else { 462 return -1; 463 } 464 } 465 } 466 467 // buffered handshake message 468 private static final class HandshakeFragment extends RecordFragment { 469 470 byte handshakeType; // handshake msg_type 471 int messageSeq; // message_seq 472 int messageLength; // Handshake body length 473 int fragmentOffset; // fragment_offset 474 int fragmentLength; // fragment_length 475 476 HandshakeFragment(byte[] fragment, byte contentType, 477 byte majorVersion, byte minorVersion, byte[] recordEnS, 478 int recordEpoch, long recordSeq, 479 byte handshakeType, int messageLength, 480 int messageSeq, int fragmentOffset, int fragmentLength) { 481 482 super(fragment, contentType, majorVersion, minorVersion, 483 recordEnS, recordEpoch , recordSeq, false); 484 485 this.handshakeType = handshakeType; 486 this.messageSeq = messageSeq; 487 this.messageLength = messageLength; 488 this.fragmentOffset = fragmentOffset; 489 this.fragmentLength = fragmentLength; 490 } 491 492 @Override 493 public int compareTo(RecordFragment o) { 494 if (o instanceof HandshakeFragment) { 495 HandshakeFragment other = (HandshakeFragment)o; 496 if (this.messageSeq != other.messageSeq) { 497 // keep the insertion order of handshake messages 498 return this.messageSeq - other.messageSeq; 499 } else if (this.fragmentOffset != other.fragmentOffset) { 500 // small fragment offset was transmitted first 501 return this.fragmentOffset - other.fragmentOffset; 502 } else if (this.fragmentLength == other.fragmentLength) { 503 // retransmissions, ignore duplicated messages. 504 return 0; 505 } 506 507 // Should be repacked for suitable fragment length. 508 // 509 // Note that the acquiring processes will reassemble the 510 // the fragments later. 511 return compareToSequence(o.recordEpoch, o.recordSeq); 512 } 513 514 return super.compareTo(o); 515 } 516 } 517 518 private static final class HoleDescriptor { 519 int offset; // fragment_offset 520 int limit; // fragment_offset + fragment_length 521 522 HoleDescriptor(int offset, int limit) { 523 this.offset = offset; 524 this.limit = limit; 525 } 526 } 527 528 private static final class HandshakeFlight implements Cloneable { 529 static final byte HF_UNKNOWN = SSLHandshake.NOT_APPLICABLE.id; 530 531 byte handshakeType; // handshake type 532 int flightEpoch; // the epoch of the first message 533 int minMessageSeq; // minimal message sequence 534 535 int maxMessageSeq; // maximum message sequence 536 int maxRecordEpoch; // maximum record sequence number 537 long maxRecordSeq; // maximum record sequence number 538 539 HashMap<Byte, List<HoleDescriptor>> holesMap; 540 541 HandshakeFlight() { 542 this.handshakeType = HF_UNKNOWN; 543 this.flightEpoch = 0; 544 this.minMessageSeq = 0; 545 546 this.maxMessageSeq = 0; 547 this.maxRecordEpoch = 0; 548 this.maxRecordSeq = -1; 549 550 this.holesMap = new HashMap<>(5); 551 } 552 553 boolean isRetransmitOf(HandshakeFlight hs) { 554 return (hs != null) && 555 (this.handshakeType == hs.handshakeType) && 556 (this.minMessageSeq == hs.minMessageSeq); 557 } 558 559 @Override 560 public Object clone() { 561 HandshakeFlight hf = new HandshakeFlight(); 562 563 hf.handshakeType = this.handshakeType; 564 hf.flightEpoch = this.flightEpoch; 565 hf.minMessageSeq = this.minMessageSeq; 566 567 hf.maxMessageSeq = this.maxMessageSeq; 568 hf.maxRecordEpoch = this.maxRecordEpoch; 569 hf.maxRecordSeq = this.maxRecordSeq; 570 571 hf.holesMap = new HashMap<>(this.holesMap); 572 573 return hf; 574 } 575 } 576 577 final class DTLSReassembler { 578 // The handshake epoch. 579 final int handshakeEpoch; 580 581 // The buffered fragments. 582 TreeSet<RecordFragment> bufferedFragments = new TreeSet<>(); 583 584 // The handshake flight in progress. 585 HandshakeFlight handshakeFlight = new HandshakeFlight(); 586 587 // The preceding handshake flight. 588 HandshakeFlight precedingFlight = null; 589 590 // Epoch, sequence number and handshake message sequence of the 591 // next message acquisition of a flight. 592 int nextRecordEpoch; // next record epoch 593 long nextRecordSeq = 0; // next record sequence number 594 595 // Expect ChangeCipherSpec and Finished messages for the final flight. 596 boolean expectCCSFlight = false; 597 598 // Ready to process this flight if received all messages of the flight. 599 boolean flightIsReady = false; 600 boolean needToCheckFlight = false; 601 602 DTLSReassembler(int handshakeEpoch) { 603 this.handshakeEpoch = handshakeEpoch; 604 this.nextRecordEpoch = handshakeEpoch; 605 606 this.handshakeFlight.flightEpoch = handshakeEpoch; 607 } 608 609 void expectingFinishFlight() { 610 expectCCSFlight = true; 611 } 612 613 // Queue up a handshake message. 614 void queueUpHandshake(HandshakeFragment hsf) { 615 if (!isDesirable(hsf)) { 616 // Not a dedired record, discard it. 617 return; 618 } 619 620 // Clean up the retransmission messages if necessary. 621 cleanUpRetransmit(hsf); 622 623 // Is it the first message of next flight? 624 // 625 // Note: the Finished message is handled in the final CCS flight. 626 boolean isMinimalFlightMessage = false; 627 if (handshakeFlight.minMessageSeq == hsf.messageSeq) { 628 isMinimalFlightMessage = true; 629 } else if ((precedingFlight != null) && 630 (precedingFlight.minMessageSeq == hsf.messageSeq)) { 631 isMinimalFlightMessage = true; 632 } 633 634 if (isMinimalFlightMessage && (hsf.fragmentOffset == 0) && 635 (hsf.handshakeType != SSLHandshake.FINISHED.id)) { 636 637 // reset the handshake flight 638 handshakeFlight.handshakeType = hsf.handshakeType; 639 handshakeFlight.flightEpoch = hsf.recordEpoch; 640 handshakeFlight.minMessageSeq = hsf.messageSeq; 641 } 642 643 if (hsf.handshakeType == SSLHandshake.FINISHED.id) { 644 handshakeFlight.maxMessageSeq = hsf.messageSeq; 645 handshakeFlight.maxRecordEpoch = hsf.recordEpoch; 646 handshakeFlight.maxRecordSeq = hsf.recordSeq; 647 } else { 648 if (handshakeFlight.maxMessageSeq < hsf.messageSeq) { 649 handshakeFlight.maxMessageSeq = hsf.messageSeq; 650 } 651 652 int n = (hsf.recordEpoch - handshakeFlight.maxRecordEpoch); 653 if (n > 0) { 654 handshakeFlight.maxRecordEpoch = hsf.recordEpoch; 655 handshakeFlight.maxRecordSeq = hsf.recordSeq; 656 } else if (n == 0) { 657 // the same epoch 658 if (handshakeFlight.maxRecordSeq < hsf.recordSeq) { 659 handshakeFlight.maxRecordSeq = hsf.recordSeq; 660 } 661 } // Otherwise, it is unlikely to happen. 662 } 663 664 boolean fragmented = false; 665 if ((hsf.fragmentOffset) != 0 || 666 (hsf.fragmentLength != hsf.messageLength)) { 667 668 fragmented = true; 669 } 670 671 List<HoleDescriptor> holes = 672 handshakeFlight.holesMap.get(hsf.handshakeType); 673 if (holes == null) { 674 if (!fragmented) { 675 holes = Collections.emptyList(); 676 } else { 677 holes = new LinkedList<HoleDescriptor>(); 678 holes.add(new HoleDescriptor(0, hsf.messageLength)); 679 } 680 handshakeFlight.holesMap.put(hsf.handshakeType, holes); 681 } else if (holes.isEmpty()) { 682 // Have got the full handshake message. This record may be 683 // a handshake message retransmission. Discard this record. 684 // 685 // It's OK to discard retransmission as the handshake hash 686 // is computed as if each handshake message had been sent 687 // as a single fragment. 688 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 689 SSLLogger.fine("Have got the full message, discard it."); 690 } 691 692 return; 693 } 694 695 if (fragmented) { 696 int fragmentLimit = hsf.fragmentOffset + hsf.fragmentLength; 697 for (int i = 0; i < holes.size(); i++) { 698 699 HoleDescriptor hole = holes.get(i); 700 if ((hole.limit <= hsf.fragmentOffset) || 701 (hole.offset >= fragmentLimit)) { 702 // Also discard overlapping handshake retransmissions. 703 continue; 704 } 705 706 // The ranges SHOULD NOT overlap. 707 if (((hole.offset > hsf.fragmentOffset) && 708 (hole.offset < fragmentLimit)) || 709 ((hole.limit > hsf.fragmentOffset) && 710 (hole.limit < fragmentLimit))) { 711 712 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 713 SSLLogger.fine("Discard invalid record: " + 714 "handshake fragment ranges are overlapping"); 715 } 716 717 // invalid, discard it [section 4.1.2.7, RFC 6347] 718 return; 719 } 720 721 // This record interacts with this hole, fill the hole. 722 holes.remove(i); 723 // i--; 724 725 if (hsf.fragmentOffset > hole.offset) { 726 holes.add(new HoleDescriptor( 727 hole.offset, hsf.fragmentOffset)); 728 // i++; 729 } 730 731 if (fragmentLimit < hole.limit) { 732 holes.add(new HoleDescriptor( 733 fragmentLimit, hole.limit)); 734 // i++; 735 } 736 737 // As no ranges overlap, no interact with other holes. 738 break; 739 } 740 } 741 742 // buffer this fragment 743 if (hsf.handshakeType == SSLHandshake.FINISHED.id) { 744 // Need no status update. 745 bufferedFragments.add(hsf); 746 } else { 747 bufferFragment(hsf); 748 } 749 } 750 751 // Queue up a ChangeCipherSpec message 752 void queueUpChangeCipherSpec(RecordFragment rf) { 753 if (!isDesirable(rf)) { 754 // Not a dedired record, discard it. 755 return; 756 } 757 758 // Clean up the retransmission messages if necessary. 759 cleanUpRetransmit(rf); 760 761 // Is it the first message of this flight? 762 // 763 // Note: the first message of the final flight is ChangeCipherSpec. 764 if (expectCCSFlight) { 765 handshakeFlight.handshakeType = HandshakeFlight.HF_UNKNOWN; 766 handshakeFlight.flightEpoch = rf.recordEpoch; 767 } 768 769 // The epoch should be the same as the first message of the flight. 770 if (handshakeFlight.maxRecordSeq < rf.recordSeq) { 771 handshakeFlight.maxRecordSeq = rf.recordSeq; 772 } 773 774 // buffer this fragment 775 bufferFragment(rf); 776 } 777 778 // Queue up a ciphertext message. 779 // 780 // Note: not yet be able to decrypt the message. 781 void queueUpFragment(RecordFragment rf) { 782 if (!isDesirable(rf)) { 783 // Not a dedired record, discard it. 784 return; 785 } 786 787 // Clean up the retransmission messages if necessary. 788 cleanUpRetransmit(rf); 789 790 // buffer this fragment 791 bufferFragment(rf); 792 } 793 794 private void bufferFragment(RecordFragment rf) { 795 // append this fragment 796 bufferedFragments.add(rf); 797 798 if (flightIsReady) { 799 flightIsReady = false; 800 } 801 802 if (!needToCheckFlight) { 803 needToCheckFlight = true; 804 } 805 } 806 807 private void cleanUpRetransmit(RecordFragment rf) { 808 // Does the next flight start? 809 boolean isNewFlight = false; 810 if (precedingFlight != null) { 811 if (precedingFlight.flightEpoch < rf.recordEpoch) { 812 isNewFlight = true; 813 } else { 814 if (rf instanceof HandshakeFragment) { 815 HandshakeFragment hsf = (HandshakeFragment)rf; 816 if (precedingFlight.maxMessageSeq < hsf.messageSeq) { 817 isNewFlight = true; 818 } 819 } else if ( 820 rf.contentType != ContentType.CHANGE_CIPHER_SPEC.id) { 821 822 // ciphertext 823 if (precedingFlight.maxRecordEpoch < rf.recordEpoch) { 824 isNewFlight = true; 825 } 826 } 827 } 828 } 829 830 if (!isNewFlight) { 831 // Need no cleanup. 832 return; 833 } 834 835 // clean up the buffer 836 for (Iterator<RecordFragment> it = bufferedFragments.iterator(); 837 it.hasNext();) { 838 839 RecordFragment frag = it.next(); 840 boolean isOld = false; 841 if (frag.recordEpoch < precedingFlight.maxRecordEpoch) { 842 isOld = true; 843 } else if (frag.recordEpoch == precedingFlight.maxRecordEpoch) { 844 if (frag.recordSeq <= precedingFlight.maxRecordSeq) { 845 isOld = true; 846 } 847 } 848 849 if (!isOld && (frag instanceof HandshakeFragment)) { 850 HandshakeFragment hsf = (HandshakeFragment)frag; 851 isOld = (hsf.messageSeq <= precedingFlight.maxMessageSeq); 852 } 853 854 if (isOld) { 855 it.remove(); 856 } else { 857 // Safe to break as items in the buffer are ordered. 858 break; 859 } 860 } 861 862 // discard retransmissions of the previous flight if any. 863 precedingFlight = null; 864 } 865 866 // Is a desired record? 867 // 868 // Check for retransmission and lost records. 869 private boolean isDesirable(RecordFragment rf) { 870 // 871 // Discard records old than the previous epoch. 872 // 873 int previousEpoch = nextRecordEpoch - 1; 874 if (rf.recordEpoch < previousEpoch) { 875 // Too old to use, discard this record. 876 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 877 SSLLogger.fine( 878 "Too old epoch to use this record, discard it."); 879 } 880 881 return false; 882 } 883 884 // 885 // Allow retransmission of last flight of the previous epoch 886 // 887 // For example, the last server delivered flight for session 888 // resuming abbreviated handshaking consist three messages: 889 // ServerHello 890 // [ChangeCipherSpec] 891 // Finished 892 // 893 // The epoch number is incremented and the sequence number is reset 894 // if the ChangeCipherSpec is sent. 895 if (rf.recordEpoch == previousEpoch) { 896 boolean isDesired = true; 897 if (precedingFlight == null) { 898 isDesired = false; 899 } else { 900 if (rf instanceof HandshakeFragment) { 901 HandshakeFragment hsf = (HandshakeFragment)rf; 902 if (precedingFlight.minMessageSeq > hsf.messageSeq) { 903 isDesired = false; 904 } 905 } else if ( 906 rf.contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 907 908 // ChangeCipherSpec 909 if (precedingFlight.flightEpoch != rf.recordEpoch) { 910 isDesired = false; 911 } 912 } else { // ciphertext 913 if ((rf.recordEpoch < precedingFlight.maxRecordEpoch) || 914 (rf.recordEpoch == precedingFlight.maxRecordEpoch && 915 rf.recordSeq <= precedingFlight.maxRecordSeq)) { 916 isDesired = false; 917 } 918 } 919 } 920 921 if (!isDesired) { 922 // Too old to use, discard this retransmitted record 923 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 924 SSLLogger.fine( 925 "Too old retransmission to use, discard it."); 926 } 927 928 return false; 929 } 930 } else if ((rf.recordEpoch == nextRecordEpoch) && 931 (nextRecordSeq > rf.recordSeq)) { 932 933 // Previously disordered record for the current epoch. 934 // 935 // Should has been retransmitted. Discard this record. 936 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 937 SSLLogger.fine( 938 "Lagging behind record (sequence), discard it."); 939 } 940 941 return false; 942 } 943 944 return true; 945 } 946 947 private boolean isEmpty() { 948 return (bufferedFragments.isEmpty() || 949 (!flightIsReady && !needToCheckFlight) || 950 (needToCheckFlight && !flightIsReady())); 951 } 952 953 Plaintext acquirePlaintext() { 954 if (bufferedFragments.isEmpty()) { 955 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 956 SSLLogger.fine("No received handshake messages"); 957 } 958 return null; 959 } 960 961 if (!flightIsReady && needToCheckFlight) { 962 // check the fligth status 963 flightIsReady = flightIsReady(); 964 965 // Reset if this flight is ready. 966 if (flightIsReady) { 967 // Retransmitted handshake messages are not needed for 968 // further handshaking processing. 969 if (handshakeFlight.isRetransmitOf(precedingFlight)) { 970 // cleanup 971 bufferedFragments.clear(); 972 973 // Reset the next handshake flight. 974 resetHandshakeFlight(precedingFlight); 975 976 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 977 SSLLogger.fine("Received a retransmission flight."); 978 } 979 980 return Plaintext.PLAINTEXT_NULL; 981 } 982 } 983 984 needToCheckFlight = false; 985 } 986 987 if (!flightIsReady) { 988 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 989 SSLLogger.fine( 990 "The handshake flight is not ready to use: " + 991 handshakeFlight.handshakeType); 992 } 993 return null; 994 } 995 996 RecordFragment rFrag = bufferedFragments.first(); 997 Plaintext plaintext; 998 if (!rFrag.isCiphertext) { 999 // handshake message, or ChangeCipherSpec message 1000 plaintext = acquireHandshakeMessage(); 1001 1002 // Reset the handshake flight. 1003 if (bufferedFragments.isEmpty()) { 1004 // Need not to backup the holes map. Clear up it at first. 1005 handshakeFlight.holesMap.clear(); // cleanup holes map 1006 1007 // Update the preceding flight. 1008 precedingFlight = (HandshakeFlight)handshakeFlight.clone(); 1009 1010 // Reset the next handshake flight. 1011 resetHandshakeFlight(precedingFlight); 1012 1013 if (expectCCSFlight && 1014 (precedingFlight.handshakeType == 1015 HandshakeFlight.HF_UNKNOWN)) { 1016 expectCCSFlight = false; 1017 } 1018 } 1019 } else { 1020 // a Finished message or other ciphertexts 1021 plaintext = acquireCachedMessage(); 1022 } 1023 1024 return plaintext; 1025 } 1026 1027 // 1028 // Reset the handshake flight from a previous one. 1029 // 1030 private void resetHandshakeFlight(HandshakeFlight prev) { 1031 // Reset the next handshake flight. 1032 handshakeFlight.handshakeType = HandshakeFlight.HF_UNKNOWN; 1033 handshakeFlight.flightEpoch = prev.maxRecordEpoch; 1034 if (prev.flightEpoch != prev.maxRecordEpoch) { 1035 // a new epoch starts 1036 handshakeFlight.minMessageSeq = 0; 1037 } else { 1038 // stay at the same epoch 1039 // 1040 // The minimal message sequence number will get updated if 1041 // a flight retransmission happens. 1042 handshakeFlight.minMessageSeq = prev.maxMessageSeq + 1; 1043 } 1044 1045 // cleanup the maximum sequence number and epoch number. 1046 // 1047 // Note: actually, we need to do nothing because the reassembler 1048 // of handshake messages will reset them properly even for 1049 // retransmissions. 1050 // 1051 handshakeFlight.maxMessageSeq = 0; 1052 handshakeFlight.maxRecordEpoch = handshakeFlight.flightEpoch; 1053 1054 // Record sequence number cannot wrap even for retransmissions. 1055 handshakeFlight.maxRecordSeq = prev.maxRecordSeq + 1; 1056 1057 // cleanup holes map 1058 handshakeFlight.holesMap.clear(); 1059 1060 // Ready to accept new input record. 1061 flightIsReady = false; 1062 needToCheckFlight = false; 1063 } 1064 1065 private Plaintext acquireCachedMessage() { 1066 RecordFragment rFrag = bufferedFragments.first(); 1067 if (readEpoch != rFrag.recordEpoch) { 1068 if (readEpoch > rFrag.recordEpoch) { 1069 // discard old records 1070 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1071 SSLLogger.fine( 1072 "Discard old buffered ciphertext fragments."); 1073 } 1074 bufferedFragments.remove(rFrag); // popup the fragment 1075 } 1076 1077 // reset the flight 1078 if (flightIsReady) { 1079 flightIsReady = false; 1080 } 1081 1082 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1083 SSLLogger.fine( 1084 "Not yet ready to decrypt the cached fragments."); 1085 } 1086 return null; 1087 } 1088 1089 bufferedFragments.remove(rFrag); // popup the fragment 1090 1091 ByteBuffer fragment = ByteBuffer.wrap(rFrag.fragment); 1092 ByteBuffer plaintextFragment = null; 1093 try { 1094 Plaintext plaintext = readCipher.decrypt( 1095 rFrag.contentType, fragment, rFrag.recordEnS); 1096 plaintextFragment = plaintext.fragment; 1097 rFrag.contentType = plaintext.contentType; 1098 } catch (GeneralSecurityException gse) { 1099 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1100 SSLLogger.fine("Discard invalid record: ", gse); 1101 } 1102 1103 // invalid, discard this record [section 4.1.2.7, RFC 6347] 1104 return null; 1105 } 1106 1107 // The ciphtext handshake message can only be Finished (the 1108 // end of this flight), ClinetHello or HelloRequest (the 1109 // beginning of the next flight) message. Need not to check 1110 // any ChangeCipherSpec message. 1111 if (rFrag.contentType == ContentType.HANDSHAKE.id) { 1112 while (plaintextFragment.remaining() > 0) { 1113 HandshakeFragment hsFrag = parseHandshakeMessage( 1114 rFrag.contentType, 1115 rFrag.majorVersion, rFrag.minorVersion, 1116 rFrag.recordEnS, rFrag.recordEpoch, rFrag.recordSeq, 1117 plaintextFragment); 1118 1119 if (hsFrag == null) { 1120 // invalid, discard this record 1121 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1122 SSLLogger.fine( 1123 "Invalid handshake fragment, discard it", 1124 plaintextFragment); 1125 } 1126 return null; 1127 } 1128 1129 queueUpHandshake(hsFrag); 1130 // The flight ready status (flightIsReady) should have 1131 // been checked and updated for the Finished handshake 1132 // message before the decryption. Please don't update 1133 // flightIsReady for Finished messages. 1134 if (hsFrag.handshakeType != SSLHandshake.FINISHED.id) { 1135 flightIsReady = false; 1136 needToCheckFlight = true; 1137 } 1138 } 1139 1140 return acquirePlaintext(); 1141 } else { 1142 return new Plaintext(rFrag.contentType, 1143 rFrag.majorVersion, rFrag.minorVersion, 1144 rFrag.recordEpoch, 1145 Authenticator.toLong(rFrag.recordEnS), 1146 plaintextFragment); 1147 } 1148 } 1149 1150 private Plaintext acquireHandshakeMessage() { 1151 1152 RecordFragment rFrag = bufferedFragments.first(); 1153 if (rFrag.contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 1154 this.nextRecordEpoch = rFrag.recordEpoch + 1; 1155 1156 // For retransmissions, the next record sequence number is a 1157 // positive value. Don't worry about it as the acquiring of 1158 // the immediately followed Finished handshake message will 1159 // reset the next record sequence number correctly. 1160 this.nextRecordSeq = 0; 1161 1162 // Popup the fragment. 1163 bufferedFragments.remove(rFrag); 1164 return new Plaintext(rFrag.contentType, 1165 rFrag.majorVersion, rFrag.minorVersion, 1166 rFrag.recordEpoch, 1167 Authenticator.toLong(rFrag.recordEnS), 1168 ByteBuffer.wrap(rFrag.fragment)); 1169 } else { // rFrag.contentType == ContentType.HANDSHAKE.id 1170 HandshakeFragment hsFrag = (HandshakeFragment)rFrag; 1171 if ((hsFrag.messageLength == hsFrag.fragmentLength) && 1172 (hsFrag.fragmentOffset == 0)) { // no fragmentation 1173 1174 bufferedFragments.remove(rFrag); // popup the fragment 1175 1176 // this.nextRecordEpoch = hsFrag.recordEpoch; 1177 this.nextRecordSeq = hsFrag.recordSeq + 1; 1178 1179 // Note: may try to avoid byte array copy in the future. 1180 byte[] recordFrag = new byte[hsFrag.messageLength + 4]; 1181 Plaintext plaintext = new Plaintext( 1182 hsFrag.contentType, 1183 hsFrag.majorVersion, hsFrag.minorVersion, 1184 hsFrag.recordEpoch, 1185 Authenticator.toLong(hsFrag.recordEnS), 1186 ByteBuffer.wrap(recordFrag)); 1187 1188 // fill the handshake fragment of the record 1189 recordFrag[0] = hsFrag.handshakeType; 1190 recordFrag[1] = 1191 (byte)((hsFrag.messageLength >>> 16) & 0xFF); 1192 recordFrag[2] = 1193 (byte)((hsFrag.messageLength >>> 8) & 0xFF); 1194 recordFrag[3] = (byte)(hsFrag.messageLength & 0xFF); 1195 1196 System.arraycopy(hsFrag.fragment, 0, 1197 recordFrag, 4, hsFrag.fragmentLength); 1198 1199 // handshake hashing 1200 handshakeHashing(hsFrag, plaintext); 1201 1202 return plaintext; 1203 } else { // fragmented handshake message 1204 // the first record 1205 // 1206 // Note: may try to avoid byte array copy in the future. 1207 byte[] recordFrag = new byte[hsFrag.messageLength + 4]; 1208 Plaintext plaintext = new Plaintext( 1209 hsFrag.contentType, 1210 hsFrag.majorVersion, hsFrag.minorVersion, 1211 hsFrag.recordEpoch, 1212 Authenticator.toLong(hsFrag.recordEnS), 1213 ByteBuffer.wrap(recordFrag)); 1214 1215 // fill the handshake fragment of the record 1216 recordFrag[0] = hsFrag.handshakeType; 1217 recordFrag[1] = 1218 (byte)((hsFrag.messageLength >>> 16) & 0xFF); 1219 recordFrag[2] = 1220 (byte)((hsFrag.messageLength >>> 8) & 0xFF); 1221 recordFrag[3] = (byte)(hsFrag.messageLength & 0xFF); 1222 1223 int msgSeq = hsFrag.messageSeq; 1224 long maxRecodeSN = hsFrag.recordSeq; 1225 HandshakeFragment hmFrag = hsFrag; 1226 do { 1227 System.arraycopy(hmFrag.fragment, 0, 1228 recordFrag, hmFrag.fragmentOffset + 4, 1229 hmFrag.fragmentLength); 1230 // popup the fragment 1231 bufferedFragments.remove(rFrag); 1232 1233 if (maxRecodeSN < hmFrag.recordSeq) { 1234 maxRecodeSN = hmFrag.recordSeq; 1235 } 1236 1237 // Note: may buffer retransmitted fragments in order to 1238 // speed up the reassembly in the future. 1239 1240 // read the next buffered record 1241 if (!bufferedFragments.isEmpty()) { 1242 rFrag = bufferedFragments.first(); 1243 if (rFrag.contentType != ContentType.HANDSHAKE.id) { 1244 break; 1245 } else { 1246 hmFrag = (HandshakeFragment)rFrag; 1247 } 1248 } 1249 } while (!bufferedFragments.isEmpty() && 1250 (msgSeq == hmFrag.messageSeq)); 1251 1252 // handshake hashing 1253 handshakeHashing(hsFrag, plaintext); 1254 1255 this.nextRecordSeq = maxRecodeSN + 1; 1256 1257 return plaintext; 1258 } 1259 } 1260 } 1261 1262 boolean flightIsReady() { 1263 1264 byte flightType = handshakeFlight.handshakeType; 1265 if (flightType == HandshakeFlight.HF_UNKNOWN) { 1266 // 1267 // the ChangeCipherSpec/Finished flight 1268 // 1269 if (expectCCSFlight) { 1270 // Have the ChangeCipherSpec/Finished flight been received? 1271 boolean isReady = hasFinishedMessage(bufferedFragments); 1272 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1273 SSLLogger.fine( 1274 "Has the final flight been received? " + isReady); 1275 } 1276 1277 return isReady; 1278 } 1279 1280 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1281 SSLLogger.fine("No flight is received yet."); 1282 } 1283 1284 return false; 1285 } 1286 1287 if ((flightType == SSLHandshake.CLIENT_HELLO.id) || 1288 (flightType == SSLHandshake.HELLO_REQUEST.id) || 1289 (flightType == SSLHandshake.HELLO_VERIFY_REQUEST.id)) { 1290 1291 // single handshake message flight 1292 boolean isReady = hasCompleted(flightType); 1293 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1294 SSLLogger.fine( 1295 "Is the handshake message completed? " + isReady); 1296 } 1297 1298 return isReady; 1299 } 1300 1301 // 1302 // the ServerHello flight 1303 // 1304 if (flightType == SSLHandshake.SERVER_HELLO.id) { 1305 // Firstly, check the first flight handshake message. 1306 if (!hasCompleted(flightType)) { 1307 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1308 SSLLogger.fine( 1309 "The ServerHello message is not completed yet."); 1310 } 1311 1312 return false; 1313 } 1314 1315 // 1316 // an abbreviated handshake 1317 // 1318 if (hasFinishedMessage(bufferedFragments)) { 1319 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1320 SSLLogger.fine("It's an abbreviated handshake."); 1321 } 1322 1323 return true; 1324 } 1325 1326 // 1327 // a full handshake 1328 // 1329 List<HoleDescriptor> holes = handshakeFlight.holesMap.get( 1330 SSLHandshake.SERVER_HELLO_DONE.id); 1331 if ((holes == null) || !holes.isEmpty()) { 1332 // Not yet got the final message of the flight. 1333 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1334 SSLLogger.fine( 1335 "Not yet got the ServerHelloDone message"); 1336 } 1337 1338 return false; 1339 } 1340 1341 // Have all handshake message been received? 1342 boolean isReady = hasCompleted(bufferedFragments, 1343 handshakeFlight.minMessageSeq, 1344 handshakeFlight.maxMessageSeq); 1345 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1346 SSLLogger.fine( 1347 "Is the ServerHello flight (message " + 1348 handshakeFlight.minMessageSeq + "-" + 1349 handshakeFlight.maxMessageSeq + 1350 ") completed? " + isReady); 1351 } 1352 1353 return isReady; 1354 } 1355 1356 // 1357 // the ClientKeyExchange flight 1358 // 1359 // Note: need to consider more messages in this flight if 1360 // ht_supplemental_data and ht_certificate_url are 1361 // suppported in the future. 1362 // 1363 if ((flightType == SSLHandshake.CERTIFICATE.id) || 1364 (flightType == SSLHandshake.CLIENT_KEY_EXCHANGE.id)) { 1365 1366 // Firstly, check the first flight handshake message. 1367 if (!hasCompleted(flightType)) { 1368 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1369 SSLLogger.fine( 1370 "The ClientKeyExchange or client Certificate " + 1371 "message is not completed yet."); 1372 } 1373 1374 return false; 1375 } 1376 1377 // Is client CertificateVerify a mandatory message? 1378 if (flightType == SSLHandshake.CERTIFICATE.id) { 1379 if (needClientVerify(bufferedFragments) && 1380 !hasCompleted(SSLHandshake.CERTIFICATE_VERIFY.id)) { 1381 1382 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1383 SSLLogger.fine( 1384 "Not yet have the CertificateVerify message"); 1385 } 1386 1387 return false; 1388 } 1389 } 1390 1391 if (!hasFinishedMessage(bufferedFragments)) { 1392 // not yet have the ChangeCipherSpec/Finished messages 1393 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1394 SSLLogger.fine( 1395 "Not yet have the ChangeCipherSpec and " + 1396 "Finished messages"); 1397 } 1398 1399 return false; 1400 } 1401 1402 // Have all handshake message been received? 1403 boolean isReady = hasCompleted(bufferedFragments, 1404 handshakeFlight.minMessageSeq, 1405 handshakeFlight.maxMessageSeq); 1406 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1407 SSLLogger.fine( 1408 "Is the ClientKeyExchange flight (message " + 1409 handshakeFlight.minMessageSeq + "-" + 1410 handshakeFlight.maxMessageSeq + 1411 ") completed? " + isReady); 1412 } 1413 1414 return isReady; 1415 } 1416 1417 // 1418 // Otherwise, need to receive more handshake messages. 1419 // 1420 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { 1421 SSLLogger.fine("Need to receive more handshake messages"); 1422 } 1423 1424 return false; 1425 } 1426 1427 // Looking for the ChangeCipherSpec and Finished messages. 1428 // 1429 // As the cached Finished message should be a ciphertext, we don't 1430 // exactly know a ciphertext is a Finished message or not. According 1431 // to the spec of TLS/DTLS handshaking, a Finished message is always 1432 // sent immediately after a ChangeCipherSpec message. The first 1433 // ciphertext handshake message should be the expected Finished message. 1434 private boolean hasFinishedMessage(Set<RecordFragment> fragments) { 1435 1436 boolean hasCCS = false; 1437 boolean hasFin = false; 1438 for (RecordFragment fragment : fragments) { 1439 if (fragment.contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 1440 if (hasFin) { 1441 return true; 1442 } 1443 hasCCS = true; 1444 } else if (fragment.contentType == ContentType.HANDSHAKE.id) { 1445 // Finished is the first expected message of a new epoch. 1446 if (fragment.isCiphertext) { 1447 if (hasCCS) { 1448 return true; 1449 } 1450 hasFin = true; 1451 } 1452 } 1453 } 1454 1455 return hasFin && hasCCS; 1456 } 1457 1458 // Is client CertificateVerify a mandatory message? 1459 // 1460 // In the current implementation, client CertificateVerify is a 1461 // mandatory message if the client Certificate is not empty. 1462 private boolean needClientVerify(Set<RecordFragment> fragments) { 1463 1464 // The caller should have checked the completion of the first 1465 // present handshake message. Need not to check it again. 1466 for (RecordFragment rFrag : fragments) { 1467 if ((rFrag.contentType != ContentType.HANDSHAKE.id) || 1468 rFrag.isCiphertext) { 1469 break; 1470 } 1471 1472 HandshakeFragment hsFrag = (HandshakeFragment)rFrag; 1473 if (hsFrag.handshakeType != SSLHandshake.CERTIFICATE.id) { 1474 continue; 1475 } 1476 1477 return (rFrag.fragment != null) && 1478 (rFrag.fragment.length > DTLSRecord.minCertPlaintextSize); 1479 } 1480 1481 return false; 1482 } 1483 1484 private boolean hasCompleted(byte handshakeType) { 1485 List<HoleDescriptor> holes = 1486 handshakeFlight.holesMap.get(handshakeType); 1487 if (holes == null) { 1488 // not yet received this kind of handshake message 1489 return false; 1490 } 1491 1492 return holes.isEmpty(); // no fragment hole for complete message 1493 } 1494 1495 private boolean hasCompleted( 1496 Set<RecordFragment> fragments, 1497 int presentMsgSeq, int endMsgSeq) { 1498 1499 // The caller should have checked the completion of the first 1500 // present handshake message. Need not to check it again. 1501 for (RecordFragment rFrag : fragments) { 1502 if ((rFrag.contentType != ContentType.HANDSHAKE.id) || 1503 rFrag.isCiphertext) { 1504 break; 1505 } 1506 1507 HandshakeFragment hsFrag = (HandshakeFragment)rFrag; 1508 if (hsFrag.messageSeq == presentMsgSeq) { 1509 continue; 1510 } else if (hsFrag.messageSeq == (presentMsgSeq + 1)) { 1511 // check the completion of the handshake message 1512 if (!hasCompleted(hsFrag.handshakeType)) { 1513 return false; 1514 } 1515 1516 presentMsgSeq = hsFrag.messageSeq; 1517 } else { 1518 // not yet got handshake message next to presentMsgSeq 1519 break; 1520 } 1521 } 1522 1523 return (presentMsgSeq >= endMsgSeq); 1524 // false: if not yet got all messages of the flight. 1525 } 1526 1527 private void handshakeHashing( 1528 HandshakeFragment hsFrag, Plaintext plaintext) { 1529 byte hsType = hsFrag.handshakeType; 1530 if (!handshakeHash.isHashable(hsType)) { 1531 // omitted from handshake hash computation 1532 return; 1533 } 1534 1535 // calculate the DTLS header and reserve the handshake message 1536 plaintext.fragment.position(4); // ignore the TLS header 1537 byte[] temporary = new byte[plaintext.fragment.remaining() + 12]; 1538 // 12: handshake header size 1539 1540 // Handshake.msg_type 1541 temporary[0] = hsFrag.handshakeType; 1542 1543 // Handshake.length 1544 temporary[1] = (byte)((hsFrag.messageLength >> 16) & 0xFF); 1545 temporary[2] = (byte)((hsFrag.messageLength >> 8) & 0xFF); 1546 temporary[3] = (byte)(hsFrag.messageLength & 0xFF); 1547 1548 // Handshake.message_seq 1549 temporary[4] = (byte)((hsFrag.messageSeq >> 8) & 0xFF); 1550 temporary[5] = (byte)(hsFrag.messageSeq & 0xFF); 1551 1552 // Handshake.fragment_offset 1553 temporary[6] = 0; 1554 temporary[7] = 0; 1555 temporary[8] = 0; 1556 1557 // Handshake.fragment_length 1558 temporary[9] = temporary[1]; 1559 temporary[10] = temporary[2]; 1560 temporary[11] = temporary[3]; 1561 1562 plaintext.fragment.get(temporary, 1563 12, plaintext.fragment.remaining()); 1564 handshakeHash.receive(temporary); 1565 plaintext.fragment.position(0); // restore the position 1566 } 1567 } 1568 } 1569