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