src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java
changeset 50768 68fa3d4026ea
parent 47216 71c04702a3d5
child 51407 910f7b56592f
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 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
    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.EOFException;
    29 import java.nio.*;
    29 import java.io.IOException;
    30 
    30 import java.io.InputStream;
       
    31 import java.io.OutputStream;
       
    32 import java.nio.ByteBuffer;
       
    33 import java.security.GeneralSecurityException;
       
    34 import java.util.ArrayList;
    31 import javax.crypto.BadPaddingException;
    35 import javax.crypto.BadPaddingException;
    32 
    36 import javax.net.ssl.SSLException;
    33 import javax.net.ssl.*;
    37 import javax.net.ssl.SSLHandshakeException;
    34 
    38 import javax.net.ssl.SSLProtocolException;
    35 import sun.security.util.HexDumpEncoder;
    39 
    36 
    40 import sun.security.ssl.SSLCipher.SSLReadCipher;
       
    41 import sun.security.ssl.KeyUpdate.KeyUpdateMessage;
       
    42 import sun.security.ssl.KeyUpdate.KeyUpdateRequest;
    37 
    43 
    38 /**
    44 /**
    39  * {@code InputRecord} implementation for {@code SSLSocket}.
    45  * {@code InputRecord} implementation for {@code SSLSocket}.
    40  *
    46  *
    41  * @author David Brownell
    47  * @author David Brownell
    42  */
    48  */
    43 final class SSLSocketInputRecord extends InputRecord implements SSLRecord {
    49 final class SSLSocketInputRecord extends InputRecord implements SSLRecord {
    44     private OutputStream deliverStream = null;
    50     private InputStream is = null;
    45     private byte[] temporary = new byte[1024];
    51     private OutputStream os = null;
    46 
    52     private final byte[] temporary = new byte[1024];
    47     // used by handshake hash computation for handshake fragment
       
    48     private byte prevType = -1;
       
    49     private int hsMsgOff = 0;
       
    50     private int hsMsgLen = 0;
       
    51 
    53 
    52     private boolean formatVerified = false;     // SSLv2 ruled out?
    54     private boolean formatVerified = false;     // SSLv2 ruled out?
    53 
    55 
       
    56     // Cache for incomplete handshake messages.
       
    57     private ByteBuffer handshakeBuffer = null;
       
    58 
    54     private boolean hasHeader = false;          // Had read the record header
    59     private boolean hasHeader = false;          // Had read the record header
    55 
    60 
    56     SSLSocketInputRecord() {
    61     SSLSocketInputRecord(HandshakeHash handshakeHash) {
    57         this.readAuthenticator = MAC.TLS_NULL;
    62         super(handshakeHash, SSLReadCipher.nullTlsReadCipher());
    58     }
    63     }
    59 
    64 
    60     @Override
    65     @Override
    61     int bytesInCompletePacket(InputStream is) throws IOException {
    66     int bytesInCompletePacket() throws IOException {
    62 
       
    63         if (!hasHeader) {
    67         if (!hasHeader) {
    64             // read exactly one record
    68             // read exactly one record
    65             int really = read(is, temporary, 0, headerSize);
    69             try {
    66             if (really < 0) {
    70                 int really = read(is, temporary, 0, headerSize);
    67                 throw new EOFException("SSL peer shut down incorrectly");
    71                 if (really < 0) {
       
    72                     // EOF: peer shut down incorrectly
       
    73                     return -1;
       
    74                 }
       
    75             } catch (EOFException eofe) {
       
    76                 // The caller will handle EOF.
       
    77                 return -1;
    68             }
    78             }
    69             hasHeader = true;
    79             hasHeader = true;
    70         }
    80         }
    71 
    81 
    72         byte byteZero = temporary[0];
    82         byte byteZero = temporary[0];
    73         int len = 0;
    83         int len = 0;
    74 
    84 
    75         /*
    85         /*
    76          * If we have already verified previous packets, we can
    86          * If we have already verified previous packets, we can
    77          * ignore the verifications steps, and jump right to the
    87          * ignore the verifications steps, and jump right to the
    78          * determination.  Otherwise, try one last hueristic to
    88          * determination.  Otherwise, try one last heuristic to
    79          * see if it's SSL/TLS.
    89          * see if it's SSL/TLS.
    80          */
    90          */
    81         if (formatVerified ||
    91         if (formatVerified ||
    82                 (byteZero == ct_handshake) || (byteZero == ct_alert)) {
    92                 (byteZero == ContentType.HANDSHAKE.id) ||
       
    93                 (byteZero == ContentType.ALERT.id)) {
    83             /*
    94             /*
    84              * Last sanity check that it's not a wild record
    95              * Last sanity check that it's not a wild record
    85              */
    96              */
    86             ProtocolVersion recordVersion =
    97             if (!ProtocolVersion.isNegotiable(
    87                     ProtocolVersion.valueOf(temporary[1], temporary[2]);
    98                     temporary[1], temporary[2], false, false)) {
    88 
    99                 throw new SSLException("Unrecognized record version " +
    89             // check the record version
   100                         ProtocolVersion.nameOf(temporary[1], temporary[2]) +
    90             checkRecordVersion(recordVersion, false);
   101                         " , plaintext connection?");
       
   102             }
    91 
   103 
    92             /*
   104             /*
    93              * Reasonably sure this is a V3, disable further checks.
   105              * Reasonably sure this is a V3, disable further checks.
    94              * We can't do the same in the v2 check below, because
   106              * We can't do the same in the v2 check below, because
    95              * read still needs to parse/handle the v2 clientHello.
   107              * read still needs to parse/handle the v2 clientHello.
   110              * Internals can warn about unsupported SSLv2
   122              * Internals can warn about unsupported SSLv2
   111              */
   123              */
   112             boolean isShort = ((byteZero & 0x80) != 0);
   124             boolean isShort = ((byteZero & 0x80) != 0);
   113 
   125 
   114             if (isShort && ((temporary[2] == 1) || (temporary[2] == 4))) {
   126             if (isShort && ((temporary[2] == 1) || (temporary[2] == 4))) {
   115                 ProtocolVersion recordVersion =
   127                 if (!ProtocolVersion.isNegotiable(
   116                         ProtocolVersion.valueOf(temporary[3], temporary[4]);
   128                         temporary[3], temporary[4], false, false)) {
   117 
   129                     throw new SSLException("Unrecognized record version " +
   118                 // check the record version
   130                             ProtocolVersion.nameOf(temporary[3], temporary[4]) +
   119                 checkRecordVersion(recordVersion, true);
   131                             " , plaintext connection?");
       
   132                 }
   120 
   133 
   121                 /*
   134                 /*
   122                  * Client or Server Hello
   135                  * Client or Server Hello
   123                  */
   136                  */
   124                 //
   137                 //
   138         }
   151         }
   139 
   152 
   140         return len;
   153         return len;
   141     }
   154     }
   142 
   155 
   143     // destination.position() is zero.
   156     // Note that the input arguments are not used actually.
   144     @Override
   157     @Override
   145     Plaintext decode(InputStream is, ByteBuffer destination)
   158     Plaintext[] decode(ByteBuffer[] srcs, int srcsOffset,
   146             throws IOException, BadPaddingException {
   159             int srcsLength) throws IOException, BadPaddingException {
   147 
   160 
   148         if (isClosed) {
   161         if (isClosed) {
   149             return null;
   162             return null;
   150         }
   163         }
   151 
   164 
   165             /*
   178             /*
   166              * The first record must either be a handshake record or an
   179              * The first record must either be a handshake record or an
   167              * alert message. If it's not, it is either invalid or an
   180              * alert message. If it's not, it is either invalid or an
   168              * SSLv2 message.
   181              * SSLv2 message.
   169              */
   182              */
   170             if ((temporary[0] != ct_handshake) &&
   183             if ((temporary[0] != ContentType.HANDSHAKE.id) &&
   171                 (temporary[0] != ct_alert)) {
   184                 (temporary[0] != ContentType.ALERT.id)) {
   172 
   185                 hasHeader = false;
   173                 plaintext = handleUnknownRecord(is, temporary, destination);
   186                 return handleUnknownRecord(temporary);
   174             }
   187             }
   175         }
   188         }
   176 
   189 
   177         if (plaintext == null) {
   190         // The record header should has consumed.
   178             plaintext = decodeInputRecord(is, temporary, destination);
       
   179         }
       
   180 
       
   181         // The record header should has comsumed.
       
   182         hasHeader = false;
   191         hasHeader = false;
   183 
   192         return decodeInputRecord(temporary);
   184         return plaintext;
   193     }
       
   194 
       
   195     @Override
       
   196     void setReceiverStream(InputStream inputStream) {
       
   197         this.is = inputStream;
   185     }
   198     }
   186 
   199 
   187     @Override
   200     @Override
   188     void setDeliverStream(OutputStream outputStream) {
   201     void setDeliverStream(OutputStream outputStream) {
   189         this.deliverStream = outputStream;
   202         this.os = outputStream;
   190     }
   203     }
   191 
   204 
   192     // Note that destination may be null
   205     // Note that destination may be null
   193     private Plaintext decodeInputRecord(InputStream is, byte[] header,
   206     private Plaintext[] decodeInputRecord(
   194             ByteBuffer destination) throws IOException, BadPaddingException {
   207             byte[] header) throws IOException, BadPaddingException {
   195 
   208         byte contentType = header[0];                   // pos: 0
   196         byte contentType = header[0];
   209         byte majorVersion = header[1];                  // pos: 1
   197         byte majorVersion = header[1];
   210         byte minorVersion = header[2];                  // pos: 2
   198         byte minorVersion = header[2];
   211         int contentLen = ((header[3] & 0xFF) << 8) +
   199         int contentLen = ((header[3] & 0xFF) << 8) + (header[4] & 0xFF);
   212                            (header[4] & 0xFF);          // pos: 3, 4
       
   213 
       
   214         if (SSLLogger.isOn && SSLLogger.isOn("record")) {
       
   215             SSLLogger.fine(
       
   216                     "READ: " +
       
   217                     ProtocolVersion.nameOf(majorVersion, minorVersion) +
       
   218                     " " + ContentType.nameOf(contentType) + ", length = " +
       
   219                     contentLen);
       
   220         }
   200 
   221 
   201         //
   222         //
   202         // Check for upper bound.
   223         // Check for upper bound.
   203         //
   224         //
   204         // Note: May check packetSize limit in the future.
   225         // Note: May check packetSize limit in the future.
   208         }
   229         }
   209 
   230 
   210         //
   231         //
   211         // Read a complete record.
   232         // Read a complete record.
   212         //
   233         //
   213         if (destination == null) {
   234         ByteBuffer destination = ByteBuffer.allocate(headerSize + contentLen);
   214             destination = ByteBuffer.allocate(headerSize + contentLen);
       
   215         }  // Otherwise, the destination buffer should have enough room.
       
   216 
       
   217         int dstPos = destination.position();
   235         int dstPos = destination.position();
   218         destination.put(temporary, 0, headerSize);
   236         destination.put(temporary, 0, headerSize);
   219         while (contentLen > 0) {
   237         while (contentLen > 0) {
   220             int howmuch = Math.min(temporary.length, contentLen);
   238             int howmuch = Math.min(temporary.length, contentLen);
   221             int really = read(is, temporary, 0, howmuch);
   239             int really = read(is, temporary, 0, howmuch);
   227             contentLen -= howmuch;
   245             contentLen -= howmuch;
   228         }
   246         }
   229         destination.flip();
   247         destination.flip();
   230         destination.position(dstPos + headerSize);
   248         destination.position(dstPos + headerSize);
   231 
   249 
   232         if (debug != null && Debug.isOn("record")) {
   250         if (SSLLogger.isOn && SSLLogger.isOn("record")) {
   233              System.out.println(Thread.currentThread().getName() +
   251             SSLLogger.fine(
   234                     ", READ: " +
   252                     "READ: " +
   235                     ProtocolVersion.valueOf(majorVersion, minorVersion) +
   253                     ProtocolVersion.nameOf(majorVersion, minorVersion) +
   236                     " " + Record.contentName(contentType) + ", length = " +
   254                     " " + ContentType.nameOf(contentType) + ", length = " +
   237                     destination.remaining());
   255                     destination.remaining());
   238         }
   256         }
   239 
   257 
   240         //
   258         //
   241         // Decrypt the fragment
   259         // Decrypt the fragment
   242         //
   260         //
   243         ByteBuffer plaintext =
   261         ByteBuffer fragment;
   244             decrypt(readAuthenticator, readCipher, contentType, destination);
   262         try {
   245 
   263             Plaintext plaintext =
   246         if ((contentType != ct_handshake) && (hsMsgOff != hsMsgLen)) {
   264                     readCipher.decrypt(contentType, destination, null);
       
   265             fragment = plaintext.fragment;
       
   266             contentType = plaintext.contentType;
       
   267         } catch (BadPaddingException bpe) {
       
   268             throw bpe;
       
   269         } catch (GeneralSecurityException gse) {
       
   270             throw (SSLProtocolException)(new SSLProtocolException(
       
   271                     "Unexpected exception")).initCause(gse);
       
   272         }
       
   273 
       
   274         if (contentType != ContentType.HANDSHAKE.id &&
       
   275                 handshakeBuffer != null && handshakeBuffer.hasRemaining()) {
   247             throw new SSLProtocolException(
   276             throw new SSLProtocolException(
   248                     "Expected to get a handshake fragment");
   277                     "Expecting a handshake fragment, but received " +
   249         }
   278                     ContentType.nameOf(contentType));
   250 
   279         }
   251         //
   280 
   252         // handshake hashing
   281         //
   253         //
   282         // parse handshake messages
   254         if (contentType == ct_handshake) {
   283         //
   255             int pltPos = plaintext.position();
   284         if (contentType == ContentType.HANDSHAKE.id) {
   256             int pltLim = plaintext.limit();
   285             ByteBuffer handshakeFrag = fragment;
   257             int frgPos = pltPos;
   286             if ((handshakeBuffer != null) &&
   258             for (int remains = plaintext.remaining(); remains > 0;) {
   287                     (handshakeBuffer.remaining() != 0)) {
   259                 int howmuch;
   288                 ByteBuffer bb = ByteBuffer.wrap(new byte[
   260                 byte handshakeType;
   289                         handshakeBuffer.remaining() + fragment.remaining()]);
   261                 if (hsMsgOff < hsMsgLen) {
   290                 bb.put(handshakeBuffer);
   262                     // a fragment of the handshake message
   291                 bb.put(fragment);
   263                     howmuch = Math.min((hsMsgLen - hsMsgOff), remains);
   292                 handshakeFrag = bb.rewind();
   264                     handshakeType = prevType;
   293                 handshakeBuffer = null;
   265 
   294             }
   266                     hsMsgOff += howmuch;
   295 
   267                     if (hsMsgOff == hsMsgLen) {
   296             ArrayList<Plaintext> plaintexts = new ArrayList<>(5);
   268                         // Now is a complete handshake message.
   297             while (handshakeFrag.hasRemaining()) {
   269                         hsMsgOff = 0;
   298                 int remaining = handshakeFrag.remaining();
   270                         hsMsgLen = 0;
   299                 if (remaining < handshakeHeaderSize) {
       
   300                     handshakeBuffer = ByteBuffer.wrap(new byte[remaining]);
       
   301                     handshakeBuffer.put(handshakeFrag);
       
   302                     handshakeBuffer.rewind();
       
   303                     break;
       
   304                 }
       
   305 
       
   306                 handshakeFrag.mark();
       
   307                 // skip the first byte: handshake type
       
   308                 byte handshakeType = handshakeFrag.get();
       
   309                 int handshakeBodyLen = Record.getInt24(handshakeFrag);
       
   310                 handshakeFrag.reset();
       
   311                 int handshakeMessageLen =
       
   312                         handshakeHeaderSize + handshakeBodyLen;
       
   313                 if (remaining < handshakeMessageLen) {
       
   314                     handshakeBuffer = ByteBuffer.wrap(new byte[remaining]);
       
   315                     handshakeBuffer.put(handshakeFrag);
       
   316                     handshakeBuffer.rewind();
       
   317                     break;
       
   318                 } if (remaining == handshakeMessageLen) {
       
   319                     if (handshakeHash.isHashable(handshakeType)) {
       
   320                         handshakeHash.receive(handshakeFrag);
   271                     }
   321                     }
   272                 } else {    // hsMsgOff == hsMsgLen, a new handshake message
   322 
   273                     handshakeType = plaintext.get();
   323                     plaintexts.add(
   274                     int handshakeLen = ((plaintext.get() & 0xFF) << 16) |
   324                         new Plaintext(contentType,
   275                                        ((plaintext.get() & 0xFF) << 8) |
   325                             majorVersion, minorVersion, -1, -1L, handshakeFrag)
   276                                         (plaintext.get() & 0xFF);
   326                     );
   277                     plaintext.position(frgPos);
   327                     break;
   278                     if (remains < (handshakeLen + 1)) { // 1: handshake type
   328                 } else {
   279                         // This handshake message is fragmented.
   329                     int fragPos = handshakeFrag.position();
   280                         prevType = handshakeType;
   330                     int fragLim = handshakeFrag.limit();
   281                         hsMsgOff = remains - 4;         // 4: handshake header
   331                     int nextPos = fragPos + handshakeMessageLen;
   282                         hsMsgLen = handshakeLen;
   332                     handshakeFrag.limit(nextPos);
       
   333 
       
   334                     if (handshakeHash.isHashable(handshakeType)) {
       
   335                         handshakeHash.receive(handshakeFrag);
   283                     }
   336                     }
   284 
   337 
   285                     howmuch = Math.min(handshakeLen + 4, remains);
   338                     plaintexts.add(
   286                 }
   339                         new Plaintext(contentType, majorVersion, minorVersion,
   287 
   340                             -1, -1L, handshakeFrag.slice())
   288                 plaintext.limit(frgPos + howmuch);
   341                     );
   289 
   342 
   290                 if (handshakeType == HandshakeMessage.ht_hello_request) {
   343                     handshakeFrag.position(nextPos);
   291                     // omitted from handshake hash computation
   344                     handshakeFrag.limit(fragLim);
   292                 } else if ((handshakeType != HandshakeMessage.ht_finished) &&
   345                 }
   293                     (handshakeType != HandshakeMessage.ht_certificate_verify)) {
   346             }
   294 
   347 
   295                     if (handshakeHash == null) {
   348             return plaintexts.toArray(new Plaintext[0]);
   296                         // used for cache only
   349         }
   297                         handshakeHash = new HandshakeHash(false);
   350 
   298                     }
   351         // KeyLimit check during application data.
   299                     handshakeHash.update(plaintext);
   352         // atKeyLimit() inactive when limits not checked, tc set when limits
   300                 } else {
   353         // are active.
   301                     // Reserve until this handshake message has been processed.
   354 
   302                     if (handshakeHash == null) {
   355         if (readCipher.atKeyLimit()) {
   303                         // used for cache only
   356             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
   304                         handshakeHash = new HandshakeHash(false);
   357                 SSLLogger.fine("KeyUpdate: triggered, read side.");
   305                     }
   358             }
   306                     handshakeHash.reserve(plaintext);
   359 
   307                 }
   360             PostHandshakeContext p = new PostHandshakeContext(tc);
   308 
   361             KeyUpdate.handshakeProducer.produce(p,
   309                 plaintext.position(frgPos + howmuch);
   362                     new KeyUpdateMessage(p, KeyUpdateRequest.REQUESTED));
   310                 plaintext.limit(pltLim);
   363         }
   311 
   364 
   312                 frgPos += howmuch;
   365         return new Plaintext[] {
   313                 remains -= howmuch;
   366                 new Plaintext(contentType,
   314             }
   367                     majorVersion, minorVersion, -1, -1L, fragment)
   315             plaintext.position(pltPos);
   368             };
   316         }
   369     }
   317 
   370 
   318         return new Plaintext(contentType,
   371     private Plaintext[] handleUnknownRecord(
   319                 majorVersion, minorVersion, -1, -1L, plaintext);
   372             byte[] header) throws IOException, BadPaddingException {
   320                 // recordEpoch, recordSeq, plaintext);
       
   321     }
       
   322 
       
   323     private Plaintext handleUnknownRecord(InputStream is, byte[] header,
       
   324             ByteBuffer destination) throws IOException, BadPaddingException {
       
   325 
       
   326         byte firstByte = header[0];
   373         byte firstByte = header[0];
   327         byte thirdByte = header[2];
   374         byte thirdByte = header[2];
   328 
   375 
   329         // Does it look like a Version 2 client hello (V2ClientHello)?
   376         // Does it look like a Version 2 client hello (V2ClientHello)?
   330         if (((firstByte & 0x80) != 0) && (thirdByte == 1)) {
   377         if (((firstByte & 0x80) != 0) && (thirdByte == 1)) {
   345                  * Looks like a V2 client hello, but not one saying
   392                  * Looks like a V2 client hello, but not one saying
   346                  * "let's talk SSLv3".  So we need to send an SSLv2
   393                  * "let's talk SSLv3".  So we need to send an SSLv2
   347                  * error message, one that's treated as fatal by
   394                  * error message, one that's treated as fatal by
   348                  * clients (Otherwise we'll hang.)
   395                  * clients (Otherwise we'll hang.)
   349                  */
   396                  */
   350                 deliverStream.write(SSLRecord.v2NoCipher);      // SSLv2Hello
   397                 os.write(SSLRecord.v2NoCipher);      // SSLv2Hello
   351 
   398 
   352                 if (debug != null) {
   399                 if (SSLLogger.isOn) {
   353                     if (Debug.isOn("record")) {
   400                     if (SSLLogger.isOn("record")) {
   354                          System.out.println(Thread.currentThread().getName() +
   401                          SSLLogger.fine(
   355                                 "Requested to negotiate unsupported SSLv2!");
   402                                 "Requested to negotiate unsupported SSLv2!");
   356                     }
   403                     }
   357 
   404 
   358                     if (Debug.isOn("packet")) {
   405                     if (SSLLogger.isOn("packet")) {
   359                         Debug.printHex(
   406                         SSLLogger.fine("Raw write", SSLRecord.v2NoCipher);
   360                                 "[Raw write]: length = " +
       
   361                                 SSLRecord.v2NoCipher.length,
       
   362                                 SSLRecord.v2NoCipher);
       
   363                     }
   407                     }
   364                 }
   408                 }
   365 
   409 
   366                 throw new SSLException("Unsupported SSL v2.0 ClientHello");
   410                 throw new SSLException("Unsupported SSL v2.0 ClientHello");
   367             }
   411             }
   368 
   412 
   369             int msgLen = ((header[0] & 0x7F) << 8) | (header[1] & 0xFF);
   413             int msgLen = ((header[0] & 0x7F) << 8) | (header[1] & 0xFF);
   370 
   414 
   371             if (destination == null) {
   415             ByteBuffer destination = ByteBuffer.allocate(headerSize + msgLen);
   372                 destination = ByteBuffer.allocate(headerSize + msgLen);
       
   373             }
       
   374             destination.put(temporary, 0, headerSize);
   416             destination.put(temporary, 0, headerSize);
   375             msgLen -= 3;            // had read 3 bytes of content as header
   417             msgLen -= 3;            // had read 3 bytes of content as header
   376             while (msgLen > 0) {
   418             while (msgLen > 0) {
   377                 int howmuch = Math.min(temporary.length, msgLen);
   419                 int howmuch = Math.min(temporary.length, msgLen);
   378                 int really = read(is, temporary, 0, howmuch);
   420                 int really = read(is, temporary, 0, howmuch);
   389              * If we can map this into a V3 ClientHello, read and
   431              * If we can map this into a V3 ClientHello, read and
   390              * hash the rest of the V2 handshake, turn it into a
   432              * hash the rest of the V2 handshake, turn it into a
   391              * V3 ClientHello message, and pass it up.
   433              * V3 ClientHello message, and pass it up.
   392              */
   434              */
   393             destination.position(2);     // exclude the header
   435             destination.position(2);     // exclude the header
   394 
   436             handshakeHash.receive(destination);
   395             if (handshakeHash == null) {
       
   396                 // used for cache only
       
   397                 handshakeHash = new HandshakeHash(false);
       
   398             }
       
   399             handshakeHash.update(destination);
       
   400             destination.position(0);
   437             destination.position(0);
   401 
   438 
   402             ByteBuffer converted = convertToClientHello(destination);
   439             ByteBuffer converted = convertToClientHello(destination);
   403 
   440 
   404             if (debug != null && Debug.isOn("packet")) {
   441             if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
   405                  Debug.printHex(
   442                 SSLLogger.fine(
   406                         "[Converted] ClientHello", converted);
   443                         "[Converted] ClientHello", converted);
   407             }
   444             }
   408 
   445 
   409             return new Plaintext(ct_handshake,
   446             return new Plaintext[] {
   410                 majorVersion, minorVersion, -1, -1L, converted);
   447                     new Plaintext(ContentType.HANDSHAKE.id,
       
   448                     majorVersion, minorVersion, -1, -1L, converted)
       
   449                 };
   411         } else {
   450         } else {
   412             if (((firstByte & 0x80) != 0) && (thirdByte == 4)) {
   451             if (((firstByte & 0x80) != 0) && (thirdByte == 4)) {
   413                 throw new SSLException("SSL V2.0 servers are not supported.");
   452                 throw new SSLException("SSL V2.0 servers are not supported.");
   414             }
   453             }
   415 
   454 
   422             byte[] buffer, int offset, int len) throws IOException {
   461             byte[] buffer, int offset, int len) throws IOException {
   423         int n = 0;
   462         int n = 0;
   424         while (n < len) {
   463         while (n < len) {
   425             int readLen = is.read(buffer, offset + n, len - n);
   464             int readLen = is.read(buffer, offset + n, len - n);
   426             if (readLen < 0) {
   465             if (readLen < 0) {
       
   466                 if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
       
   467                     SSLLogger.fine("Raw read: EOF");
       
   468                 }
   427                 return -1;
   469                 return -1;
   428             }
   470             }
   429 
   471 
   430             if (debug != null && Debug.isOn("packet")) {
   472             if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
   431                  Debug.printHex(
   473                 ByteBuffer bb = ByteBuffer.wrap(buffer, offset + n, readLen);
   432                         "[Raw read]: length = " + readLen,
   474                 SSLLogger.fine("Raw read", bb);
   433                         buffer, offset + n, readLen);
       
   434             }
   475             }
   435 
   476 
   436             n += readLen;
   477             n += readLen;
   437         }
   478         }
   438 
   479