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