src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47478 438e0c9f2f17
child 56646 e57205a6e4ee
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    16  *
    16  *
    17  * You should have received a copy of the GNU General Public License version
    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,
    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.
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    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
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.io.*;
    28 import java.io.*;
    29 import java.nio.*;
    29 import java.nio.*;
       
    30 import java.security.GeneralSecurityException;
    30 import java.util.*;
    31 import java.util.*;
    31 import javax.crypto.BadPaddingException;
    32 import javax.crypto.BadPaddingException;
    32 
       
    33 import javax.net.ssl.*;
    33 import javax.net.ssl.*;
    34 
    34 import sun.security.ssl.SSLCipher.SSLReadCipher;
    35 import sun.security.util.HexDumpEncoder;
       
    36 import static sun.security.ssl.HandshakeMessage.*;
       
    37 
    35 
    38 /**
    36 /**
    39  * DTLS {@code InputRecord} implementation for {@code SSLEngine}.
    37  * DTLS {@code InputRecord} implementation for {@code SSLEngine}.
    40  */
    38  */
    41 final class DTLSInputRecord extends InputRecord implements DTLSRecord {
    39 final class DTLSInputRecord extends InputRecord implements DTLSRecord {
    42 
       
    43     private DTLSReassembler reassembler = null;
    40     private DTLSReassembler reassembler = null;
    44 
    41     private int             readEpoch;
    45     int                 readEpoch;
    42 
    46 
    43     DTLSInputRecord(HandshakeHash handshakeHash) {
    47     int                 prevReadEpoch;
    44         super(handshakeHash, SSLReadCipher.nullDTlsReadCipher());
    48     Authenticator       prevReadAuthenticator;
       
    49     CipherBox           prevReadCipher;
       
    50 
       
    51     DTLSInputRecord() {
       
    52         this.readEpoch = 0;
    45         this.readEpoch = 0;
    53         this.readAuthenticator = new MAC(true);
       
    54 
       
    55         this.prevReadEpoch = 0;
       
    56         this.prevReadCipher = CipherBox.NULL;
       
    57         this.prevReadAuthenticator = new MAC(true);
       
    58     }
    46     }
    59 
    47 
    60     @Override
    48     @Override
    61     void changeReadCiphers(Authenticator readAuthenticator,
    49     void changeReadCiphers(SSLReadCipher readCipher) {
    62             CipherBox readCipher) {
       
    63 
       
    64         prevReadCipher.dispose();
       
    65 
       
    66         this.prevReadAuthenticator = this.readAuthenticator;
       
    67         this.prevReadCipher = this.readCipher;
       
    68         this.prevReadEpoch = this.readEpoch;
       
    69 
       
    70         this.readAuthenticator = readAuthenticator;
       
    71         this.readCipher = readCipher;
    50         this.readCipher = readCipher;
    72         this.readEpoch++;
    51         this.readEpoch++;
    73     }
    52     }
    74 
    53 
    75     @Override
    54     @Override
    76     public synchronized void close() throws IOException {
    55     public synchronized void close() throws IOException {
    77         if (!isClosed) {
    56         if (!isClosed) {
    78             prevReadCipher.dispose();
       
    79             super.close();
    57             super.close();
    80         }
    58         }
    81     }
    59     }
    82 
    60 
    83     @Override
    61     @Override
    85         return ((reassembler == null) || reassembler.isEmpty());
    63         return ((reassembler == null) || reassembler.isEmpty());
    86     }
    64     }
    87 
    65 
    88     @Override
    66     @Override
    89     int estimateFragmentSize(int packetSize) {
    67     int estimateFragmentSize(int packetSize) {
    90         int macLen = 0;
       
    91         if (readAuthenticator instanceof MAC) {
       
    92             macLen = ((MAC)readAuthenticator).MAClen();
       
    93         }
       
    94 
       
    95         if (packetSize > 0) {
    68         if (packetSize > 0) {
    96             return readCipher.estimateFragmentSize(
    69             return readCipher.estimateFragmentSize(packetSize, headerSize);
    97                     packetSize, macLen, headerSize);
       
    98         } else {
    70         } else {
    99             return Record.maxDataSize;
    71             return Record.maxDataSize;
   100         }
    72         }
   101     }
    73     }
   102 
    74 
   106             reassembler.expectingFinishFlight();
    78             reassembler.expectingFinishFlight();
   107         }
    79         }
   108     }
    80     }
   109 
    81 
   110     @Override
    82     @Override
       
    83     void finishHandshake() {
       
    84         reassembler = null;
       
    85     }
       
    86 
       
    87     @Override
   111     Plaintext acquirePlaintext() {
    88     Plaintext acquirePlaintext() {
   112         if (reassembler != null) {
    89         if (reassembler != null) {
   113             return reassembler.acquirePlaintext();
    90             return reassembler.acquirePlaintext();
   114         }
    91         }
   115 
    92 
   116         return null;
    93         return null;
   117     }
    94     }
   118 
    95 
   119     @Override
    96      @Override
   120     Plaintext decode(ByteBuffer packet) {
    97     Plaintext[] decode(ByteBuffer[] srcs, int srcsOffset,
   121 
    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) {
   122         if (isClosed) {
   112         if (isClosed) {
   123             return null;
   113             return null;
   124         }
   114         }
   125 
   115 
   126         if (debug != null && Debug.isOn("packet")) {
   116         if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
   127              Debug.printHex(
   117             SSLLogger.fine("Raw read", packet);
   128                     "[Raw read]: length = " + packet.remaining(), packet);
       
   129         }
   118         }
   130 
   119 
   131         // The caller should have validated the record.
   120         // The caller should have validated the record.
   132         int srcPos = packet.position();
   121         int srcPos = packet.position();
   133         int srcLim = packet.limit();
   122         int srcLim = packet.limit();
   147                            (recordEnS[7] & 0xFFL);         // pos: 5-10
   136                            (recordEnS[7] & 0xFFL);         // pos: 5-10
   148 
   137 
   149         int contentLen = ((packet.get() & 0xFF) << 8) |
   138         int contentLen = ((packet.get() & 0xFF) << 8) |
   150                           (packet.get() & 0xFF);           // pos: 11, 12
   139                           (packet.get() & 0xFF);           // pos: 11, 12
   151 
   140 
   152         if (debug != null && Debug.isOn("record")) {
   141         if (SSLLogger.isOn && SSLLogger.isOn("record")) {
   153             Debug.log("READ: " +
   142             SSLLogger.fine("READ: " +
   154                     ProtocolVersion.valueOf(majorVersion, minorVersion) +
   143                     ProtocolVersion.nameOf(majorVersion, minorVersion) +
   155                     " " + Record.contentName(contentType) + ", length = " +
   144                     " " + ContentType.nameOf(contentType) + ", length = " +
   156                     contentLen);
   145                     contentLen);
   157         }
   146         }
   158 
   147 
   159         int recLim = srcPos + DTLSRecord.headerSize + contentLen;
   148         int recLim = srcPos + DTLSRecord.headerSize + contentLen;
   160 
   149 
   161         if (this.prevReadEpoch > recordEpoch) {
   150         if (this.readEpoch > recordEpoch) {
   162             // Reset the position of the packet buffer.
   151             // Reset the position of the packet buffer.
   163             packet.position(recLim);
   152             packet.position(recLim);
   164             if (debug != null && Debug.isOn("record")) {
   153             if (SSLLogger.isOn && SSLLogger.isOn("record")) {
   165                 Debug.printHex("READ: discard this old record", recordEnS);
   154                 SSLLogger.fine("READ: discard this old record", recordEnS);
   166             }
   155             }
   167             return null;
   156             return null;
   168         }
   157         }
   169 
   158 
   170         // Buffer next epoch message if necessary.
   159         // Buffer next epoch message if necessary.
   171         if (this.readEpoch < recordEpoch) {
   160         if (this.readEpoch < recordEpoch) {
   172             // Discard the record younger than the current epcoh if:
   161             // Discard the record younger than the current epcoh if:
   173             // 1. it is not a handshake message, or
   162             // 1. it is not a handshake message, or
   174             // 2. it is not of next epoch.
   163             // 3. it is not of next epoch.
   175             if (((contentType != Record.ct_handshake) &&
   164             if ((contentType != ContentType.HANDSHAKE.id &&
   176                     (contentType != Record.ct_change_cipher_spec)) ||
   165                     contentType != ContentType.CHANGE_CIPHER_SPEC.id) ||
       
   166                 (reassembler == null &&
       
   167                     contentType != ContentType.HANDSHAKE.id) ||
   177                 (this.readEpoch < (recordEpoch - 1))) {
   168                 (this.readEpoch < (recordEpoch - 1))) {
   178 
   169 
   179                 packet.position(recLim);
   170                 packet.position(recLim);
   180 
   171 
   181                 if (debug != null && Debug.isOn("verbose")) {
   172                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   182                     Debug.log("Premature record (epoch), discard it.");
   173                     SSLLogger.fine("Premature record (epoch), discard it.");
   183                 }
   174                 }
   184 
   175 
   185                 return null;
   176                 return null;
   186             }
   177             }
       
   178 
   187 
   179 
   188             // Not ready to decrypt this record, may be an encrypted Finished
   180             // Not ready to decrypt this record, may be an encrypted Finished
   189             // message, need to buffer it.
   181             // message, need to buffer it.
   190             byte[] fragment = new byte[contentLen];
   182             byte[] fragment = new byte[contentLen];
   191             packet.get(fragment);              // copy the fragment
   183             packet.get(fragment);              // copy the fragment
   192             RecordFragment buffered = new RecordFragment(fragment, contentType,
   184             RecordFragment buffered = new RecordFragment(fragment, contentType,
   193                     majorVersion, minorVersion,
   185                     majorVersion, minorVersion,
   194                     recordEnS, recordEpoch, recordSeq, true);
   186                     recordEnS, recordEpoch, recordSeq, true);
   195 
   187 
       
   188             if (reassembler == null) {
       
   189                 reassembler = new DTLSReassembler(recordEpoch);
       
   190             }
   196             reassembler.queueUpFragment(buffered);
   191             reassembler.queueUpFragment(buffered);
   197 
   192 
   198             // consume the full record in the packet buffer.
   193             // consume the full record in the packet buffer.
   199             packet.position(recLim);
   194             packet.position(recLim);
   200 
   195 
   201             return reassembler.acquirePlaintext();
   196             Plaintext pt = reassembler.acquirePlaintext();
       
   197             return pt == null ? null : new Plaintext[] { pt };
   202         }
   198         }
   203 
   199 
   204         //
   200         //
   205         // Now, the message is of this epoch or the previous epoch.
   201         // Now, the message is of this epoch.
   206         //
   202         //
   207         Authenticator decodeAuthenticator;
       
   208         CipherBox decodeCipher;
       
   209         if (this.readEpoch == recordEpoch) {
       
   210             decodeAuthenticator = readAuthenticator;
       
   211             decodeCipher = readCipher;
       
   212         } else {                        // prevReadEpoch == recordEpoch
       
   213             decodeAuthenticator = prevReadAuthenticator;
       
   214             decodeCipher = prevReadCipher;
       
   215         }
       
   216 
       
   217         // decrypt the fragment
   203         // decrypt the fragment
   218         packet.limit(recLim);
   204         packet.limit(recLim);
   219         packet.position(srcPos + DTLSRecord.headerSize);
   205         packet.position(srcPos + DTLSRecord.headerSize);
   220 
   206 
   221         ByteBuffer plaintextFragment;
   207         ByteBuffer plaintextFragment;
   222         try {
   208         try {
   223             plaintextFragment = decrypt(decodeAuthenticator,
   209             Plaintext plaintext =
   224                     decodeCipher, contentType, packet, recordEnS);
   210                     readCipher.decrypt(contentType, packet, recordEnS);
   225         } catch (BadPaddingException bpe) {
   211             plaintextFragment = plaintext.fragment;
   226             if (debug != null && Debug.isOn("ssl")) {
   212             contentType = plaintext.contentType;
   227                 Debug.log("Discard invalid record: " + bpe);
   213         } catch (GeneralSecurityException gse) {
       
   214             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
       
   215                 SSLLogger.fine("Discard invalid record: " + gse);
   228             }
   216             }
   229 
   217 
   230             // invalid, discard this record [section 4.1.2.7, RFC 6347]
   218             // invalid, discard this record [section 4.1.2.7, RFC 6347]
   231             return null;
   219             return null;
   232         } finally {
   220         } finally {
   233             // comsume a complete record
   221             // comsume a complete record
   234             packet.limit(srcLim);
   222             packet.limit(srcLim);
   235             packet.position(recLim);
   223             packet.position(recLim);
   236         }
   224         }
   237 
   225 
   238         if (contentType != Record.ct_change_cipher_spec &&
   226         if (contentType != ContentType.CHANGE_CIPHER_SPEC.id &&
   239             contentType != Record.ct_handshake) {   // app data or alert
   227             contentType != ContentType.HANDSHAKE.id) {   // app data or alert
   240                                                     // no retransmission
   228                                                     // no retransmission
   241             // Cleanup the handshake reassembler if necessary.
   229             // Cleanup the handshake reassembler if necessary.
   242             if ((reassembler != null) &&
   230             if ((reassembler != null) &&
   243                     (reassembler.handshakeEpoch < recordEpoch)) {
   231                     (reassembler.handshakeEpoch < recordEpoch)) {
   244                 if (debug != null && Debug.isOn("verbose")) {
   232                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   245                     Debug.log("Cleanup the handshake reassembler");
   233                     SSLLogger.fine("Cleanup the handshake reassembler");
   246                 }
   234                 }
   247 
   235 
   248                 reassembler = null;
   236                 reassembler = null;
   249             }
   237             }
   250 
   238 
   251             return new Plaintext(contentType, majorVersion, minorVersion,
   239             return new Plaintext[] {
   252                     recordEpoch, Authenticator.toLong(recordEnS),
   240                     new Plaintext(contentType, majorVersion, minorVersion,
   253                     plaintextFragment);
   241                             recordEpoch, Authenticator.toLong(recordEnS),
   254         }
   242                             plaintextFragment)};
   255 
   243         }
   256         if (contentType == Record.ct_change_cipher_spec) {
   244 
       
   245         if (contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
   257             if (reassembler == null) {
   246             if (reassembler == null) {
   258                 if (this.readEpoch != recordEpoch) {
       
   259                     // handshake has not started, should be an
       
   260                     // old handshake message, discard it.
       
   261 
       
   262                     if (debug != null && Debug.isOn("verbose")) {
       
   263                         Debug.log(
       
   264                                 "Lagging behind ChangeCipherSpec, discard it.");
       
   265                     }
       
   266 
       
   267                     return null;
       
   268                 }
       
   269 
       
   270                 reassembler = new DTLSReassembler(recordEpoch);
   247                 reassembler = new DTLSReassembler(recordEpoch);
   271             }
   248             }
   272 
   249 
   273             reassembler.queueUpChangeCipherSpec(
   250             reassembler.queueUpChangeCipherSpec(
   274                     new RecordFragment(plaintextFragment, contentType,
   251                     new RecordFragment(plaintextFragment, contentType,
   282                     contentType, majorVersion, minorVersion,
   259                     contentType, majorVersion, minorVersion,
   283                     recordEnS, recordEpoch, recordSeq, plaintextFragment);
   260                     recordEnS, recordEpoch, recordSeq, plaintextFragment);
   284 
   261 
   285                 if (hsFrag == null) {
   262                 if (hsFrag == null) {
   286                     // invalid, discard this record
   263                     // invalid, discard this record
   287                     if (debug != null && Debug.isOn("verbose")) {
   264                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   288                         Debug.log("Invalid handshake message, discard it.");
   265                         SSLLogger.fine(
       
   266                                 "Invalid handshake message, discard it.");
   289                     }
   267                     }
   290 
   268 
   291                     return null;
   269                     return null;
   292                 }
   270                 }
   293 
   271 
   294                 if (reassembler == null) {
   272                 if (reassembler == null) {
   295                     if (this.readEpoch != recordEpoch) {
       
   296                         // handshake has not started, should be an
       
   297                         // old handshake message, discard it.
       
   298 
       
   299                         if (debug != null && Debug.isOn("verbose")) {
       
   300                             Debug.log(
       
   301                                 "Lagging behind handshake record, discard it.");
       
   302                         }
       
   303 
       
   304                         return null;
       
   305                     }
       
   306 
       
   307                     reassembler = new DTLSReassembler(recordEpoch);
   273                     reassembler = new DTLSReassembler(recordEpoch);
   308                 }
   274                 }
   309 
   275 
   310                 reassembler.queueUpHandshake(hsFrag);
   276                 reassembler.queueUpHandshake(hsFrag);
   311             }
   277             }
   312         }
   278         }
   313 
   279 
   314         // Completed the read of the full record.  Acquire the reassembled
   280         // Completed the read of the full record.  Acquire the reassembled
   315         // messages.
   281         // messages.
   316         if (reassembler != null) {
   282         if (reassembler != null) {
   317             return reassembler.acquirePlaintext();
   283             Plaintext pt = reassembler.acquirePlaintext();
   318         }
   284             return pt == null ? null : new Plaintext[] { pt };
   319 
   285         }
   320         if (debug != null && Debug.isOn("verbose")) {
   286 
   321             Debug.log("The reassembler is not initialized yet.");
   287         if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
       
   288              SSLLogger.fine("The reassembler is not initialized yet.");
   322         }
   289         }
   323 
   290 
   324         return null;
   291         return null;
   325     }
   292     }
   326 
   293 
   327     @Override
   294     @Override
   328     int bytesInCompletePacket(ByteBuffer packet) throws SSLException {
   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 {
   329 
   302 
   330         // DTLS length field is in bytes 11/12
   303         // DTLS length field is in bytes 11/12
   331         if (packet.remaining() < headerSize) {
   304         if (packet.remaining() < headerSize) {
   332             return -1;
   305             return -1;
   333         }
   306         }
   335         // Last sanity check that it's not a wild record
   308         // Last sanity check that it's not a wild record
   336         int pos = packet.position();
   309         int pos = packet.position();
   337 
   310 
   338         // Check the content type of the record.
   311         // Check the content type of the record.
   339         byte contentType = packet.get(pos);
   312         byte contentType = packet.get(pos);
   340         if (!Record.isValidContentType(contentType)) {
   313         if (ContentType.valueOf(contentType) == null) {
   341             throw new SSLException(
   314             throw new SSLException(
   342                     "Unrecognized SSL message, plaintext connection?");
   315                     "Unrecognized SSL message, plaintext connection?");
   343         }
   316         }
   344 
   317 
   345         // Check the protocol version of the record.
   318         // Check the protocol version of the record.
   346         ProtocolVersion recordVersion =
   319         byte majorVersion = packet.get(pos + 1);
   347             ProtocolVersion.valueOf(packet.get(pos + 1), packet.get(pos + 2));
   320         byte minorVersion = packet.get(pos + 2);
   348         checkRecordVersion(recordVersion, false);
   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         }
   349 
   327 
   350         // Get the fragment length of the record.
   328         // Get the fragment length of the record.
   351         int fragLen = ((packet.get(pos + 11) & 0xFF) << 8) +
   329         int fragLen = ((packet.get(pos + 11) & 0xFF) << 8) +
   352                        (packet.get(pos + 12) & 0xFF) + headerSize;
   330                        (packet.get(pos + 12) & 0xFF) + headerSize;
   353         if (fragLen > Record.maxFragmentSize) {
   331         if (fragLen > Record.maxFragmentSize) {
   357         }
   335         }
   358 
   336 
   359         return fragLen;
   337         return fragLen;
   360     }
   338     }
   361 
   339 
   362     @Override
       
   363     void checkRecordVersion(ProtocolVersion recordVersion,
       
   364             boolean allowSSL20Hello) throws SSLException {
       
   365 
       
   366         if (!recordVersion.maybeDTLSProtocol()) {
       
   367             throw new SSLException(
       
   368                     "Unrecognized record version " + recordVersion +
       
   369                     " , plaintext connection?");
       
   370         }
       
   371     }
       
   372 
       
   373     private static HandshakeFragment parseHandshakeMessage(
   340     private static HandshakeFragment parseHandshakeMessage(
   374             byte contentType, byte majorVersion, byte minorVersion,
   341             byte contentType, byte majorVersion, byte minorVersion,
   375             byte[] recordEnS, int recordEpoch, long recordSeq,
   342             byte[] recordEnS, int recordEpoch, long recordSeq,
   376             ByteBuffer plaintextFragment) {
   343             ByteBuffer plaintextFragment) {
   377 
   344 
   378         int remaining = plaintextFragment.remaining();
   345         int remaining = plaintextFragment.remaining();
   379         if (remaining < handshakeHeaderSize) {
   346         if (remaining < handshakeHeaderSize) {
   380             if (debug != null && Debug.isOn("ssl")) {
   347             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
   381                 Debug.log("Discard invalid record: " +
   348                 SSLLogger.fine("Discard invalid record: " +
   382                         "too small record to hold a handshake fragment");
   349                         "too small record to hold a handshake fragment");
   383             }
   350             }
   384 
   351 
   385             // invalid, discard this record [section 4.1.2.7, RFC 6347]
   352             // invalid, discard this record [section 4.1.2.7, RFC 6347]
   386             return null;
   353             return null;
   401         int fragmentLength =
   368         int fragmentLength =
   402                 ((plaintextFragment.get() & 0xFF) << 16) |
   369                 ((plaintextFragment.get() & 0xFF) << 16) |
   403                 ((plaintextFragment.get() & 0xFF) << 8) |
   370                 ((plaintextFragment.get() & 0xFF) << 8) |
   404                  (plaintextFragment.get() & 0xFF);          // pos: 9-11
   371                  (plaintextFragment.get() & 0xFF);          // pos: 9-11
   405         if ((remaining - handshakeHeaderSize) < fragmentLength) {
   372         if ((remaining - handshakeHeaderSize) < fragmentLength) {
   406             if (debug != null && Debug.isOn("ssl")) {
   373             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
   407                 Debug.log("Discard invalid record: " +
   374                 SSLLogger.fine("Discard invalid record: " +
   408                         "not a complete handshake fragment in the record");
   375                         "not a complete handshake fragment in the record");
   409             }
   376             }
   410 
   377 
   411             // invalid, discard this record [section 4.1.2.7, RFC 6347]
   378             // invalid, discard this record [section 4.1.2.7, RFC 6347]
   412             return null;
   379             return null;
   459                                             // the buffer if necessary.
   426                                             // the buffer if necessary.
   460         }
   427         }
   461 
   428 
   462         @Override
   429         @Override
   463         public int compareTo(RecordFragment o) {
   430         public int compareTo(RecordFragment o) {
   464             if (this.contentType == Record.ct_change_cipher_spec) {
   431             if (this.contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
   465                 if (o.contentType == Record.ct_change_cipher_spec) {
   432                 if (o.contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
   466                     // Only one incoming ChangeCipherSpec message for an epoch.
   433                     // Only one incoming ChangeCipherSpec message for an epoch.
   467                     //
   434                     //
   468                     // Ignore duplicated ChangeCipherSpec messages.
   435                     // Ignore duplicated ChangeCipherSpec messages.
   469                     return Integer.compare(this.recordEpoch, o.recordEpoch);
   436                     return Integer.compare(this.recordEpoch, o.recordEpoch);
   470                 } else if ((this.recordEpoch == o.recordEpoch) &&
   437                 } else if ((this.recordEpoch == o.recordEpoch) &&
   471                         (o.contentType == Record.ct_handshake)) {
   438                         (o.contentType == ContentType.HANDSHAKE.id)) {
   472                     // ChangeCipherSpec is the latest message of an epoch.
   439                     // ChangeCipherSpec is the latest message of an epoch.
   473                     return 1;
   440                     return 1;
   474                 }
   441                 }
   475             } else if (o.contentType == Record.ct_change_cipher_spec) {
   442             } else if (o.contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
   476                 if ((this.recordEpoch == o.recordEpoch) &&
   443                 if ((this.recordEpoch == o.recordEpoch) &&
   477                         (this.contentType == Record.ct_handshake)) {
   444                         (this.contentType == ContentType.HANDSHAKE.id)) {
   478                     // ChangeCipherSpec is the latest message of an epoch.
   445                     // ChangeCipherSpec is the latest message of an epoch.
   479                     return -1;
   446                     return -1;
   480                 } else {
   447                 } else {
   481                     // different epoch or this is not a handshake message
   448                     // different epoch or this is not a handshake message
   482                     return compareToSequence(o.recordEpoch, o.recordSeq);
   449                     return compareToSequence(o.recordEpoch, o.recordSeq);
   537                     return 0;
   504                     return 0;
   538                 }
   505                 }
   539 
   506 
   540                 // Should be repacked for suitable fragment length.
   507                 // Should be repacked for suitable fragment length.
   541                 //
   508                 //
   542                 // Note that the acquiring processes will reassemble
   509                 // Note that the acquiring processes will reassemble the
   543                 // the fragments later.
   510                 // the fragments later.
   544                 return compareToSequence(o.recordEpoch, o.recordSeq);
   511                 return compareToSequence(o.recordEpoch, o.recordSeq);
   545             }
   512             }
   546 
   513 
   547             return super.compareTo(o);
   514             return super.compareTo(o);
   557             this.limit = limit;
   524             this.limit = limit;
   558         }
   525         }
   559     }
   526     }
   560 
   527 
   561     private static final class HandshakeFlight implements Cloneable {
   528     private static final class HandshakeFlight implements Cloneable {
   562         static final byte HF_UNKNOWN = HandshakeMessage.ht_not_applicable;
   529         static final byte HF_UNKNOWN = SSLHandshake.NOT_APPLICABLE.id;
   563 
   530 
   564         byte        handshakeType;      // handshake type
   531         byte        handshakeType;      // handshake type
   565         int         flightEpoch;        // the epoch of the first message
   532         int         flightEpoch;        // the epoch of the first message
   566         int         minMessageSeq;      // minimal message sequence
   533         int         minMessageSeq;      // minimal message sequence
   567 
   534 
   663                     (precedingFlight.minMessageSeq == hsf.messageSeq)) {
   630                     (precedingFlight.minMessageSeq == hsf.messageSeq)) {
   664                 isMinimalFlightMessage = true;
   631                 isMinimalFlightMessage = true;
   665             }
   632             }
   666 
   633 
   667             if (isMinimalFlightMessage && (hsf.fragmentOffset == 0) &&
   634             if (isMinimalFlightMessage && (hsf.fragmentOffset == 0) &&
   668                     (hsf.handshakeType != HandshakeMessage.ht_finished)) {
   635                     (hsf.handshakeType != SSLHandshake.FINISHED.id)) {
   669 
   636 
   670                 // reset the handshake flight
   637                 // reset the handshake flight
   671                 handshakeFlight.handshakeType = hsf.handshakeType;
   638                 handshakeFlight.handshakeType = hsf.handshakeType;
   672                 handshakeFlight.flightEpoch = hsf.recordEpoch;
   639                 handshakeFlight.flightEpoch = hsf.recordEpoch;
   673                 handshakeFlight.minMessageSeq = hsf.messageSeq;
   640                 handshakeFlight.minMessageSeq = hsf.messageSeq;
   674             }
   641             }
   675 
   642 
   676             if (hsf.handshakeType == HandshakeMessage.ht_finished) {
   643             if (hsf.handshakeType == SSLHandshake.FINISHED.id) {
   677                 handshakeFlight.maxMessageSeq = hsf.messageSeq;
   644                 handshakeFlight.maxMessageSeq = hsf.messageSeq;
   678                 handshakeFlight.maxRecordEpoch = hsf.recordEpoch;
   645                 handshakeFlight.maxRecordEpoch = hsf.recordEpoch;
   679                 handshakeFlight.maxRecordSeq = hsf.recordSeq;
   646                 handshakeFlight.maxRecordSeq = hsf.recordSeq;
   680             } else {
   647             } else {
   681                 if (handshakeFlight.maxMessageSeq < hsf.messageSeq) {
   648                 if (handshakeFlight.maxMessageSeq < hsf.messageSeq) {
   716                 // a handshake message retransmission.  Discard this record.
   683                 // a handshake message retransmission.  Discard this record.
   717                 //
   684                 //
   718                 // It's OK to discard retransmission as the handshake hash
   685                 // It's OK to discard retransmission as the handshake hash
   719                 // is computed as if each handshake message had been sent
   686                 // is computed as if each handshake message had been sent
   720                 // as a single fragment.
   687                 // as a single fragment.
   721                 if (debug != null && Debug.isOn("verbose")) {
   688                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   722                     Debug.log("Have got the full message, discard it.");
   689                     SSLLogger.fine("Have got the full message, discard it.");
   723                 }
   690                 }
   724 
   691 
   725                 return;
   692                 return;
   726             }
   693             }
   727 
   694 
   740                     if (((hole.offset > hsf.fragmentOffset) &&
   707                     if (((hole.offset > hsf.fragmentOffset) &&
   741                          (hole.offset < fragmentLimit)) ||
   708                          (hole.offset < fragmentLimit)) ||
   742                         ((hole.limit > hsf.fragmentOffset) &&
   709                         ((hole.limit > hsf.fragmentOffset) &&
   743                          (hole.limit < fragmentLimit))) {
   710                          (hole.limit < fragmentLimit))) {
   744 
   711 
   745                         if (debug != null && Debug.isOn("ssl")) {
   712                         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
   746                             Debug.log("Discard invalid record: " +
   713                             SSLLogger.fine("Discard invalid record: " +
   747                                 "handshake fragment ranges are overlapping");
   714                                 "handshake fragment ranges are overlapping");
   748                         }
   715                         }
   749 
   716 
   750                         // invalid, discard it [section 4.1.2.7, RFC 6347]
   717                         // invalid, discard it [section 4.1.2.7, RFC 6347]
   751                         return;
   718                         return;
   771                     break;
   738                     break;
   772                 }
   739                 }
   773             }
   740             }
   774 
   741 
   775             // buffer this fragment
   742             // buffer this fragment
   776             if (hsf.handshakeType == HandshakeMessage.ht_finished) {
   743             if (hsf.handshakeType == SSLHandshake.FINISHED.id) {
   777                 // Need no status update.
   744                 // Need no status update.
   778                 bufferedFragments.add(hsf);
   745                 bufferedFragments.add(hsf);
   779             } else {
   746             } else {
   780                 bufferFragment(hsf);
   747                 bufferFragment(hsf);
   781             }
   748             }
   847                     if (rf instanceof HandshakeFragment) {
   814                     if (rf instanceof HandshakeFragment) {
   848                         HandshakeFragment hsf = (HandshakeFragment)rf;
   815                         HandshakeFragment hsf = (HandshakeFragment)rf;
   849                         if (precedingFlight.maxMessageSeq  < hsf.messageSeq) {
   816                         if (precedingFlight.maxMessageSeq  < hsf.messageSeq) {
   850                             isNewFlight = true;
   817                             isNewFlight = true;
   851                         }
   818                         }
   852                     } else if (rf.contentType != Record.ct_change_cipher_spec) {
   819                     } else if (
       
   820                         rf.contentType != ContentType.CHANGE_CIPHER_SPEC.id) {
       
   821 
   853                         // ciphertext
   822                         // ciphertext
   854                         if (precedingFlight.maxRecordEpoch < rf.recordEpoch) {
   823                         if (precedingFlight.maxRecordEpoch < rf.recordEpoch) {
   855                             isNewFlight = true;
   824                             isNewFlight = true;
   856                         }
   825                         }
   857                     }
   826                     }
   902             // Discard records old than the previous epoch.
   871             // Discard records old than the previous epoch.
   903             //
   872             //
   904             int previousEpoch = nextRecordEpoch - 1;
   873             int previousEpoch = nextRecordEpoch - 1;
   905             if (rf.recordEpoch < previousEpoch) {
   874             if (rf.recordEpoch < previousEpoch) {
   906                 // Too old to use, discard this record.
   875                 // Too old to use, discard this record.
   907                 if (debug != null && Debug.isOn("verbose")) {
   876                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   908                     Debug.log("Too old epoch to use this record, discard it.");
   877                     SSLLogger.fine(
       
   878                             "Too old epoch to use this record, discard it.");
   909                 }
   879                 }
   910 
   880 
   911                 return false;
   881                 return false;
   912             }
   882             }
   913 
   883 
   930                     if (rf instanceof HandshakeFragment) {
   900                     if (rf instanceof HandshakeFragment) {
   931                         HandshakeFragment hsf = (HandshakeFragment)rf;
   901                         HandshakeFragment hsf = (HandshakeFragment)rf;
   932                         if (precedingFlight.minMessageSeq > hsf.messageSeq) {
   902                         if (precedingFlight.minMessageSeq > hsf.messageSeq) {
   933                             isDesired = false;
   903                             isDesired = false;
   934                         }
   904                         }
   935                     } else if (rf.contentType == Record.ct_change_cipher_spec) {
   905                     } else if (
       
   906                         rf.contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
       
   907 
   936                         // ChangeCipherSpec
   908                         // ChangeCipherSpec
   937                         if (precedingFlight.flightEpoch != rf.recordEpoch) {
   909                         if (precedingFlight.flightEpoch != rf.recordEpoch) {
   938                             isDesired = false;
   910                             isDesired = false;
   939                         }
   911                         }
   940                     } else {        // ciphertext
   912                     } else {        // ciphertext
   946                     }
   918                     }
   947                 }
   919                 }
   948 
   920 
   949                 if (!isDesired) {
   921                 if (!isDesired) {
   950                     // Too old to use, discard this retransmitted record
   922                     // Too old to use, discard this retransmitted record
   951                     if (debug != null && Debug.isOn("verbose")) {
   923                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   952                         Debug.log("Too old retransmission to use, discard it.");
   924                         SSLLogger.fine(
       
   925                                 "Too old retransmission to use, discard it.");
   953                     }
   926                     }
   954 
   927 
   955                     return false;
   928                     return false;
   956                 }
   929                 }
   957             } else if ((rf.recordEpoch == nextRecordEpoch) &&
   930             } else if ((rf.recordEpoch == nextRecordEpoch) &&
   958                     (nextRecordSeq > rf.recordSeq)) {
   931                     (nextRecordSeq > rf.recordSeq)) {
   959 
   932 
   960                 // Previously disordered record for the current epoch.
   933                 // Previously disordered record for the current epoch.
   961                 //
   934                 //
   962                 // Should has been retransmitted. Discard this record.
   935                 // Should has been retransmitted. Discard this record.
   963                 if (debug != null && Debug.isOn("verbose")) {
   936                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   964                     Debug.log("Lagging behind record (sequence), discard it.");
   937                     SSLLogger.fine(
       
   938                             "Lagging behind record (sequence), discard it.");
   965                 }
   939                 }
   966 
   940 
   967                 return false;
   941                 return false;
   968             }
   942             }
   969 
   943 
   976                     (needToCheckFlight && !flightIsReady()));
   950                     (needToCheckFlight && !flightIsReady()));
   977         }
   951         }
   978 
   952 
   979         Plaintext acquirePlaintext() {
   953         Plaintext acquirePlaintext() {
   980             if (bufferedFragments.isEmpty()) {
   954             if (bufferedFragments.isEmpty()) {
   981                 if (debug != null && Debug.isOn("verbose")) {
   955                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
   982                     Debug.log("No received handshake messages");
   956                     SSLLogger.fine("No received handshake messages");
   983                 }
   957                 }
   984                 return null;
   958                 return null;
   985             }
   959             }
   986 
   960 
   987             if (!flightIsReady && needToCheckFlight) {
   961             if (!flightIsReady && needToCheckFlight) {
   997                         bufferedFragments.clear();
   971                         bufferedFragments.clear();
   998 
   972 
   999                         // Reset the next handshake flight.
   973                         // Reset the next handshake flight.
  1000                         resetHandshakeFlight(precedingFlight);
   974                         resetHandshakeFlight(precedingFlight);
  1001 
   975 
  1002                         if (debug != null && Debug.isOn("verbose")) {
   976                         if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1003                             Debug.log("Received a retransmission flight.");
   977                             SSLLogger.fine("Received a retransmission flight.");
  1004                         }
   978                         }
  1005 
   979 
  1006                         return Plaintext.PLAINTEXT_NULL;
   980                         return Plaintext.PLAINTEXT_NULL;
  1007                     }
   981                     }
  1008                 }
   982                 }
  1009 
   983 
  1010                 needToCheckFlight = false;
   984                 needToCheckFlight = false;
  1011             }
   985             }
  1012 
   986 
  1013             if (!flightIsReady) {
   987             if (!flightIsReady) {
  1014                 if (debug != null && Debug.isOn("verbose")) {
   988                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1015                     Debug.log("The handshake flight is not ready to use: " +
   989                     SSLLogger.fine(
  1016                                 handshakeFlight.handshakeType);
   990                             "The handshake flight is not ready to use: " +
       
   991                             handshakeFlight.handshakeType);
  1017                 }
   992                 }
  1018                 return null;
   993                 return null;
  1019             }
   994             }
  1020 
   995 
  1021             RecordFragment rFrag = bufferedFragments.first();
   996             RecordFragment rFrag = bufferedFragments.first();
  1034 
  1009 
  1035                     // Reset the next handshake flight.
  1010                     // Reset the next handshake flight.
  1036                     resetHandshakeFlight(precedingFlight);
  1011                     resetHandshakeFlight(precedingFlight);
  1037 
  1012 
  1038                     if (expectCCSFlight &&
  1013                     if (expectCCSFlight &&
  1039                             (precedingFlight.flightEpoch ==
  1014                             (precedingFlight.handshakeType ==
  1040                                     HandshakeFlight.HF_UNKNOWN)) {
  1015                                     HandshakeFlight.HF_UNKNOWN)) {
  1041                         expectCCSFlight = false;
  1016                         expectCCSFlight = false;
  1042                     }
  1017                     }
  1043                 }
  1018                 }
  1044             } else {
  1019             } else {
  1086             flightIsReady = false;
  1061             flightIsReady = false;
  1087             needToCheckFlight = false;
  1062             needToCheckFlight = false;
  1088         }
  1063         }
  1089 
  1064 
  1090         private Plaintext acquireCachedMessage() {
  1065         private Plaintext acquireCachedMessage() {
  1091 
       
  1092             RecordFragment rFrag = bufferedFragments.first();
  1066             RecordFragment rFrag = bufferedFragments.first();
  1093             if (readEpoch != rFrag.recordEpoch) {
  1067             if (readEpoch != rFrag.recordEpoch) {
  1094                 if (readEpoch > rFrag.recordEpoch) {
  1068                 if (readEpoch > rFrag.recordEpoch) {
  1095                     // discard old records
  1069                     // discard old records
  1096                     if (debug != null && Debug.isOn("verbose")) {
  1070                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1097                         Debug.log("Discard old buffered ciphertext fragments.");
  1071                         SSLLogger.fine(
       
  1072                                 "Discard old buffered ciphertext fragments.");
  1098                     }
  1073                     }
  1099                     bufferedFragments.remove(rFrag);    // popup the fragment
  1074                     bufferedFragments.remove(rFrag);    // popup the fragment
  1100                 }
  1075                 }
  1101 
  1076 
  1102                 // reset the flight
  1077                 // reset the flight
  1103                 if (flightIsReady) {
  1078                 if (flightIsReady) {
  1104                     flightIsReady = false;
  1079                     flightIsReady = false;
  1105                 }
  1080                 }
  1106 
  1081 
  1107                 if (debug != null && Debug.isOn("verbose")) {
  1082                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1108                     Debug.log("Not yet ready to decrypt the cached fragments.");
  1083                     SSLLogger.fine(
       
  1084                             "Not yet ready to decrypt the cached fragments.");
  1109                 }
  1085                 }
  1110                 return null;
  1086                 return null;
  1111             }
  1087             }
  1112 
  1088 
  1113             bufferedFragments.remove(rFrag);    // popup the fragment
  1089             bufferedFragments.remove(rFrag);    // popup the fragment
  1114 
  1090 
  1115             ByteBuffer fragment = ByteBuffer.wrap(rFrag.fragment);
  1091             ByteBuffer fragment = ByteBuffer.wrap(rFrag.fragment);
  1116             ByteBuffer plaintextFragment = null;
  1092             ByteBuffer plaintextFragment = null;
  1117             try {
  1093             try {
  1118                 plaintextFragment = decrypt(readAuthenticator, readCipher,
  1094                 Plaintext plaintext = readCipher.decrypt(
  1119                         rFrag.contentType, fragment, rFrag.recordEnS);
  1095                         rFrag.contentType, fragment, rFrag.recordEnS);
  1120             } catch (BadPaddingException bpe) {
  1096                 plaintextFragment = plaintext.fragment;
  1121                 if (debug != null && Debug.isOn("verbose")) {
  1097                 rFrag.contentType = plaintext.contentType;
  1122                     Debug.log("Discard invalid record: " + bpe);
  1098             } catch (GeneralSecurityException gse) {
       
  1099                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
       
  1100                     SSLLogger.fine("Discard invalid record: ", gse);
  1123                 }
  1101                 }
  1124 
  1102 
  1125                 // invalid, discard this record [section 4.1.2.7, RFC 6347]
  1103                 // invalid, discard this record [section 4.1.2.7, RFC 6347]
  1126                 return null;
  1104                 return null;
  1127             }
  1105             }
  1128 
  1106 
  1129             // The ciphtext handshake message can only be Finished (the
  1107             // The ciphtext handshake message can only be Finished (the
  1130             // end of this flight), ClinetHello or HelloRequest (the
  1108             // end of this flight), ClinetHello or HelloRequest (the
  1131             // beginning of the next flight) message.  Need not to check
  1109             // beginning of the next flight) message.  Need not to check
  1132             // any ChangeCipherSpec message.
  1110             // any ChangeCipherSpec message.
  1133             if (rFrag.contentType == Record.ct_handshake) {
  1111             if (rFrag.contentType == ContentType.HANDSHAKE.id) {
  1134                 while (plaintextFragment.remaining() > 0) {
  1112                 while (plaintextFragment.remaining() > 0) {
  1135                     HandshakeFragment hsFrag = parseHandshakeMessage(
  1113                     HandshakeFragment hsFrag = parseHandshakeMessage(
  1136                             rFrag.contentType,
  1114                             rFrag.contentType,
  1137                             rFrag.majorVersion, rFrag.minorVersion,
  1115                             rFrag.majorVersion, rFrag.minorVersion,
  1138                             rFrag.recordEnS, rFrag.recordEpoch, rFrag.recordSeq,
  1116                             rFrag.recordEnS, rFrag.recordEpoch, rFrag.recordSeq,
  1139                             plaintextFragment);
  1117                             plaintextFragment);
  1140 
  1118 
  1141                     if (hsFrag == null) {
  1119                     if (hsFrag == null) {
  1142                         // invalid, discard this record
  1120                         // invalid, discard this record
  1143                         if (debug != null && Debug.isOn("verbose")) {
  1121                         if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1144                             Debug.printHex(
  1122                             SSLLogger.fine(
  1145                                     "Invalid handshake fragment, discard it",
  1123                                     "Invalid handshake fragment, discard it",
  1146                                     plaintextFragment);
  1124                                     plaintextFragment);
  1147                         }
  1125                         }
  1148                         return null;
  1126                         return null;
  1149                     }
  1127                     }
  1151                     queueUpHandshake(hsFrag);
  1129                     queueUpHandshake(hsFrag);
  1152                     // The flight ready status (flightIsReady) should have
  1130                     // The flight ready status (flightIsReady) should have
  1153                     // been checked and updated for the Finished handshake
  1131                     // been checked and updated for the Finished handshake
  1154                     // message before the decryption.  Please don't update
  1132                     // message before the decryption.  Please don't update
  1155                     // flightIsReady for Finished messages.
  1133                     // flightIsReady for Finished messages.
  1156                     if (hsFrag.handshakeType != HandshakeMessage.ht_finished) {
  1134                     if (hsFrag.handshakeType != SSLHandshake.FINISHED.id) {
  1157                         flightIsReady = false;
  1135                         flightIsReady = false;
  1158                         needToCheckFlight = true;
  1136                         needToCheckFlight = true;
  1159                     }
  1137                     }
  1160                 }
  1138                 }
  1161 
  1139 
  1170         }
  1148         }
  1171 
  1149 
  1172         private Plaintext acquireHandshakeMessage() {
  1150         private Plaintext acquireHandshakeMessage() {
  1173 
  1151 
  1174             RecordFragment rFrag = bufferedFragments.first();
  1152             RecordFragment rFrag = bufferedFragments.first();
  1175             if (rFrag.contentType == Record.ct_change_cipher_spec) {
  1153             if (rFrag.contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
  1176                 this.nextRecordEpoch = rFrag.recordEpoch + 1;
  1154                 this.nextRecordEpoch = rFrag.recordEpoch + 1;
  1177 
  1155 
  1178                 // For retransmissions, the next record sequence number is a
  1156                 // For retransmissions, the next record sequence number is a
  1179                 // positive value.  Don't worry about it as the acquiring of
  1157                 // positive value.  Don't worry about it as the acquiring of
  1180                 // the immediately followed Finished handshake message will
  1158                 // the immediately followed Finished handshake message will
  1181                 // reset the next record sequence number correctly.
  1159                 // reset the next record sequence number correctly.
  1182                 this.nextRecordSeq = 0;
  1160                 this.nextRecordSeq = 0;
  1183 
  1161 
  1184                 // Popup the fragment.
  1162                 // Popup the fragment.
  1185                 bufferedFragments.remove(rFrag);
  1163                 bufferedFragments.remove(rFrag);
  1186 
       
  1187                 // Reload if this message has been reserved for handshake hash.
       
  1188                 handshakeHash.reload();
       
  1189 
       
  1190                 return new Plaintext(rFrag.contentType,
  1164                 return new Plaintext(rFrag.contentType,
  1191                         rFrag.majorVersion, rFrag.minorVersion,
  1165                         rFrag.majorVersion, rFrag.minorVersion,
  1192                         rFrag.recordEpoch,
  1166                         rFrag.recordEpoch,
  1193                         Authenticator.toLong(rFrag.recordEnS),
  1167                         Authenticator.toLong(rFrag.recordEnS),
  1194                         ByteBuffer.wrap(rFrag.fragment));
  1168                         ByteBuffer.wrap(rFrag.fragment));
  1195             } else {    // rFrag.contentType == Record.ct_handshake
  1169             } else {    // rFrag.contentType == ContentType.HANDSHAKE.id
  1196                 HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
  1170                 HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
  1197                 if ((hsFrag.messageLength == hsFrag.fragmentLength) &&
  1171                 if ((hsFrag.messageLength == hsFrag.fragmentLength) &&
  1198                     (hsFrag.fragmentOffset == 0)) {     // no fragmentation
  1172                     (hsFrag.fragmentOffset == 0)) {     // no fragmentation
  1199 
  1173 
  1200                     bufferedFragments.remove(rFrag);    // popup the fragment
  1174                     bufferedFragments.remove(rFrag);    // popup the fragment
  1202                     // this.nextRecordEpoch = hsFrag.recordEpoch;
  1176                     // this.nextRecordEpoch = hsFrag.recordEpoch;
  1203                     this.nextRecordSeq = hsFrag.recordSeq + 1;
  1177                     this.nextRecordSeq = hsFrag.recordSeq + 1;
  1204 
  1178 
  1205                     // Note: may try to avoid byte array copy in the future.
  1179                     // Note: may try to avoid byte array copy in the future.
  1206                     byte[] recordFrag = new byte[hsFrag.messageLength + 4];
  1180                     byte[] recordFrag = new byte[hsFrag.messageLength + 4];
  1207                     Plaintext plaintext = new Plaintext(hsFrag.contentType,
  1181                     Plaintext plaintext = new Plaintext(
       
  1182                             hsFrag.contentType,
  1208                             hsFrag.majorVersion, hsFrag.minorVersion,
  1183                             hsFrag.majorVersion, hsFrag.minorVersion,
  1209                             hsFrag.recordEpoch,
  1184                             hsFrag.recordEpoch,
  1210                             Authenticator.toLong(hsFrag.recordEnS),
  1185                             Authenticator.toLong(hsFrag.recordEnS),
  1211                             ByteBuffer.wrap(recordFrag));
  1186                             ByteBuffer.wrap(recordFrag));
  1212 
  1187 
  1228                 } else {                // fragmented handshake message
  1203                 } else {                // fragmented handshake message
  1229                     // the first record
  1204                     // the first record
  1230                     //
  1205                     //
  1231                     // Note: may try to avoid byte array copy in the future.
  1206                     // Note: may try to avoid byte array copy in the future.
  1232                     byte[] recordFrag = new byte[hsFrag.messageLength + 4];
  1207                     byte[] recordFrag = new byte[hsFrag.messageLength + 4];
  1233                     Plaintext plaintext = new Plaintext(hsFrag.contentType,
  1208                     Plaintext plaintext = new Plaintext(
       
  1209                             hsFrag.contentType,
  1234                             hsFrag.majorVersion, hsFrag.minorVersion,
  1210                             hsFrag.majorVersion, hsFrag.minorVersion,
  1235                             hsFrag.recordEpoch,
  1211                             hsFrag.recordEpoch,
  1236                             Authenticator.toLong(hsFrag.recordEnS),
  1212                             Authenticator.toLong(hsFrag.recordEnS),
  1237                             ByteBuffer.wrap(recordFrag));
  1213                             ByteBuffer.wrap(recordFrag));
  1238 
  1214 
  1262                         // speed up the reassembly in the future.
  1238                         // speed up the reassembly in the future.
  1263 
  1239 
  1264                         // read the next buffered record
  1240                         // read the next buffered record
  1265                         if (!bufferedFragments.isEmpty()) {
  1241                         if (!bufferedFragments.isEmpty()) {
  1266                             rFrag = bufferedFragments.first();
  1242                             rFrag = bufferedFragments.first();
  1267                             if (rFrag.contentType != Record.ct_handshake) {
  1243                             if (rFrag.contentType != ContentType.HANDSHAKE.id) {
  1268                                 break;
  1244                                 break;
  1269                             } else {
  1245                             } else {
  1270                                 hmFrag = (HandshakeFragment)rFrag;
  1246                                 hmFrag = (HandshakeFragment)rFrag;
  1271                             }
  1247                             }
  1272                         }
  1248                         }
  1291                 // the ChangeCipherSpec/Finished flight
  1267                 // the ChangeCipherSpec/Finished flight
  1292                 //
  1268                 //
  1293                 if (expectCCSFlight) {
  1269                 if (expectCCSFlight) {
  1294                     // Have the ChangeCipherSpec/Finished flight been received?
  1270                     // Have the ChangeCipherSpec/Finished flight been received?
  1295                     boolean isReady = hasFinishedMessage(bufferedFragments);
  1271                     boolean isReady = hasFinishedMessage(bufferedFragments);
  1296                     if (debug != null && Debug.isOn("verbose")) {
  1272                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1297                         Debug.log(
  1273                         SSLLogger.fine(
  1298                             "Has the final flight been received? " + isReady);
  1274                             "Has the final flight been received? " + isReady);
  1299                     }
  1275                     }
  1300 
  1276 
  1301                     return isReady;
  1277                     return isReady;
  1302                 }
  1278                 }
  1303 
  1279 
  1304                 if (debug != null && Debug.isOn("verbose")) {
  1280                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1305                     Debug.log("No flight is received yet.");
  1281                     SSLLogger.fine("No flight is received yet.");
  1306                 }
  1282                 }
  1307 
  1283 
  1308                 return false;
  1284                 return false;
  1309             }
  1285             }
  1310 
  1286 
  1311             if ((flightType == HandshakeMessage.ht_client_hello) ||
  1287             if ((flightType == SSLHandshake.CLIENT_HELLO.id) ||
  1312                 (flightType == HandshakeMessage.ht_hello_request) ||
  1288                 (flightType == SSLHandshake.HELLO_REQUEST.id) ||
  1313                 (flightType == HandshakeMessage.ht_hello_verify_request)) {
  1289                 (flightType == SSLHandshake.HELLO_VERIFY_REQUEST.id)) {
  1314 
  1290 
  1315                 // single handshake message flight
  1291                 // single handshake message flight
  1316                 boolean isReady = hasCompleted(flightType);
  1292                 boolean isReady = hasCompleted(flightType);
  1317                 if (debug != null && Debug.isOn("verbose")) {
  1293                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1318                     Debug.log("Is the handshake message completed? " + isReady);
  1294                     SSLLogger.fine(
       
  1295                             "Is the handshake message completed? " + isReady);
  1319                 }
  1296                 }
  1320 
  1297 
  1321                 return isReady;
  1298                 return isReady;
  1322             }
  1299             }
  1323 
  1300 
  1324             //
  1301             //
  1325             // the ServerHello flight
  1302             // the ServerHello flight
  1326             //
  1303             //
  1327             if (flightType == HandshakeMessage.ht_server_hello) {
  1304             if (flightType == SSLHandshake.SERVER_HELLO.id) {
  1328                 // Firstly, check the first flight handshake message.
  1305                 // Firstly, check the first flight handshake message.
  1329                 if (!hasCompleted(flightType)) {
  1306                 if (!hasCompleted(flightType)) {
  1330                     if (debug != null && Debug.isOn("verbose")) {
  1307                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1331                         Debug.log(
  1308                         SSLLogger.fine(
  1332                             "The ServerHello message is not completed yet.");
  1309                             "The ServerHello message is not completed yet.");
  1333                     }
  1310                     }
  1334 
  1311 
  1335                     return false;
  1312                     return false;
  1336                 }
  1313                 }
  1337 
  1314 
  1338                 //
  1315                 //
  1339                 // an abbreviated handshake
  1316                 // an abbreviated handshake
  1340                 //
  1317                 //
  1341                 if (hasFinishedMessage(bufferedFragments)) {
  1318                 if (hasFinishedMessage(bufferedFragments)) {
  1342                     if (debug != null && Debug.isOn("verbose")) {
  1319                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1343                         Debug.log("It's an abbreviated handshake.");
  1320                         SSLLogger.fine("It's an abbreviated handshake.");
  1344                     }
  1321                     }
  1345 
  1322 
  1346                     return true;
  1323                     return true;
  1347                 }
  1324                 }
  1348 
  1325 
  1349                 //
  1326                 //
  1350                 // a full handshake
  1327                 // a full handshake
  1351                 //
  1328                 //
  1352                 List<HoleDescriptor> holes = handshakeFlight.holesMap.get(
  1329                 List<HoleDescriptor> holes = handshakeFlight.holesMap.get(
  1353                         HandshakeMessage.ht_server_hello_done);
  1330                         SSLHandshake.SERVER_HELLO_DONE.id);
  1354                 if ((holes == null) || !holes.isEmpty()) {
  1331                 if ((holes == null) || !holes.isEmpty()) {
  1355                     // Not yet got the final message of the flight.
  1332                     // Not yet got the final message of the flight.
  1356                     if (debug != null && Debug.isOn("verbose")) {
  1333                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1357                         Debug.log("Not yet got the ServerHelloDone message");
  1334                         SSLLogger.fine(
       
  1335                                 "Not yet got the ServerHelloDone message");
  1358                     }
  1336                     }
  1359 
  1337 
  1360                     return false;
  1338                     return false;
  1361                 }
  1339                 }
  1362 
  1340 
  1363                 // Have all handshake message been received?
  1341                 // Have all handshake message been received?
  1364                 boolean isReady = hasCompleted(bufferedFragments,
  1342                 boolean isReady = hasCompleted(bufferedFragments,
  1365                             handshakeFlight.minMessageSeq,
  1343                             handshakeFlight.minMessageSeq,
  1366                             handshakeFlight.maxMessageSeq);
  1344                             handshakeFlight.maxMessageSeq);
  1367                 if (debug != null && Debug.isOn("verbose")) {
  1345                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1368                     Debug.log("Is the ServerHello flight (message " +
  1346                     SSLLogger.fine(
       
  1347                             "Is the ServerHello flight (message " +
  1369                             handshakeFlight.minMessageSeq + "-" +
  1348                             handshakeFlight.minMessageSeq + "-" +
  1370                             handshakeFlight.maxMessageSeq +
  1349                             handshakeFlight.maxMessageSeq +
  1371                             ") completed? " + isReady);
  1350                             ") completed? " + isReady);
  1372                 }
  1351                 }
  1373 
  1352 
  1379             //
  1358             //
  1380             // Note: need to consider more messages in this flight if
  1359             // Note: need to consider more messages in this flight if
  1381             //       ht_supplemental_data and ht_certificate_url are
  1360             //       ht_supplemental_data and ht_certificate_url are
  1382             //       suppported in the future.
  1361             //       suppported in the future.
  1383             //
  1362             //
  1384             if ((flightType == HandshakeMessage.ht_certificate) ||
  1363             if ((flightType == SSLHandshake.CERTIFICATE.id) ||
  1385                 (flightType == HandshakeMessage.ht_client_key_exchange)) {
  1364                 (flightType == SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {
  1386 
  1365 
  1387                 // Firstly, check the first flight handshake message.
  1366                 // Firstly, check the first flight handshake message.
  1388                 if (!hasCompleted(flightType)) {
  1367                 if (!hasCompleted(flightType)) {
  1389                     if (debug != null && Debug.isOn("verbose")) {
  1368                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1390                         Debug.log(
  1369                         SSLLogger.fine(
  1391                             "The ClientKeyExchange or client Certificate " +
  1370                             "The ClientKeyExchange or client Certificate " +
  1392                             "message is not completed yet.");
  1371                             "message is not completed yet.");
  1393                     }
  1372                     }
  1394 
  1373 
  1395                     return false;
  1374                     return false;
  1396                 }
  1375                 }
  1397 
  1376 
  1398                 // Is client CertificateVerify a mandatory message?
  1377                 // Is client CertificateVerify a mandatory message?
  1399                 if (flightType == HandshakeMessage.ht_certificate) {
  1378                 if (flightType == SSLHandshake.CERTIFICATE.id) {
  1400                     if (needClientVerify(bufferedFragments) &&
  1379                     if (needClientVerify(bufferedFragments) &&
  1401                         !hasCompleted(ht_certificate_verify)) {
  1380                         !hasCompleted(SSLHandshake.CERTIFICATE_VERIFY.id)) {
  1402 
  1381 
  1403                         if (debug != null && Debug.isOn("verbose")) {
  1382                         if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1404                             Debug.log(
  1383                             SSLLogger.fine(
  1405                                 "Not yet have the CertificateVerify message");
  1384                                 "Not yet have the CertificateVerify message");
  1406                         }
  1385                         }
  1407 
  1386 
  1408                         return false;
  1387                         return false;
  1409                     }
  1388                     }
  1410                 }
  1389                 }
  1411 
  1390 
  1412                 if (!hasFinishedMessage(bufferedFragments)) {
  1391                 if (!hasFinishedMessage(bufferedFragments)) {
  1413                     // not yet have the ChangeCipherSpec/Finished messages
  1392                     // not yet have the ChangeCipherSpec/Finished messages
  1414                     if (debug != null && Debug.isOn("verbose")) {
  1393                     if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1415                         Debug.log(
  1394                         SSLLogger.fine(
  1416                             "Not yet have the ChangeCipherSpec and " +
  1395                             "Not yet have the ChangeCipherSpec and " +
  1417                             "Finished messages");
  1396                             "Finished messages");
  1418                     }
  1397                     }
  1419 
  1398 
  1420                     return false;
  1399                     return false;
  1422 
  1401 
  1423                 // Have all handshake message been received?
  1402                 // Have all handshake message been received?
  1424                 boolean isReady = hasCompleted(bufferedFragments,
  1403                 boolean isReady = hasCompleted(bufferedFragments,
  1425                             handshakeFlight.minMessageSeq,
  1404                             handshakeFlight.minMessageSeq,
  1426                             handshakeFlight.maxMessageSeq);
  1405                             handshakeFlight.maxMessageSeq);
  1427                 if (debug != null && Debug.isOn("verbose")) {
  1406                 if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1428                     Debug.log("Is the ClientKeyExchange flight (message " +
  1407                     SSLLogger.fine(
       
  1408                             "Is the ClientKeyExchange flight (message " +
  1429                             handshakeFlight.minMessageSeq + "-" +
  1409                             handshakeFlight.minMessageSeq + "-" +
  1430                             handshakeFlight.maxMessageSeq +
  1410                             handshakeFlight.maxMessageSeq +
  1431                             ") completed? " + isReady);
  1411                             ") completed? " + isReady);
  1432                 }
  1412                 }
  1433 
  1413 
  1435             }
  1415             }
  1436 
  1416 
  1437             //
  1417             //
  1438             // Otherwise, need to receive more handshake messages.
  1418             // Otherwise, need to receive more handshake messages.
  1439             //
  1419             //
  1440             if (debug != null && Debug.isOn("verbose")) {
  1420             if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
  1441                 Debug.log("Need to receive more handshake messages");
  1421                 SSLLogger.fine("Need to receive more handshake messages");
  1442             }
  1422             }
  1443 
  1423 
  1444             return false;
  1424             return false;
  1445         }
  1425         }
  1446 
  1426 
  1454         private boolean hasFinishedMessage(Set<RecordFragment> fragments) {
  1434         private boolean hasFinishedMessage(Set<RecordFragment> fragments) {
  1455 
  1435 
  1456             boolean hasCCS = false;
  1436             boolean hasCCS = false;
  1457             boolean hasFin = false;
  1437             boolean hasFin = false;
  1458             for (RecordFragment fragment : fragments) {
  1438             for (RecordFragment fragment : fragments) {
  1459                 if (fragment.contentType == Record.ct_change_cipher_spec) {
  1439                 if (fragment.contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
  1460                     if (hasFin) {
  1440                     if (hasFin) {
  1461                         return true;
  1441                         return true;
  1462                     }
  1442                     }
  1463                     hasCCS = true;
  1443                     hasCCS = true;
  1464                 } else if (fragment.contentType == Record.ct_handshake) {
  1444                 } else if (fragment.contentType == ContentType.HANDSHAKE.id) {
  1465                     // Finished is the first expected message of a new epoch.
  1445                     // Finished is the first expected message of a new epoch.
  1466                     if (fragment.isCiphertext) {
  1446                     if (fragment.isCiphertext) {
  1467                         if (hasCCS) {
  1447                         if (hasCCS) {
  1468                             return true;
  1448                             return true;
  1469                         }
  1449                         }
  1482         private boolean needClientVerify(Set<RecordFragment> fragments) {
  1462         private boolean needClientVerify(Set<RecordFragment> fragments) {
  1483 
  1463 
  1484             // The caller should have checked the completion of the first
  1464             // The caller should have checked the completion of the first
  1485             // present handshake message.  Need not to check it again.
  1465             // present handshake message.  Need not to check it again.
  1486             for (RecordFragment rFrag : fragments) {
  1466             for (RecordFragment rFrag : fragments) {
  1487                 if ((rFrag.contentType != Record.ct_handshake) ||
  1467                 if ((rFrag.contentType != ContentType.HANDSHAKE.id) ||
  1488                         rFrag.isCiphertext) {
  1468                         rFrag.isCiphertext) {
  1489                     break;
  1469                     break;
  1490                 }
  1470                 }
  1491 
  1471 
  1492                 HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
  1472                 HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
  1493                 if (hsFrag.handshakeType != HandshakeMessage.ht_certificate) {
  1473                 if (hsFrag.handshakeType != SSLHandshake.CERTIFICATE.id) {
  1494                     continue;
  1474                     continue;
  1495                 }
  1475                 }
  1496 
  1476 
  1497                 return (rFrag.fragment != null) &&
  1477                 return (rFrag.fragment != null) &&
  1498                    (rFrag.fragment.length > DTLSRecord.minCertPlaintextSize);
  1478                    (rFrag.fragment.length > DTLSRecord.minCertPlaintextSize);
  1517                 int presentMsgSeq, int endMsgSeq) {
  1497                 int presentMsgSeq, int endMsgSeq) {
  1518 
  1498 
  1519             // The caller should have checked the completion of the first
  1499             // The caller should have checked the completion of the first
  1520             // present handshake message.  Need not to check it again.
  1500             // present handshake message.  Need not to check it again.
  1521             for (RecordFragment rFrag : fragments) {
  1501             for (RecordFragment rFrag : fragments) {
  1522                 if ((rFrag.contentType != Record.ct_handshake) ||
  1502                 if ((rFrag.contentType != ContentType.HANDSHAKE.id) ||
  1523                         rFrag.isCiphertext) {
  1503                         rFrag.isCiphertext) {
  1524                     break;
  1504                     break;
  1525                 }
  1505                 }
  1526 
  1506 
  1527                 HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
  1507                 HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
  1544                         // false: if not yet got all messages of the flight.
  1524                         // false: if not yet got all messages of the flight.
  1545         }
  1525         }
  1546 
  1526 
  1547         private void handshakeHashing(
  1527         private void handshakeHashing(
  1548                 HandshakeFragment hsFrag, Plaintext plaintext) {
  1528                 HandshakeFragment hsFrag, Plaintext plaintext) {
  1549 
       
  1550             byte hsType = hsFrag.handshakeType;
  1529             byte hsType = hsFrag.handshakeType;
  1551             if ((hsType == HandshakeMessage.ht_hello_request) ||
  1530             if (!handshakeHash.isHashable(hsType)) {
  1552                 (hsType == HandshakeMessage.ht_hello_verify_request)) {
       
  1553 
       
  1554                 // omitted from handshake hash computation
  1531                 // omitted from handshake hash computation
  1555                 return;
  1532                 return;
  1556             }
  1533             }
  1557 
  1534 
  1558             if ((hsFrag.messageSeq == 0) &&
  1535             // calculate the DTLS header and reserve the handshake message
  1559                 (hsType == HandshakeMessage.ht_client_hello)) {
  1536             plaintext.fragment.position(4);     // ignore the TLS header
  1560 
  1537             byte[] temporary = new byte[plaintext.fragment.remaining() + 12];
  1561                 // omit initial ClientHello message
  1538                                                 // 12: handshake header size
  1562                 //
       
  1563                 //  4: handshake header
       
  1564                 //  2: ClientHello.client_version
       
  1565                 // 32: ClientHello.random
       
  1566                 int sidLen = plaintext.fragment.get(38);
       
  1567 
       
  1568                 if (sidLen == 0) {      // empty session_id, initial handshake
       
  1569                     return;
       
  1570                 }
       
  1571             }
       
  1572 
       
  1573             // calculate the DTLS header
       
  1574             byte[] temporary = new byte[12];    // 12: handshake header size
       
  1575 
  1539 
  1576             // Handshake.msg_type
  1540             // Handshake.msg_type
  1577             temporary[0] = hsFrag.handshakeType;
  1541             temporary[0] = hsFrag.handshakeType;
  1578 
  1542 
  1579             // Handshake.length
  1543             // Handshake.length
  1593             // Handshake.fragment_length
  1557             // Handshake.fragment_length
  1594             temporary[9] = temporary[1];
  1558             temporary[9] = temporary[1];
  1595             temporary[10] = temporary[2];
  1559             temporary[10] = temporary[2];
  1596             temporary[11] = temporary[3];
  1560             temporary[11] = temporary[3];
  1597 
  1561 
  1598             plaintext.fragment.position(4);     // ignore the TLS header
  1562             plaintext.fragment.get(temporary,
  1599             if ((hsType != HandshakeMessage.ht_finished) &&
  1563                     12, plaintext.fragment.remaining());
  1600                 (hsType != HandshakeMessage.ht_certificate_verify)) {
  1564             handshakeHash.receive(temporary);
  1601 
       
  1602                 if (handshakeHash == null) {
       
  1603                     // used for cache only
       
  1604                     handshakeHash = new HandshakeHash(false);
       
  1605                 }
       
  1606                 handshakeHash.update(temporary, 0, 12);
       
  1607                 handshakeHash.update(plaintext.fragment);
       
  1608             } else {
       
  1609                 // Reserve until this handshake message has been processed.
       
  1610                 if (handshakeHash == null) {
       
  1611                     // used for cache only
       
  1612                     handshakeHash = new HandshakeHash(false);
       
  1613                 }
       
  1614                 handshakeHash.reserve(temporary, 0, 12);
       
  1615                 handshakeHash.reserve(plaintext.fragment);
       
  1616             }
       
  1617             plaintext.fragment.position(0);     // restore the position
  1565             plaintext.fragment.position(0);     // restore the position
  1618         }
  1566         }
  1619     }
  1567     }
  1620 }
  1568 }
  1621 
  1569