jdk/src/java.base/share/classes/sun/security/ssl/OutputRecord.java
changeset 30904 ec0224270f90
parent 25859 3317bb8137f4
child 32649 2ee9017c7597
equal deleted inserted replaced
30903:0c7d705209c6 30904:ec0224270f90
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 
       
    27 package sun.security.ssl;
    26 package sun.security.ssl;
    28 
    27 
    29 import java.io.*;
    28 import java.io.*;
    30 import java.nio.*;
    29 import java.nio.*;
    31 import java.util.Arrays;
    30 import java.util.Arrays;
    33 import javax.net.ssl.SSLException;
    32 import javax.net.ssl.SSLException;
    34 import sun.misc.HexDumpEncoder;
    33 import sun.misc.HexDumpEncoder;
    35 
    34 
    36 
    35 
    37 /**
    36 /**
    38  * SSL 3.0 records, as written to a TCP stream.
    37  * {@code OutputRecord} takes care of the management of SSL/TLS/DTLS output
    39  *
    38  * records, including buffering, encryption, handshake messages marshal, etc.
    40  * Each record has a message area that starts out with data supplied by the
       
    41  * application.  It may grow/shrink due to compression and will be modified
       
    42  * in place for mac-ing and encryption.
       
    43  *
       
    44  * Handshake records have additional needs, notably accumulation of a set
       
    45  * of hashes which are used to establish that handshaking was done right.
       
    46  * Handshake records usually have several handshake messages each, and we
       
    47  * need message-level control over what's hashed.
       
    48  *
    39  *
    49  * @author David Brownell
    40  * @author David Brownell
    50  */
    41  */
    51 class OutputRecord extends ByteArrayOutputStream implements Record {
    42 abstract class OutputRecord extends ByteArrayOutputStream
    52 
    43             implements Record, Closeable {
    53     private HandshakeHash       handshakeHash;
    44 
    54     private int                 lastHashed;
    45     /* Class and subclass dynamic debugging support */
    55     private boolean             firstMessage;
    46     static final Debug          debug = Debug.getInstance("ssl");
    56     final private byte          contentType;
    47 
    57     private int                 headerOffset;
    48     Authenticator               writeAuthenticator;
       
    49     CipherBox                   writeCipher;
       
    50 
       
    51     HandshakeHash               handshakeHash;
       
    52     boolean                     firstMessage;
    58 
    53 
    59     // current protocol version, sent as record version
    54     // current protocol version, sent as record version
    60     ProtocolVersion     protocolVersion;
    55     ProtocolVersion             protocolVersion;
    61 
    56 
    62     // version for the ClientHello message. Only relevant if this is a
    57     // version for the ClientHello message. Only relevant if this is a
    63     // client handshake record. If set to ProtocolVersion.SSL20Hello,
    58     // client handshake record. If set to ProtocolVersion.SSL20Hello,
    64     // the V3 client hello is converted to V2 format.
    59     // the V3 client hello is converted to V2 format.
    65     private ProtocolVersion     helloVersion;
    60     ProtocolVersion             helloVersion;
    66 
    61 
    67     /* Class and subclass dynamic debugging support */
    62     // Is it the first application record to write?
    68     static final Debug debug = Debug.getInstance("ssl");
    63     boolean                     isFirstAppOutputRecord = true;
    69 
    64 
    70     /*
    65     // packet size
    71      * Default constructor makes a record supporting the maximum
    66     int                         packetSize;
    72      * SSL record size.  It allocates the header bytes directly.
    67 
    73      *
    68     // fragment size
    74      * The structure of the byte buffer looks like:
    69     int                         fragmentSize;
    75      *
    70 
    76      *     |---------+--------+-------+---------------------------------|
    71     // closed or not?
    77      *     | unused  | header |  IV   | content, MAC/TAG, padding, etc. |
    72     boolean                     isClosed;
    78      *     |    headerPlusMaxIVSize   |
       
    79      *
       
    80      * unused: unused part of the buffer of size
       
    81      *
       
    82      *             headerPlusMaxIVSize - header size - IV size
       
    83      *
       
    84      *         When this object is created, we don't know the protocol
       
    85      *         version number, IV length, etc., so reserve space in front
       
    86      *         to avoid extra data movement (copies).
       
    87      * header: the header of an SSL record
       
    88      * IV:     the optional IV/nonce field, it is only required for block
       
    89      *         (TLS 1.1 or later) and AEAD cipher suites.
       
    90      *
       
    91      * @param type the content type for the record
       
    92      */
       
    93     OutputRecord(byte type, int size) {
       
    94         super(size);
       
    95         this.protocolVersion = ProtocolVersion.DEFAULT;
       
    96         this.helloVersion = ProtocolVersion.DEFAULT_HELLO;
       
    97         firstMessage = true;
       
    98         count = headerPlusMaxIVSize;
       
    99         contentType = type;
       
   100         lastHashed = count;
       
   101         headerOffset = headerPlusMaxIVSize - headerSize;
       
   102     }
       
   103 
       
   104     OutputRecord(byte type) {
       
   105         this(type, recordSize(type));
       
   106     }
       
   107 
       
   108     /**
       
   109      * Get the size of the buffer we need for records of the specified
       
   110      * type.
       
   111      */
       
   112     private static int recordSize(byte type) {
       
   113         if ((type == ct_change_cipher_spec) || (type == ct_alert)) {
       
   114             return maxAlertRecordSize;
       
   115         } else {
       
   116             return maxRecordSize;
       
   117         }
       
   118     }
       
   119 
       
   120     /*
       
   121      * Updates the SSL version of this record.
       
   122      */
       
   123     synchronized void setVersion(ProtocolVersion protocolVersion) {
       
   124         this.protocolVersion = protocolVersion;
       
   125     }
       
   126 
       
   127     /*
       
   128      * Updates helloVersion of this record.
       
   129      */
       
   130     synchronized void setHelloVersion(ProtocolVersion helloVersion) {
       
   131         this.helloVersion = helloVersion;
       
   132     }
       
   133 
       
   134     /*
       
   135      * Reset the record so that it can be refilled, starting
       
   136      * immediately after the header.
       
   137      */
       
   138     @Override
       
   139     public synchronized void reset() {
       
   140         super.reset();
       
   141         count = headerPlusMaxIVSize;
       
   142         lastHashed = count;
       
   143         headerOffset = headerPlusMaxIVSize - headerSize;
       
   144     }
       
   145 
       
   146     /*
       
   147      * For handshaking, we need to be able to hash every byte above the
       
   148      * record marking layer.  This is where we're guaranteed to see those
       
   149      * bytes, so this is where we can hash them.
       
   150      */
       
   151     void setHandshakeHash(HandshakeHash handshakeHash) {
       
   152         assert(contentType == ct_handshake);
       
   153         this.handshakeHash = handshakeHash;
       
   154     }
       
   155 
       
   156     /*
       
   157      * We hash (the plaintext) on demand.  There is one place where
       
   158      * we want to access the hash in the middle of a record:  client
       
   159      * cert message gets hashed, and part of the same record is the
       
   160      * client cert verify message which uses that hash.  So we track
       
   161      * how much of each record we've hashed so far.
       
   162      */
       
   163     void doHashes() {
       
   164         int len = count - lastHashed;
       
   165 
       
   166         if (len > 0) {
       
   167             hashInternal(buf, lastHashed, len);
       
   168             lastHashed = count;
       
   169         }
       
   170     }
       
   171 
       
   172     /*
       
   173      * Need a helper function so we can hash the V2 hello correctly
       
   174      */
       
   175     private void hashInternal(byte buf [], int offset, int len) {
       
   176         if (debug != null && Debug.isOn("data")) {
       
   177             try {
       
   178                 HexDumpEncoder hd = new HexDumpEncoder();
       
   179 
       
   180                 System.out.println("[write] MD5 and SHA1 hashes:  len = "
       
   181                     + len);
       
   182                 hd.encodeBuffer(new ByteArrayInputStream(buf,
       
   183                     lastHashed, len), System.out);
       
   184             } catch (IOException e) { }
       
   185         }
       
   186 
       
   187         handshakeHash.update(buf, lastHashed, len);
       
   188         lastHashed = count;
       
   189     }
       
   190 
       
   191     /*
       
   192      * Return true iff the record is empty -- to avoid doing the work
       
   193      * of sending empty records over the network.
       
   194      */
       
   195     boolean isEmpty() {
       
   196         return count == headerPlusMaxIVSize;
       
   197     }
       
   198 
       
   199     /*
       
   200      * Return true if the record is of an alert of the given description.
       
   201      *
       
   202      * Per SSL/TLS specifications, alert messages convey the severity of the
       
   203      * message (warning or fatal) and a description of the alert. An alert
       
   204      * is defined with a two bytes struct, {byte level, byte description},
       
   205      * following after the header bytes.
       
   206      */
       
   207     boolean isAlert(byte description) {
       
   208         if ((count > (headerPlusMaxIVSize + 1)) && (contentType == ct_alert)) {
       
   209             return buf[headerPlusMaxIVSize + 1] == description;
       
   210         }
       
   211 
       
   212         return false;
       
   213     }
       
   214 
       
   215     /*
       
   216      * Encrypt ... length may grow due to block cipher padding, or
       
   217      * message authentication code or tag.
       
   218      */
       
   219     void encrypt(Authenticator authenticator, CipherBox box)
       
   220             throws IOException {
       
   221 
       
   222         // In case we are automatically flushing a handshake stream, make
       
   223         // sure we have hashed the message first.
       
   224         //
       
   225         // when we support compression, hashing can't go here
       
   226         // since it'll need to be done on the uncompressed data,
       
   227         // and the MAC applies to the compressed data.
       
   228         if (contentType == ct_handshake) {
       
   229             doHashes();
       
   230         }
       
   231 
       
   232         // Requires message authentication code for stream and block
       
   233         // cipher suites.
       
   234         if (authenticator instanceof MAC) {
       
   235             MAC signer = (MAC)authenticator;
       
   236             if (signer.MAClen() != 0) {
       
   237                 byte[] hash = signer.compute(contentType, buf,
       
   238                     headerPlusMaxIVSize, count - headerPlusMaxIVSize, false);
       
   239                 write(hash);
       
   240             }
       
   241         }
       
   242 
       
   243         if (!box.isNullCipher()) {
       
   244             // Requires explicit IV/nonce for CBC/AEAD cipher suites for
       
   245             // TLS 1.1 or later.
       
   246             if ((protocolVersion.v >= ProtocolVersion.TLS11.v) &&
       
   247                                     (box.isCBCMode() || box.isAEADMode())) {
       
   248                 byte[] nonce = box.createExplicitNonce(authenticator,
       
   249                                     contentType, count - headerPlusMaxIVSize);
       
   250                 int offset = headerPlusMaxIVSize - nonce.length;
       
   251                 System.arraycopy(nonce, 0, buf, offset, nonce.length);
       
   252                 headerOffset = offset - headerSize;
       
   253             } else {
       
   254                 headerOffset = headerPlusMaxIVSize - headerSize;
       
   255             }
       
   256 
       
   257             // encrypt the content
       
   258             int offset = headerPlusMaxIVSize;
       
   259             if (!box.isAEADMode()) {
       
   260                 // The explicit IV can be encrypted.
       
   261                 offset = headerOffset + headerSize;
       
   262             }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
       
   263 
       
   264             count = offset + box.encrypt(buf, offset, count - offset);
       
   265         }
       
   266     }
       
   267 
       
   268     /*
       
   269      * Tell how full the buffer is ... for filling it with application or
       
   270      * handshake data.
       
   271      */
       
   272     final int availableDataBytes() {
       
   273         int dataSize = count - headerPlusMaxIVSize;
       
   274         return maxDataSize - dataSize;
       
   275     }
       
   276 
       
   277     /*
       
   278      * Increases the capacity if necessary to ensure that it can hold
       
   279      * at least the number of elements specified by the minimum
       
   280      * capacity argument.
       
   281      *
       
   282      * Note that the increased capacity is only can be used for held
       
   283      * record buffer. Please DO NOT update the availableDataBytes()
       
   284      * according to the expended buffer capacity.
       
   285      *
       
   286      * @see availableDataBytes()
       
   287      */
       
   288     private void ensureCapacity(int minCapacity) {
       
   289         // overflow-conscious code
       
   290         if (minCapacity > buf.length) {
       
   291             buf = Arrays.copyOf(buf, minCapacity);
       
   292         }
       
   293     }
       
   294 
       
   295     /*
       
   296      * Return the type of SSL record that's buffered here.
       
   297      */
       
   298     final byte contentType() {
       
   299         return contentType;
       
   300     }
       
   301 
       
   302     /*
       
   303      * Write the record out on the stream.  Note that you must have (in
       
   304      * order) compressed the data, appended the MAC, and encrypted it in
       
   305      * order for the record to be understood by the other end.  (Some of
       
   306      * those steps will be null early in handshaking.)
       
   307      *
       
   308      * Note that this does no locking for the connection, it's required
       
   309      * that synchronization be done elsewhere.  Also, this does its work
       
   310      * in a single low level write, for efficiency.
       
   311      */
       
   312     void write(OutputStream s, boolean holdRecord,
       
   313             ByteArrayOutputStream heldRecordBuffer) throws IOException {
       
   314 
       
   315         /*
       
   316          * Don't emit content-free records.  (Even change cipher spec
       
   317          * messages have a byte of data!)
       
   318          */
       
   319         if (count == headerPlusMaxIVSize) {
       
   320             return;
       
   321         }
       
   322 
       
   323         int length = count - headerOffset - headerSize;
       
   324         // "should" really never write more than about 14 Kb...
       
   325         if (length < 0) {
       
   326             throw new SSLException("output record size too small: "
       
   327                 + length);
       
   328         }
       
   329 
       
   330         if (debug != null
       
   331                 && (Debug.isOn("record") || Debug.isOn("handshake"))) {
       
   332             if ((debug != null && Debug.isOn("record"))
       
   333                     || contentType() == ct_change_cipher_spec)
       
   334                 System.out.println(Thread.currentThread().getName()
       
   335                     // v3.0/v3.1 ...
       
   336                     + ", WRITE: " + protocolVersion
       
   337                     + " " + InputRecord.contentName(contentType())
       
   338                     + ", length = " + length);
       
   339         }
       
   340 
       
   341         /*
       
   342          * If this is the initial ClientHello on this connection and
       
   343          * we're not trying to resume a (V3) session then send a V2
       
   344          * ClientHello instead so we can detect V2 servers cleanly.
       
   345          */
       
   346          if (firstMessage && useV2Hello()) {
       
   347             byte[] v3Msg = new byte[length - 4];
       
   348             System.arraycopy(buf, headerPlusMaxIVSize + 4,
       
   349                                         v3Msg, 0, v3Msg.length);
       
   350             headerOffset = 0;   // reset the header offset
       
   351             V3toV2ClientHello(v3Msg);
       
   352             handshakeHash.reset();
       
   353             lastHashed = 2;
       
   354             doHashes();
       
   355             if (debug != null && Debug.isOn("record"))  {
       
   356                 System.out.println(
       
   357                     Thread.currentThread().getName()
       
   358                     + ", WRITE: SSLv2 client hello message"
       
   359                     + ", length = " + (count - 2)); // 2 byte SSLv2 header
       
   360             }
       
   361         } else {
       
   362             /*
       
   363              * Fill out the header, write it and the message.
       
   364              */
       
   365             buf[headerOffset + 0] = contentType;
       
   366             buf[headerOffset + 1] = protocolVersion.major;
       
   367             buf[headerOffset + 2] = protocolVersion.minor;
       
   368             buf[headerOffset + 3] = (byte)(length >> 8);
       
   369             buf[headerOffset + 4] = (byte)(length);
       
   370         }
       
   371         firstMessage = false;
       
   372 
       
   373         /*
       
   374          * The upper levels may want us to delay sending this packet so
       
   375          * multiple TLS Records can be sent in one (or more) TCP packets.
       
   376          * If so, add this packet to the heldRecordBuffer.
       
   377          *
       
   378          * NOTE:  all writes have been synchronized by upper levels.
       
   379          */
       
   380         int debugOffset = 0;
       
   381         if (holdRecord) {
       
   382             /*
       
   383              * If holdRecord is true, we must have a heldRecordBuffer.
       
   384              *
       
   385              * Don't worry about the override of writeBuffer(), because
       
   386              * when holdRecord is true, the implementation in this class
       
   387              * will be used.
       
   388              */
       
   389             writeBuffer(heldRecordBuffer,
       
   390                         buf, headerOffset, count - headerOffset, debugOffset);
       
   391         } else {
       
   392             // It's time to send, do we have buffered data?
       
   393             // May or may not have a heldRecordBuffer.
       
   394             if (heldRecordBuffer != null && heldRecordBuffer.size() > 0) {
       
   395                 int heldLen = heldRecordBuffer.size();
       
   396 
       
   397                 // Ensure the capacity of this buffer.
       
   398                 int newCount = count + heldLen - headerOffset;
       
   399                 ensureCapacity(newCount);
       
   400 
       
   401                 // Slide everything in the buffer to the right.
       
   402                 System.arraycopy(buf, headerOffset,
       
   403                                     buf, heldLen, count - headerOffset);
       
   404 
       
   405                 // Prepend the held record to the buffer.
       
   406                 System.arraycopy(
       
   407                     heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen);
       
   408                 count = newCount;
       
   409                 headerOffset = 0;
       
   410 
       
   411                 // Clear the held buffer.
       
   412                 heldRecordBuffer.reset();
       
   413 
       
   414                 // The held buffer has been dumped, set the debug dump offset.
       
   415                 debugOffset = heldLen;
       
   416             }
       
   417             writeBuffer(s, buf, headerOffset,
       
   418                         count - headerOffset, debugOffset);
       
   419         }
       
   420 
       
   421         reset();
       
   422     }
       
   423 
       
   424     /*
       
   425      * Actually do the write here.  For SSLEngine's HS data,
       
   426      * we'll override this method and let it take the appropriate
       
   427      * action.
       
   428      */
       
   429     void writeBuffer(OutputStream s, byte [] buf, int off, int len,
       
   430             int debugOffset) throws IOException {
       
   431         s.write(buf, off, len);
       
   432         s.flush();
       
   433 
       
   434         // Output only the record from the specified debug offset.
       
   435         if (debug != null && Debug.isOn("packet")) {
       
   436             try {
       
   437                 HexDumpEncoder hd = new HexDumpEncoder();
       
   438 
       
   439                 System.out.println("[Raw write]: length = " +
       
   440                                                     (len - debugOffset));
       
   441                 hd.encodeBuffer(new ByteArrayInputStream(buf,
       
   442                     off + debugOffset, len - debugOffset), System.out);
       
   443             } catch (IOException e) { }
       
   444         }
       
   445     }
       
   446 
       
   447     /*
       
   448      * Return whether the buffer contains a ClientHello message that should
       
   449      * be converted to V2 format.
       
   450      */
       
   451     private boolean useV2Hello() {
       
   452         return firstMessage
       
   453             && (helloVersion == ProtocolVersion.SSL20Hello)
       
   454             && (contentType == ct_handshake)
       
   455             && (buf[headerOffset + 5] == HandshakeMessage.ht_client_hello)
       
   456                                             //  5: recode header size
       
   457             && (buf[headerPlusMaxIVSize + 4 + 2 + 32] == 0);
       
   458                                             // V3 session ID is empty
       
   459                                             //  4: handshake header size
       
   460                                             //  2: client_version in ClientHello
       
   461                                             // 32: random in ClientHello
       
   462     }
       
   463 
       
   464     /*
       
   465      * Detect "old" servers which are capable of SSL V2.0 protocol ... for
       
   466      * example, Netscape Commerce 1.0 servers.  The V3 message is in the
       
   467      * header and the bytes passed as parameter.  This routine translates
       
   468      * the V3 message into an equivalent V2 one.
       
   469      *
       
   470      * Note that the translation will strip off all hello extensions as
       
   471      * SSL V2.0 does not support hello extension.
       
   472      */
       
   473     private void V3toV2ClientHello(byte v3Msg []) throws SSLException {
       
   474         int v3SessionIdLenOffset = 2 + 32; // version + nonce
       
   475         int v3SessionIdLen = v3Msg[v3SessionIdLenOffset];
       
   476         int v3CipherSpecLenOffset = v3SessionIdLenOffset + 1 + v3SessionIdLen;
       
   477         int v3CipherSpecLen = ((v3Msg[v3CipherSpecLenOffset] & 0xff) << 8) +
       
   478           (v3Msg[v3CipherSpecLenOffset + 1] & 0xff);
       
   479         int cipherSpecs = v3CipherSpecLen / 2; // 2 bytes each in V3
       
   480 
       
   481         /*
       
   482          * Copy over the cipher specs. We don't care about actually translating
       
   483          * them for use with an actual V2 server since we only talk V3.
       
   484          * Therefore, just copy over the V3 cipher spec values with a leading
       
   485          * 0.
       
   486          */
       
   487         int v3CipherSpecOffset = v3CipherSpecLenOffset + 2; // skip length
       
   488         int v2CipherSpecLen = 0;
       
   489         count = 11;
       
   490         boolean containsRenegoInfoSCSV = false;
       
   491         for (int i = 0; i < cipherSpecs; i++) {
       
   492             byte byte1, byte2;
       
   493 
       
   494             byte1 = v3Msg[v3CipherSpecOffset++];
       
   495             byte2 = v3Msg[v3CipherSpecOffset++];
       
   496             v2CipherSpecLen += V3toV2CipherSuite(byte1, byte2);
       
   497             if (!containsRenegoInfoSCSV &&
       
   498                         byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
       
   499                 containsRenegoInfoSCSV = true;
       
   500             }
       
   501         }
       
   502 
       
   503         if (!containsRenegoInfoSCSV) {
       
   504             v2CipherSpecLen += V3toV2CipherSuite((byte)0x00, (byte)0xFF);
       
   505         }
       
   506 
       
   507         /*
       
   508          * Build the first part of the V3 record header from the V2 one
       
   509          * that's now buffered up.  (Lengths are fixed up later).
       
   510          */
       
   511         buf[2] = HandshakeMessage.ht_client_hello;
       
   512         buf[3] = v3Msg[0];      // major version
       
   513         buf[4] = v3Msg[1];      // minor version
       
   514         buf[5] = (byte)(v2CipherSpecLen >>> 8);
       
   515         buf[6] = (byte)v2CipherSpecLen;
       
   516         buf[7] = 0;
       
   517         buf[8] = 0;             // always no session
       
   518         buf[9] = 0;
       
   519         buf[10] = 32;           // nonce length (always 32 in V3)
       
   520 
       
   521         /*
       
   522          * Copy in the nonce.
       
   523          */
       
   524         System.arraycopy(v3Msg, 2, buf, count, 32);
       
   525         count += 32;
       
   526 
       
   527         /*
       
   528          * Set the length of the message.
       
   529          */
       
   530         count -= 2; // don't include length field itself
       
   531         buf[0] = (byte)(count >>> 8);
       
   532         buf[0] |= 0x80;
       
   533         buf[1] = (byte)(count);
       
   534         count += 2;
       
   535     }
       
   536 
    73 
   537     /*
    74     /*
   538      * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
    75      * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
   539      * This is taken from the SSL V3 specification, Appendix E.
    76      * This is taken from the SSL V3 specification, Appendix E.
   540      */
    77      */
   541     private static int[] V3toV2CipherMap1 =
    78     private static int[] V3toV2CipherMap1 =
   542         {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
    79         {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
   543     private static int[] V3toV2CipherMap3 =
    80     private static int[] V3toV2CipherMap3 =
   544         {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
    81         {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
   545 
    82 
       
    83     OutputRecord() {
       
    84         this.writeCipher = CipherBox.NULL;
       
    85         this.firstMessage = true;
       
    86         this.fragmentSize = Record.maxDataSize;
       
    87 
       
    88         // Please set packetSize and protocolVersion in the implementation.
       
    89     }
       
    90 
       
    91     void setVersion(ProtocolVersion protocolVersion) {
       
    92         this.protocolVersion = protocolVersion;
       
    93     }
       
    94 
   546     /*
    95     /*
   547      * See which matching pure-V2 cipher specs we need to include.
    96      * Updates helloVersion of this record.
   548      * We are including these not because we are actually prepared
       
   549      * to talk V2 but because the Oracle Web Server insists on receiving
       
   550      * at least 1 "pure V2" cipher suite that it supports and returns an
       
   551      * illegal_parameter alert unless one is present. Rather than mindlessly
       
   552      * claiming to implement all documented pure V2 cipher suites the code below
       
   553      * just claims to implement the V2 cipher suite that is "equivalent"
       
   554      * in terms of cipher algorithm & exportability with the actual V3 cipher
       
   555      * suite that we do support.
       
   556      */
    97      */
   557     private int V3toV2CipherSuite(byte byte1, byte byte2) {
    98     synchronized void setHelloVersion(ProtocolVersion helloVersion) {
   558         buf[count++] = 0;
    99         this.helloVersion = helloVersion;
   559         buf[count++] = byte1;
   100     }
   560         buf[count++] = byte2;
   101 
   561 
   102     /*
   562         if (((byte2 & 0xff) > 0xA) ||
   103      * For handshaking, we need to be able to hash every byte above the
   563                 (V3toV2CipherMap1[byte2] == -1)) {
   104      * record marking layer.  This is where we're guaranteed to see those
       
   105      * bytes, so this is where we can hash them.
       
   106      */
       
   107     void setHandshakeHash(HandshakeHash handshakeHash) {
       
   108         this.handshakeHash = handshakeHash;
       
   109     }
       
   110 
       
   111     /*
       
   112      * Return true iff the record is empty -- to avoid doing the work
       
   113      * of sending empty records over the network.
       
   114      */
       
   115     boolean isEmpty() {
       
   116         return false;
       
   117     }
       
   118 
       
   119     boolean seqNumIsHuge() {
       
   120         return (writeAuthenticator != null) &&
       
   121                         writeAuthenticator.seqNumIsHuge();
       
   122     }
       
   123 
       
   124     // SSLEngine and SSLSocket
       
   125     abstract void encodeAlert(byte level, byte description) throws IOException;
       
   126 
       
   127     // SSLEngine and SSLSocket
       
   128     abstract void encodeHandshake(byte[] buffer,
       
   129             int offset, int length) throws IOException;
       
   130 
       
   131     // SSLEngine and SSLSocket
       
   132     abstract void encodeChangeCipherSpec() throws IOException;
       
   133 
       
   134     // apply to SSLEngine only
       
   135     Ciphertext encode(ByteBuffer[] sources, int offset, int length,
       
   136             ByteBuffer destination) throws IOException {
       
   137         throw new UnsupportedOperationException();
       
   138     }
       
   139 
       
   140     // apply to SSLEngine only
       
   141     void encodeV2NoCipher() throws IOException {
       
   142         throw new UnsupportedOperationException();
       
   143     }
       
   144 
       
   145     // apply to SSLSocket only
       
   146     void deliver(byte[] source, int offset, int length) throws IOException {
       
   147         throw new UnsupportedOperationException();
       
   148     }
       
   149 
       
   150     // apply to SSLSocket only
       
   151     void setDeliverStream(OutputStream outputStream) {
       
   152         throw new UnsupportedOperationException();
       
   153     }
       
   154 
       
   155     // apply to SSLEngine only
       
   156     Ciphertext acquireCiphertext(ByteBuffer destination) throws IOException {
       
   157         throw new UnsupportedOperationException();
       
   158     }
       
   159 
       
   160     void changeWriteCiphers(Authenticator writeAuthenticator,
       
   161             CipherBox writeCipher) throws IOException {
       
   162 
       
   163         encodeChangeCipherSpec();
       
   164 
       
   165         /*
       
   166          * Dispose of any intermediate state in the underlying cipher.
       
   167          * For PKCS11 ciphers, this will release any attached sessions,
       
   168          * and thus make finalization faster.
       
   169          *
       
   170          * Since MAC's doFinal() is called for every SSL/TLS packet, it's
       
   171          * not necessary to do the same with MAC's.
       
   172          */
       
   173         writeCipher.dispose();
       
   174 
       
   175         this.writeAuthenticator = writeAuthenticator;
       
   176         this.writeCipher = writeCipher;
       
   177         this.isFirstAppOutputRecord = true;
       
   178     }
       
   179 
       
   180     void changePacketSize(int packetSize) {
       
   181         this.packetSize = packetSize;
       
   182     }
       
   183 
       
   184     void changeFragmentSize(int fragmentSize) {
       
   185         this.fragmentSize = fragmentSize;
       
   186     }
       
   187 
       
   188     int getMaxPacketSize() {
       
   189         return packetSize;
       
   190     }
       
   191 
       
   192     // apply to DTLS SSLEngine
       
   193     void initHandshaker() {
       
   194         // blank
       
   195     }
       
   196 
       
   197     @Override
       
   198     synchronized public void close() throws IOException {
       
   199         if (!isClosed) {
       
   200             isClosed = true;
       
   201             writeCipher.dispose();
       
   202         }
       
   203     }
       
   204 
       
   205     //
       
   206     // shared helpers
       
   207     //
       
   208 
       
   209     // Encrypt a fragment and wrap up a record.
       
   210     //
       
   211     // To be consistent with the spec of SSLEngine.wrap() methods, the
       
   212     // destination ByteBuffer's position is updated to reflect the amount
       
   213     // of data produced.  The limit remains the same.
       
   214     static long encrypt(Authenticator authenticator,
       
   215             CipherBox encCipher, byte contentType, ByteBuffer destination,
       
   216             int headerOffset, int dstLim, int headerSize,
       
   217             ProtocolVersion protocolVersion, boolean isDTLS) {
       
   218 
       
   219         byte[] sequenceNumber = null;
       
   220         int dstContent = destination.position();
       
   221 
       
   222         // Acquire the current sequence number before using.
       
   223         if (isDTLS) {
       
   224             sequenceNumber = authenticator.sequenceNumber();
       
   225         }
       
   226 
       
   227         // "flip" but skip over header again, add MAC & encrypt
       
   228         if (authenticator instanceof MAC) {
       
   229             MAC signer = (MAC)authenticator;
       
   230             if (signer.MAClen() != 0) {
       
   231                 byte[] hash = signer.compute(contentType, destination, false);
       
   232 
       
   233                 /*
       
   234                  * position was advanced to limit in MAC compute above.
       
   235                  *
       
   236                  * Mark next area as writable (above layers should have
       
   237                  * established that we have plenty of room), then write
       
   238                  * out the hash.
       
   239                  */
       
   240                 destination.limit(destination.limit() + hash.length);
       
   241                 destination.put(hash);
       
   242 
       
   243                 // reset the position and limit
       
   244                 destination.limit(destination.position());
       
   245                 destination.position(dstContent);
       
   246             }
       
   247         }
       
   248 
       
   249         if (!encCipher.isNullCipher()) {
       
   250             if (protocolVersion.useTLS11PlusSpec() &&
       
   251                     (encCipher.isCBCMode() || encCipher.isAEADMode())) {
       
   252                 byte[] nonce = encCipher.createExplicitNonce(
       
   253                         authenticator, contentType, destination.remaining());
       
   254                 destination.position(headerOffset + headerSize);
       
   255                 destination.put(nonce);
       
   256             }
       
   257             if (!encCipher.isAEADMode()) {
       
   258                 // The explicit IV in TLS 1.1 and later can be encrypted.
       
   259                 destination.position(headerOffset + headerSize);
       
   260             }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
       
   261 
       
   262             // Encrypt may pad, so again the limit may be changed.
       
   263             encCipher.encrypt(destination, dstLim);
       
   264         } else {
       
   265             destination.position(destination.limit());
       
   266         }
       
   267 
       
   268         // Finish out the record header.
       
   269         int fragLen = destination.limit() - headerOffset - headerSize;
       
   270 
       
   271         destination.put(headerOffset, contentType);         // content type
       
   272         destination.put(headerOffset + 1, protocolVersion.major);
       
   273         destination.put(headerOffset + 2, protocolVersion.minor);
       
   274         if (!isDTLS) {
       
   275             // fragment length
       
   276             destination.put(headerOffset + 3, (byte)(fragLen >> 8));
       
   277             destination.put(headerOffset + 4, (byte)fragLen);
       
   278         } else {
       
   279             // epoch and sequence_number
       
   280             destination.put(headerOffset + 3, sequenceNumber[0]);
       
   281             destination.put(headerOffset + 4, sequenceNumber[1]);
       
   282             destination.put(headerOffset + 5, sequenceNumber[2]);
       
   283             destination.put(headerOffset + 6, sequenceNumber[3]);
       
   284             destination.put(headerOffset + 7, sequenceNumber[4]);
       
   285             destination.put(headerOffset + 8, sequenceNumber[5]);
       
   286             destination.put(headerOffset + 9, sequenceNumber[6]);
       
   287             destination.put(headerOffset + 10, sequenceNumber[7]);
       
   288 
       
   289             // fragment length
       
   290             destination.put(headerOffset + 11, (byte)(fragLen >> 8));
       
   291             destination.put(headerOffset + 12, (byte)fragLen);
       
   292 
       
   293             // Increase the sequence number for next use.
       
   294             authenticator.increaseSequenceNumber();
       
   295         }
       
   296 
       
   297         // Update destination position to reflect the amount of data produced.
       
   298         destination.position(destination.limit());
       
   299 
       
   300         return Authenticator.toLong(sequenceNumber);
       
   301     }
       
   302 
       
   303     // Encrypt a fragment and wrap up a record.
       
   304     //
       
   305     // Uses the internal expandable buf variable and the current
       
   306     // protocolVersion variable.
       
   307     void encrypt(Authenticator authenticator,
       
   308             CipherBox encCipher, byte contentType, int headerSize) {
       
   309 
       
   310         int position = headerSize + writeCipher.getExplicitNonceSize();
       
   311 
       
   312         // "flip" but skip over header again, add MAC & encrypt
       
   313         int macLen = 0;
       
   314         if (authenticator instanceof MAC) {
       
   315             MAC signer = (MAC)authenticator;
       
   316             macLen = signer.MAClen();
       
   317             if (macLen != 0) {
       
   318                 byte[] hash = signer.compute(contentType,
       
   319                         buf, position, (count - position), false);
       
   320 
       
   321                 write(hash, 0, hash.length);
       
   322             }
       
   323         }
       
   324 
       
   325         if (!encCipher.isNullCipher()) {
       
   326             // Requires explicit IV/nonce for CBC/AEAD cipher suites for
       
   327             // TLS 1.1 or later.
       
   328             if (protocolVersion.useTLS11PlusSpec() &&
       
   329                     (encCipher.isCBCMode() || encCipher.isAEADMode())) {
       
   330 
       
   331                 byte[] nonce = encCipher.createExplicitNonce(
       
   332                         authenticator, contentType, (count - position));
       
   333                 int noncePos = position - nonce.length;
       
   334                 System.arraycopy(nonce, 0, buf, noncePos, nonce.length);
       
   335             }
       
   336 
       
   337             if (!encCipher.isAEADMode()) {
       
   338                 // The explicit IV in TLS 1.1 and later can be encrypted.
       
   339                 position = headerSize;
       
   340             }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
       
   341 
       
   342             // increase buf capacity if necessary
       
   343             int fragSize = count - position;
       
   344             int packetSize =
       
   345                     encCipher.calculatePacketSize(fragSize, macLen, headerSize);
       
   346             if (packetSize > (buf.length - position)) {
       
   347                 byte[] newBuf = new byte[position + packetSize];
       
   348                 System.arraycopy(buf, 0, newBuf, 0, count);
       
   349                 buf = newBuf;
       
   350             }
       
   351 
       
   352             // Encrypt may pad, so again the count may be changed.
       
   353             count = position +
       
   354                     encCipher.encrypt(buf, position, (count - position));
       
   355         }
       
   356 
       
   357         // Fill out the header, write it and the message.
       
   358         int fragLen = count - headerSize;
       
   359         buf[0] = contentType;
       
   360         buf[1] = protocolVersion.major;
       
   361         buf[2] = protocolVersion.minor;
       
   362         buf[3] = (byte)((fragLen >> 8) & 0xFF);
       
   363         buf[4] = (byte)(fragLen & 0xFF);
       
   364     }
       
   365 
       
   366     static ByteBuffer encodeV2ClientHello(
       
   367             byte[] fragment, int offset, int length) throws IOException {
       
   368 
       
   369         int v3SessIdLenOffset = offset + 34;      //  2: client_version
       
   370                                                   // 32: random
       
   371 
       
   372         int v3SessIdLen = fragment[v3SessIdLenOffset];
       
   373         int v3CSLenOffset = v3SessIdLenOffset + 1 + v3SessIdLen;
       
   374         int v3CSLen = ((fragment[v3CSLenOffset] & 0xff) << 8) +
       
   375                        (fragment[v3CSLenOffset + 1] & 0xff);
       
   376         int cipherSpecs = v3CSLen / 2;        // 2: cipher spec size
       
   377 
       
   378         // Estimate the max V2ClientHello message length
       
   379         //
       
   380         // 11: header size
       
   381         // (cipherSpecs * 6): cipher_specs
       
   382         //    6: one cipher suite may need 6 bytes, see V3toV2CipherSuite.
       
   383         // 3: placeholder for the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
       
   384         //    signaling cipher suite
       
   385         // 32: challenge size
       
   386         int v2MaxMsgLen = 11 + (cipherSpecs * 6) + 3 + 32;
       
   387 
       
   388         // Create a ByteBuffer backed by an accessible byte array.
       
   389         byte[] dstBytes = new byte[v2MaxMsgLen];
       
   390         ByteBuffer dstBuf = ByteBuffer.wrap(dstBytes);
       
   391 
       
   392         /*
       
   393          * Copy over the cipher specs. We don't care about actually
       
   394          * translating them for use with an actual V2 server since
       
   395          * we only talk V3.  Therefore, just copy over the V3 cipher
       
   396          * spec values with a leading 0.
       
   397          */
       
   398         int v3CSOffset = v3CSLenOffset + 2;   // skip length field
       
   399         int v2CSLen = 0;
       
   400 
       
   401         dstBuf.position(11);
       
   402         boolean containsRenegoInfoSCSV = false;
       
   403         for (int i = 0; i < cipherSpecs; i++) {
       
   404             byte byte1, byte2;
       
   405 
       
   406             byte1 = fragment[v3CSOffset++];
       
   407             byte2 = fragment[v3CSOffset++];
       
   408             v2CSLen += V3toV2CipherSuite(dstBuf, byte1, byte2);
       
   409             if (!containsRenegoInfoSCSV &&
       
   410                     byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
       
   411                 containsRenegoInfoSCSV = true;
       
   412             }
       
   413         }
       
   414 
       
   415         if (!containsRenegoInfoSCSV) {
       
   416             v2CSLen += V3toV2CipherSuite(dstBuf, (byte)0x00, (byte)0xFF);
       
   417         }
       
   418 
       
   419         /*
       
   420          * Copy in the nonce.
       
   421          */
       
   422         dstBuf.put(fragment, (offset + 2), 32);
       
   423 
       
   424         /*
       
   425          * Build the first part of the V3 record header from the V2 one
       
   426          * that's now buffered up.  (Lengths are fixed up later).
       
   427          */
       
   428         int msgLen = dstBuf.position() - 2;   // Exclude the legth field itself
       
   429         dstBuf.position(0);
       
   430         dstBuf.put((byte)(0x80 | ((msgLen >>> 8) & 0xFF)));  // pos: 0
       
   431         dstBuf.put((byte)(msgLen & 0xFF));                   // pos: 1
       
   432         dstBuf.put(HandshakeMessage.ht_client_hello);        // pos: 2
       
   433         dstBuf.put(fragment[offset]);         // major version, pos: 3
       
   434         dstBuf.put(fragment[offset + 1]);     // minor version, pos: 4
       
   435         dstBuf.put((byte)(v2CSLen >>> 8));                   // pos: 5
       
   436         dstBuf.put((byte)(v2CSLen & 0xFF));                  // pos: 6
       
   437         dstBuf.put((byte)0x00);           // session_id_length, pos: 7
       
   438         dstBuf.put((byte)0x00);                              // pos: 8
       
   439         dstBuf.put((byte)0x00);           // challenge_length,  pos: 9
       
   440         dstBuf.put((byte)32);                                // pos: 10
       
   441 
       
   442         dstBuf.position(0);
       
   443         dstBuf.limit(msgLen + 2);
       
   444 
       
   445         return dstBuf;
       
   446     }
       
   447 
       
   448     private static int V3toV2CipherSuite(ByteBuffer dstBuf,
       
   449             byte byte1, byte byte2) {
       
   450         dstBuf.put((byte)0);
       
   451         dstBuf.put(byte1);
       
   452         dstBuf.put(byte2);
       
   453 
       
   454         if (((byte2 & 0xff) > 0xA) || (V3toV2CipherMap1[byte2] == -1)) {
   564             return 3;
   455             return 3;
   565         }
   456         }
   566 
   457 
   567         buf[count++] = (byte)V3toV2CipherMap1[byte2];
   458         dstBuf.put((byte)V3toV2CipherMap1[byte2]);
   568         buf[count++] = 0;
   459         dstBuf.put((byte)0);
   569         buf[count++] = (byte)V3toV2CipherMap3[byte2];
   460         dstBuf.put((byte)V3toV2CipherMap3[byte2]);
   570 
   461 
   571         return 6;
   462         return 6;
   572     }
   463     }
   573 }
   464 }