1 /*
   2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.io.IOException;
  29 import java.nio.ByteBuffer;
  30 import java.nio.ReadOnlyBufferException;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedActionException;
  33 import java.security.PrivilegedExceptionAction;
  34 import java.util.List;
  35 import java.util.Map;
  36 import java.util.concurrent.locks.ReentrantLock;
  37 import java.util.function.BiFunction;
  38 import javax.net.ssl.SSLEngine;
  39 import javax.net.ssl.SSLEngineResult;
  40 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
  41 import javax.net.ssl.SSLEngineResult.Status;
  42 import javax.net.ssl.SSLException;
  43 import javax.net.ssl.SSLHandshakeException;
  44 import javax.net.ssl.SSLKeyException;
  45 import javax.net.ssl.SSLParameters;
  46 import javax.net.ssl.SSLPeerUnverifiedException;
  47 import javax.net.ssl.SSLProtocolException;
  48 import javax.net.ssl.SSLSession;
  49 
  50 /**
  51  * Implementation of an non-blocking SSLEngine.
  52  *
  53  * @author Brad Wetmore
  54  */
  55 final class SSLEngineImpl extends SSLEngine implements SSLTransport {
  56     private final SSLContextImpl        sslContext;
  57     final TransportContext              conContext;
  58     private final ReentrantLock         engineLock = new ReentrantLock();
  59 
  60     /**
  61      * Constructor for an SSLEngine from SSLContext, without
  62      * host/port hints.
  63      *
  64      * This Engine will not be able to cache sessions, but must renegotiate
  65      * everything by hand.
  66      */
  67     SSLEngineImpl(SSLContextImpl sslContext) {
  68         this(sslContext, null, -1);
  69     }
  70 
  71     /**
  72      * Constructor for an SSLEngine from SSLContext.
  73      */
  74     SSLEngineImpl(SSLContextImpl sslContext,
  75             String host, int port) {
  76         super(host, port);
  77         this.sslContext = sslContext;
  78         HandshakeHash handshakeHash = new HandshakeHash();
  79         if (sslContext.isDTLS()) {
  80             this.conContext = new TransportContext(sslContext, this,
  81                     new DTLSInputRecord(handshakeHash),
  82                     new DTLSOutputRecord(handshakeHash));
  83         } else {
  84             this.conContext = new TransportContext(sslContext, this,
  85                     new SSLEngineInputRecord(handshakeHash),
  86                     new SSLEngineOutputRecord(handshakeHash));
  87         }
  88 
  89         // Server name indication is a connection scope extension.
  90         if (host != null) {
  91             this.conContext.sslConfig.serverNames =
  92                     Utilities.addToSNIServerNameList(
  93                             conContext.sslConfig.serverNames, host);
  94         }
  95     }
  96 
  97     @Override
  98     public void beginHandshake() throws SSLException {
  99         engineLock.lock();
 100         try {
 101             if (conContext.isUnsureMode) {
 102                 throw new IllegalStateException(
 103                         "Client/Server mode has not yet been set.");
 104             }
 105 
 106             try {
 107                 conContext.kickstart();
 108             } catch (IOException ioe) {
 109                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE,
 110                     "Couldn't kickstart handshaking", ioe);
 111             } catch (Exception ex) {     // including RuntimeException
 112                 throw conContext.fatal(Alert.INTERNAL_ERROR,
 113                     "Fail to begin handshake", ex);
 114             }
 115         } finally {
 116             engineLock.unlock();
 117         }
 118     }
 119 
 120     @Override
 121     public SSLEngineResult wrap(ByteBuffer[] appData,
 122             int offset, int length, ByteBuffer netData) throws SSLException {
 123         return wrap(appData, offset, length, new ByteBuffer[]{ netData }, 0, 1);
 124     }
 125 
 126     // @Override
 127     public SSLEngineResult wrap(
 128         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 129         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException {
 130 
 131         engineLock.lock();
 132         try {
 133             if (conContext.isUnsureMode) {
 134                 throw new IllegalStateException(
 135                         "Client/Server mode has not yet been set.");
 136             }
 137 
 138             // See if the handshaker needs to report back some SSLException.
 139             checkTaskThrown();
 140 
 141             // check parameters
 142             checkParams(srcs, srcsOffset, srcsLength,
 143                     dsts, dstsOffset, dstsLength);
 144 
 145             try {
 146                 return writeRecord(
 147                     srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
 148             } catch (SSLProtocolException spe) {
 149                 // may be an unexpected handshake message
 150                 throw conContext.fatal(Alert.UNEXPECTED_MESSAGE, spe);
 151             } catch (IOException ioe) {
 152                 throw conContext.fatal(Alert.INTERNAL_ERROR,
 153                     "problem wrapping app data", ioe);
 154             } catch (Exception ex) {     // including RuntimeException
 155                 throw conContext.fatal(Alert.INTERNAL_ERROR,
 156                     "Fail to wrap application data", ex);
 157             }
 158         } finally {
 159             engineLock.unlock();
 160         }
 161     }
 162 
 163     private SSLEngineResult writeRecord(
 164         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 165         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
 166 
 167         // May need to deliver cached records.
 168         if (isOutboundDone()) {
 169             return new SSLEngineResult(
 170                     Status.CLOSED, getHandshakeStatus(), 0, 0);
 171         }
 172 
 173         HandshakeContext hc = conContext.handshakeContext;
 174         HandshakeStatus hsStatus = null;
 175         if (!conContext.isNegotiated && !conContext.isBroken &&
 176                 !conContext.isInboundClosed() &&
 177                 !conContext.isOutboundClosed()) {
 178             conContext.kickstart();
 179 
 180             hsStatus = getHandshakeStatus();
 181             if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
 182                 /*
 183                  * For DTLS, if the handshake state is
 184                  * HandshakeStatus.NEED_UNWRAP, a call to SSLEngine.wrap()
 185                  * means that the previous handshake packets (if delivered)
 186                  * get lost, and need retransmit the handshake messages.
 187                  */
 188                 if (!sslContext.isDTLS() || hc == null ||
 189                         !hc.sslConfig.enableRetransmissions ||
 190                         conContext.outputRecord.firstMessage) {
 191 
 192                     return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
 193                 }   // otherwise, need retransmission
 194             }
 195         }
 196 
 197         if (hsStatus == null) {
 198             hsStatus = getHandshakeStatus();
 199         }
 200 
 201         /*
 202          * If we have a task outstanding, this *MUST* be done before
 203          * doing any more wrapping, because we could be in the middle
 204          * of receiving a handshake message, for example, a finished
 205          * message which would change the ciphers.
 206          */
 207         if (hsStatus == HandshakeStatus.NEED_TASK) {
 208             return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
 209         }
 210 
 211         int dstsRemains = 0;
 212         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
 213             dstsRemains += dsts[i].remaining();
 214         }
 215 
 216         // Check destination buffer size.
 217         //
 218         // We can be smarter about using smaller buffer sizes later.  For
 219         // now, force it to be large enough to handle any valid record.
 220         if (dstsRemains < conContext.conSession.getPacketBufferSize()) {
 221             return new SSLEngineResult(
 222                 Status.BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
 223         }
 224 
 225         int srcsRemains = 0;
 226         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
 227             srcsRemains += srcs[i].remaining();
 228         }
 229 
 230         Ciphertext ciphertext = null;
 231         try {
 232             // Acquire the buffered to-be-delivered records or retransmissions.
 233             //
 234             // May have buffered records, or need retransmission if handshaking.
 235             if (!conContext.outputRecord.isEmpty() || (hc != null &&
 236                     hc.sslConfig.enableRetransmissions &&
 237                     hc.sslContext.isDTLS() &&
 238                     hsStatus == HandshakeStatus.NEED_UNWRAP)) {
 239                 ciphertext = encode(null, 0, 0,
 240                         dsts, dstsOffset, dstsLength);
 241             }
 242 
 243             if (ciphertext == null && srcsRemains != 0) {
 244                 ciphertext = encode(srcs, srcsOffset, srcsLength,
 245                         dsts, dstsOffset, dstsLength);
 246             }
 247         } catch (IOException ioe) {
 248             if (ioe instanceof SSLException) {
 249                 throw ioe;
 250             } else {
 251                 throw new SSLException("Write problems", ioe);
 252             }
 253         }
 254 
 255         /*
 256          * Check for status.
 257          */
 258         Status status = (isOutboundDone() ? Status.CLOSED : Status.OK);
 259         if (ciphertext != null && ciphertext.handshakeStatus != null) {
 260             hsStatus = ciphertext.handshakeStatus;
 261         } else {
 262             hsStatus = getHandshakeStatus();
 263             if (ciphertext == null && !conContext.isNegotiated &&
 264                     conContext.isInboundClosed() &&
 265                     hsStatus == HandshakeStatus.NEED_WRAP) {
 266                 // Even the outboud is open, no futher data could be wrapped as:
 267                 //     1. the outbound is empty
 268                 //     2. no negotiated connection
 269                 //     3. the inbound has closed, cannot complete the handshake
 270                 //
 271                 // Mark the engine as closed if the handshake status is
 272                 // NEED_WRAP. Otherwise, it could lead to dead loops in
 273                 // applications.
 274                 status = Status.CLOSED;
 275             }
 276         }
 277 
 278         int deltaSrcs = srcsRemains;
 279         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
 280             deltaSrcs -= srcs[i].remaining();
 281         }
 282 
 283         int deltaDsts = dstsRemains;
 284         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
 285             deltaDsts -= dsts[i].remaining();
 286         }
 287 
 288         return new SSLEngineResult(status, hsStatus, deltaSrcs, deltaDsts,
 289                 ciphertext != null ? ciphertext.recordSN : -1L);
 290     }
 291 
 292     private Ciphertext encode(
 293         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 294         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
 295 
 296         Ciphertext ciphertext = null;
 297         try {
 298             ciphertext = conContext.outputRecord.encode(
 299                 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
 300         } catch (SSLHandshakeException she) {
 301             // may be record sequence number overflow
 302             throw conContext.fatal(Alert.HANDSHAKE_FAILURE, she);
 303         } catch (IOException e) {
 304             throw conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
 305         }
 306 
 307         if (ciphertext == null) {
 308             return null;
 309         }
 310 
 311         // Is the handshake completed?
 312         boolean needRetransmission =
 313                 conContext.sslContext.isDTLS() &&
 314                 conContext.handshakeContext != null &&
 315                 conContext.handshakeContext.sslConfig.enableRetransmissions;
 316         HandshakeStatus hsStatus =
 317                 tryToFinishHandshake(ciphertext.contentType);
 318         if (needRetransmission &&
 319                 hsStatus == HandshakeStatus.FINISHED &&
 320                 conContext.sslContext.isDTLS() &&
 321                 ciphertext.handshakeType == SSLHandshake.FINISHED.id) {
 322             // Retransmit the last flight for DTLS.
 323             //
 324             // The application data transactions may begin immediately
 325             // after the last flight.  If the last flight get lost, the
 326             // application data may be discarded accordingly.  As could
 327             // be an issue for some applications.  This impact can be
 328             // mitigated by sending the last fligth twice.
 329             if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) {
 330                 SSLLogger.finest("retransmit the last flight messages");
 331             }
 332 
 333             conContext.outputRecord.launchRetransmission();
 334             hsStatus = HandshakeStatus.NEED_WRAP;
 335         }
 336 
 337         if (hsStatus == null) {
 338             hsStatus = conContext.getHandshakeStatus();
 339         }
 340 
 341         // Is the sequence number is nearly overflow?
 342         if (conContext.outputRecord.seqNumIsHuge() ||
 343                 conContext.outputRecord.writeCipher.atKeyLimit()) {
 344             hsStatus = tryKeyUpdate(hsStatus);
 345         }
 346 
 347         // update context status
 348         ciphertext.handshakeStatus = hsStatus;
 349 
 350         return ciphertext;
 351     }
 352 
 353     private HandshakeStatus tryToFinishHandshake(byte contentType) {
 354         HandshakeStatus hsStatus = null;
 355         if ((contentType == ContentType.HANDSHAKE.id) &&
 356                 conContext.outputRecord.isEmpty()) {
 357             if (conContext.handshakeContext == null) {
 358                 hsStatus = HandshakeStatus.FINISHED;
 359             } else if (conContext.isPostHandshakeContext()) {
 360                 // unlikely, but just in case.
 361                 hsStatus = conContext.finishPostHandshake();
 362             } else if (conContext.handshakeContext.handshakeFinished) {
 363                 hsStatus = conContext.finishHandshake();
 364             }
 365         }   // Otherwise, the followed call to getHSStatus() will help.
 366 
 367         return hsStatus;
 368     }
 369 
 370     /**
 371      * Try key update for sequence number wrap or key usage limit.
 372      *
 373      * Note that in order to maintain the handshake status properly, we check
 374      * the sequence number and key usage limit after the last record
 375      * reading/writing process.
 376      *
 377      * As we request renegotiation or close the connection for wrapped sequence
 378      * number when there is enough sequence number space left to handle a few
 379      * more records, so the sequence number of the last record cannot be
 380      * wrapped.
 381      */
 382     private HandshakeStatus tryKeyUpdate(
 383             HandshakeStatus currentHandshakeStatus) throws IOException {
 384         // Don't bother to kickstart if handshaking is in progress, or if the
 385         // connection is not duplex-open.
 386         if ((conContext.handshakeContext == null) &&
 387                 !conContext.isOutboundClosed() &&
 388                 !conContext.isInboundClosed() &&
 389                 !conContext.isBroken) {
 390             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 391                 SSLLogger.finest("trigger key update");
 392             }
 393             beginHandshake();
 394             return conContext.getHandshakeStatus();
 395         }
 396 
 397         return currentHandshakeStatus;
 398     }
 399 
 400     private static void checkParams(
 401             ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 402             ByteBuffer[] dsts, int dstsOffset, int dstsLength) {
 403 
 404         if ((srcs == null) || (dsts == null)) {
 405             throw new IllegalArgumentException(
 406                     "source or destination buffer is null");
 407         }
 408 
 409         if ((dstsOffset < 0) || (dstsLength < 0) ||
 410                 (dstsOffset > dsts.length - dstsLength)) {
 411             throw new IndexOutOfBoundsException(
 412                     "index out of bound of the destination buffers");
 413         }
 414 
 415         if ((srcsOffset < 0) || (srcsLength < 0) ||
 416                 (srcsOffset > srcs.length - srcsLength)) {
 417             throw new IndexOutOfBoundsException(
 418                     "index out of bound of the source buffers");
 419         }
 420 
 421         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
 422             if (dsts[i] == null) {
 423                 throw new IllegalArgumentException(
 424                         "destination buffer[" + i + "] == null");
 425             }
 426 
 427             /*
 428              * Make sure the destination bufffers are writable.
 429              */
 430             if (dsts[i].isReadOnly()) {
 431                 throw new ReadOnlyBufferException();
 432             }
 433         }
 434 
 435         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
 436             if (srcs[i] == null) {
 437                 throw new IllegalArgumentException(
 438                         "source buffer[" + i + "] == null");
 439             }
 440         }
 441     }
 442 
 443     @Override
 444     public SSLEngineResult unwrap(ByteBuffer src,
 445             ByteBuffer[] dsts, int offset, int length) throws SSLException {
 446         return unwrap(
 447                 new ByteBuffer[]{src}, 0, 1, dsts, offset, length);
 448     }
 449 
 450     // @Override
 451     public SSLEngineResult unwrap(
 452         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 453         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException {
 454 
 455         engineLock.lock();
 456         try {
 457             if (conContext.isUnsureMode) {
 458                 throw new IllegalStateException(
 459                         "Client/Server mode has not yet been set.");
 460             }
 461 
 462             // See if the handshaker needs to report back some SSLException.
 463             checkTaskThrown();
 464 
 465             // check parameters
 466             checkParams(srcs, srcsOffset, srcsLength,
 467                     dsts, dstsOffset, dstsLength);
 468 
 469             try {
 470                 return readRecord(
 471                     srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
 472             } catch (SSLProtocolException spe) {
 473                 // may be an unexpected handshake message
 474                 throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
 475                         spe.getMessage(), spe);
 476             } catch (IOException ioe) {
 477                 /*
 478                  * Don't reset position so it looks like we didn't
 479                  * consume anything.  We did consume something, and it
 480                  * got us into this situation, so report that much back.
 481                  * Our days of consuming are now over anyway.
 482                  */
 483                 throw conContext.fatal(Alert.INTERNAL_ERROR,
 484                         "problem unwrapping net record", ioe);
 485             } catch (Exception ex) {     // including RuntimeException
 486                 throw conContext.fatal(Alert.INTERNAL_ERROR,
 487                     "Fail to unwrap network record", ex);
 488             }
 489         } finally {
 490             engineLock.unlock();
 491         }
 492     }
 493 
 494     private SSLEngineResult readRecord(
 495         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 496         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
 497 
 498         /*
 499          * Check if we are closing/closed.
 500          */
 501         if (isInboundDone()) {
 502             return new SSLEngineResult(
 503                     Status.CLOSED, getHandshakeStatus(), 0, 0);
 504         }
 505 
 506         HandshakeStatus hsStatus = null;
 507         if (!conContext.isNegotiated && !conContext.isBroken &&
 508                 !conContext.isInboundClosed() &&
 509                 !conContext.isOutboundClosed()) {
 510             conContext.kickstart();
 511 
 512             /*
 513              * If there's still outbound data to flush, we
 514              * can return without trying to unwrap anything.
 515              */
 516             hsStatus = getHandshakeStatus();
 517             if (hsStatus == HandshakeStatus.NEED_WRAP) {
 518                 return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
 519             }
 520         }
 521 
 522         if (hsStatus == null) {
 523             hsStatus = getHandshakeStatus();
 524         }
 525 
 526         /*
 527          * If we have a task outstanding, this *MUST* be done before
 528          * doing any more unwrapping, because we could be in the middle
 529          * of receiving a handshake message, for example, a finished
 530          * message which would change the ciphers.
 531          */
 532         if (hsStatus == HandshakeStatus.NEED_TASK) {
 533             return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
 534         }
 535 
 536         if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
 537             Plaintext plainText = null;
 538             try {
 539                 plainText = decode(null, 0, 0,
 540                         dsts, dstsOffset, dstsLength);
 541             } catch (IOException ioe) {
 542                 if (ioe instanceof SSLException) {
 543                     throw ioe;
 544                 } else {
 545                     throw new SSLException("readRecord", ioe);
 546                 }
 547             }
 548 
 549             Status status = (isInboundDone() ? Status.CLOSED : Status.OK);
 550             if (plainText.handshakeStatus != null) {
 551                 hsStatus = plainText.handshakeStatus;
 552             } else {
 553                 hsStatus = getHandshakeStatus();
 554             }
 555 
 556             return new SSLEngineResult(
 557                     status, hsStatus, 0, 0, plainText.recordSN);
 558         }
 559 
 560         int srcsRemains = 0;
 561         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
 562             srcsRemains += srcs[i].remaining();
 563         }
 564 
 565         if (srcsRemains == 0) {
 566             return new SSLEngineResult(
 567                 Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
 568         }
 569 
 570         /*
 571          * Check the packet to make sure enough is here.
 572          * This will also indirectly check for 0 len packets.
 573          */
 574         int packetLen = 0;
 575         try {
 576             packetLen = conContext.inputRecord.bytesInCompletePacket(
 577                     srcs, srcsOffset, srcsLength);
 578         } catch (SSLException ssle) {
 579             // Need to discard invalid records for DTLS protocols.
 580             if (sslContext.isDTLS()) {
 581                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) {
 582                     SSLLogger.finest("Discard invalid DTLS records", ssle);
 583                 }
 584 
 585                 // invalid, discard the entire data [section 4.1.2.7, RFC 6347]
 586                 int deltaNet = 0;
 587                 // int deltaNet = netData.remaining();
 588                 // netData.position(netData.limit());
 589 
 590                 Status status = (isInboundDone() ? Status.CLOSED : Status.OK);
 591                 if (hsStatus == null) {
 592                     hsStatus = getHandshakeStatus();
 593                 }
 594 
 595                 return new SSLEngineResult(status, hsStatus, deltaNet, 0, -1L);
 596             } else {
 597                 throw ssle;
 598             }
 599         }
 600 
 601         // Is this packet bigger than SSL/TLS normally allows?
 602         if (packetLen > conContext.conSession.getPacketBufferSize()) {
 603             int largestRecordSize = sslContext.isDTLS() ?
 604                     DTLSRecord.maxRecordSize : SSLRecord.maxLargeRecordSize;
 605             if ((packetLen <= largestRecordSize) && !sslContext.isDTLS()) {
 606                 // Expand the expected maximum packet/application buffer
 607                 // sizes.
 608                 //
 609                 // Only apply to SSL/TLS protocols.
 610 
 611                 // Old behavior: shall we honor the System Property
 612                 // "jsse.SSLEngine.acceptLargeFragments" if it is "false"?
 613                 conContext.conSession.expandBufferSizes();
 614             }
 615 
 616             // check the packet again
 617             largestRecordSize = conContext.conSession.getPacketBufferSize();
 618             if (packetLen > largestRecordSize) {
 619                 throw new SSLProtocolException(
 620                         "Input record too big: max = " +
 621                         largestRecordSize + " len = " + packetLen);
 622             }
 623         }
 624 
 625         /*
 626          * Check for OVERFLOW.
 627          *
 628          * Delay enforcing the application buffer free space requirement
 629          * until after the initial handshaking.
 630          */
 631         int dstsRemains = 0;
 632         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
 633             dstsRemains += dsts[i].remaining();
 634         }
 635 
 636         if (conContext.isNegotiated) {
 637             int FragLen =
 638                     conContext.inputRecord.estimateFragmentSize(packetLen);
 639             if (FragLen > dstsRemains) {
 640                 return new SSLEngineResult(
 641                         Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
 642             }
 643         }
 644 
 645         // check for UNDERFLOW.
 646         if ((packetLen == -1) || (srcsRemains < packetLen)) {
 647             return new SSLEngineResult(Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
 648         }
 649 
 650         /*
 651          * We're now ready to actually do the read.
 652          */
 653         Plaintext plainText = null;
 654         try {
 655             plainText = decode(srcs, srcsOffset, srcsLength,
 656                             dsts, dstsOffset, dstsLength);
 657         } catch (IOException ioe) {
 658             if (ioe instanceof SSLException) {
 659                 throw ioe;
 660             } else {
 661                 throw new SSLException("readRecord", ioe);
 662             }
 663         }
 664 
 665         /*
 666          * Check the various condition that we could be reporting.
 667          *
 668          * It's *possible* something might have happened between the
 669          * above and now, but it was better to minimally lock "this"
 670          * during the read process.  We'll return the current
 671          * status, which is more representative of the current state.
 672          *
 673          * status above should cover:  FINISHED, NEED_TASK
 674          */
 675         Status status = (isInboundDone() ? Status.CLOSED : Status.OK);
 676         if (plainText.handshakeStatus != null) {
 677             hsStatus = plainText.handshakeStatus;
 678         } else {
 679             hsStatus = getHandshakeStatus();
 680         }
 681 
 682         int deltaNet = srcsRemains;
 683         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
 684             deltaNet -= srcs[i].remaining();
 685         }
 686 
 687         int deltaApp = dstsRemains;
 688         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
 689             deltaApp -= dsts[i].remaining();
 690         }
 691 
 692         return new SSLEngineResult(
 693                 status, hsStatus, deltaNet, deltaApp, plainText.recordSN);
 694     }
 695 
 696     private Plaintext decode(
 697         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
 698         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
 699 
 700         Plaintext pt = SSLTransport.decode(conContext,
 701                             srcs, srcsOffset, srcsLength,
 702                             dsts, dstsOffset, dstsLength);
 703 
 704         // Is the handshake completed?
 705         if (pt != Plaintext.PLAINTEXT_NULL) {
 706             HandshakeStatus hsStatus = tryToFinishHandshake(pt.contentType);
 707             if (hsStatus == null) {
 708                 pt.handshakeStatus = conContext.getHandshakeStatus();
 709             } else {
 710                 pt.handshakeStatus = hsStatus;
 711             }
 712 
 713             // Is the sequence number is nearly overflow?
 714             if (conContext.inputRecord.seqNumIsHuge() ||
 715                     conContext.inputRecord.readCipher.atKeyLimit()) {
 716                 pt.handshakeStatus =
 717                         tryKeyUpdate(pt.handshakeStatus);
 718             }
 719         }
 720 
 721         return pt;
 722     }
 723 
 724     @Override
 725     public Runnable getDelegatedTask() {
 726         engineLock.lock();
 727         try {
 728             if (conContext.handshakeContext != null && // PRE or POST handshake
 729                     !conContext.handshakeContext.taskDelegated &&
 730                     !conContext.handshakeContext.delegatedActions.isEmpty()) {
 731                 conContext.handshakeContext.taskDelegated = true;
 732                 return new DelegatedTask(this);
 733             }
 734         } finally {
 735             engineLock.unlock();
 736         }
 737 
 738         return null;
 739     }
 740 
 741     @Override
 742     public void closeInbound() throws SSLException {
 743         engineLock.lock();
 744         try {
 745             if (isInboundDone()) {
 746                 return;
 747             }
 748 
 749             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 750                 SSLLogger.finest("Closing inbound of SSLEngine");
 751             }
 752 
 753             // Is it ready to close inbound?
 754             //
 755             // No exception if the initial handshake is not started.
 756             if (!conContext.isInputCloseNotified &&
 757                 (conContext.isNegotiated ||
 758                     conContext.handshakeContext != null)) {
 759 
 760                 throw conContext.fatal(Alert.INTERNAL_ERROR,
 761                         "closing inbound before receiving peer's close_notify");
 762             }
 763 
 764             conContext.closeInbound();
 765         } finally {
 766             engineLock.unlock();
 767         }
 768     }
 769 
 770     @Override
 771     public boolean isInboundDone() {
 772         engineLock.lock();
 773         try {
 774             return conContext.isInboundClosed();
 775         } finally {
 776             engineLock.unlock();
 777         }
 778     }
 779 
 780     @Override
 781     public void closeOutbound() {
 782         engineLock.lock();
 783         try {
 784             if (conContext.isOutboundClosed()) {
 785                 return;
 786             }
 787 
 788             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 789                 SSLLogger.finest("Closing outbound of SSLEngine");
 790             }
 791 
 792             conContext.closeOutbound();
 793         } finally {
 794             engineLock.unlock();
 795         }
 796     }
 797 
 798     @Override
 799     public boolean isOutboundDone() {
 800         engineLock.lock();
 801         try {
 802             return conContext.isOutboundDone();
 803         } finally {
 804             engineLock.unlock();
 805         }
 806     }
 807 
 808     @Override
 809     public String[] getSupportedCipherSuites() {
 810         return CipherSuite.namesOf(sslContext.getSupportedCipherSuites());
 811     }
 812 
 813     @Override
 814     public String[] getEnabledCipherSuites() {
 815         engineLock.lock();
 816         try {
 817             return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites);
 818         } finally {
 819             engineLock.unlock();
 820         }
 821     }
 822 
 823     @Override
 824     public void setEnabledCipherSuites(String[] suites) {
 825         engineLock.lock();
 826         try {
 827             conContext.sslConfig.enabledCipherSuites =
 828                     CipherSuite.validValuesOf(suites);
 829         } finally {
 830             engineLock.unlock();
 831         }
 832     }
 833 
 834     @Override
 835     public String[] getSupportedProtocols() {
 836         return ProtocolVersion.toStringArray(
 837                 sslContext.getSupportedProtocolVersions());
 838     }
 839 
 840     @Override
 841     public String[] getEnabledProtocols() {
 842         engineLock.lock();
 843         try {
 844             return ProtocolVersion.toStringArray(
 845                     conContext.sslConfig.enabledProtocols);
 846         } finally {
 847             engineLock.unlock();
 848         }
 849     }
 850 
 851     @Override
 852     public void setEnabledProtocols(String[] protocols) {
 853         engineLock.lock();
 854         try {
 855             if (protocols == null) {
 856                 throw new IllegalArgumentException("Protocols cannot be null");
 857             }
 858 
 859             conContext.sslConfig.enabledProtocols =
 860                     ProtocolVersion.namesOf(protocols);
 861         } finally {
 862             engineLock.unlock();
 863         }
 864     }
 865 
 866     @Override
 867     public SSLSession getSession() {
 868         engineLock.lock();
 869         try {
 870             return conContext.conSession;
 871         } finally {
 872             engineLock.unlock();
 873         }
 874     }
 875 
 876     @Override
 877     public SSLSession getHandshakeSession() {
 878         engineLock.lock();
 879         try {
 880             return conContext.handshakeContext == null ?
 881                     null : conContext.handshakeContext.handshakeSession;
 882         } finally {
 883             engineLock.unlock();
 884         }
 885     }
 886 
 887     @Override
 888     public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
 889         engineLock.lock();
 890         try {
 891             return conContext.getHandshakeStatus();
 892         } finally {
 893             engineLock.unlock();
 894         }
 895     }
 896 
 897     @Override
 898     public void setUseClientMode(boolean mode) {
 899         engineLock.lock();
 900         try {
 901             conContext.setUseClientMode(mode);
 902         } finally {
 903             engineLock.unlock();
 904         }
 905     }
 906 
 907     @Override
 908     public boolean getUseClientMode() {
 909         engineLock.lock();
 910         try {
 911             return conContext.sslConfig.isClientMode;
 912         } finally {
 913             engineLock.unlock();
 914         }
 915     }
 916 
 917     @Override
 918     public void setNeedClientAuth(boolean need) {
 919         engineLock.lock();
 920         try {
 921             conContext.sslConfig.clientAuthType =
 922                     (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
 923                             ClientAuthType.CLIENT_AUTH_NONE);
 924         } finally {
 925             engineLock.unlock();
 926         }
 927     }
 928 
 929     @Override
 930     public boolean getNeedClientAuth() {
 931         engineLock.lock();
 932         try {
 933             return (conContext.sslConfig.clientAuthType ==
 934                             ClientAuthType.CLIENT_AUTH_REQUIRED);
 935         } finally {
 936             engineLock.unlock();
 937         }
 938     }
 939 
 940     @Override
 941     public void setWantClientAuth(boolean want) {
 942         engineLock.lock();
 943         try {
 944             conContext.sslConfig.clientAuthType =
 945                     (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
 946                             ClientAuthType.CLIENT_AUTH_NONE);
 947         } finally {
 948             engineLock.unlock();
 949         }
 950     }
 951 
 952     @Override
 953     public boolean getWantClientAuth() {
 954         engineLock.lock();
 955         try {
 956             return (conContext.sslConfig.clientAuthType ==
 957                             ClientAuthType.CLIENT_AUTH_REQUESTED);
 958         } finally {
 959             engineLock.unlock();
 960         }
 961     }
 962 
 963     @Override
 964     public void setEnableSessionCreation(boolean flag) {
 965         engineLock.lock();
 966         try {
 967             conContext.sslConfig.enableSessionCreation = flag;
 968         } finally {
 969             engineLock.unlock();
 970         }
 971     }
 972 
 973     @Override
 974     public boolean getEnableSessionCreation() {
 975         engineLock.lock();
 976         try {
 977             return conContext.sslConfig.enableSessionCreation;
 978         } finally {
 979             engineLock.unlock();
 980         }
 981     }
 982 
 983     @Override
 984     public SSLParameters getSSLParameters() {
 985         engineLock.lock();
 986         try {
 987             return conContext.sslConfig.getSSLParameters();
 988         } finally {
 989             engineLock.unlock();
 990         }
 991    }
 992 
 993     @Override
 994     public void setSSLParameters(SSLParameters params) {
 995         engineLock.lock();
 996         try {
 997             conContext.sslConfig.setSSLParameters(params);
 998 
 999             if (conContext.sslConfig.maximumPacketSize != 0) {
1000                 conContext.outputRecord.changePacketSize(
1001                         conContext.sslConfig.maximumPacketSize);
1002             }
1003         } finally {
1004             engineLock.unlock();
1005         }
1006    }
1007 
1008     @Override
1009     public String getApplicationProtocol() {
1010         engineLock.lock();
1011         try {
1012             return conContext.applicationProtocol;
1013         } finally {
1014             engineLock.unlock();
1015         }
1016     }
1017 
1018     @Override
1019     public String getHandshakeApplicationProtocol() {
1020         engineLock.lock();
1021         try {
1022             return conContext.handshakeContext == null ?
1023                     null : conContext.handshakeContext.applicationProtocol;
1024         } finally {
1025             engineLock.unlock();
1026         }
1027     }
1028 
1029     @Override
1030     public void setHandshakeApplicationProtocolSelector(
1031             BiFunction<SSLEngine, List<String>, String> selector) {
1032         engineLock.lock();
1033         try {
1034             conContext.sslConfig.engineAPSelector = selector;
1035         } finally {
1036             engineLock.unlock();
1037         }
1038     }
1039 
1040     @Override
1041     public BiFunction<SSLEngine, List<String>, String>
1042             getHandshakeApplicationProtocolSelector() {
1043         engineLock.lock();
1044         try {
1045             return conContext.sslConfig.engineAPSelector;
1046         } finally {
1047             engineLock.unlock();
1048         }
1049     }
1050 
1051     @Override
1052     public boolean useDelegatedTask() {
1053         return true;
1054     }
1055 
1056     /*
1057      * Depending on whether the error was just a warning and the
1058      * handshaker wasn't closed, or fatal and the handshaker is now
1059      * null, report back the Exception that happened in the delegated
1060      * task(s).
1061      */
1062     private void checkTaskThrown() throws SSLException {
1063 
1064         Exception exc = null;
1065         engineLock.lock();
1066         try {
1067             // First check the handshake context.
1068             HandshakeContext hc = conContext.handshakeContext;
1069             if ((hc != null) && (hc.delegatedThrown != null)) {
1070                 exc = hc.delegatedThrown;
1071                 hc.delegatedThrown = null;
1072             }
1073 
1074             /*
1075              * hc.delegatedThrown and conContext.delegatedThrown are most
1076              * likely the same, but it's possible we could have had a non-fatal
1077              * exception and thus the new HandshakeContext is still valid
1078              * (alert warning).  If so, then we may have a secondary exception
1079              * waiting to be reported from the TransportContext, so we will
1080              * need to clear that on a successive call. Otherwise, clear it now.
1081              */
1082             if (conContext.delegatedThrown != null) {
1083                 if (exc != null) {
1084                     // hc object comparison
1085                     if (conContext.delegatedThrown == exc) {
1086                         // clear if/only if both are the same
1087                         conContext.delegatedThrown = null;
1088                     } // otherwise report the hc delegatedThrown
1089                 } else {
1090                     // Nothing waiting in HandshakeContext, but one is in the
1091                     // TransportContext.
1092                     exc = conContext.delegatedThrown;
1093                     conContext.delegatedThrown = null;
1094                 }
1095             }
1096         } finally {
1097             engineLock.unlock();
1098         }
1099 
1100         // Anything to report?
1101         if (exc == null) {
1102             return;
1103         }
1104 
1105         // If it wasn't a RuntimeException/SSLException, need to wrap it.
1106         if (exc instanceof SSLException) {
1107             throw (SSLException)exc;
1108         } else if (exc instanceof RuntimeException) {
1109             throw (RuntimeException)exc;
1110         } else {
1111             throw getTaskThrown(exc);
1112         }
1113     }
1114 
1115     private static SSLException getTaskThrown(Exception taskThrown) {
1116         String msg = taskThrown.getMessage();
1117 
1118         if (msg == null) {
1119             msg = "Delegated task threw Exception or Error";
1120         }
1121 
1122         if (taskThrown instanceof RuntimeException) {
1123             throw new RuntimeException(msg, taskThrown);
1124         } else if (taskThrown instanceof SSLHandshakeException) {
1125             return (SSLHandshakeException)
1126                 new SSLHandshakeException(msg).initCause(taskThrown);
1127         } else if (taskThrown instanceof SSLKeyException) {
1128             return (SSLKeyException)
1129                 new SSLKeyException(msg).initCause(taskThrown);
1130         } else if (taskThrown instanceof SSLPeerUnverifiedException) {
1131             return (SSLPeerUnverifiedException)
1132                 new SSLPeerUnverifiedException(msg).initCause(taskThrown);
1133         } else if (taskThrown instanceof SSLProtocolException) {
1134             return (SSLProtocolException)
1135                 new SSLProtocolException(msg).initCause(taskThrown);
1136         } else if (taskThrown instanceof SSLException) {
1137             return (SSLException)taskThrown;
1138         } else {
1139             return new SSLException(msg, taskThrown);
1140         }
1141     }
1142 
1143     /**
1144      * Implement a simple task delegator.
1145      */
1146     private static class DelegatedTask implements Runnable {
1147         private final SSLEngineImpl engine;
1148 
1149         DelegatedTask(SSLEngineImpl engineInstance) {
1150             this.engine = engineInstance;
1151         }
1152 
1153         @Override
1154         public void run() {
1155             engine.engineLock.lock();
1156             try {
1157                 HandshakeContext hc = engine.conContext.handshakeContext;
1158                 if (hc == null || hc.delegatedActions.isEmpty()) {
1159                     return;
1160                 }
1161 
1162                 try {
1163                     AccessController.doPrivileged(
1164                             new DelegatedAction(hc), engine.conContext.acc);
1165                 } catch (PrivilegedActionException pae) {
1166                     // Get the handshake context again in case the
1167                     // handshaking has completed.
1168                     Exception reportedException = pae.getException();
1169 
1170                     // Report to both the TransportContext...
1171                     if (engine.conContext.delegatedThrown == null) {
1172                         engine.conContext.delegatedThrown = reportedException;
1173                     }
1174 
1175                     // ...and the HandshakeContext in case condition
1176                     // wasn't fatal and the handshakeContext is still
1177                     // around.
1178                     hc = engine.conContext.handshakeContext;
1179                     if (hc != null) {
1180                         hc.delegatedThrown = reportedException;
1181                     } else if (engine.conContext.closeReason != null) {
1182                         // Update the reason in case there was a previous.
1183                         engine.conContext.closeReason =
1184                                 getTaskThrown(reportedException);
1185                     }
1186                 } catch (RuntimeException rte) {
1187                     // Get the handshake context again in case the
1188                     // handshaking has completed.
1189 
1190                     // Report to both the TransportContext...
1191                     if (engine.conContext.delegatedThrown == null) {
1192                         engine.conContext.delegatedThrown = rte;
1193                     }
1194 
1195                     // ...and the HandshakeContext in case condition
1196                     // wasn't fatal and the handshakeContext is still
1197                     // around.
1198                     hc = engine.conContext.handshakeContext;
1199                     if (hc != null) {
1200                         hc.delegatedThrown = rte;
1201                     } else if (engine.conContext.closeReason != null) {
1202                         // Update the reason in case there was a previous.
1203                         engine.conContext.closeReason = rte;
1204                     }
1205                 }
1206 
1207                 // Get the handshake context again in case the
1208                 // handshaking has completed.
1209                 hc = engine.conContext.handshakeContext;
1210                 if (hc != null) {
1211                     hc.taskDelegated = false;
1212                 }
1213             } finally {
1214                 engine.engineLock.unlock();
1215             }
1216         }
1217 
1218         private static class DelegatedAction
1219                 implements PrivilegedExceptionAction<Void> {
1220             final HandshakeContext context;
1221             DelegatedAction(HandshakeContext context) {
1222                 this.context = context;
1223             }
1224 
1225             @Override
1226             public Void run() throws Exception {
1227                 while (!context.delegatedActions.isEmpty()) {
1228                     Map.Entry<Byte, ByteBuffer> me =
1229                             context.delegatedActions.poll();
1230                     if (me != null) {
1231                         context.dispatch(me.getKey(), me.getValue());
1232                     }
1233                 }
1234                 return null;
1235             }
1236         }
1237     }
1238 }