1 /*
   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.
   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 package sun.security.ssl;
  27 
  28 import java.io.ByteArrayOutputStream;
  29 import java.io.Closeable;
  30 import java.io.IOException;
  31 import java.io.OutputStream;
  32 import java.nio.ByteBuffer;
  33 import sun.security.ssl.SSLCipher.SSLWriteCipher;
  34 
  35 /**
  36  * {@code OutputRecord} takes care of the management of SSL/(D)TLS
  37  * output records, including buffering, encryption, handshake
  38  * messages marshal, etc.
  39  *
  40  * @author David Brownell
  41  */
  42 abstract class OutputRecord
  43         extends ByteArrayOutputStream implements Record, Closeable {
  44     SSLWriteCipher              writeCipher;
  45     // Needed for KeyUpdate, used after Handshake.Finished
  46     TransportContext            tc;
  47 
  48     final HandshakeHash         handshakeHash;
  49     boolean                     firstMessage;
  50 
  51     // current protocol version, sent as record version
  52     ProtocolVersion             protocolVersion;
  53 
  54     // version for the ClientHello message. Only relevant if this is a
  55     // client handshake record. If set to ProtocolVersion.SSL20Hello,
  56     // the V3 client hello is converted to V2 format.
  57     ProtocolVersion             helloVersion;
  58 
  59     // Is it the first application record to write?
  60     boolean                     isFirstAppOutputRecord = true;
  61 
  62     // packet size
  63     int                         packetSize;
  64 
  65     // fragment size
  66     int                         fragmentSize;
  67 
  68     // closed or not?
  69     volatile boolean            isClosed;
  70 
  71     /*
  72      * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
  73      * This is taken from the SSL V3 specification, Appendix E.
  74      */
  75     private static final int[] V3toV2CipherMap1 =
  76         {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
  77     private static final int[] V3toV2CipherMap3 =
  78         {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
  79     private static final byte[] HANDSHAKE_MESSAGE_KEY_UPDATE =
  80         {SSLHandshake.KEY_UPDATE.id, 0x00, 0x00, 0x01, 0x00};
  81 
  82     OutputRecord(HandshakeHash handshakeHash, SSLWriteCipher writeCipher) {
  83         this.writeCipher = writeCipher;
  84         this.firstMessage = true;
  85         this.fragmentSize = Record.maxDataSize;
  86 
  87         this.handshakeHash = handshakeHash;
  88 
  89         // Please set packetSize and protocolVersion in the implementation.
  90     }
  91 
  92     synchronized void setVersion(ProtocolVersion protocolVersion) {
  93         this.protocolVersion = protocolVersion;
  94     }
  95 
  96     /*
  97      * Updates helloVersion of this record.
  98      */
  99     synchronized void setHelloVersion(ProtocolVersion helloVersion) {
 100         this.helloVersion = helloVersion;
 101     }
 102 
 103     /*
 104      * Return true iff the record is empty -- to avoid doing the work
 105      * of sending empty records over the network.
 106      */
 107     boolean isEmpty() {
 108         return false;
 109     }
 110 
 111     synchronized boolean seqNumIsHuge() {
 112         return (writeCipher.authenticator != null) &&
 113                         writeCipher.authenticator.seqNumIsHuge();
 114     }
 115 
 116     // SSLEngine and SSLSocket
 117     abstract void encodeAlert(byte level, byte description) throws IOException;
 118 
 119     // SSLEngine and SSLSocket
 120     abstract void encodeHandshake(byte[] buffer,
 121             int offset, int length) throws IOException;
 122 
 123     // SSLEngine and SSLSocket
 124     abstract void encodeChangeCipherSpec() throws IOException;
 125 
 126     // apply to SSLEngine only
 127     Ciphertext encode(
 128         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 129         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
 130 
 131         throw new UnsupportedOperationException();
 132     }
 133 
 134     // apply to SSLEngine only
 135     void encodeV2NoCipher() throws IOException {
 136         throw new UnsupportedOperationException();
 137     }
 138 
 139     // apply to SSLSocket only
 140     void deliver(
 141             byte[] source, int offset, int length) throws IOException {
 142         throw new UnsupportedOperationException();
 143     }
 144 
 145     // apply to SSLSocket only
 146     void setDeliverStream(OutputStream outputStream) {
 147         throw new UnsupportedOperationException();
 148     }
 149 
 150     // Change write ciphers, may use change_cipher_spec record.
 151     synchronized void changeWriteCiphers(SSLWriteCipher writeCipher,
 152             boolean useChangeCipherSpec) throws IOException {
 153         if (isClosed()) {
 154             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 155                 SSLLogger.warning("outbound has closed, ignore outbound " +
 156                     "change_cipher_spec message");
 157             }
 158             return;
 159         }
 160 
 161         if (useChangeCipherSpec) {
 162             encodeChangeCipherSpec();
 163         }
 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.writeCipher = writeCipher;
 176         this.isFirstAppOutputRecord = true;
 177     }
 178 
 179     // Change write ciphers using key_update handshake message.
 180     synchronized void changeWriteCiphers(SSLWriteCipher writeCipher,
 181             byte keyUpdateRequest) throws IOException {
 182         if (isClosed()) {
 183             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 184                 SSLLogger.warning("outbound has closed, ignore outbound " +
 185                     "key_update handshake message");
 186             }
 187             return;
 188         }
 189 
 190         // encode the handshake message, KeyUpdate
 191         byte[] hm = HANDSHAKE_MESSAGE_KEY_UPDATE.clone();
 192         hm[hm.length - 1] = keyUpdateRequest;
 193         encodeHandshake(hm, 0, hm.length);
 194         flush();
 195 
 196         // Dispose of any intermediate state in the underlying cipher.
 197         writeCipher.dispose();
 198 
 199         this.writeCipher = writeCipher;
 200         this.isFirstAppOutputRecord = true;
 201     }
 202 
 203     synchronized void changePacketSize(int packetSize) {
 204         this.packetSize = packetSize;
 205     }
 206 
 207     synchronized void changeFragmentSize(int fragmentSize) {
 208         this.fragmentSize = fragmentSize;
 209     }
 210 
 211     synchronized int getMaxPacketSize() {
 212         return packetSize;
 213     }
 214 
 215     // apply to DTLS SSLEngine
 216     void initHandshaker() {
 217         // blank
 218     }
 219 
 220     // apply to DTLS SSLEngine
 221     void finishHandshake() {
 222         // blank
 223     }
 224 
 225     // apply to DTLS SSLEngine
 226     void launchRetransmission() {
 227         // blank
 228     }
 229 
 230     @Override
 231     public synchronized void close() throws IOException {
 232         if (isClosed) {
 233             return;
 234         }
 235 
 236         isClosed = true;
 237         writeCipher.dispose();
 238     }
 239 
 240     boolean isClosed() {
 241         return isClosed;
 242     }
 243 
 244     //
 245     // shared helpers
 246     //
 247 
 248     // Encrypt a fragment and wrap up a record.
 249     //
 250     // To be consistent with the spec of SSLEngine.wrap() methods, the
 251     // destination ByteBuffer's position is updated to reflect the amount
 252     // of data produced.  The limit remains the same.
 253     static long encrypt(
 254             SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
 255             int headerOffset, int dstLim, int headerSize,
 256             ProtocolVersion protocolVersion) {
 257         boolean isDTLS = protocolVersion.isDTLS;
 258         if (isDTLS) {
 259             if (protocolVersion.useTLS13PlusSpec()) {
 260                 return d13Encrypt(encCipher,
 261                         contentType, destination, headerOffset,
 262                         dstLim, headerSize, protocolVersion);
 263             } else {
 264                 return d10Encrypt(encCipher,
 265                         contentType, destination, headerOffset,
 266                         dstLim, headerSize, protocolVersion);
 267             }
 268         } else {
 269             if (protocolVersion.useTLS13PlusSpec()) {
 270                 return t13Encrypt(encCipher,
 271                         contentType, destination, headerOffset,
 272                         dstLim, headerSize, protocolVersion);
 273             } else {
 274                 return t10Encrypt(encCipher,
 275                         contentType, destination, headerOffset,
 276                         dstLim, headerSize, protocolVersion);
 277             }
 278         }
 279     }
 280 
 281     private static long d13Encrypt(
 282             SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
 283             int headerOffset, int dstLim, int headerSize,
 284             ProtocolVersion protocolVersion) {
 285         throw new UnsupportedOperationException("Not supported yet.");
 286     }
 287 
 288     private static long d10Encrypt(
 289             SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
 290             int headerOffset, int dstLim, int headerSize,
 291             ProtocolVersion protocolVersion) {
 292         byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
 293         encCipher.encrypt(contentType, destination);
 294 
 295         // Finish out the record header.
 296         int fragLen = destination.limit() - headerOffset - headerSize;
 297 
 298         destination.put(headerOffset, contentType);         // content type
 299         destination.put(headerOffset + 1, protocolVersion.major);
 300         destination.put(headerOffset + 2, protocolVersion.minor);
 301 
 302         // epoch and sequence_number
 303         destination.put(headerOffset + 3, sequenceNumber[0]);
 304         destination.put(headerOffset + 4, sequenceNumber[1]);
 305         destination.put(headerOffset + 5, sequenceNumber[2]);
 306         destination.put(headerOffset + 6, sequenceNumber[3]);
 307         destination.put(headerOffset + 7, sequenceNumber[4]);
 308         destination.put(headerOffset + 8, sequenceNumber[5]);
 309         destination.put(headerOffset + 9, sequenceNumber[6]);
 310         destination.put(headerOffset + 10, sequenceNumber[7]);
 311 
 312         // fragment length
 313         destination.put(headerOffset + 11, (byte)(fragLen >> 8));
 314         destination.put(headerOffset + 12, (byte)fragLen);
 315 
 316         // Update destination position to reflect the amount of data produced.
 317         destination.position(destination.limit());
 318 
 319         return Authenticator.toLong(sequenceNumber);
 320     }
 321 
 322     private static long t13Encrypt(
 323             SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
 324             int headerOffset, int dstLim, int headerSize,
 325             ProtocolVersion protocolVersion) {
 326         if (!encCipher.isNullCipher()) {
 327             // inner plaintext, using zero length padding.
 328             int endOfPt = destination.limit();
 329             destination.limit(endOfPt + 1);
 330             destination.put(endOfPt, contentType);
 331         }
 332 
 333         // use the right TLSCiphertext.opaque_type and legacy_record_version
 334         ProtocolVersion pv = protocolVersion;
 335         if (!encCipher.isNullCipher()) {
 336             pv = ProtocolVersion.TLS12;
 337             contentType = ContentType.APPLICATION_DATA.id;
 338         } else if (protocolVersion.useTLS13PlusSpec()) {
 339             pv = ProtocolVersion.TLS12;
 340         }
 341 
 342         byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
 343         encCipher.encrypt(contentType, destination);
 344 
 345         // Finish out the record header.
 346         int fragLen = destination.limit() - headerOffset - headerSize;
 347         destination.put(headerOffset, contentType);
 348         destination.put(headerOffset + 1, pv.major);
 349         destination.put(headerOffset + 2, pv.minor);
 350 
 351         // fragment length
 352         destination.put(headerOffset + 3, (byte)(fragLen >> 8));
 353         destination.put(headerOffset + 4, (byte)fragLen);
 354 
 355         // Update destination position to reflect the amount of data produced.
 356         destination.position(destination.limit());
 357 
 358         return Authenticator.toLong(sequenceNumber);
 359     }
 360 
 361     private static long t10Encrypt(
 362             SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
 363             int headerOffset, int dstLim, int headerSize,
 364             ProtocolVersion protocolVersion) {
 365         byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
 366         encCipher.encrypt(contentType, destination);
 367 
 368         // Finish out the record header.
 369         int fragLen = destination.limit() - headerOffset - headerSize;
 370 
 371         destination.put(headerOffset, contentType);         // content type
 372         destination.put(headerOffset + 1, protocolVersion.major);
 373         destination.put(headerOffset + 2, protocolVersion.minor);
 374 
 375         // fragment length
 376         destination.put(headerOffset + 3, (byte)(fragLen >> 8));
 377         destination.put(headerOffset + 4, (byte)fragLen);
 378 
 379         // Update destination position to reflect the amount of data produced.
 380         destination.position(destination.limit());
 381 
 382         return Authenticator.toLong(sequenceNumber);
 383     }
 384 
 385     // Encrypt a fragment and wrap up a record.
 386     //
 387     // Uses the internal expandable buf variable and the current
 388     // protocolVersion variable.
 389     long encrypt(
 390             SSLWriteCipher encCipher, byte contentType, int headerSize) {
 391         if (protocolVersion.useTLS13PlusSpec()) {
 392             return t13Encrypt(encCipher, contentType, headerSize);
 393         } else {
 394             return t10Encrypt(encCipher, contentType, headerSize);
 395         }
 396     }
 397 
 398     private static final class T13PaddingHolder {
 399         private static final byte[] zeros = new byte[16];
 400     }
 401 
 402     private long t13Encrypt(
 403             SSLWriteCipher encCipher, byte contentType, int headerSize) {
 404         if (!encCipher.isNullCipher()) {
 405             // inner plaintext
 406             write(contentType);
 407             write(T13PaddingHolder.zeros, 0, T13PaddingHolder.zeros.length);
 408         }
 409 
 410         byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
 411         int position = headerSize;
 412         int contentLen = count - position;
 413 
 414         // ensure the capacity
 415         int requiredPacketSize =
 416                 encCipher.calculatePacketSize(contentLen, headerSize);
 417         if (requiredPacketSize > buf.length) {
 418             byte[] newBuf = new byte[requiredPacketSize];
 419             System.arraycopy(buf, 0, newBuf, 0, count);
 420             buf = newBuf;
 421         }
 422 
 423         // use the right TLSCiphertext.opaque_type and legacy_record_version
 424         ProtocolVersion pv = protocolVersion;
 425         if (!encCipher.isNullCipher()) {
 426             pv = ProtocolVersion.TLS12;
 427             contentType = ContentType.APPLICATION_DATA.id;
 428         } else {
 429             pv = ProtocolVersion.TLS12;
 430         }
 431 
 432         ByteBuffer destination = ByteBuffer.wrap(buf, position, contentLen);
 433         count = headerSize + encCipher.encrypt(contentType, destination);
 434 
 435         // Fill out the header, write it and the message.
 436         int fragLen = count - headerSize;
 437 
 438         buf[0] = contentType;
 439         buf[1] = pv.major;
 440         buf[2] = pv.minor;
 441         buf[3] = (byte)((fragLen >> 8) & 0xFF);
 442         buf[4] = (byte)(fragLen & 0xFF);
 443 
 444         return Authenticator.toLong(sequenceNumber);
 445     }
 446 
 447     private long t10Encrypt(
 448             SSLWriteCipher encCipher, byte contentType, int headerSize) {
 449         byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
 450         int position = headerSize + writeCipher.getExplicitNonceSize();
 451         int contentLen = count - position;
 452 
 453         // ensure the capacity
 454         int requiredPacketSize =
 455                 encCipher.calculatePacketSize(contentLen, headerSize);
 456         if (requiredPacketSize > buf.length) {
 457             byte[] newBuf = new byte[requiredPacketSize];
 458             System.arraycopy(buf, 0, newBuf, 0, count);
 459             buf = newBuf;
 460         }
 461         ByteBuffer destination = ByteBuffer.wrap(buf, position, contentLen);
 462         count = headerSize + encCipher.encrypt(contentType, destination);
 463 
 464         // Fill out the header, write it and the message.
 465         int fragLen = count - headerSize;
 466         buf[0] = contentType;
 467         buf[1] = protocolVersion.major;
 468         buf[2] = protocolVersion.minor;
 469         buf[3] = (byte)((fragLen >> 8) & 0xFF);
 470         buf[4] = (byte)(fragLen & 0xFF);
 471 
 472         return Authenticator.toLong(sequenceNumber);
 473     }
 474 
 475     static ByteBuffer encodeV2ClientHello(
 476             byte[] fragment, int offset, int length) throws IOException {
 477         int v3SessIdLenOffset = offset + 34;      //  2: client_version
 478                                                   // 32: random
 479 
 480         int v3SessIdLen = fragment[v3SessIdLenOffset];
 481         int v3CSLenOffset = v3SessIdLenOffset + 1 + v3SessIdLen;
 482         int v3CSLen = ((fragment[v3CSLenOffset] & 0xff) << 8) +
 483                        (fragment[v3CSLenOffset + 1] & 0xff);
 484         int cipherSpecs = v3CSLen / 2;        // 2: cipher spec size
 485 
 486         // Estimate the max V2ClientHello message length
 487         //
 488         // 11: header size
 489         // (cipherSpecs * 6): cipher_specs
 490         //    6: one cipher suite may need 6 bytes, see V3toV2CipherSuite.
 491         // 3: placeholder for the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
 492         //    signaling cipher suite
 493         // 32: challenge size
 494         int v2MaxMsgLen = 11 + (cipherSpecs * 6) + 3 + 32;
 495 
 496         // Create a ByteBuffer backed by an accessible byte array.
 497         byte[] dstBytes = new byte[v2MaxMsgLen];
 498         ByteBuffer dstBuf = ByteBuffer.wrap(dstBytes);
 499 
 500         /*
 501          * Copy over the cipher specs. We don't care about actually
 502          * translating them for use with an actual V2 server since
 503          * we only talk V3.  Therefore, just copy over the V3 cipher
 504          * spec values with a leading 0.
 505          */
 506         int v3CSOffset = v3CSLenOffset + 2;   // skip length field
 507         int v2CSLen = 0;
 508 
 509         dstBuf.position(11);
 510         boolean containsRenegoInfoSCSV = false;
 511         for (int i = 0; i < cipherSpecs; i++) {
 512             byte byte1, byte2;
 513 
 514             byte1 = fragment[v3CSOffset++];
 515             byte2 = fragment[v3CSOffset++];
 516             v2CSLen += V3toV2CipherSuite(dstBuf, byte1, byte2);
 517             if (!containsRenegoInfoSCSV &&
 518                     byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
 519                 containsRenegoInfoSCSV = true;
 520             }
 521         }
 522 
 523         if (!containsRenegoInfoSCSV) {
 524             v2CSLen += V3toV2CipherSuite(dstBuf, (byte)0x00, (byte)0xFF);
 525         }
 526 
 527         /*
 528          * Copy in the nonce.
 529          */
 530         dstBuf.put(fragment, (offset + 2), 32);
 531 
 532         /*
 533          * Build the first part of the V3 record header from the V2 one
 534          * that's now buffered up.  (Lengths are fixed up later).
 535          */
 536         int msgLen = dstBuf.position() - 2;   // Exclude the legth field itself
 537         dstBuf.position(0);
 538         dstBuf.put((byte)(0x80 | ((msgLen >>> 8) & 0xFF)));  // pos: 0
 539         dstBuf.put((byte)(msgLen & 0xFF));                   // pos: 1
 540         dstBuf.put(SSLHandshake.CLIENT_HELLO.id);            // pos: 2
 541         dstBuf.put(fragment[offset]);         // major version, pos: 3
 542         dstBuf.put(fragment[offset + 1]);     // minor version, pos: 4
 543         dstBuf.put((byte)(v2CSLen >>> 8));                   // pos: 5
 544         dstBuf.put((byte)(v2CSLen & 0xFF));                  // pos: 6
 545         dstBuf.put((byte)0x00);           // session_id_length, pos: 7
 546         dstBuf.put((byte)0x00);                              // pos: 8
 547         dstBuf.put((byte)0x00);           // challenge_length,  pos: 9
 548         dstBuf.put((byte)32);                                // pos: 10
 549 
 550         dstBuf.position(0);
 551         dstBuf.limit(msgLen + 2);
 552 
 553         return dstBuf;
 554     }
 555 
 556     private static int V3toV2CipherSuite(ByteBuffer dstBuf,
 557             byte byte1, byte byte2) {
 558         dstBuf.put((byte)0);
 559         dstBuf.put(byte1);
 560         dstBuf.put(byte2);
 561 
 562         if (((byte2 & 0xff) > 0xA) || (V3toV2CipherMap1[byte2] == -1)) {
 563             return 3;
 564         }
 565 
 566         dstBuf.put((byte)V3toV2CipherMap1[byte2]);
 567         dstBuf.put((byte)0);
 568         dstBuf.put((byte)V3toV2CipherMap3[byte2]);
 569 
 570         return 6;
 571     }
 572 }