< prev index next >

src/java.base/share/classes/sun/security/ssl/OutputRecord.java

Print this page


   1 /*
   2  * Copyright (c) 1996, 2019, 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 java.util.concurrent.locks.ReentrantLock;
  34 import sun.security.ssl.SSLCipher.SSLWriteCipher;
  35 
  36 /**
  37  * {@code OutputRecord} takes care of the management of SSL/(D)TLS
  38  * output records, including buffering, encryption, handshake
  39  * messages marshal, etc.
  40  *
  41  * @author David Brownell
  42  */
  43 abstract class OutputRecord
  44         extends ByteArrayOutputStream implements Record, Closeable {
  45     SSLWriteCipher              writeCipher;
  46     // Needed for KeyUpdate, used after Handshake.Finished
  47     TransportContext            tc;
  48 
  49     final HandshakeHash         handshakeHash;
  50     boolean                     firstMessage;
  51 
  52     // current protocol version, sent as record version
  53     ProtocolVersion             protocolVersion;
  54 
  55     // version for the ClientHello message. Only relevant if this is a
  56     // client handshake record. If set to ProtocolVersion.SSL20Hello,
  57     // the V3 client hello is converted to V2 format.
  58     ProtocolVersion             helloVersion;
  59 
  60     // Is it the first application record to write?
  61     boolean                     isFirstAppOutputRecord = true;
  62 
  63     // packet size
  64     int                         packetSize;
  65 
  66     // fragment size
  67     private int                 fragmentSize;
  68 
  69     // closed or not?
  70     volatile boolean            isClosed;
  71 
  72     final ReentrantLock recordLock = new ReentrantLock();
  73 
  74     /*
  75      * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
  76      * This is taken from the SSL V3 specification, Appendix E.
  77      */
  78     private static final int[] V3toV2CipherMap1 =
  79         {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
  80     private static final int[] V3toV2CipherMap3 =
  81         {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
  82     private static final byte[] HANDSHAKE_MESSAGE_KEY_UPDATE =
  83         {SSLHandshake.KEY_UPDATE.id, 0x00, 0x00, 0x01, 0x00};
  84 
  85     OutputRecord(HandshakeHash handshakeHash, SSLWriteCipher writeCipher) {
  86         this.writeCipher = writeCipher;
  87         this.firstMessage = true;
  88         this.fragmentSize = Record.maxDataSize;
  89 
  90         this.handshakeHash = handshakeHash;
  91 
  92         // Please set packetSize and protocolVersion in the implementation.
  93     }
  94 
  95     void setVersion(ProtocolVersion protocolVersion) {
  96         recordLock.lock();
  97         try {
  98             this.protocolVersion = protocolVersion;
  99         } finally {
 100             recordLock.unlock();
 101         }
 102     }
 103 
 104     /*
 105      * Updates helloVersion of this record.
 106      */
 107     void setHelloVersion(ProtocolVersion helloVersion) {
 108         recordLock.lock();
 109         try {
 110             this.helloVersion = helloVersion;
 111         } finally {
 112             recordLock.unlock();
 113         }
 114     }
 115 
 116     /*
 117      * Return true iff the record is empty -- to avoid doing the work
 118      * of sending empty records over the network.
 119      */
 120     boolean isEmpty() {
 121         return false;
 122     }
 123 
 124     boolean seqNumIsHuge() {
 125         recordLock.lock();
 126         try {
 127             return (writeCipher.authenticator != null) &&
 128                         writeCipher.authenticator.seqNumIsHuge();
 129         } finally {
 130             recordLock.unlock();
 131         }
 132     }
 133 
 134     // SSLEngine and SSLSocket
 135     abstract void encodeAlert(byte level, byte description) throws IOException;
 136 
 137     // SSLEngine and SSLSocket
 138     abstract void encodeHandshake(byte[] buffer,
 139             int offset, int length) throws IOException;
 140 
 141     // SSLEngine and SSLSocket
 142     abstract void encodeChangeCipherSpec() throws IOException;
 143 
 144     // apply to SSLEngine only
 145     Ciphertext encode(
 146         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 147         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
 148 
 149         throw new UnsupportedOperationException();
 150     }
 151 
 152     // apply to SSLEngine only
 153     void encodeV2NoCipher() throws IOException {
 154         throw new UnsupportedOperationException();
 155     }
 156 
 157     // apply to SSLSocket only
 158     void deliver(
 159             byte[] source, int offset, int length) throws IOException {
 160         throw new UnsupportedOperationException();
 161     }
 162 
 163     // apply to SSLSocket only
 164     void setDeliverStream(OutputStream outputStream) {
 165         throw new UnsupportedOperationException();
 166     }
 167 
 168     // Change write ciphers, may use change_cipher_spec record.
 169     void changeWriteCiphers(SSLWriteCipher writeCipher,
 170             boolean useChangeCipherSpec) throws IOException {
 171         recordLock.lock();
 172         try {
 173             if (isClosed()) {
 174                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 175                     SSLLogger.warning("outbound has closed, ignore outbound " +
 176                         "change_cipher_spec message");
 177                 }
 178                 return;
 179             }
 180 
 181             if (useChangeCipherSpec) {
 182                 encodeChangeCipherSpec();
 183             }


 184 
 185             /*
 186              * Dispose of any intermediate state in the underlying cipher.
 187              * For PKCS11 ciphers, this will release any attached sessions,
 188              * and thus make finalization faster.
 189              *
 190              * Since MAC's doFinal() is called for every SSL/TLS packet, it's
 191              * not necessary to do the same with MAC's.
 192              */
 193             writeCipher.dispose();
 194 
 195             this.writeCipher = writeCipher;
 196             this.isFirstAppOutputRecord = true;
 197         } finally {
 198             recordLock.unlock();
 199         }













 200     }
 201 
 202     // Change write ciphers using key_update handshake message.
 203     void changeWriteCiphers(SSLWriteCipher writeCipher,
 204             byte keyUpdateRequest) throws IOException {
 205         recordLock.lock();
 206         try {
 207             if (isClosed()) {
 208                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 209                     SSLLogger.warning("outbound has closed, ignore outbound " +
 210                         "key_update handshake message");
 211                 }
 212                 return;
 213             }
 214 
 215             // encode the handshake message, KeyUpdate
 216             byte[] hm = HANDSHAKE_MESSAGE_KEY_UPDATE.clone();
 217             hm[hm.length - 1] = keyUpdateRequest;
 218             encodeHandshake(hm, 0, hm.length);
 219             flush();
 220 
 221             // Dispose of any intermediate state in the underlying cipher.
 222             writeCipher.dispose();
 223 
 224             this.writeCipher = writeCipher;
 225             this.isFirstAppOutputRecord = true;
 226         } finally {
 227             recordLock.unlock();
 228         }












 229     }
 230 
 231     void changePacketSize(int packetSize) {
 232         recordLock.lock();
 233         try {
 234             this.packetSize = packetSize;
 235         } finally {
 236             recordLock.unlock();
 237         }
 238     }
 239 
 240     void changeFragmentSize(int fragmentSize) {
 241         recordLock.lock();
 242         try {
 243             this.fragmentSize = fragmentSize;
 244         } finally {
 245             recordLock.unlock();
 246         }
 247     }
 248 
 249     int getMaxPacketSize() {
 250         recordLock.lock();
 251         try {
 252             return packetSize;
 253         } finally {
 254             recordLock.unlock();
 255         }
 256     }
 257 
 258     // apply to DTLS SSLEngine
 259     void initHandshaker() {
 260         // blank
 261     }
 262 
 263     // apply to DTLS SSLEngine
 264     void finishHandshake() {
 265         // blank
 266     }
 267 
 268     // apply to DTLS SSLEngine
 269     void launchRetransmission() {
 270         // blank
 271     }
 272 
 273     @Override
 274     public void close() throws IOException {
 275         recordLock.lock();
 276         try {
 277             if (isClosed) {
 278                 return;
 279             }
 280 
 281             isClosed = true;
 282             writeCipher.dispose();
 283         } finally {
 284             recordLock.unlock();
 285         }



 286     }
 287 
 288     boolean isClosed() {
 289         return isClosed;
 290     }
 291 
 292     //
 293     // shared helpers
 294     //
 295 
 296     private static final class T13PaddingHolder {
 297         private static final byte[] zeros = new byte[16];
 298     }
 299 
 300     int calculateFragmentSize(int fragmentLimit) {
 301         if (fragmentSize > 0) {
 302             fragmentLimit = Math.min(fragmentLimit, fragmentSize);
 303         }
 304 
 305         if (protocolVersion.useTLS13PlusSpec()) {
 306             // No negative integer checking as the fragment capacity should
 307             // have been ensured.
 308             return fragmentLimit -  T13PaddingHolder.zeros.length - 1;
 309         }
 310 
 311         return fragmentLimit;
 312     }
 313 
 314     // Encrypt a fragment and wrap up a record.
 315     //
 316     // To be consistent with the spec of SSLEngine.wrap() methods, the
 317     // destination ByteBuffer's position is updated to reflect the amount
 318     // of data produced.  The limit remains the same.
 319     static long encrypt(
 320             SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
 321             int headerOffset, int dstLim, int headerSize,
 322             ProtocolVersion protocolVersion) {
 323         boolean isDTLS = protocolVersion.isDTLS;
 324         if (isDTLS) {
 325             if (protocolVersion.useTLS13PlusSpec()) {
 326                 return d13Encrypt(encCipher,
 327                         contentType, destination, headerOffset,
 328                         dstLim, headerSize, protocolVersion);
 329             } else {
 330                 return d10Encrypt(encCipher,
 331                         contentType, destination, headerOffset,
 332                         dstLim, headerSize, protocolVersion);
 333             }


 375         destination.put(headerOffset + 9, sequenceNumber[6]);
 376         destination.put(headerOffset + 10, sequenceNumber[7]);
 377 
 378         // fragment length
 379         destination.put(headerOffset + 11, (byte)(fragLen >> 8));
 380         destination.put(headerOffset + 12, (byte)fragLen);
 381 
 382         // Update destination position to reflect the amount of data produced.
 383         destination.position(destination.limit());
 384 
 385         return Authenticator.toLong(sequenceNumber);
 386     }
 387 
 388     private static long t13Encrypt(
 389             SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
 390             int headerOffset, int dstLim, int headerSize,
 391             ProtocolVersion protocolVersion) {
 392         if (!encCipher.isNullCipher()) {
 393             // inner plaintext, using zero length padding.
 394             int endOfPt = destination.limit();
 395             int startOfPt = destination.position();
 396             destination.position(endOfPt);
 397             destination.limit(endOfPt + 1 + T13PaddingHolder.zeros.length);
 398             destination.put(contentType);
 399             destination.put(T13PaddingHolder.zeros);
 400             destination.position(startOfPt);
 401         }
 402 
 403         // use the right TLSCiphertext.opaque_type and legacy_record_version
 404         ProtocolVersion pv = protocolVersion;
 405         if (!encCipher.isNullCipher()) {
 406             pv = ProtocolVersion.TLS12;
 407             contentType = ContentType.APPLICATION_DATA.id;
 408         } else if (protocolVersion.useTLS13PlusSpec()) {
 409             pv = ProtocolVersion.TLS12;
 410         }
 411 
 412         byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
 413         encCipher.encrypt(contentType, destination);
 414 
 415         // Finish out the record header.
 416         int fragLen = destination.limit() - headerOffset - headerSize;
 417         destination.put(headerOffset, contentType);
 418         destination.put(headerOffset + 1, pv.major);
 419         destination.put(headerOffset + 2, pv.minor);
 420 


 446         destination.put(headerOffset + 3, (byte)(fragLen >> 8));
 447         destination.put(headerOffset + 4, (byte)fragLen);
 448 
 449         // Update destination position to reflect the amount of data produced.
 450         destination.position(destination.limit());
 451 
 452         return Authenticator.toLong(sequenceNumber);
 453     }
 454 
 455     // Encrypt a fragment and wrap up a record.
 456     //
 457     // Uses the internal expandable buf variable and the current
 458     // protocolVersion variable.
 459     long encrypt(
 460             SSLWriteCipher encCipher, byte contentType, int headerSize) {
 461         if (protocolVersion.useTLS13PlusSpec()) {
 462             return t13Encrypt(encCipher, contentType, headerSize);
 463         } else {
 464             return t10Encrypt(encCipher, contentType, headerSize);
 465         }




 466     }
 467 
 468     private long t13Encrypt(
 469             SSLWriteCipher encCipher, byte contentType, int headerSize) {
 470         if (!encCipher.isNullCipher()) {
 471             // inner plaintext
 472             write(contentType);
 473             write(T13PaddingHolder.zeros, 0, T13PaddingHolder.zeros.length);
 474         }
 475 
 476         byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
 477         int position = headerSize;
 478         int contentLen = count - position;
 479 
 480         // ensure the capacity
 481         int requiredPacketSize =
 482                 encCipher.calculatePacketSize(contentLen, headerSize);
 483         if (requiredPacketSize > buf.length) {
 484             byte[] newBuf = new byte[requiredPacketSize];
 485             System.arraycopy(buf, 0, newBuf, 0, count);


   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             }


 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 


 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);


< prev index next >