src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56686 07dc566630ee
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.io.*;
    28 import java.io.*;
    29 import java.nio.*;
    29 import java.nio.*;
    30 import java.util.*;
    30 import java.util.*;
    31 
       
    32 import javax.crypto.BadPaddingException;
       
    33 
       
    34 import javax.net.ssl.*;
    31 import javax.net.ssl.*;
    35 
    32 import sun.security.ssl.SSLCipher.SSLWriteCipher;
    36 import sun.security.util.HexDumpEncoder;
       
    37 import static sun.security.ssl.Ciphertext.RecordType;
       
    38 
    33 
    39 /**
    34 /**
    40  * DTLS {@code OutputRecord} implementation for {@code SSLEngine}.
    35  * DTLS {@code OutputRecord} implementation for {@code SSLEngine}.
    41  */
    36  */
    42 final class DTLSOutputRecord extends OutputRecord implements DTLSRecord {
    37 final class DTLSOutputRecord extends OutputRecord implements DTLSRecord {
    45 
    40 
    46     int                 writeEpoch;
    41     int                 writeEpoch;
    47 
    42 
    48     int                 prevWriteEpoch;
    43     int                 prevWriteEpoch;
    49     Authenticator       prevWriteAuthenticator;
    44     Authenticator       prevWriteAuthenticator;
    50     CipherBox           prevWriteCipher;
    45     SSLWriteCipher      prevWriteCipher;
    51 
    46 
    52     private LinkedList<RecordMemo> alertMemos = new LinkedList<>();
    47     private final LinkedList<RecordMemo> alertMemos = new LinkedList<>();
    53 
    48 
    54     DTLSOutputRecord() {
    49     DTLSOutputRecord(HandshakeHash handshakeHash) {
    55         this.writeAuthenticator = new MAC(true);
    50         super(handshakeHash, SSLWriteCipher.nullDTlsWriteCipher());
    56 
    51 
    57         this.writeEpoch = 0;
    52         this.writeEpoch = 0;
    58         this.prevWriteEpoch = 0;
    53         this.prevWriteEpoch = 0;
    59         this.prevWriteCipher = CipherBox.NULL;
    54         this.prevWriteCipher = SSLWriteCipher.nullDTlsWriteCipher();
    60         this.prevWriteAuthenticator = new MAC(true);
       
    61 
    55 
    62         this.packetSize = DTLSRecord.maxRecordSize;
    56         this.packetSize = DTLSRecord.maxRecordSize;
    63         this.protocolVersion = ProtocolVersion.DEFAULT_DTLS;
    57         this.protocolVersion = ProtocolVersion.NONE;
    64     }
    58     }
    65 
    59 
    66     @Override
    60     @Override
    67     void changeWriteCiphers(Authenticator writeAuthenticator,
    61     void initHandshaker() {
    68             CipherBox writeCipher) throws IOException {
    62         // clean up
    69 
    63         fragmenter = null;
    70         encodeChangeCipherSpec();
    64     }
       
    65 
       
    66     @Override
       
    67     void finishHandshake() {
       
    68 //        fragmenter = null;
       
    69     }
       
    70 
       
    71     @Override
       
    72     void changeWriteCiphers(SSLWriteCipher writeCipher,
       
    73             boolean useChangeCipherSpec) throws IOException {
       
    74         if (useChangeCipherSpec) {
       
    75             encodeChangeCipherSpec();
       
    76         }
    71 
    77 
    72         prevWriteCipher.dispose();
    78         prevWriteCipher.dispose();
    73 
    79 
    74         this.prevWriteAuthenticator = this.writeAuthenticator;
       
    75         this.prevWriteCipher = this.writeCipher;
    80         this.prevWriteCipher = this.writeCipher;
    76         this.prevWriteEpoch = this.writeEpoch;
    81         this.prevWriteEpoch = this.writeEpoch;
    77 
    82 
    78         this.writeAuthenticator = writeAuthenticator;
       
    79         this.writeCipher = writeCipher;
    83         this.writeCipher = writeCipher;
    80         this.writeEpoch++;
    84         this.writeEpoch++;
    81 
    85 
    82         this.isFirstAppOutputRecord = true;
    86         this.isFirstAppOutputRecord = true;
    83 
    87 
    84         // set the epoch number
    88         // set the epoch number
    85         this.writeAuthenticator.setEpochNumber(this.writeEpoch);
    89         this.writeCipher.authenticator.setEpochNumber(this.writeEpoch);
    86     }
    90     }
    87 
    91 
    88     @Override
    92     @Override
    89     void encodeAlert(byte level, byte description) throws IOException {
    93     void encodeAlert(byte level, byte description) throws IOException {
    90         RecordMemo memo = new RecordMemo();
    94         RecordMemo memo = new RecordMemo();
    91 
    95 
    92         memo.contentType = Record.ct_alert;
    96         memo.contentType = ContentType.ALERT.id;
    93         memo.majorVersion = protocolVersion.major;
    97         memo.majorVersion = protocolVersion.major;
    94         memo.minorVersion = protocolVersion.minor;
    98         memo.minorVersion = protocolVersion.minor;
    95         memo.encodeEpoch = writeEpoch;
    99         memo.encodeEpoch = writeEpoch;
    96         memo.encodeCipher = writeCipher;
   100         memo.encodeCipher = writeCipher;
    97         memo.encodeAuthenticator = writeAuthenticator;
       
    98 
   101 
    99         memo.fragment = new byte[2];
   102         memo.fragment = new byte[2];
   100         memo.fragment[0] = level;
   103         memo.fragment[0] = level;
   101         memo.fragment[1] = description;
   104         memo.fragment[1] = description;
   102 
   105 
   112     }
   115     }
   113 
   116 
   114     @Override
   117     @Override
   115     void encodeHandshake(byte[] source,
   118     void encodeHandshake(byte[] source,
   116             int offset, int length) throws IOException {
   119             int offset, int length) throws IOException {
   117 
       
   118         if (firstMessage) {
   120         if (firstMessage) {
   119             firstMessage = false;
   121             firstMessage = false;
   120         }
   122         }
   121 
   123 
   122         if (fragmenter == null) {
   124         if (fragmenter == null) {
   125 
   127 
   126         fragmenter.queueUpHandshake(source, offset, length);
   128         fragmenter.queueUpHandshake(source, offset, length);
   127     }
   129     }
   128 
   130 
   129     @Override
   131     @Override
   130     Ciphertext encode(ByteBuffer[] sources, int offset, int length,
   132     Ciphertext encode(
       
   133         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
       
   134         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
       
   135         return encode(srcs, srcsOffset, srcsLength, dsts[0]);
       
   136     }
       
   137 
       
   138     private Ciphertext encode(ByteBuffer[] sources, int offset, int length,
   131             ByteBuffer destination) throws IOException {
   139             ByteBuffer destination) throws IOException {
   132 
   140 
   133         if (writeAuthenticator.seqNumOverflow()) {
   141         if (writeCipher.authenticator.seqNumOverflow()) {
   134             if (debug != null && Debug.isOn("ssl")) {
   142             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
   135                 System.out.println(Thread.currentThread().getName() +
   143                 SSLLogger.fine(
   136                     ", sequence number extremely close to overflow " +
   144                     "sequence number extremely close to overflow " +
   137                     "(2^64-1 packets). Closing connection.");
   145                     "(2^64-1 packets). Closing connection.");
   138             }
   146             }
   139 
   147 
   140             throw new SSLHandshakeException("sequence number overflow");
   148             throw new SSLHandshakeException("sequence number overflow");
   141         }
   149         }
   142 
   150 
       
   151         // Don't process the incoming record until all of the buffered records
       
   152         // get handled.  May need retransmission if no sources specified.
       
   153         if (!isEmpty() || sources == null || sources.length == 0) {
       
   154             Ciphertext ct = acquireCiphertext(destination);
       
   155             if (ct != null) {
       
   156                 return ct;
       
   157             }
       
   158         }
       
   159 
       
   160         if (sources == null || sources.length == 0) {
       
   161             return null;
       
   162         }
       
   163 
       
   164         int srcsRemains = 0;
       
   165         for (int i = offset; i < offset + length; i++) {
       
   166             srcsRemains += sources[i].remaining();
       
   167         }
       
   168 
       
   169         if (srcsRemains == 0) {
       
   170             return null;
       
   171         }
       
   172 
   143         // not apply to handshake message
   173         // not apply to handshake message
   144         int macLen = 0;
       
   145         if (writeAuthenticator instanceof MAC) {
       
   146             macLen = ((MAC)writeAuthenticator).MAClen();
       
   147         }
       
   148 
       
   149         int fragLen;
   174         int fragLen;
   150         if (packetSize > 0) {
   175         if (packetSize > 0) {
   151             fragLen = Math.min(maxRecordSize, packetSize);
   176             fragLen = Math.min(maxRecordSize, packetSize);
   152             fragLen = writeCipher.calculateFragmentSize(
   177             fragLen = writeCipher.calculateFragmentSize(
   153                     fragLen, macLen, headerSize);
   178                     fragLen, headerSize);
   154 
   179 
   155             fragLen = Math.min(fragLen, Record.maxDataSize);
   180             fragLen = Math.min(fragLen, Record.maxDataSize);
   156         } else {
   181         } else {
   157             fragLen = Record.maxDataSize;
   182             fragLen = Record.maxDataSize;
   158         }
   183         }
   181         }
   206         }
   182 
   207 
   183         destination.limit(destination.position());
   208         destination.limit(destination.position());
   184         destination.position(dstContent);
   209         destination.position(dstContent);
   185 
   210 
   186         if ((debug != null) && Debug.isOn("record")) {
   211         if (SSLLogger.isOn && SSLLogger.isOn("record")) {
   187             System.out.println(Thread.currentThread().getName() +
   212             SSLLogger.fine(
   188                     ", WRITE: " + protocolVersion + " " +
   213                     "WRITE: " + protocolVersion + " " +
   189                     Record.contentName(Record.ct_application_data) +
   214                     ContentType.APPLICATION_DATA.name +
   190                     ", length = " + destination.remaining());
   215                     ", length = " + destination.remaining());
   191         }
   216         }
   192 
   217 
   193         // Encrypt the fragment and wrap up a record.
   218         // Encrypt the fragment and wrap up a record.
   194         long recordSN = encrypt(writeAuthenticator, writeCipher,
   219         long recordSN = encrypt(writeCipher,
   195                 Record.ct_application_data, destination,
   220                 ContentType.APPLICATION_DATA.id, destination,
   196                 dstPos, dstLim, headerSize,
   221                 dstPos, dstLim, headerSize,
   197                 protocolVersion, true);
   222                 protocolVersion);
   198 
   223 
   199         if ((debug != null) && Debug.isOn("packet")) {
   224         if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
   200             ByteBuffer temporary = destination.duplicate();
   225             ByteBuffer temporary = destination.duplicate();
   201             temporary.limit(temporary.position());
   226             temporary.limit(temporary.position());
   202             temporary.position(dstPos);
   227             temporary.position(dstPos);
   203             Debug.printHex(
   228             SSLLogger.fine("Raw write", temporary);
   204                     "[Raw write]: length = " + temporary.remaining(),
       
   205                     temporary);
       
   206         }
   229         }
   207 
   230 
   208         // remain the limit unchanged
   231         // remain the limit unchanged
   209         destination.limit(dstLim);
   232         destination.limit(dstLim);
   210 
   233 
   211         return new Ciphertext(RecordType.RECORD_APPLICATION_DATA, recordSN);
   234         return new Ciphertext(ContentType.APPLICATION_DATA.id,
   212     }
   235                 SSLHandshake.NOT_APPLICABLE.id, recordSN);
   213 
   236     }
   214     @Override
   237 
   215     Ciphertext acquireCiphertext(ByteBuffer destination) throws IOException {
   238     private Ciphertext acquireCiphertext(
       
   239             ByteBuffer destination) throws IOException {
   216         if (alertMemos != null && !alertMemos.isEmpty()) {
   240         if (alertMemos != null && !alertMemos.isEmpty()) {
   217             RecordMemo memo = alertMemos.pop();
   241             RecordMemo memo = alertMemos.pop();
   218 
       
   219             int macLen = 0;
       
   220             if (memo.encodeAuthenticator instanceof MAC) {
       
   221                 macLen = ((MAC)memo.encodeAuthenticator).MAClen();
       
   222             }
       
   223 
   242 
   224             int dstPos = destination.position();
   243             int dstPos = destination.position();
   225             int dstLim = destination.limit();
   244             int dstLim = destination.limit();
   226             int dstContent = dstPos + headerSize +
   245             int dstContent = dstPos + headerSize +
   227                                 writeCipher.getExplicitNonceSize();
   246                                 writeCipher.getExplicitNonceSize();
   230             destination.put(memo.fragment);
   249             destination.put(memo.fragment);
   231 
   250 
   232             destination.limit(destination.position());
   251             destination.limit(destination.position());
   233             destination.position(dstContent);
   252             destination.position(dstContent);
   234 
   253 
   235             if ((debug != null) && Debug.isOn("record")) {
   254             if (SSLLogger.isOn && SSLLogger.isOn("record")) {
   236                 System.out.println(Thread.currentThread().getName() +
   255                 SSLLogger.fine(
   237                         ", WRITE: " + protocolVersion + " " +
   256                         "WRITE: " + protocolVersion + " " +
   238                         Record.contentName(Record.ct_alert) +
   257                         ContentType.ALERT.name +
   239                         ", length = " + destination.remaining());
   258                         ", length = " + destination.remaining());
   240             }
   259             }
   241 
   260 
   242             // Encrypt the fragment and wrap up a record.
   261             // Encrypt the fragment and wrap up a record.
   243             long recordSN = encrypt(memo.encodeAuthenticator, memo.encodeCipher,
   262             long recordSN = encrypt(memo.encodeCipher,
   244                     Record.ct_alert, destination, dstPos, dstLim, headerSize,
   263                     ContentType.ALERT.id,
       
   264                     destination, dstPos, dstLim, headerSize,
   245                     ProtocolVersion.valueOf(memo.majorVersion,
   265                     ProtocolVersion.valueOf(memo.majorVersion,
   246                             memo.minorVersion), true);
   266                             memo.minorVersion));
   247 
   267 
   248             if ((debug != null) && Debug.isOn("packet")) {
   268             if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
   249                 ByteBuffer temporary = destination.duplicate();
   269                 ByteBuffer temporary = destination.duplicate();
   250                 temporary.limit(temporary.position());
   270                 temporary.limit(temporary.position());
   251                 temporary.position(dstPos);
   271                 temporary.position(dstPos);
   252                 Debug.printHex(
   272                 SSLLogger.fine("Raw write", temporary);
   253                         "[Raw write]: length = " + temporary.remaining(),
       
   254                         temporary);
       
   255             }
   273             }
   256 
   274 
   257             // remain the limit unchanged
   275             // remain the limit unchanged
   258             destination.limit(dstLim);
   276             destination.limit(dstLim);
   259 
   277 
   260             return new Ciphertext(RecordType.RECORD_ALERT, recordSN);
   278             return new Ciphertext(ContentType.ALERT.id,
       
   279                     SSLHandshake.NOT_APPLICABLE.id, recordSN);
   261         }
   280         }
   262 
   281 
   263         if (fragmenter != null) {
   282         if (fragmenter != null) {
   264             return fragmenter.acquireCiphertext(destination);
   283             return fragmenter.acquireCiphertext(destination);
   265         }
   284         }
   269 
   288 
   270     @Override
   289     @Override
   271     boolean isEmpty() {
   290     boolean isEmpty() {
   272         return ((fragmenter == null) || fragmenter.isEmpty()) &&
   291         return ((fragmenter == null) || fragmenter.isEmpty()) &&
   273                ((alertMemos == null) || alertMemos.isEmpty());
   292                ((alertMemos == null) || alertMemos.isEmpty());
   274     }
       
   275 
       
   276     @Override
       
   277     void initHandshaker() {
       
   278         // clean up
       
   279         fragmenter = null;
       
   280     }
   293     }
   281 
   294 
   282     @Override
   295     @Override
   283     void launchRetransmission() {
   296     void launchRetransmission() {
   284         // Note: Please don't retransmit if there are handshake messages
   297         // Note: Please don't retransmit if there are handshake messages
   293     private static class RecordMemo {
   306     private static class RecordMemo {
   294         byte            contentType;
   307         byte            contentType;
   295         byte            majorVersion;
   308         byte            majorVersion;
   296         byte            minorVersion;
   309         byte            minorVersion;
   297         int             encodeEpoch;
   310         int             encodeEpoch;
   298         CipherBox       encodeCipher;
   311         SSLWriteCipher  encodeCipher;
   299         Authenticator   encodeAuthenticator;
       
   300 
   312 
   301         byte[]          fragment;
   313         byte[]          fragment;
   302     }
   314     }
   303 
   315 
   304     private static class HandshakeMemo extends RecordMemo {
   316     private static class HandshakeMemo extends RecordMemo {
   306         int             messageSequence;
   318         int             messageSequence;
   307         int             acquireOffset;
   319         int             acquireOffset;
   308     }
   320     }
   309 
   321 
   310     private final class DTLSFragmenter {
   322     private final class DTLSFragmenter {
   311         private LinkedList<RecordMemo> handshakeMemos = new LinkedList<>();
   323         private final LinkedList<RecordMemo> handshakeMemos =
       
   324                 new LinkedList<>();
   312         private int acquireIndex = 0;
   325         private int acquireIndex = 0;
   313         private int messageSequence = 0;
   326         private int messageSequence = 0;
   314         private boolean flightIsReady = false;
   327         private boolean flightIsReady = false;
   315 
   328 
   316         // Per section 4.1.1, RFC 6347:
   329         // Per section 4.1.1, RFC 6347:
   334                 flightIsReady = false;
   347                 flightIsReady = false;
   335             }
   348             }
   336 
   349 
   337             RecordMemo memo = new RecordMemo();
   350             RecordMemo memo = new RecordMemo();
   338 
   351 
   339             memo.contentType = Record.ct_change_cipher_spec;
   352             memo.contentType = ContentType.CHANGE_CIPHER_SPEC.id;
   340             memo.majorVersion = protocolVersion.major;
   353             memo.majorVersion = protocolVersion.major;
   341             memo.minorVersion = protocolVersion.minor;
   354             memo.minorVersion = protocolVersion.minor;
   342             memo.encodeEpoch = writeEpoch;
   355             memo.encodeEpoch = writeEpoch;
   343             memo.encodeCipher = writeCipher;
   356             memo.encodeCipher = writeCipher;
   344             memo.encodeAuthenticator = writeAuthenticator;
       
   345 
   357 
   346             memo.fragment = new byte[1];
   358             memo.fragment = new byte[1];
   347             memo.fragment[0] = 1;
   359             memo.fragment[0] = 1;
   348 
   360 
   349             handshakeMemos.add(memo);
   361             handshakeMemos.add(memo);
   359                 flightIsReady = false;
   371                 flightIsReady = false;
   360             }
   372             }
   361 
   373 
   362             HandshakeMemo memo = new HandshakeMemo();
   374             HandshakeMemo memo = new HandshakeMemo();
   363 
   375 
   364             memo.contentType = Record.ct_handshake;
   376             memo.contentType = ContentType.HANDSHAKE.id;
   365             memo.majorVersion = protocolVersion.major;
   377             memo.majorVersion = protocolVersion.major;
   366             memo.minorVersion = protocolVersion.minor;
   378             memo.minorVersion = protocolVersion.minor;
   367             memo.encodeEpoch = writeEpoch;
   379             memo.encodeEpoch = writeEpoch;
   368             memo.encodeCipher = writeCipher;
   380             memo.encodeCipher = writeCipher;
   369             memo.encodeAuthenticator = writeAuthenticator;
       
   370 
   381 
   371             memo.handshakeType = buf[offset];
   382             memo.handshakeType = buf[offset];
   372             memo.messageSequence = messageSequence++;
   383             memo.messageSequence = messageSequence++;
   373             memo.acquireOffset = 0;
   384             memo.acquireOffset = 0;
   374             memo.fragment = new byte[length - 4];       // 4: header size
   385             memo.fragment = new byte[length - 4];       // 4: header size
   377             System.arraycopy(buf, offset + 4, memo.fragment, 0, length - 4);
   388             System.arraycopy(buf, offset + 4, memo.fragment, 0, length - 4);
   378 
   389 
   379             handshakeHashing(memo, memo.fragment);
   390             handshakeHashing(memo, memo.fragment);
   380             handshakeMemos.add(memo);
   391             handshakeMemos.add(memo);
   381 
   392 
   382             if ((memo.handshakeType == HandshakeMessage.ht_client_hello) ||
   393             if ((memo.handshakeType == SSLHandshake.CLIENT_HELLO.id) ||
   383                 (memo.handshakeType == HandshakeMessage.ht_hello_request) ||
   394                 (memo.handshakeType == SSLHandshake.HELLO_REQUEST.id) ||
   384                 (memo.handshakeType ==
   395                 (memo.handshakeType ==
   385                         HandshakeMessage.ht_hello_verify_request) ||
   396                         SSLHandshake.HELLO_VERIFY_REQUEST.id) ||
   386                 (memo.handshakeType == HandshakeMessage.ht_server_hello_done) ||
   397                 (memo.handshakeType == SSLHandshake.SERVER_HELLO_DONE.id) ||
   387                 (memo.handshakeType == HandshakeMessage.ht_finished)) {
   398                 (memo.handshakeType == SSLHandshake.FINISHED.id)) {
   388 
   399 
   389                 flightIsReady = true;
   400                 flightIsReady = true;
   390             }
   401             }
   391         }
   402         }
   392 
   403 
   399                 }
   410                 }
   400             }
   411             }
   401 
   412 
   402             RecordMemo memo = handshakeMemos.get(acquireIndex);
   413             RecordMemo memo = handshakeMemos.get(acquireIndex);
   403             HandshakeMemo hsMemo = null;
   414             HandshakeMemo hsMemo = null;
   404             if (memo.contentType == Record.ct_handshake) {
   415             if (memo.contentType == ContentType.HANDSHAKE.id) {
   405                 hsMemo = (HandshakeMemo)memo;
   416                 hsMemo = (HandshakeMemo)memo;
   406             }
       
   407 
       
   408             int macLen = 0;
       
   409             if (memo.encodeAuthenticator instanceof MAC) {
       
   410                 macLen = ((MAC)memo.encodeAuthenticator).MAClen();
       
   411             }
   417             }
   412 
   418 
   413             // ChangeCipherSpec message is pretty small.  Don't worry about
   419             // ChangeCipherSpec message is pretty small.  Don't worry about
   414             // the fragmentation of ChangeCipherSpec record.
   420             // the fragmentation of ChangeCipherSpec record.
   415             int fragLen;
   421             int fragLen;
   416             if (packetSize > 0) {
   422             if (packetSize > 0) {
   417                 fragLen = Math.min(maxRecordSize, packetSize);
   423                 fragLen = Math.min(maxRecordSize, packetSize);
   418                 fragLen = memo.encodeCipher.calculateFragmentSize(
   424                 fragLen = memo.encodeCipher.calculateFragmentSize(
   419                         fragLen, macLen, 25);   // 25: header size
   425                         fragLen, 25);   // 25: header size
   420                                                 //   13: DTLS record
   426                                                 //   13: DTLS record
   421                                                 //   12: DTLS handshake message
   427                                                 //   12: DTLS handshake message
   422                 fragLen = Math.min(fragLen, Record.maxDataSize);
   428                 fragLen = Math.min(fragLen, Record.maxDataSize);
   423             } else {
   429             } else {
   424                 fragLen = Record.maxDataSize;
   430                 fragLen = Record.maxDataSize;
   457             }
   463             }
   458 
   464 
   459             dstBuf.limit(dstBuf.position());
   465             dstBuf.limit(dstBuf.position());
   460             dstBuf.position(dstContent);
   466             dstBuf.position(dstContent);
   461 
   467 
   462             if ((debug != null) && Debug.isOn("record")) {
   468             if (SSLLogger.isOn && SSLLogger.isOn("record")) {
   463                 System.out.println(Thread.currentThread().getName() +
   469                 SSLLogger.fine(
   464                         ", WRITE: " + protocolVersion + " " +
   470                         "WRITE: " + protocolVersion + " " +
   465                         Record.contentName(memo.contentType) +
   471                         ContentType.nameOf(memo.contentType) +
   466                         ", length = " + dstBuf.remaining());
   472                         ", length = " + dstBuf.remaining());
   467             }
   473             }
   468 
   474 
   469             // Encrypt the fragment and wrap up a record.
   475             // Encrypt the fragment and wrap up a record.
   470             long recordSN = encrypt(memo.encodeAuthenticator, memo.encodeCipher,
   476             long recordSN = encrypt(memo.encodeCipher,
   471                     memo.contentType, dstBuf,
   477                     memo.contentType, dstBuf,
   472                     dstPos, dstLim, headerSize,
   478                     dstPos, dstLim, headerSize,
   473                     ProtocolVersion.valueOf(memo.majorVersion,
   479                     ProtocolVersion.valueOf(memo.majorVersion,
   474                             memo.minorVersion), true);
   480                             memo.minorVersion));
   475 
   481 
   476             if ((debug != null) && Debug.isOn("packet")) {
   482             if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
   477                 ByteBuffer temporary = dstBuf.duplicate();
   483                 ByteBuffer temporary = dstBuf.duplicate();
   478                 temporary.limit(temporary.position());
   484                 temporary.limit(temporary.position());
   479                 temporary.position(dstPos);
   485                 temporary.position(dstPos);
   480                 Debug.printHex(
   486                 SSLLogger.fine(
   481                         "[Raw write]: length = " + temporary.remaining(),
   487                         "Raw write (" + temporary.remaining() + ")", temporary);
   482                         temporary);
       
   483             }
   488             }
   484 
   489 
   485             // remain the limit unchanged
   490             // remain the limit unchanged
   486             dstBuf.limit(dstLim);
   491             dstBuf.limit(dstLim);
   487 
   492 
   490                 hsMemo.acquireOffset += fragLen;
   495                 hsMemo.acquireOffset += fragLen;
   491                 if (hsMemo.acquireOffset == hsMemo.fragment.length) {
   496                 if (hsMemo.acquireOffset == hsMemo.fragment.length) {
   492                     acquireIndex++;
   497                     acquireIndex++;
   493                 }
   498                 }
   494 
   499 
   495                 return new Ciphertext(RecordType.valueOf(
   500                 return new Ciphertext(hsMemo.contentType,
   496                         hsMemo.contentType, hsMemo.handshakeType), recordSN);
   501                         hsMemo.handshakeType, recordSN);
   497             } else {
   502             } else {
   498                 acquireIndex++;
   503                 acquireIndex++;
   499                 return new Ciphertext(
   504                 return new Ciphertext(ContentType.CHANGE_CIPHER_SPEC.id,
   500                         RecordType.RECORD_CHANGE_CIPHER_SPEC, recordSN);
   505                         SSLHandshake.NOT_APPLICABLE.id, recordSN);
   501             }
   506             }
   502         }
   507         }
   503 
   508 
   504         private void handshakeHashing(HandshakeMemo hsFrag, byte[] hsBody) {
   509         private void handshakeHashing(HandshakeMemo hsFrag, byte[] hsBody) {
   505 
   510 
   506             byte hsType = hsFrag.handshakeType;
   511             byte hsType = hsFrag.handshakeType;
   507             if ((hsType == HandshakeMessage.ht_hello_request) ||
   512             if (!handshakeHash.isHashable(hsType)) {
   508                 (hsType == HandshakeMessage.ht_hello_verify_request)) {
       
   509 
       
   510                 // omitted from handshake hash computation
   513                 // omitted from handshake hash computation
   511                 return;
   514                 return;
   512             }
       
   513 
       
   514             if ((hsFrag.messageSequence == 0) &&
       
   515                 (hsType == HandshakeMessage.ht_client_hello)) {
       
   516 
       
   517                 // omit initial ClientHello message
       
   518                 //
       
   519                 //  2: ClientHello.client_version
       
   520                 // 32: ClientHello.random
       
   521                 int sidLen = hsBody[34];
       
   522 
       
   523                 if (sidLen == 0) {      // empty session_id, initial handshake
       
   524                     return;
       
   525                 }
       
   526             }
   515             }
   527 
   516 
   528             // calculate the DTLS header
   517             // calculate the DTLS header
   529             byte[] temporary = new byte[12];    // 12: handshake header size
   518             byte[] temporary = new byte[12];    // 12: handshake header size
   530 
   519 
   548             // Handshake.fragment_length
   537             // Handshake.fragment_length
   549             temporary[9] = temporary[1];
   538             temporary[9] = temporary[1];
   550             temporary[10] = temporary[2];
   539             temporary[10] = temporary[2];
   551             temporary[11] = temporary[3];
   540             temporary[11] = temporary[3];
   552 
   541 
   553             if ((hsType != HandshakeMessage.ht_finished) &&
   542             handshakeHash.deliver(temporary, 0, 12);
   554                 (hsType != HandshakeMessage.ht_certificate_verify)) {
   543             handshakeHash.deliver(hsBody, 0, hsBody.length);
   555 
       
   556                 handshakeHash.update(temporary, 0, 12);
       
   557                 handshakeHash.update(hsBody, 0, hsBody.length);
       
   558             } else {
       
   559                 // Reserve until this handshake message has been processed.
       
   560                 handshakeHash.reserve(temporary, 0, 12);
       
   561                 handshakeHash.reserve(hsBody, 0, hsBody.length);
       
   562             }
       
   563 
       
   564         }
   544         }
   565 
   545 
   566         boolean isEmpty() {
   546         boolean isEmpty() {
   567             if (!flightIsReady || handshakeMemos.isEmpty() ||
   547             if (!flightIsReady || handshakeMemos.isEmpty() ||
   568                     acquireIndex >= handshakeMemos.size()) {
   548                     acquireIndex >= handshakeMemos.size()) {