8167680 DTLS implementation bugs

   1 /*
   2  * Copyright (c) 2003, 2016, 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.*;
  29 import java.nio.*;
  30 import java.util.*;
  31 import java.security.*;
  32 
  33 import javax.crypto.BadPaddingException;
  34 
  35 import javax.net.ssl.*;
  36 import javax.net.ssl.SSLEngineResult.*;
  37 
  38 /**
  39  * Implementation of an non-blocking SSLEngine.
  40  *
  41  * *Currently*, the SSLEngine code exists in parallel with the current
  42  * SSLSocket.  As such, the current implementation is using legacy code
  43  * with many of the same abstractions.  However, it varies in many
  44  * areas, most dramatically in the IO handling.
  45  *
  46  * There are three main I/O threads that can be existing in parallel:
  47  * wrap(), unwrap(), and beginHandshake().  We are encouraging users to
  48  * not call multiple instances of wrap or unwrap, because the data could
  49  * appear to flow out of the SSLEngine in a non-sequential order.  We
  50  * take all steps we can to at least make sure the ordering remains
  51  * consistent, but once the calls returns, anything can happen.  For
  52  * example, thread1 and thread2 both call wrap, thread1 gets the first
  53  * packet, thread2 gets the second packet, but thread2 gets control back
  54  * before thread1, and sends the data.  The receiving side would see an
  55  * out-of-order error.
  56  *
  57  * @author Brad Wetmore
  58  */
  59 public final class SSLEngineImpl extends SSLEngine {
  60 
  61     //
  62     // Fields and global comments
  63     //
  64 
  65     /*
  66      * There's a state machine associated with each connection, which
  67      * among other roles serves to negotiate session changes.
  68      *
  69      * - START with constructor, until the TCP connection's around.
  70      * - HANDSHAKE picks session parameters before allowing traffic.
  71      *          There are many substates due to sequencing requirements
  72      *          for handshake messages.
  73      * - DATA may be transmitted.
  74      * - RENEGOTIATE state allows concurrent data and handshaking
  75      *          traffic ("same" substates as HANDSHAKE), and terminates
  76      *          in selection of new session (and connection) parameters
  77      * - ERROR state immediately precedes abortive disconnect.
  78      * - CLOSED when one side closes down, used to start the shutdown
  79      *          process.  SSL connection objects are not reused.
  80      *
  81      * State affects what SSL record types may legally be sent:
  82      *
  83      * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
  84      * - App Data ... only in DATA and RENEGOTIATE states
  85      * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
  86      *
  87      * Re what may be received:  same as what may be sent, except that
  88      * HandshakeRequest handshaking messages can come from servers even
  89      * in the application data state, to request entry to RENEGOTIATE.
  90      *
  91      * The state machine within HANDSHAKE and RENEGOTIATE states controls
  92      * the pending session, not the connection state, until the change
  93      * cipher spec and "Finished" handshake messages are processed and
  94      * make the "new" session become the current one.
  95      *
  96      * NOTE: details of the SMs always need to be nailed down better.
  97      * The text above illustrates the core ideas.
  98      *
  99      *                +---->-------+------>--------->-------+
 100      *                |            |                        |
 101      *     <-----<    ^            ^  <-----<               |
 102      *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE    |
 103      *                v            v               v        |
 104      *                |            |               |        |
 105      *                +------------+---------------+        |
 106      *                |                                     |
 107      *                v                                     |
 108      *               ERROR>------>----->CLOSED<--------<----+
 109      *
 110      * ALSO, note that the purpose of handshaking (renegotiation is
 111      * included) is to assign a different, and perhaps new, session to
 112      * the connection.  The SSLv3 spec is a bit confusing on that new
 113      * protocol feature.
 114      */
 115     private int                 connectionState;
 116 
 117     private static final int    cs_START = 0;
 118     private static final int    cs_HANDSHAKE = 1;
 119     private static final int    cs_DATA = 2;
 120     private static final int    cs_RENEGOTIATE = 3;
 121     private static final int    cs_ERROR = 4;
 122     private static final int    cs_CLOSED = 6;
 123 
 124     /*
 125      * Once we're in state cs_CLOSED, we can continue to
 126      * wrap/unwrap until we finish sending/receiving the messages
 127      * for close_notify.
 128      */
 129     private boolean             inboundDone = false;
 130     private boolean             outboundDone = false;
 131 
 132     /*
 133      * The authentication context holds all information used to establish
 134      * who this end of the connection is (certificate chains, private keys,
 135      * etc) and who is trusted (e.g. as CAs or websites).
 136      */
 137     private SSLContextImpl      sslContext;
 138 
 139     /*
 140      * This connection is one of (potentially) many associated with
 141      * any given session.  The output of the handshake protocol is a
 142      * new session ... although all the protocol description talks
 143      * about changing the cipher spec (and it does change), in fact
 144      * that's incidental since it's done by changing everything that
 145      * is associated with a session at the same time.  (TLS/IETF may
 146      * change that to add client authentication w/o new key exchg.)
 147      */
 148     private Handshaker                  handshaker;
 149     private SSLSessionImpl              sess;
 150     private volatile SSLSessionImpl     handshakeSession;
 151 
 152     /*
 153      * Flag indicating if the next record we receive MUST be a Finished
 154      * message. Temporarily set during the handshake to ensure that
 155      * a change cipher spec message is followed by a finished message.
 156      */
 157     private boolean             expectingFinished;
 158 
 159 
 160     /*
 161      * If someone tries to closeInbound() (say at End-Of-Stream)
 162      * our engine having received a close_notify, we need to
 163      * notify the app that we may have a truncation attack underway.
 164      */
 165     private boolean             recvCN;
 166 
 167     /*
 168      * For improved diagnostics, we detail connection closure
 169      * If the engine is closed (connectionState >= cs_ERROR),
 170      * closeReason != null indicates if the engine was closed
 171      * because of an error or because or normal shutdown.
 172      */
 173     private SSLException        closeReason;
 174 
 175     /*
 176      * Per-connection private state that doesn't change when the
 177      * session is changed.
 178      */
 179     private ClientAuthType          doClientAuth =
 180                                             ClientAuthType.CLIENT_AUTH_NONE;
 181     private boolean                 enableSessionCreation = true;
 182     InputRecord                     inputRecord;
 183     OutputRecord                    outputRecord;
 184     private AccessControlContext    acc;
 185 
 186     // The cipher suites enabled for use on this connection.
 187     private CipherSuiteList             enabledCipherSuites;
 188 
 189     // the endpoint identification protocol
 190     private String                      identificationProtocol = null;
 191 
 192     // The cryptographic algorithm constraints
 193     private AlgorithmConstraints        algorithmConstraints = null;
 194 
 195     // The server name indication and matchers
 196     List<SNIServerName>         serverNames =
 197                                     Collections.<SNIServerName>emptyList();
 198     Collection<SNIMatcher>      sniMatchers =
 199                                     Collections.<SNIMatcher>emptyList();
 200 
 201     // Configured application protocol values
 202     String[] applicationProtocols = new String[0];
 203 
 204     // Negotiated application protocol value.
 205     //
 206     // The value under negotiation will be obtained from handshaker.
 207     String applicationProtocol = null;
 208 
 209     // Have we been told whether we're client or server?
 210     private boolean                     serverModeSet = false;
 211     private boolean                     roleIsServer;
 212 
 213     /*
 214      * The protocol versions enabled for use on this connection.
 215      *
 216      * Note: we support a pseudo protocol called SSLv2Hello which when
 217      * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
 218      * or TLS (version 3.1, 3.2, etc.) version info.
 219      */
 220     private ProtocolList        enabledProtocols;
 221 
 222     /*
 223      * The SSL version associated with this connection.
 224      */
 225     private ProtocolVersion     protocolVersion;
 226 
 227     /*
 228      * security parameters for secure renegotiation.
 229      */
 230     private boolean             secureRenegotiation;
 231     private byte[]              clientVerifyData;
 232     private byte[]              serverVerifyData;
 233 
 234     /*
 235      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
 236      * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
 237      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
 238      *
 239      * There are several locks here.
 240      *
 241      * The primary lock is the per-instance lock used by
 242      * synchronized(this) and the synchronized methods.  It controls all
 243      * access to things such as the connection state and variables which
 244      * affect handshaking.  If we are inside a synchronized method, we
 245      * can access the state directly, otherwise, we must use the
 246      * synchronized equivalents.
 247      *
 248      * Note that we must never acquire the <code>this</code> lock after
 249      * <code>writeLock</code> or run the risk of deadlock.
 250      *
 251      * Grab some coffee, and be careful with any code changes.
 252      */
 253     private Object              wrapLock;
 254     private Object              unwrapLock;
 255     Object                      writeLock;
 256 
 257     /*
 258      * Whether local cipher suites preference in server side should be
 259      * honored during handshaking?
 260      */
 261     private boolean preferLocalCipherSuites = false;
 262 
 263     /*
 264      * whether DTLS handshake retransmissions should be enabled?
 265      */
 266     private boolean enableRetransmissions = false;
 267 
 268     /*
 269      * The maximum expected network packet size for SSL/TLS/DTLS records.
 270      */
 271     private int maximumPacketSize = 0;
 272 
 273     /*
 274      * Is this an instance for Datagram Transport Layer Security (DTLS)?
 275      */
 276     private final boolean isDTLS;
 277 
 278     /*
 279      * Class and subclass dynamic debugging support
 280      */
 281     private static final Debug debug = Debug.getInstance("ssl");
 282 
 283     //
 284     // Initialization/Constructors
 285     //
 286 
 287     /**
 288      * Constructor for an SSLEngine from SSLContext, without
 289      * host/port hints.  This Engine will not be able to cache
 290      * sessions, but must renegotiate everything by hand.
 291      */
 292     SSLEngineImpl(SSLContextImpl ctx, boolean isDTLS) {
 293         super();
 294         this.isDTLS = isDTLS;
 295         init(ctx, isDTLS);
 296     }
 297 
 298     /**
 299      * Constructor for an SSLEngine from SSLContext.
 300      */
 301     SSLEngineImpl(SSLContextImpl ctx, String host, int port, boolean isDTLS) {
 302         super(host, port);
 303         this.isDTLS = isDTLS;
 304         init(ctx, isDTLS);
 305     }
 306 
 307     /**
 308      * Initializes the Engine
 309      */
 310     private void init(SSLContextImpl ctx, boolean isDTLS) {
 311         if (debug != null && Debug.isOn("ssl")) {
 312             System.out.println("Using SSLEngineImpl.");
 313         }
 314 
 315         sslContext = ctx;
 316         sess = SSLSessionImpl.nullSession;
 317         handshakeSession = null;
 318         protocolVersion = isDTLS ?
 319                 ProtocolVersion.DEFAULT_DTLS : ProtocolVersion.DEFAULT_TLS;
 320 
 321         /*
 322          * State is cs_START until we initialize the handshaker.
 323          *
 324          * Apps using SSLEngine are probably going to be server.
 325          * Somewhat arbitrary choice.
 326          */
 327         roleIsServer = true;
 328         connectionState = cs_START;
 329 
 330         // default server name indication
 331         serverNames =
 332             Utilities.addToSNIServerNameList(serverNames, getPeerHost());
 333 
 334         // default security parameters for secure renegotiation
 335         secureRenegotiation = false;
 336         clientVerifyData = new byte[0];
 337         serverVerifyData = new byte[0];
 338 
 339         enabledCipherSuites =
 340                 sslContext.getDefaultCipherSuiteList(roleIsServer);
 341         enabledProtocols =
 342                 sslContext.getDefaultProtocolList(roleIsServer);
 343 
 344         wrapLock = new Object();
 345         unwrapLock = new Object();
 346         writeLock = new Object();
 347 
 348         /*
 349          * Save the Access Control Context.  This will be used later
 350          * for a couple of things, including providing a context to
 351          * run tasks in, and for determining which credentials
 352          * to use for Subject based (JAAS) decisions
 353          */
 354         acc = AccessController.getContext();
 355 
 356         /*
 357          * All outbound application data goes through this OutputRecord,
 358          * other data goes through their respective records created
 359          * elsewhere.  All inbound data goes through this one
 360          * input record.
 361          */
 362         if (isDTLS) {
 363             enableRetransmissions = true;
 364 
 365             // SSLEngine needs no record local buffer
 366             outputRecord = new DTLSOutputRecord();
 367             inputRecord = new DTLSInputRecord();
 368 
 369         } else {
 370             outputRecord = new SSLEngineOutputRecord();
 371             inputRecord = new SSLEngineInputRecord();
 372         }
 373 
 374         maximumPacketSize = outputRecord.getMaxPacketSize();
 375     }
 376 
 377     /**
 378      * Initialize the handshaker object. This means:
 379      *
 380      *  . if a handshake is already in progress (state is cs_HANDSHAKE
 381      *    or cs_RENEGOTIATE), do nothing and return
 382      *
 383      *  . if the engine is already closed, throw an Exception (internal error)
 384      *
 385      *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
 386      *    object and advance the connection state (to cs_HANDSHAKE or
 387      *    cs_RENEGOTIATE, respectively).
 388      *
 389      * This method is called right after a new engine is created, when
 390      * starting renegotiation, or when changing client/server mode of the
 391      * engine.
 392      */
 393     private void initHandshaker() {
 394         switch (connectionState) {
 395 
 396         //
 397         // Starting a new handshake.
 398         //
 399         case cs_START:
 400         case cs_DATA:
 401             break;
 402 
 403         //
 404         // We're already in the middle of a handshake.
 405         //
 406         case cs_HANDSHAKE:
 407         case cs_RENEGOTIATE:
 408             return;
 409 
 410         //
 411         // Anyone allowed to call this routine is required to
 412         // do so ONLY if the connection state is reasonable...
 413         //
 414         default:
 415             throw new IllegalStateException("Internal error");
 416         }
 417 
 418         // state is either cs_START or cs_DATA
 419         if (connectionState == cs_START) {
 420             connectionState = cs_HANDSHAKE;
 421         } else { // cs_DATA
 422             connectionState = cs_RENEGOTIATE;
 423         }
 424 
 425         if (roleIsServer) {
 426             handshaker = new ServerHandshaker(this, sslContext,
 427                     enabledProtocols, doClientAuth,
 428                     protocolVersion, connectionState == cs_HANDSHAKE,
 429                     secureRenegotiation, clientVerifyData, serverVerifyData,
 430                     isDTLS);
 431             handshaker.setSNIMatchers(sniMatchers);
 432             handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
 433         } else {
 434             handshaker = new ClientHandshaker(this, sslContext,
 435                     enabledProtocols,
 436                     protocolVersion, connectionState == cs_HANDSHAKE,
 437                     secureRenegotiation, clientVerifyData, serverVerifyData,
 438                     isDTLS);
 439             handshaker.setSNIServerNames(serverNames);
 440         }
 441         handshaker.setMaximumPacketSize(maximumPacketSize);
 442         handshaker.setEnabledCipherSuites(enabledCipherSuites);
 443         handshaker.setEnableSessionCreation(enableSessionCreation);
 444         handshaker.setApplicationProtocols(applicationProtocols);
 445 
 446         outputRecord.initHandshaker();
 447     }
 448 
 449     /*
 450      * Report the current status of the Handshaker
 451      */
 452     private HandshakeStatus getHSStatus(HandshakeStatus hss) {
 453 
 454         if (hss != null) {
 455             return hss;
 456         }
 457 
 458         synchronized (this) {
 459             if (!outputRecord.isEmpty()) {
 460                 // If no handshaking, special case to wrap alters.
 461                 return HandshakeStatus.NEED_WRAP;
 462             } else if (handshaker != null) {
 463                 if (handshaker.taskOutstanding()) {
 464                     return HandshakeStatus.NEED_TASK;
 465                 } else if (isDTLS && !inputRecord.isEmpty()) {
 466                     return HandshakeStatus.NEED_UNWRAP_AGAIN;
 467                 } else {
 468                     return HandshakeStatus.NEED_UNWRAP;
 469                 }
 470             } else if (connectionState == cs_CLOSED) {
 471                 /*
 472                  * Special case where we're closing, but
 473                  * still need the close_notify before we
 474                  * can officially be closed.
 475                  *
 476                  * Note isOutboundDone is taken care of by
 477                  * hasOutboundData() above.
 478                  */
 479                 if (!isInboundDone()) {
 480                     return HandshakeStatus.NEED_UNWRAP;
 481                 } // else not handshaking
 482             }
 483 
 484             return HandshakeStatus.NOT_HANDSHAKING;
 485         }
 486     }
 487 
 488     private synchronized void checkTaskThrown() throws SSLException {
 489         if (handshaker != null) {
 490             handshaker.checkThrown();
 491         }
 492     }
 493 
 494     //
 495     // Handshaking and connection state code
 496     //
 497 
 498     /*
 499      * Provides "this" synchronization for connection state.
 500      * Otherwise, you can access it directly.
 501      */
 502     private synchronized int getConnectionState() {
 503         return connectionState;
 504     }
 505 
 506     private synchronized void setConnectionState(int state) {
 507         connectionState = state;
 508     }
 509 
 510     /*
 511      * Get the Access Control Context.
 512      *
 513      * Used for a known context to
 514      * run tasks in, and for determining which credentials
 515      * to use for Subject-based (JAAS) decisions.
 516      */
 517     AccessControlContext getAcc() {
 518         return acc;
 519     }
 520 
 521     /*
 522      * Is a handshake currently underway?
 523      */
 524     @Override
 525     public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
 526         return getHSStatus(null);
 527     }
 528 
 529     /*
 530      * used by Handshaker to change the active write cipher, follows
 531      * the output of the CCS message.
 532      *
 533      * Also synchronized on "this" from readRecord/delegatedTask.
 534      */
 535     void changeWriteCiphers() throws IOException {
 536 
 537         Authenticator writeAuthenticator;
 538         CipherBox writeCipher;
 539         try {
 540             writeCipher = handshaker.newWriteCipher();
 541             writeAuthenticator = handshaker.newWriteAuthenticator();
 542         } catch (GeneralSecurityException e) {
 543             // "can't happen"
 544             throw new SSLException("Algorithm missing:  ", e);
 545         }
 546 
 547         outputRecord.changeWriteCiphers(writeAuthenticator, writeCipher);
 548     }
 549 
 550     /*
 551      * Updates the SSL version associated with this connection.
 552      * Called from Handshaker once it has determined the negotiated version.
 553      */
 554     synchronized void setVersion(ProtocolVersion protocolVersion) {
 555         this.protocolVersion = protocolVersion;
 556         outputRecord.setVersion(protocolVersion);
 557     }
 558 
 559 
 560     /**
 561      * Kickstart the handshake if it is not already in progress.
 562      * This means:
 563      *
 564      *  . if handshaking is already underway, do nothing and return
 565      *
 566      *  . if the engine is not connected or already closed, throw an
 567      *    Exception.
 568      *
 569      *  . otherwise, call initHandshake() to initialize the handshaker
 570      *    object and progress the state. Then, send the initial
 571      *    handshaking message if appropriate (always on clients and
 572      *    on servers when renegotiating).
 573      */
 574     private synchronized void kickstartHandshake() throws IOException {
 575         switch (connectionState) {
 576 
 577         case cs_START:
 578             if (!serverModeSet) {
 579                 throw new IllegalStateException(
 580                     "Client/Server mode not yet set.");
 581             }
 582             initHandshaker();
 583             break;
 584 
 585         case cs_HANDSHAKE:
 586             // handshaker already setup, proceed
 587             break;
 588 
 589         case cs_DATA:
 590             if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
 591                 throw new SSLHandshakeException(
 592                         "Insecure renegotiation is not allowed");
 593             }
 594 
 595             if (!secureRenegotiation) {
 596                 if (debug != null && Debug.isOn("handshake")) {
 597                     System.out.println(
 598                         "Warning: Using insecure renegotiation");
 599                 }
 600             }
 601 
 602             // initialize the handshaker, move to cs_RENEGOTIATE
 603             initHandshaker();
 604             break;
 605 
 606         case cs_RENEGOTIATE:
 607             // handshaking already in progress, return
 608             return;
 609 
 610         default:
 611             // cs_ERROR/cs_CLOSED
 612             throw new SSLException("SSLEngine is closing/closed");
 613         }
 614 
 615         //
 616         // Kickstart handshake state machine if we need to ...
 617         //
 618         if (!handshaker.activated()) {
 619              // prior to handshaking, activate the handshake
 620             if (connectionState == cs_RENEGOTIATE) {
 621                 // don't use SSLv2Hello when renegotiating
 622                 handshaker.activate(protocolVersion);
 623             } else {
 624                 handshaker.activate(null);
 625             }
 626 
 627             if (handshaker instanceof ClientHandshaker) {
 628                 // send client hello
 629                 handshaker.kickstart();
 630             } else {    // instanceof ServerHandshaker
 631                 if (connectionState == cs_HANDSHAKE) {
 632                     // initial handshake, no kickstart message to send
 633                 } else {
 634                     // we want to renegotiate, send hello request
 635                     handshaker.kickstart();
 636                 }
 637             }
 638         }
 639     }
 640 
 641     /*
 642      * Start a SSLEngine handshake
 643      */
 644     @Override
 645     public void beginHandshake() throws SSLException {
 646         try {
 647             kickstartHandshake();
 648         } catch (Exception e) {
 649             fatal(Alerts.alert_handshake_failure,
 650                 "Couldn't kickstart handshaking", e);
 651         }
 652     }
 653 
 654 
 655     //
 656     // Read/unwrap side
 657     //
 658 
 659 
 660     /**
 661      * Unwraps a buffer.  Does a variety of checks before grabbing
 662      * the unwrapLock, which blocks multiple unwraps from occurring.
 663      */
 664     @Override
 665     public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer[] appData,
 666             int offset, int length) throws SSLException {
 667 
 668         // check engine parameters
 669         checkEngineParas(netData, appData, offset, length, false);
 670 
 671         try {
 672             synchronized (unwrapLock) {
 673                 return readNetRecord(netData, appData, offset, length);
 674             }
 675         } catch (SSLProtocolException spe) {
 676             // may be an unexpected handshake message
 677             fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
 678             return null;  // make compiler happy
 679         } catch (Exception e) {
 680             /*
 681              * Don't reset position so it looks like we didn't
 682              * consume anything.  We did consume something, and it
 683              * got us into this situation, so report that much back.
 684              * Our days of consuming are now over anyway.
 685              */
 686             fatal(Alerts.alert_internal_error,
 687                 "problem unwrapping net record", e);
 688             return null;  // make compiler happy
 689         }
 690     }
 691 
 692     private static void checkEngineParas(ByteBuffer netData,
 693             ByteBuffer[] appData, int offset, int len, boolean isForWrap) {
 694 
 695         if ((netData == null) || (appData == null)) {
 696             throw new IllegalArgumentException("src/dst is null");
 697         }
 698 
 699         if ((offset < 0) || (len < 0) || (offset > appData.length - len)) {
 700             throw new IndexOutOfBoundsException();
 701         }
 702 
 703         /*
 704          * If wrapping, make sure the destination bufffer is writable.
 705          */
 706         if (isForWrap && netData.isReadOnly()) {
 707             throw new ReadOnlyBufferException();
 708         }
 709 
 710         for (int i = offset; i < offset + len; i++) {
 711             if (appData[i] == null) {
 712                 throw new IllegalArgumentException(
 713                         "appData[" + i + "] == null");
 714             }
 715 
 716             /*
 717              * If unwrapping, make sure the destination bufffers are writable.
 718              */
 719             if (!isForWrap && appData[i].isReadOnly()) {
 720                 throw new ReadOnlyBufferException();
 721             }
 722         }
 723     }
 724 
 725     /*
 726      * Makes additional checks for unwrap, but this time more
 727      * specific to this packet and the current state of the machine.
 728      */
 729     private SSLEngineResult readNetRecord(ByteBuffer netData,
 730             ByteBuffer[] appData, int offset, int length) throws IOException {
 731 
 732         Status status = null;
 733         HandshakeStatus hsStatus = null;
 734 
 735         /*
 736          * See if the handshaker needs to report back some SSLException.
 737          */
 738         checkTaskThrown();
 739 
 740         /*
 741          * Check if we are closing/closed.
 742          */
 743         if (isInboundDone()) {
 744             return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
 745         }
 746 
 747         /*
 748          * If we're still in cs_HANDSHAKE, make sure it's been
 749          * started.
 750          */
 751         synchronized (this) {
 752             if ((connectionState == cs_HANDSHAKE) ||
 753                     (connectionState == cs_START)) {
 754                 kickstartHandshake();
 755 
 756                 /*
 757                  * If there's still outbound data to flush, we
 758                  * can return without trying to unwrap anything.
 759                  */
 760                 hsStatus = getHSStatus(null);
 761 
 762                 if (hsStatus == HandshakeStatus.NEED_WRAP) {
 763                     return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
 764                 }
 765             }
 766         }
 767 
 768         /*
 769          * Grab a copy of this if it doesn't already exist,
 770          * and we can use it several places before anything major
 771          * happens on this side.  Races aren't critical
 772          * here.
 773          */
 774         if (hsStatus == null) {
 775             hsStatus = getHSStatus(null);
 776         }
 777 
 778         /*
 779          * If we have a task outstanding, this *MUST* be done before
 780          * doing any more unwrapping, because we could be in the middle
 781          * of receiving a handshake message, for example, a finished
 782          * message which would change the ciphers.
 783          */
 784         if (hsStatus == HandshakeStatus.NEED_TASK) {
 785             return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
 786         }
 787 
 788         if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
 789             Plaintext plainText = null;
 790             try {
 791                 plainText = readRecord(null, null, 0, 0);
 792             } catch (SSLException e) {
 793                 throw e;
 794             } catch (IOException e) {
 795                 throw new SSLException("readRecord", e);
 796             }
 797 
 798             status = (isInboundDone() ? Status.CLOSED : Status.OK);
 799             hsStatus = getHSStatus(plainText.handshakeStatus);
 800 
 801             return new SSLEngineResult(
 802                     status, hsStatus, 0, 0, plainText.recordSN);
 803         }
 804 
 805         /*
 806          * Check the packet to make sure enough is here.
 807          * This will also indirectly check for 0 len packets.
 808          */
 809         int packetLen = 0;
 810         try {
 811             packetLen = inputRecord.bytesInCompletePacket(netData);
 812         } catch (SSLException ssle) {
 813             // Need to discard invalid records for DTLS protocols.
 814             if (isDTLS) {
 815                 if (debug != null && Debug.isOn("ssl")) {
 816                     System.out.println(
 817                         Thread.currentThread().getName() +
 818                         " discard invalid record: " + ssle);
 819                 }
 820 
 821                 // invalid, discard the entire data [section 4.1.2.7, RFC 6347]
 822                 int deltaNet = netData.remaining();
 823                 netData.position(netData.limit());
 824 
 825                 status = (isInboundDone() ? Status.CLOSED : Status.OK);
 826                 hsStatus = getHSStatus(hsStatus);
 827 
 828                 return new SSLEngineResult(status, hsStatus, deltaNet, 0, -1L);
 829             } else {
 830                 throw ssle;
 831             }
 832         }
 833 
 834         // Is this packet bigger than SSL/TLS normally allows?
 835         if (packetLen > sess.getPacketBufferSize()) {
 836             int largestRecordSize = isDTLS ?
 837                     DTLSRecord.maxRecordSize : SSLRecord.maxLargeRecordSize;
 838             if ((packetLen <= largestRecordSize) && !isDTLS) {
 839                 // Expand the expected maximum packet/application buffer
 840                 // sizes.
 841                 //
 842                 // Only apply to SSL/TLS protocols.
 843 
 844                 // Old behavior: shall we honor the System Property
 845                 // "jsse.SSLEngine.acceptLargeFragments" if it is "false"?
 846                 sess.expandBufferSizes();
 847             }
 848 
 849             // check the packet again
 850             largestRecordSize = sess.getPacketBufferSize();
 851             if (packetLen > largestRecordSize) {
 852                 throw new SSLProtocolException(
 853                         "Input record too big: max = " +
 854                         largestRecordSize + " len = " + packetLen);
 855             }
 856         }
 857 
 858         int netPos = netData.position();
 859         int appRemains = 0;
 860         for (int i = offset; i < offset + length; i++) {
 861             if (appData[i] == null) {
 862                 throw new IllegalArgumentException(
 863                         "appData[" + i + "] == null");
 864             }
 865             appRemains += appData[i].remaining();
 866         }
 867 
 868         /*
 869          * Check for OVERFLOW.
 870          *
 871          * Delay enforcing the application buffer free space requirement
 872          * until after the initial handshaking.
 873          */
 874         // synchronize connectionState?
 875         if ((connectionState == cs_DATA) ||
 876                 (connectionState == cs_RENEGOTIATE)) {
 877 
 878             int FragLen = inputRecord.estimateFragmentSize(packetLen);
 879             if (FragLen > appRemains) {
 880                 return new SSLEngineResult(
 881                         Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
 882             }
 883         }
 884 
 885         // check for UNDERFLOW.
 886         if ((packetLen == -1) || (netData.remaining() < packetLen)) {
 887             return new SSLEngineResult(Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
 888         }
 889 
 890         /*
 891          * We're now ready to actually do the read.
 892          */
 893         Plaintext plainText = null;
 894         try {
 895             plainText = readRecord(netData, appData, offset, length);
 896         } catch (SSLException e) {
 897             throw e;
 898         } catch (IOException e) {
 899             throw new SSLException("readRecord", e);
 900         }
 901 
 902         /*
 903          * Check the various condition that we could be reporting.
 904          *
 905          * It's *possible* something might have happened between the
 906          * above and now, but it was better to minimally lock "this"
 907          * during the read process.  We'll return the current
 908          * status, which is more representative of the current state.
 909          *
 910          * status above should cover:  FINISHED, NEED_TASK
 911          */
 912         status = (isInboundDone() ? Status.CLOSED : Status.OK);
 913         hsStatus = getHSStatus(plainText.handshakeStatus);
 914 
 915         int deltaNet = netData.position() - netPos;
 916         int deltaApp = appRemains;
 917         for (int i = offset; i < offset + length; i++) {
 918             deltaApp -= appData[i].remaining();
 919         }
 920 
 921         return new SSLEngineResult(
 922                 status, hsStatus, deltaNet, deltaApp, plainText.recordSN);
 923     }
 924 
 925     // the caller have synchronized readLock
 926     void expectingFinishFlight() {
 927         inputRecord.expectingFinishFlight();
 928     }
 929 
 930     /*
 931      * Actually do the read record processing.
 932      *
 933      * Returns a Status if it can make specific determinations
 934      * of the engine state.  In particular, we need to signal
 935      * that a handshake just completed.
 936      *
 937      * It would be nice to be symmetrical with the write side and move
 938      * the majority of this to SSLInputRecord, but there's too much
 939      * SSLEngine state to do that cleanly.  It must still live here.
 940      */
 941     private Plaintext readRecord(ByteBuffer netData,
 942             ByteBuffer[] appData, int offset, int length) throws IOException {
 943 
 944         /*
 945          * The various operations will return new sliced BB's,
 946          * this will avoid having to worry about positions and
 947          * limits in the netBB.
 948          */
 949         Plaintext plainText = null;
 950 
 951         if (getConnectionState() == cs_ERROR) {
 952             return Plaintext.PLAINTEXT_NULL;
 953         }
 954 
 955         /*
 956          * Read a record ... maybe emitting an alert if we get a
 957          * comprehensible but unsupported "hello" message during
 958          * format checking (e.g. V2).
 959          */
 960         try {
 961             if (isDTLS) {
 962                 // Don't process the incoming record until all of the
 963                 // buffered records get handled.
 964                 plainText = inputRecord.acquirePlaintext();
 965             }
 966 
 967             if ((!isDTLS || plainText == null) && netData != null) {
 968                 plainText = inputRecord.decode(netData);
 969             }
 970         } catch (UnsupportedOperationException unsoe) {         // SSLv2Hello
 971             // Hack code to deliver SSLv2 error message for SSL/TLS connections.
 972             if (!isDTLS) {
 973                 outputRecord.encodeV2NoCipher();
 974             }
 975 
 976             fatal(Alerts.alert_unexpected_message, unsoe);
 977         } catch (BadPaddingException e) {
 978             /*
 979              * The basic SSLv3 record protection involves (optional)
 980              * encryption for privacy, and an integrity check ensuring
 981              * data origin authentication.  We do them both here, and
 982              * throw a fatal alert if the integrity check fails.
 983              */
 984             byte alertType = (connectionState != cs_DATA) ?
 985                     Alerts.alert_handshake_failure :
 986                     Alerts.alert_bad_record_mac;
 987             fatal(alertType, e.getMessage(), e);
 988         } catch (SSLHandshakeException she) {
 989             // may be record sequence number overflow
 990             fatal(Alerts.alert_handshake_failure, she);
 991         } catch (IOException ioe) {
 992             fatal(Alerts.alert_unexpected_message, ioe);
 993         }
 994 
 995         // plainText should never be null for TLS protocols
 996         HandshakeStatus hsStatus = null;
 997         if (plainText == Plaintext.PLAINTEXT_NULL) {
 998             // Only happens for DTLS protocols.
 999             //
1000             // Received a retransmitted flight, and need to retransmit the
1001             // previous delivered handshake flight messages.
1002             if (enableRetransmissions) {
1003                 if (debug != null && Debug.isOn("verbose")) {
1004                     Debug.log(
1005                         "Retransmit the previous handshake flight messages.");
1006                 }
1007 
1008                 synchronized (this) {
1009                     outputRecord.launchRetransmission();
1010                 }
1011             }   // Otherwise, discard the retransmitted flight.
1012         } else if (!isDTLS || plainText != null) {
1013             hsStatus = processInputRecord(plainText, appData, offset, length);
1014         }
1015 
1016         if (hsStatus == null) {
1017             hsStatus = getHSStatus(null);
1018         }
1019 
1020         if (plainText == null) {
1021             plainText = Plaintext.PLAINTEXT_NULL;
1022         }
1023         plainText.handshakeStatus = hsStatus;
1024 
1025         return plainText;
1026     }
1027 
1028     /*
1029      * Process the record.
1030      */
1031     private synchronized HandshakeStatus processInputRecord(
1032             Plaintext plainText,
1033             ByteBuffer[] appData, int offset, int length) throws IOException {
1034 
1035         HandshakeStatus hsStatus = null;
1036         switch (plainText.contentType) {
1037             case Record.ct_handshake:
1038                 /*
1039                  * Handshake messages always go to a pending session
1040                  * handshaker ... if there isn't one, create one.  This
1041                  * must work asynchronously, for renegotiation.
1042                  *
1043                  * NOTE that handshaking will either resume a session
1044                  * which was in the cache (and which might have other
1045                  * connections in it already), or else will start a new
1046                  * session (new keys exchanged) with just this connection
1047                  * in it.
1048                  */
1049                 initHandshaker();
1050                 if (!handshaker.activated()) {
1051                     // prior to handshaking, activate the handshake
1052                     if (connectionState == cs_RENEGOTIATE) {
1053                         // don't use SSLv2Hello when renegotiating
1054                         handshaker.activate(protocolVersion);
1055                     } else {
1056                         handshaker.activate(null);
1057                     }
1058                 }
1059 
1060                 /*
1061                  * process the handshake record ... may contain just
1062                  * a partial handshake message or multiple messages.
1063                  *
1064                  * The handshaker state machine will ensure that it's
1065                  * a finished message.
1066                  */
1067                 handshaker.processRecord(plainText.fragment, expectingFinished);
1068                 expectingFinished = false;
1069 
1070                 if (handshaker.invalidated) {
1071                     finishHandshake();
1072 
1073                     // if state is cs_RENEGOTIATE, revert it to cs_DATA
1074                     if (connectionState == cs_RENEGOTIATE) {
1075                         connectionState = cs_DATA;
1076                     }
1077                 } else if (handshaker.isDone()) {
1078                     // reset the parameters for secure renegotiation.
1079                     secureRenegotiation =
1080                                 handshaker.isSecureRenegotiation();
1081                     clientVerifyData = handshaker.getClientVerifyData();
1082                     serverVerifyData = handshaker.getServerVerifyData();
1083                     // set connection ALPN value
1084                     applicationProtocol =
1085                         handshaker.getHandshakeApplicationProtocol();
1086 
1087                     sess = handshaker.getSession();
1088                     handshakeSession = null;
1089                     if (outputRecord.isEmpty()) {
1090                         hsStatus = finishHandshake();
1091                         connectionState = cs_DATA;
1092                     }
1093 
1094                     // No handshakeListeners here.  That's a
1095                     // SSLSocket thing.
1096                 } else if (handshaker.taskOutstanding()) {
1097                     hsStatus = HandshakeStatus.NEED_TASK;
1098                 }
1099                 break;
1100 
1101             case Record.ct_application_data:
1102                 // Pass this right back up to the application.
1103                 if ((connectionState != cs_DATA)
1104                         && (connectionState != cs_RENEGOTIATE)
1105                         && (connectionState != cs_CLOSED)) {
1106                     throw new SSLProtocolException(
1107                             "Data received in non-data state: " +
1108                             connectionState);
1109                 }
1110 
1111                 if (expectingFinished) {
1112                     throw new SSLProtocolException
1113                             ("Expecting finished message, received data");
1114                 }
1115 
1116                 if (!inboundDone) {
1117                     ByteBuffer fragment = plainText.fragment;
1118                     int remains = fragment.remaining();
1119 
1120                     // Should have enough room in appData.
1121                     for (int i = offset;
1122                             ((i < (offset + length)) && (remains > 0)); i++) {
1123                         int amount = Math.min(appData[i].remaining(), remains);
1124                         fragment.limit(fragment.position() + amount);
1125                         appData[i].put(fragment);
1126                         remains -= amount;
1127                     }
1128                 }
1129 
1130                 break;
1131 
1132             case Record.ct_alert:
1133                 recvAlert(plainText.fragment);
1134                 break;
1135 
1136             case Record.ct_change_cipher_spec:
1137                 if ((connectionState != cs_HANDSHAKE
1138                         && connectionState != cs_RENEGOTIATE)) {
1139                     // For the CCS message arriving in the wrong state
1140                     fatal(Alerts.alert_unexpected_message,
1141                             "illegal change cipher spec msg, conn state = "
1142                             + connectionState);
1143                 } else if (plainText.fragment.remaining() != 1
1144                         || plainText.fragment.get() != 1) {
1145                     // For structural/content issues with the CCS
1146                     fatal(Alerts.alert_unexpected_message,
1147                             "Malformed change cipher spec msg");
1148                 }
1149 
1150                 //
1151                 // The first message after a change_cipher_spec
1152                 // record MUST be a "Finished" handshake record,
1153                 // else it's a protocol violation.  We force this
1154                 // to be checked by a minor tweak to the state
1155                 // machine.
1156                 //
1157                 handshaker.receiveChangeCipherSpec();
1158 
1159                 CipherBox readCipher;
1160                 Authenticator readAuthenticator;
1161                 try {
1162                     readCipher = handshaker.newReadCipher();
1163                     readAuthenticator = handshaker.newReadAuthenticator();
1164                 } catch (GeneralSecurityException e) {
1165                     // can't happen
1166                     throw new SSLException("Algorithm missing:  ", e);
1167                 }
1168                 inputRecord.changeReadCiphers(readAuthenticator, readCipher);
1169 
1170                 // next message MUST be a finished message
1171                 expectingFinished = true;
1172                 break;
1173 
1174             default:
1175                 //
1176                 // TLS requires that unrecognized records be ignored.
1177                 //
1178                 if (debug != null && Debug.isOn("ssl")) {
1179                     System.out.println(Thread.currentThread().getName() +
1180                             ", Received record type: " + plainText.contentType);
1181                 }
1182                 break;
1183         } // switch
1184 
1185         /*
1186          * We only need to check the sequence number state for
1187          * non-handshaking record.
1188          *
1189          * Note that in order to maintain the handshake status
1190          * properly, we check the sequence number after the last
1191          * record reading process. As we request renegotiation
1192          * or close the connection for wrapped sequence number
1193          * when there is enough sequence number space left to
1194          * handle a few more records, so the sequence number
1195          * of the last record cannot be wrapped.
1196          */
1197         hsStatus = getHSStatus(hsStatus);
1198         if (connectionState < cs_ERROR && !isInboundDone() &&
1199                 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) &&
1200                 (inputRecord.seqNumIsHuge())) {
1201             /*
1202              * Ask for renegotiation when need to renew sequence number.
1203              *
1204              * Don't bother to kickstart the renegotiation when the local is
1205              * asking for it.
1206              */
1207             if (debug != null && Debug.isOn("ssl")) {
1208                 System.out.println(Thread.currentThread().getName() +
1209                         ", request renegotiation " +
1210                         "to avoid sequence number overflow");
1211             }
1212 
1213             beginHandshake();
1214 
1215             hsStatus = getHSStatus(null);
1216         }
1217 
1218         return hsStatus;
1219     }
1220 
1221 
1222     //
1223     // write/wrap side
1224     //
1225 
1226 
1227     /**
1228      * Wraps a buffer.  Does a variety of checks before grabbing
1229      * the wrapLock, which blocks multiple wraps from occurring.
1230      */
1231     @Override
1232     public SSLEngineResult wrap(ByteBuffer[] appData,
1233             int offset, int length, ByteBuffer netData) throws SSLException {
1234 
1235         // check engine parameters
1236         checkEngineParas(netData, appData, offset, length, true);
1237 
1238         /*
1239          * We can be smarter about using smaller buffer sizes later.
1240          * For now, force it to be large enough to handle any valid record.
1241          */
1242         if (netData.remaining() < sess.getPacketBufferSize()) {
1243             return new SSLEngineResult(
1244                 Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);
1245         }
1246 
1247         try {
1248             synchronized (wrapLock) {
1249                 return writeAppRecord(appData, offset, length, netData);
1250             }
1251         } catch (SSLProtocolException spe) {
1252             // may be an unexpected handshake message
1253             fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
1254             return null;  // make compiler happy
1255         } catch (Exception e) {
1256             fatal(Alerts.alert_internal_error,
1257                 "problem wrapping app data", e);
1258             return null;  // make compiler happy
1259         }
1260     }
1261 
1262     /*
1263      * Makes additional checks for unwrap, but this time more
1264      * specific to this packet and the current state of the machine.
1265      */
1266     private SSLEngineResult writeAppRecord(ByteBuffer[] appData,
1267             int offset, int length, ByteBuffer netData) throws IOException {
1268 
1269         Status status = null;
1270         HandshakeStatus hsStatus = null;
1271 
1272         /*
1273          * See if the handshaker needs to report back some SSLException.
1274          */
1275         checkTaskThrown();
1276 
1277         /*
1278          * short circuit if we're closed/closing.
1279          */
1280         if (isOutboundDone()) {
1281             return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
1282         }
1283 
1284         /*
1285          * If we're still in cs_HANDSHAKE, make sure it's been
1286          * started.
1287          */
1288         synchronized (this) {
1289             if ((connectionState == cs_HANDSHAKE) ||
1290                 (connectionState == cs_START)) {
1291 
1292                 kickstartHandshake();
1293 
1294                 /*
1295                  * If there's no HS data available to write, we can return
1296                  * without trying to wrap anything.
1297                  */
1298                 hsStatus = getHSStatus(null);
1299                 if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
1300                     /*
1301                      * For DTLS, if the handshake state is
1302                      * HandshakeStatus.NEED_UNWRAP, a call to SSLEngine.wrap()
1303                      * means that the previous handshake packets (if delivered)
1304                      * get lost, and need retransmit the handshake messages.
1305                      */
1306                     if (!isDTLS || !enableRetransmissions ||
1307                             (handshaker == null) || outputRecord.firstMessage) {
1308 
1309                         return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
1310                     }   // otherwise, need retransmission
1311                 }
1312             }
1313         }
1314 
1315         /*
1316          * Grab a copy of this if it doesn't already exist,
1317          * and we can use it several places before anything major
1318          * happens on this side.  Races aren't critical
1319          * here.
1320          */
1321         if (hsStatus == null) {
1322             hsStatus = getHSStatus(null);
1323         }
1324 
1325         /*
1326          * If we have a task outstanding, this *MUST* be done before
1327          * doing any more wrapping, because we could be in the middle
1328          * of receiving a handshake message, for example, a finished
1329          * message which would change the ciphers.
1330          */
1331         if (hsStatus == HandshakeStatus.NEED_TASK) {
1332             return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
1333         }
1334 
1335         /*
1336          * This will obtain any waiting outbound data, or will
1337          * process the outbound appData.
1338          */
1339         int netPos = netData.position();
1340         int appRemains = 0;
1341         for (int i = offset; i < offset + length; i++) {
1342             if (appData[i] == null) {
1343                 throw new IllegalArgumentException(
1344                         "appData[" + i + "] == null");
1345             }
1346             appRemains += appData[i].remaining();
1347         }
1348 
1349         Ciphertext ciphertext = null;
1350         try {
1351             if (appRemains != 0) {
1352                 synchronized (writeLock) {
1353                     ciphertext = writeRecord(appData, offset, length, netData);
1354                 }
1355             } else {
1356                 synchronized (writeLock) {
1357                     ciphertext = writeRecord(null, 0, 0, netData);
1358                 }
1359             }
1360         } catch (SSLException e) {
1361             throw e;
1362         } catch (IOException e) {
1363             throw new SSLException("Write problems", e);
1364         }
1365 
1366         /*
1367          * writeRecord might have reported some status.
1368          * Now check for the remaining cases.
1369          *
1370          * status above should cover:  NEED_WRAP/FINISHED
1371          */
1372         status = (isOutboundDone() ? Status.CLOSED : Status.OK);
1373         hsStatus = getHSStatus(ciphertext.handshakeStatus);
1374 
1375         int deltaNet = netData.position() - netPos;
1376         int deltaApp = appRemains;
1377         for (int i = offset; i < offset + length; i++) {
1378             deltaApp -= appData[i].remaining();
1379         }
1380 
1381         return new SSLEngineResult(
1382                 status, hsStatus, deltaApp, deltaNet, ciphertext.recordSN);
1383     }
1384 
1385     /*
1386      * Central point to write/get all of the outgoing data.
1387      */
1388     private Ciphertext writeRecord(ByteBuffer[] appData,
1389             int offset, int length, ByteBuffer netData) throws IOException {
1390 
1391         Ciphertext ciphertext = null;
1392         try {
1393             // Acquire the buffered to-be-delivered records or retransmissions.
1394             //
1395             // May have buffered records, or need retransmission if handshaking.
1396             if (!outputRecord.isEmpty() ||
1397                     (enableRetransmissions && handshaker != null)) {
1398                 ciphertext = outputRecord.acquireCiphertext(netData);
1399             }
1400 
1401             if ((ciphertext == null) && (appData != null)) {
1402                 ciphertext = outputRecord.encode(
1403                         appData, offset, length, netData);
1404             }
1405         } catch (SSLHandshakeException she) {
1406             // may be record sequence number overflow
1407             fatal(Alerts.alert_handshake_failure, she);
1408 
1409             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
1410         } catch (IOException e) {
1411             fatal(Alerts.alert_unexpected_message, e);
1412 
1413             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
1414         }
1415 
1416         if (ciphertext == null) {
1417             return Ciphertext.CIPHERTEXT_NULL;
1418         }
1419 
1420         HandshakeStatus hsStatus = null;
1421         Ciphertext.RecordType recordType = ciphertext.recordType;
1422         if ((recordType.contentType == Record.ct_handshake) &&

1423             (recordType.handshakeType == HandshakeMessage.ht_finished) &&
1424             outputRecord.isEmpty()) {
1425 
1426             if (handshaker == null) {
1427                 hsStatus = HandshakeStatus.FINISHED;
1428             } else if (handshaker.isDone()) {
1429                 hsStatus = finishHandshake();
1430                 connectionState = cs_DATA;
1431 
1432                 // Retransmit the last flight twice.
1433                 //
1434                 // The application data transactions may begin immediately
1435                 // after the last flight.  If the last flight get lost, the
1436                 // application data may be discarded accordingly.  As could
1437                 // be an issue for some applications.  This impact can be
1438                 // mitigated by sending the last fligth twice.
1439                 if (isDTLS && enableRetransmissions) {
1440                     if (debug != null && Debug.isOn("verbose")) {
1441                         Debug.log(
1442                             "Retransmit the last flight messages.");
1443                     }
1444 
1445                     synchronized (this) {
1446                         outputRecord.launchRetransmission();
1447                     }
1448 
1449                     hsStatus = HandshakeStatus.NEED_WRAP;
1450                 }
1451             }
1452         }   // Otherwise, the followed call to getHSStatus() will help.
1453 
1454         /*
1455          * We only need to check the sequence number state for
1456          * non-handshaking record.
1457          *
1458          * Note that in order to maintain the handshake status
1459          * properly, we check the sequence number after the last
1460          * record writing process. As we request renegotiation
1461          * or close the connection for wrapped sequence number
1462          * when there is enough sequence number space left to
1463          * handle a few more records, so the sequence number
1464          * of the last record cannot be wrapped.
1465          */
1466         hsStatus = getHSStatus(hsStatus);
1467         if (connectionState < cs_ERROR && !isOutboundDone() &&
1468                 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) &&
1469                 (outputRecord.seqNumIsHuge())) {
1470             /*
1471              * Ask for renegotiation when need to renew sequence number.
1472              *
1473              * Don't bother to kickstart the renegotiation when the local is
1474              * asking for it.
1475              */
1476             if (debug != null && Debug.isOn("ssl")) {
1477                 System.out.println(Thread.currentThread().getName() +
1478                         ", request renegotiation " +
1479                         "to avoid sequence number overflow");
1480             }
1481 
1482             beginHandshake();
1483 
1484             hsStatus = getHSStatus(null);
1485         }
1486         ciphertext.handshakeStatus = hsStatus;
1487 
1488         return ciphertext;
1489     }
1490 
1491     private HandshakeStatus finishHandshake() {
1492         handshaker = null;
1493         inputRecord.setHandshakeHash(null);
1494         outputRecord.setHandshakeHash(null);
1495         connectionState = cs_DATA;
1496 
1497        return HandshakeStatus.FINISHED;
1498    }
1499 
1500     //
1501     // Close code
1502     //
1503 
1504     /**
1505      * Signals that no more outbound application data will be sent
1506      * on this <code>SSLEngine</code>.
1507      */
1508     private void closeOutboundInternal() {
1509 
1510         if ((debug != null) && Debug.isOn("ssl")) {
1511             System.out.println(Thread.currentThread().getName() +
1512                                     ", closeOutboundInternal()");
1513         }
1514 
1515         /*
1516          * Already closed, ignore
1517          */
1518         if (outboundDone) {
1519             return;
1520         }
1521 
1522         switch (connectionState) {
1523 
1524         /*
1525          * If we haven't even started yet, don't bother reading inbound.
1526          */
1527         case cs_START:
1528             try {
1529                 outputRecord.close();
1530             } catch (IOException ioe) {
1531                // ignore
1532             }
1533             outboundDone = true;
1534 
1535             try {
1536                 inputRecord.close();
1537             } catch (IOException ioe) {
1538                // ignore
1539             }
1540             inboundDone = true;
1541             break;
1542 
1543         case cs_ERROR:
1544         case cs_CLOSED:
1545             break;
1546 
1547         /*
1548          * Otherwise we indicate clean termination.
1549          */
1550         // case cs_HANDSHAKE:
1551         // case cs_DATA:
1552         // case cs_RENEGOTIATE:
1553         default:
1554             warning(Alerts.alert_close_notify);
1555             try {
1556                 outputRecord.close();
1557             } catch (IOException ioe) {
1558                // ignore
1559             }
1560             outboundDone = true;
1561             break;
1562         }
1563 
1564         connectionState = cs_CLOSED;
1565     }
1566 
1567     @Override
1568     public synchronized void closeOutbound() {
1569         /*
1570          * Dump out a close_notify to the remote side
1571          */
1572         if ((debug != null) && Debug.isOn("ssl")) {
1573             System.out.println(Thread.currentThread().getName() +
1574                                     ", called closeOutbound()");
1575         }
1576 
1577         closeOutboundInternal();
1578     }
1579 
1580     /**
1581      * Returns the outbound application data closure state
1582      */
1583     @Override
1584     public boolean isOutboundDone() {
1585         return outboundDone && outputRecord.isEmpty();
1586     }
1587 
1588     /**
1589      * Signals that no more inbound network data will be sent
1590      * to this <code>SSLEngine</code>.
1591      */
1592     private void closeInboundInternal() {
1593 
1594         if ((debug != null) && Debug.isOn("ssl")) {
1595             System.out.println(Thread.currentThread().getName() +
1596                                     ", closeInboundInternal()");
1597         }
1598 
1599         /*
1600          * Already closed, ignore
1601          */
1602         if (inboundDone) {
1603             return;
1604         }
1605 
1606         closeOutboundInternal();
1607 
1608         try {
1609             inputRecord.close();
1610         } catch (IOException ioe) {
1611            // ignore
1612         }
1613         inboundDone = true;
1614 
1615         connectionState = cs_CLOSED;
1616     }
1617 
1618     /*
1619      * Close the inbound side of the connection.  We grab the
1620      * lock here, and do the real work in the internal verison.
1621      * We do check for truncation attacks.
1622      */
1623     @Override
1624     public synchronized void closeInbound() throws SSLException {
1625         /*
1626          * Currently closes the outbound side as well.  The IETF TLS
1627          * working group has expressed the opinion that 1/2 open
1628          * connections are not allowed by the spec.  May change
1629          * someday in the future.
1630          */
1631         if ((debug != null) && Debug.isOn("ssl")) {
1632             System.out.println(Thread.currentThread().getName() +
1633                                     ", called closeInbound()");
1634         }
1635 
1636         /*
1637          * No need to throw an Exception if we haven't even started yet.
1638          */
1639         if ((connectionState != cs_START) && !recvCN) {
1640             recvCN = true;  // Only receive the Exception once
1641             fatal(Alerts.alert_internal_error,
1642                 "Inbound closed before receiving peer's close_notify: " +
1643                 "possible truncation attack?");
1644         } else {
1645             /*
1646              * Currently, this is a no-op, but in case we change
1647              * the close inbound code later.
1648              */
1649             closeInboundInternal();
1650         }
1651     }
1652 
1653     /**
1654      * Returns the network inbound data closure state
1655      */
1656     @Override
1657     public synchronized boolean isInboundDone() {
1658         return inboundDone;
1659     }
1660 
1661 
1662     //
1663     // Misc stuff
1664     //
1665 
1666 
1667     /**
1668      * Returns the current <code>SSLSession</code> for this
1669      * <code>SSLEngine</code>
1670      * <P>
1671      * These can be long lived, and frequently correspond to an
1672      * entire login session for some user.
1673      */
1674     @Override
1675     public synchronized SSLSession getSession() {
1676         return sess;
1677     }
1678 
1679     @Override
1680     public synchronized SSLSession getHandshakeSession() {
1681         return handshakeSession;
1682     }
1683 
1684     synchronized void setHandshakeSession(SSLSessionImpl session) {
1685         // update the fragment size, which may be negotiated during handshaking
1686         inputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize());
1687         outputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize());
1688 
1689         handshakeSession = session;
1690     }
1691 
1692     /**
1693      * Returns a delegated <code>Runnable</code> task for
1694      * this <code>SSLEngine</code>.
1695      */
1696     @Override
1697     public synchronized Runnable getDelegatedTask() {
1698         if (handshaker != null) {
1699             return handshaker.getTask();
1700         }
1701         return null;
1702     }
1703 
1704 
1705     //
1706     // EXCEPTION AND ALERT HANDLING
1707     //
1708 
1709     /*
1710      * Send a warning alert.
1711      */
1712     void warning(byte description) {
1713         sendAlert(Alerts.alert_warning, description);
1714     }
1715 
1716     synchronized void fatal(byte description, String diagnostic)
1717             throws SSLException {
1718         fatal(description, diagnostic, null);
1719     }
1720 
1721     synchronized void fatal(byte description, Throwable cause)
1722             throws SSLException {
1723         fatal(description, null, cause);
1724     }
1725 
1726     /*
1727      * We've got a fatal error here, so start the shutdown process.
1728      *
1729      * Because of the way the code was written, we have some code
1730      * calling fatal directly when the "description" is known
1731      * and some throwing Exceptions which are then caught by higher
1732      * levels which then call here.  This code needs to determine
1733      * if one of the lower levels has already started the process.
1734      *
1735      * We won't worry about Error's, if we have one of those,
1736      * we're in worse trouble.  Note:  the networking code doesn't
1737      * deal with Errors either.
1738      */
1739     synchronized void fatal(byte description, String diagnostic,
1740             Throwable cause) throws SSLException {
1741 
1742         /*
1743          * If we have no further information, make a general-purpose
1744          * message for folks to see.  We generally have one or the other.
1745          */
1746         if (diagnostic == null) {
1747             diagnostic = "General SSLEngine problem";
1748         }
1749         if (cause == null) {
1750             cause = Alerts.getSSLException(description, cause, diagnostic);
1751         }
1752 
1753         /*
1754          * If we've already shutdown because of an error,
1755          * there is nothing we can do except rethrow the exception.
1756          *
1757          * Most exceptions seen here will be SSLExceptions.
1758          * We may find the occasional Exception which hasn't been
1759          * converted to a SSLException, so we'll do it here.
1760          */
1761         if (closeReason != null) {
1762             if ((debug != null) && Debug.isOn("ssl")) {
1763                 System.out.println(Thread.currentThread().getName() +
1764                     ", fatal: engine already closed.  Rethrowing " +
1765                     cause.toString());
1766             }
1767             if (cause instanceof RuntimeException) {
1768                 throw (RuntimeException)cause;
1769             } else if (cause instanceof SSLException) {
1770                 throw (SSLException)cause;
1771             } else if (cause instanceof Exception) {
1772                 throw new SSLException("fatal SSLEngine condition", cause);
1773             }
1774         }
1775 
1776         if ((debug != null) && Debug.isOn("ssl")) {
1777             System.out.println(Thread.currentThread().getName()
1778                         + ", fatal error: " + description +
1779                         ": " + diagnostic + "\n" + cause.toString());
1780         }
1781 
1782         /*
1783          * Ok, this engine's going down.
1784          */
1785         int oldState = connectionState;
1786         connectionState = cs_ERROR;
1787 
1788         try {
1789             inputRecord.close();
1790         } catch (IOException ioe) {
1791            // ignore
1792         }
1793         inboundDone = true;
1794 
1795         sess.invalidate();
1796         if (handshakeSession != null) {
1797             handshakeSession.invalidate();
1798         }
1799 
1800         /*
1801          * If we haven't even started handshaking yet, no need
1802          * to generate the fatal close alert.
1803          */
1804         if (oldState != cs_START) {
1805             sendAlert(Alerts.alert_fatal, description);
1806         }
1807 
1808         if (cause instanceof SSLException) { // only true if != null
1809             closeReason = (SSLException)cause;
1810         } else {
1811             /*
1812              * Including RuntimeExceptions, but we'll throw those
1813              * down below.  The closeReason isn't used again,
1814              * except for null checks.
1815              */
1816             closeReason =
1817                 Alerts.getSSLException(description, cause, diagnostic);
1818         }
1819 
1820         try {
1821             outputRecord.close();
1822         } catch (IOException ioe) {
1823            // ignore
1824         }
1825         outboundDone = true;
1826 
1827         connectionState = cs_CLOSED;
1828 
1829         if (cause instanceof RuntimeException) {
1830             throw (RuntimeException)cause;
1831         } else {
1832             throw closeReason;
1833         }
1834     }
1835 
1836     /*
1837      * Process an incoming alert ... caller must already have synchronized
1838      * access to "this".
1839      */
1840     private void recvAlert(ByteBuffer fragment) throws IOException {
1841         byte level = fragment.get();
1842         byte description = fragment.get();
1843 
1844         if (description == -1) { // check for short message
1845             fatal(Alerts.alert_illegal_parameter, "Short alert message");
1846         }
1847 
1848         if (debug != null && (Debug.isOn("record") ||
1849                 Debug.isOn("handshake"))) {
1850             synchronized (System.out) {
1851                 System.out.print(Thread.currentThread().getName());
1852                 System.out.print(", RECV " + protocolVersion + " ALERT:  ");
1853                 if (level == Alerts.alert_fatal) {
1854                     System.out.print("fatal, ");
1855                 } else if (level == Alerts.alert_warning) {
1856                     System.out.print("warning, ");
1857                 } else {
1858                     System.out.print("<level " + (0x0ff & level) + ">, ");
1859                 }
1860                 System.out.println(Alerts.alertDescription(description));
1861             }
1862         }
1863 
1864         if (level == Alerts.alert_warning) {
1865             if (description == Alerts.alert_close_notify) {
1866                 if (connectionState == cs_HANDSHAKE) {
1867                     fatal(Alerts.alert_unexpected_message,
1868                                 "Received close_notify during handshake");
1869                 } else {
1870                     recvCN = true;
1871                     closeInboundInternal();  // reply to close
1872                 }
1873             } else {
1874 
1875                 //
1876                 // The other legal warnings relate to certificates,
1877                 // e.g. no_certificate, bad_certificate, etc; these
1878                 // are important to the handshaking code, which can
1879                 // also handle illegal protocol alerts if needed.
1880                 //
1881                 if (handshaker != null) {
1882                     handshaker.handshakeAlert(description);
1883                 }
1884             }
1885         } else { // fatal or unknown level
1886             String reason = "Received fatal alert: "
1887                 + Alerts.alertDescription(description);
1888             if (closeReason == null) {
1889                 closeReason = Alerts.getSSLException(description, reason);
1890             }
1891             fatal(Alerts.alert_unexpected_message, reason);
1892         }
1893     }
1894 
1895 
1896     /*
1897      * Emit alerts.  Caller must have synchronized with "this".
1898      */
1899     private void sendAlert(byte level, byte description) {
1900         // the connectionState cannot be cs_START
1901         if (connectionState >= cs_CLOSED) {
1902             return;
1903         }
1904 
1905         // For initial handshaking, don't send alert message to peer if
1906         // handshaker has not started.
1907         //
1908         // Shall we send an fatal alter to terminate the connection gracefully?
1909         if (connectionState <= cs_HANDSHAKE &&
1910                 (handshaker == null || !handshaker.started() ||
1911                         !handshaker.activated())) {
1912             return;
1913         }
1914 
1915         try {
1916             outputRecord.encodeAlert(level, description);
1917         } catch (IOException ioe) {
1918             // ignore
1919         }
1920     }
1921 
1922 
1923     //
1924     // VARIOUS OTHER METHODS (COMMON TO SSLSocket)
1925     //
1926 
1927 
1928     /**
1929      * Controls whether new connections may cause creation of new SSL
1930      * sessions.
1931      *
1932      * As long as handshaking has not started, we can change
1933      * whether we enable session creations.  Otherwise,
1934      * we will need to wait for the next handshake.
1935      */
1936     @Override
1937     public synchronized void setEnableSessionCreation(boolean flag) {
1938         enableSessionCreation = flag;
1939 
1940         if ((handshaker != null) && !handshaker.activated()) {
1941             handshaker.setEnableSessionCreation(enableSessionCreation);
1942         }
1943     }
1944 
1945     /**
1946      * Returns true if new connections may cause creation of new SSL
1947      * sessions.
1948      */
1949     @Override
1950     public synchronized boolean getEnableSessionCreation() {
1951         return enableSessionCreation;
1952     }
1953 
1954 
1955     /**
1956      * Sets the flag controlling whether a server mode engine
1957      * *REQUIRES* SSL client authentication.
1958      *
1959      * As long as handshaking has not started, we can change
1960      * whether client authentication is needed.  Otherwise,
1961      * we will need to wait for the next handshake.
1962      */
1963     @Override
1964     public synchronized void setNeedClientAuth(boolean flag) {
1965         doClientAuth = (flag ?
1966                 ClientAuthType.CLIENT_AUTH_REQUIRED :
1967                 ClientAuthType.CLIENT_AUTH_NONE);
1968 
1969         if ((handshaker != null) &&
1970                 (handshaker instanceof ServerHandshaker) &&
1971                 !handshaker.activated()) {
1972             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
1973         }
1974     }
1975 
1976     @Override
1977     public synchronized boolean getNeedClientAuth() {
1978         return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUIRED);
1979     }
1980 
1981     /**
1982      * Sets the flag controlling whether a server mode engine
1983      * *REQUESTS* SSL client authentication.
1984      *
1985      * As long as handshaking has not started, we can change
1986      * whether client authentication is requested.  Otherwise,
1987      * we will need to wait for the next handshake.
1988      */
1989     @Override
1990     public synchronized void setWantClientAuth(boolean flag) {
1991         doClientAuth = (flag ?
1992                 ClientAuthType.CLIENT_AUTH_REQUESTED :
1993                 ClientAuthType.CLIENT_AUTH_NONE);
1994 
1995         if ((handshaker != null) &&
1996                 (handshaker instanceof ServerHandshaker) &&
1997                 !handshaker.activated()) {
1998             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
1999         }
2000     }
2001 
2002     @Override
2003     public synchronized boolean getWantClientAuth() {
2004         return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUESTED);
2005     }
2006 
2007 
2008     /**
2009      * Sets the flag controlling whether the engine is in SSL
2010      * client or server mode.  Must be called before any SSL
2011      * traffic has started.
2012      */
2013     @Override
2014     @SuppressWarnings("fallthrough")
2015     public synchronized void setUseClientMode(boolean flag) {
2016         switch (connectionState) {
2017 
2018         case cs_START:
2019             /*
2020              * If we need to change the socket mode and the enabled
2021              * protocols and cipher suites haven't specifically been
2022              * set by the user, change them to the corresponding
2023              * default ones.
2024              */
2025             if (roleIsServer != (!flag)) {
2026                 if (sslContext.isDefaultProtocolList(enabledProtocols)) {
2027                     enabledProtocols =
2028                             sslContext.getDefaultProtocolList(!flag);
2029                 }
2030 
2031                 if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) {
2032                     enabledCipherSuites =
2033                             sslContext.getDefaultCipherSuiteList(!flag);
2034                 }
2035             }
2036 
2037             roleIsServer = !flag;
2038             serverModeSet = true;
2039             break;
2040 
2041         case cs_HANDSHAKE:
2042             /*
2043              * If we have a handshaker, but haven't started
2044              * SSL traffic, we can throw away our current
2045              * handshaker, and start from scratch.  Don't
2046              * need to call doneConnect() again, we already
2047              * have the streams.
2048              */
2049             assert(handshaker != null);
2050             if (!handshaker.activated()) {
2051                 /*
2052                  * If we need to change the socket mode and the enabled
2053                  * protocols and cipher suites haven't specifically been
2054                  * set by the user, change them to the corresponding
2055                  * default ones.
2056                  */
2057                 if (roleIsServer != (!flag)) {
2058                     if (sslContext.isDefaultProtocolList(enabledProtocols)) {
2059                         enabledProtocols =
2060                                 sslContext.getDefaultProtocolList(!flag);
2061                     }
2062 
2063                     if (sslContext.isDefaultCipherSuiteList(
2064                                                     enabledCipherSuites)) {
2065                         enabledCipherSuites =
2066                             sslContext.getDefaultCipherSuiteList(!flag);
2067                     }
2068                 }
2069 
2070                 roleIsServer = !flag;
2071                 connectionState = cs_START;
2072                 initHandshaker();
2073                 break;
2074             }
2075 
2076             // If handshake has started, that's an error.  Fall through...
2077 
2078         default:
2079             if (debug != null && Debug.isOn("ssl")) {
2080                 System.out.println(Thread.currentThread().getName() +
2081                     ", setUseClientMode() invoked in state = " +
2082                     connectionState);
2083             }
2084 
2085             /*
2086              * We can let them continue if they catch this correctly,
2087              * we don't need to shut this down.
2088              */
2089             throw new IllegalArgumentException(
2090                 "Cannot change mode after SSL traffic has started");
2091         }
2092     }
2093 
2094     @Override
2095     public synchronized boolean getUseClientMode() {
2096         return !roleIsServer;
2097     }
2098 
2099 
2100     /**
2101      * Returns the names of the cipher suites which could be enabled for use
2102      * on an SSL connection.  Normally, only a subset of these will actually
2103      * be enabled by default, since this list may include cipher suites which
2104      * do not support the mutual authentication of servers and clients, or
2105      * which do not protect data confidentiality.  Servers may also need
2106      * certain kinds of certificates to use certain cipher suites.
2107      *
2108      * @return an array of cipher suite names
2109      */
2110     @Override
2111     public String[] getSupportedCipherSuites() {
2112         return sslContext.getSupportedCipherSuiteList().toStringArray();
2113     }
2114 
2115     /**
2116      * Controls which particular cipher suites are enabled for use on
2117      * this connection.  The cipher suites must have been listed by
2118      * getCipherSuites() as being supported.  Even if a suite has been
2119      * enabled, it might never be used if no peer supports it or the
2120      * requisite certificates (and private keys) are not available.
2121      *
2122      * @param suites Names of all the cipher suites to enable.
2123      */
2124     @Override
2125     public synchronized void setEnabledCipherSuites(String[] suites) {
2126         enabledCipherSuites = new CipherSuiteList(suites);
2127         if ((handshaker != null) && !handshaker.activated()) {
2128             handshaker.setEnabledCipherSuites(enabledCipherSuites);
2129         }
2130     }
2131 
2132     /**
2133      * Returns the names of the SSL cipher suites which are currently enabled
2134      * for use on this connection.  When an SSL engine is first created,
2135      * all enabled cipher suites <em>(a)</em> protect data confidentiality,
2136      * by traffic encryption, and <em>(b)</em> can mutually authenticate
2137      * both clients and servers.  Thus, in some environments, this value
2138      * might be empty.
2139      *
2140      * @return an array of cipher suite names
2141      */
2142     @Override
2143     public synchronized String[] getEnabledCipherSuites() {
2144         return enabledCipherSuites.toStringArray();
2145     }
2146 
2147 
2148     /**
2149      * Returns the protocols that are supported by this implementation.
2150      * A subset of the supported protocols may be enabled for this connection
2151      * @return an array of protocol names.
2152      */
2153     @Override
2154     public String[] getSupportedProtocols() {
2155         return sslContext.getSuportedProtocolList().toStringArray();
2156     }
2157 
2158     /**
2159      * Controls which protocols are enabled for use on
2160      * this connection.  The protocols must have been listed by
2161      * getSupportedProtocols() as being supported.
2162      *
2163      * @param protocols protocols to enable.
2164      * @exception IllegalArgumentException when one of the protocols
2165      *  named by the parameter is not supported.
2166      */
2167     @Override
2168     public synchronized void setEnabledProtocols(String[] protocols) {
2169         enabledProtocols = new ProtocolList(protocols);
2170         if ((handshaker != null) && !handshaker.activated()) {
2171             handshaker.setEnabledProtocols(enabledProtocols);
2172         }
2173     }
2174 
2175     @Override
2176     public synchronized String[] getEnabledProtocols() {
2177         return enabledProtocols.toStringArray();
2178     }
2179 
2180     /**
2181      * Returns the SSLParameters in effect for this SSLEngine.
2182      */
2183     @Override
2184     public synchronized SSLParameters getSSLParameters() {
2185         SSLParameters params = super.getSSLParameters();
2186 
2187         // the super implementation does not handle the following parameters
2188         params.setEndpointIdentificationAlgorithm(identificationProtocol);
2189         params.setAlgorithmConstraints(algorithmConstraints);
2190         params.setSNIMatchers(sniMatchers);
2191         params.setServerNames(serverNames);
2192         params.setUseCipherSuitesOrder(preferLocalCipherSuites);
2193         params.setEnableRetransmissions(enableRetransmissions);
2194         params.setMaximumPacketSize(maximumPacketSize);
2195         params.setApplicationProtocols(applicationProtocols);
2196 
2197         return params;
2198     }
2199 
2200     /**
2201      * Applies SSLParameters to this engine.
2202      */
2203     @Override
2204     public synchronized void setSSLParameters(SSLParameters params) {
2205         super.setSSLParameters(params);
2206 
2207         // the super implementation does not handle the following parameters
2208         identificationProtocol = params.getEndpointIdentificationAlgorithm();
2209         algorithmConstraints = params.getAlgorithmConstraints();
2210         preferLocalCipherSuites = params.getUseCipherSuitesOrder();
2211         enableRetransmissions = params.getEnableRetransmissions();
2212         maximumPacketSize = params.getMaximumPacketSize();
2213 
2214         if (maximumPacketSize != 0) {
2215             outputRecord.changePacketSize(maximumPacketSize);
2216         } else {
2217             // use the implicit maximum packet size.
2218             maximumPacketSize = outputRecord.getMaxPacketSize();
2219         }
2220 
2221         List<SNIServerName> sniNames = params.getServerNames();
2222         if (sniNames != null) {
2223             serverNames = sniNames;
2224         }
2225 
2226         Collection<SNIMatcher> matchers = params.getSNIMatchers();
2227         if (matchers != null) {
2228             sniMatchers = matchers;
2229         }
2230         applicationProtocols = params.getApplicationProtocols();
2231 
2232         if ((handshaker != null) && !handshaker.started()) {
2233             handshaker.setIdentificationProtocol(identificationProtocol);
2234             handshaker.setAlgorithmConstraints(algorithmConstraints);
2235             handshaker.setMaximumPacketSize(maximumPacketSize);
2236             handshaker.setApplicationProtocols(applicationProtocols);
2237             if (roleIsServer) {
2238                 handshaker.setSNIMatchers(sniMatchers);
2239                 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
2240             } else {
2241                 handshaker.setSNIServerNames(serverNames);
2242             }
2243         }
2244     }
2245 
2246     @Override
2247     public synchronized String getApplicationProtocol() {
2248         return applicationProtocol;
2249     }
2250 
2251     @Override
2252     public synchronized String getHandshakeApplicationProtocol() {
2253         if ((handshaker != null) && handshaker.started()) {
2254             return handshaker.getHandshakeApplicationProtocol();
2255         }
2256         return null;
2257     }
2258 
2259     /**
2260      * Returns a printable representation of this end of the connection.
2261      */
2262     @Override
2263     public String toString() {
2264         StringBuilder retval = new StringBuilder(80);
2265 
2266         retval.append(Integer.toHexString(hashCode()));
2267         retval.append("[");
2268         retval.append("SSLEngine[hostname=");
2269         String host = getPeerHost();
2270         retval.append((host == null) ? "null" : host);
2271         retval.append(" port=");
2272         retval.append(Integer.toString(getPeerPort()));
2273         retval.append(" role=" + (roleIsServer ? "Server" : "Client"));
2274         retval.append("] ");
2275         retval.append(getSession().getCipherSuite());
2276         retval.append("]");
2277 
2278         return retval.toString();
2279     }
2280 }
--- EOF ---