1 /*
   2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package sun.security.ssl;
  28 
  29 import java.io.*;
  30 import java.nio.*;
  31 import java.util.Arrays;
  32 
  33 import javax.net.ssl.SSLException;
  34 import sun.misc.HexDumpEncoder;
  35 
  36 
  37 /**
  38  * SSL 3.0 records, as written to a TCP stream.
  39  *
  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  *
  49  * @author David Brownell
  50  */
  51 class OutputRecord extends ByteArrayOutputStream implements Record {
  52 
  53     private HandshakeHash       handshakeHash;
  54     private int                 lastHashed;
  55     private boolean             firstMessage;
  56     final private byte          contentType;
  57     private int                 headerOffset;
  58 
  59     // current protocol version, sent as record version
  60     ProtocolVersion     protocolVersion;
  61 
  62     // version for the ClientHello message. Only relevant if this is a
  63     // client handshake record. If set to ProtocolVersion.SSL20Hello,
  64     // the V3 client hello is converted to V2 format.
  65     private ProtocolVersion     helloVersion;
  66 
  67     /* Class and subclass dynamic debugging support */
  68     static final Debug debug = Debug.getInstance("ssl");
  69 
  70     /*
  71      * Default constructor makes a record supporting the maximum
  72      * SSL record size.  It allocates the header bytes directly.
  73      *
  74      * The structure of the byte buffer looks like:
  75      *
  76      *     |---------+--------+-------+---------------------------------|
  77      *     | unused  | header |  IV   | content, MAC/TAG, padding, etc. |
  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 
 537     /*
 538      * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
 539      * This is taken from the SSL V3 specification, Appendix E.
 540      */
 541     private static int[] V3toV2CipherMap1 =
 542         {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
 543     private static int[] V3toV2CipherMap3 =
 544         {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
 545 
 546     /*
 547      * See which matching pure-V2 cipher specs we need to include.
 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      */
 557     private int V3toV2CipherSuite(byte byte1, byte byte2) {
 558         buf[count++] = 0;
 559         buf[count++] = byte1;
 560         buf[count++] = byte2;
 561 
 562         if (((byte2 & 0xff) > 0xA) ||
 563                 (V3toV2CipherMap1[byte2] == -1)) {
 564             return 3;
 565         }
 566 
 567         buf[count++] = (byte)V3toV2CipherMap1[byte2];
 568         buf[count++] = 0;
 569         buf[count++] = (byte)V3toV2CipherMap3[byte2];
 570 
 571         return 6;
 572     }
 573 }