OpenSSLEngineImpl.java revision 5ac8e317836e901e7b241b224b92f00cba2ed701
1/* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * Copyright 2016 The Netty Project 19 * 20 * The Netty Project licenses this file to you under the Apache License, 21 * version 2.0 (the "License"); you may not use this file except in compliance 22 * with the License. You may obtain a copy of the License at: 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 28 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 29 * License for the specific language governing permissions and limitations 30 * under the License. 31 */ 32 33package org.conscrypt; 34 35import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED; 36import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP; 37import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP; 38import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING; 39import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW; 40import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW; 41import static javax.net.ssl.SSLEngineResult.Status.CLOSED; 42import static javax.net.ssl.SSLEngineResult.Status.OK; 43import static org.conscrypt.NativeConstants.SSL3_RT_HEADER_LENGTH; 44import static org.conscrypt.NativeConstants.SSL3_RT_MAX_PACKET_SIZE; 45import static org.conscrypt.NativeConstants.SSL3_RT_MAX_PLAIN_LENGTH; 46import static org.conscrypt.NativeConstants.SSL_CB_HANDSHAKE_DONE; 47import static org.conscrypt.NativeConstants.SSL_CB_HANDSHAKE_START; 48import static org.conscrypt.NativeConstants.SSL_ERROR_NONE; 49import static org.conscrypt.NativeConstants.SSL_ERROR_WANT_READ; 50import static org.conscrypt.NativeConstants.SSL_ERROR_WANT_WRITE; 51import static org.conscrypt.NativeConstants.SSL_ERROR_ZERO_RETURN; 52import static org.conscrypt.NativeConstants.SSL_RECEIVED_SHUTDOWN; 53import static org.conscrypt.NativeConstants.SSL_SENT_SHUTDOWN; 54import static org.conscrypt.SSLUtils.calculateOutNetBufSize; 55import static org.conscrypt.SSLUtils.toSSLHandshakeException; 56 57import java.io.IOException; 58import java.nio.ByteBuffer; 59import java.nio.ReadOnlyBufferException; 60import java.security.cert.CertificateEncodingException; 61import java.security.cert.CertificateException; 62import javax.crypto.SecretKey; 63import javax.net.ssl.SSLEngine; 64import javax.net.ssl.SSLEngineResult; 65import javax.net.ssl.SSLEngineResult.HandshakeStatus; 66import javax.net.ssl.SSLEngineResult.Status; 67import javax.net.ssl.SSLException; 68import javax.net.ssl.SSLHandshakeException; 69import javax.net.ssl.SSLSession; 70import javax.net.ssl.X509ExtendedKeyManager; 71import javax.net.ssl.X509KeyManager; 72import javax.net.ssl.X509TrustManager; 73import javax.security.auth.x500.X500Principal; 74 75/** 76 * Implements the {@link SSLEngine} API using OpenSSL's non-blocking interfaces. 77 */ 78public final class OpenSSLEngineImpl extends SSLEngine 79 implements NativeCrypto.SSLHandshakeCallbacks, SSLParametersImpl.AliasChooser, 80 SSLParametersImpl.PSKCallbacks { 81 private static final SSLEngineResult NEED_UNWRAP_OK = 82 new SSLEngineResult(OK, NEED_UNWRAP, 0, 0); 83 private static final SSLEngineResult NEED_UNWRAP_CLOSED = 84 new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0); 85 private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0); 86 private static final SSLEngineResult NEED_WRAP_CLOSED = 87 new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0); 88 private static final SSLEngineResult CLOSED_NOT_HANDSHAKING = 89 new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0); 90 private static final ByteBuffer EMPTY = ByteBuffer.allocateDirect(0); 91 private static final long EMPTY_ADDR = NativeCrypto.getDirectBufferAddress(EMPTY); 92 93 /** 94 * Similar in concept to {@link javax.net.ssl.HandshakeCompletedListener}. Allows the caller to be 95 * notified immediately upon completion of the TLS handshake. 96 */ 97 public interface HandshakeListener { 98 99 /** 100 * Called by the engine when the TLS handshake has completed. 101 */ 102 void onHandshakeFinished() throws SSLException; 103 } 104 105 private final SSLParametersImpl sslParameters; 106 107 /** 108 * Protects {@link #engineState} and {@link #handshakeFinished}. 109 */ 110 private final Object stateLock = new Object(); 111 112 private enum EngineState { 113 /** 114 * The {@link OpenSSLSocketImpl} object is constructed, but {@link #beginHandshake()} has 115 * not yet been called. 116 */ 117 NEW, 118 /** 119 * {@link #setUseClientMode(boolean)} has been called at least once. 120 */ 121 MODE_SET, 122 /** 123 * Handshake task has been started. 124 */ 125 HANDSHAKE_STARTED, 126 /** 127 * Handshake has been completed, but {@link #beginHandshake()} hasn't returned yet. 128 */ 129 HANDSHAKE_COMPLETED, 130 /** 131 * {@link #beginHandshake()} has completed but the task hasn't been called. This is expected 132 * behaviour in cut-through mode, where SSL_do_handshake returns before the handshake is 133 * complete. We can now start writing data to the socket. 134 */ 135 READY_HANDSHAKE_CUT_THROUGH, 136 /** 137 * {@link #beginHandshake()} has completed and socket is ready to go. 138 */ 139 READY, 140 CLOSED_INBOUND, 141 CLOSED_OUTBOUND, 142 /** 143 * Inbound and outbound has been called. 144 */ 145 CLOSED, 146 } 147 148 // @GuardedBy("stateLock"); 149 private EngineState engineState = EngineState.NEW; 150 private boolean handshakeFinished; 151 152 /** 153 * Protected by synchronizing on stateLock. Starts as 0, set by startHandshake, reset to 0 on 154 * close. 155 */ 156 // @GuardedBy("stateLock"); 157 private long sslNativePointer; 158 159 /** 160 * Protected by synchronizing on stateLock. Starts as 0, set by startHandshake, reset to 0 on 161 * close. 162 */ 163 // @GuardedBy("stateLock"); 164 private long networkBio; 165 166 /** 167 * Set during startHandshake. 168 */ 169 private AbstractOpenSSLSession sslSession; 170 171 /** 172 * Used during handshake callbacks. 173 */ 174 private AbstractOpenSSLSession handshakeSession; 175 176 /** 177 * Private key for the TLS Channel ID extension. This field is client-side only. Set during 178 * startHandshake. 179 */ 180 OpenSSLKey channelIdPrivateKey; 181 182 private int maxSealOverhead; 183 184 private HandshakeListener handshakeListener; 185 186 private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1]; 187 private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1]; 188 189 public OpenSSLEngineImpl(SSLParametersImpl sslParameters) { 190 this.sslParameters = sslParameters; 191 } 192 193 public OpenSSLEngineImpl(String host, int port, SSLParametersImpl sslParameters) { 194 super(host, port); 195 this.sslParameters = sslParameters; 196 } 197 198 /** 199 * Returns the maximum overhead, in bytes, of sealing a record with SSL. 200 */ 201 public final int maxSealOverhead() { 202 return maxSealOverhead; 203 } 204 205 /** 206 * Sets the listener for the completion of the TLS handshake. 207 */ 208 public OpenSSLEngineImpl setHandshakeListener(HandshakeListener handshakeListener) { 209 switch(engineState) { 210 case NEW: 211 case MODE_SET: 212 // Allowed. 213 break; 214 default: 215 // Disallow anything else. 216 throw new IllegalStateException("Handshake listener must be set before starting the handshake."); 217 } 218 this.handshakeListener = handshakeListener; 219 return this; 220 } 221 222 @Override 223 public void beginHandshake() throws SSLException { 224 synchronized (stateLock) { 225 beginHandshakeInternal(); 226 } 227 } 228 229 private void beginHandshakeInternal() throws SSLException { 230 switch (engineState) { 231 case MODE_SET: 232 // This is the only allowed state. 233 break; 234 case HANDSHAKE_STARTED: 235 throw new IllegalStateException("Handshake has already been started"); 236 case CLOSED_INBOUND: 237 case CLOSED_OUTBOUND: 238 case CLOSED: 239 throw new IllegalStateException("Engine has already been closed"); 240 default: 241 throw new IllegalStateException("Client/server mode must be set before handshake"); 242 } 243 244 engineState = EngineState.HANDSHAKE_STARTED; 245 246 boolean releaseResources = true; 247 try { 248 final AbstractSessionContext sessionContext = sslParameters.getSessionContext(); 249 sslNativePointer = NativeCrypto.SSL_new(sessionContext.sslCtxNativePointer); 250 networkBio = NativeCrypto.SSL_BIO_new(sslNativePointer); 251 sslSession = 252 sslParameters.getSessionToReuse(sslNativePointer, getPeerHost(), getPeerPort()); 253 sslParameters.setSSLParameters(sslNativePointer, this, this, getPeerHost()); 254 sslParameters.setCertificateValidation(sslNativePointer); 255 sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey); 256 if (getUseClientMode()) { 257 NativeCrypto.SSL_set_connect_state(sslNativePointer); 258 } else { 259 NativeCrypto.SSL_set_accept_state(sslNativePointer); 260 } 261 maxSealOverhead = NativeCrypto.SSL_max_seal_overhead(sslNativePointer); 262 handshake(); 263 releaseResources = false; 264 } catch (IOException e) { 265 // Write CCS errors to EventLog 266 String message = e.getMessage(); 267 // Must match error reason string of SSL_R_UNEXPECTED_CCS (in ssl/ssl_err.c) 268 if (message.contains("unexpected CCS")) { 269 String logMessage = String.format("ssl_unexpected_ccs: host=%s", getPeerHost()); 270 Platform.logEvent(logMessage); 271 } 272 throw new SSLException(e); 273 } finally { 274 if (releaseResources) { 275 engineState = EngineState.CLOSED; 276 shutdownAndFreeSslNative(); 277 } 278 } 279 } 280 281 @Override 282 public void closeInbound() throws SSLException { 283 synchronized (stateLock) { 284 if (engineState == EngineState.CLOSED) { 285 return; 286 } 287 if (engineState == EngineState.CLOSED_OUTBOUND) { 288 engineState = EngineState.CLOSED; 289 } else { 290 engineState = EngineState.CLOSED_INBOUND; 291 } 292 } 293 // TODO anything else to notify OpenSSL layer? 294 } 295 296 @Override 297 public void closeOutbound() { 298 synchronized (stateLock) { 299 if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND) { 300 return; 301 } 302 if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) { 303 shutdownAndFreeSslNative(); 304 } 305 if (engineState == EngineState.CLOSED_INBOUND) { 306 engineState = EngineState.CLOSED; 307 } else { 308 engineState = EngineState.CLOSED_OUTBOUND; 309 } 310 } 311 shutdown(); 312 } 313 314 @Override 315 public Runnable getDelegatedTask() { 316 // This implementation doesn't use any delegated tasks. 317 return null; 318 } 319 320 @Override 321 public String[] getEnabledCipherSuites() { 322 return sslParameters.getEnabledCipherSuites(); 323 } 324 325 @Override 326 public String[] getEnabledProtocols() { 327 return sslParameters.getEnabledProtocols(); 328 } 329 330 @Override 331 public boolean getEnableSessionCreation() { 332 return sslParameters.getEnableSessionCreation(); 333 } 334 335 @Override 336 public HandshakeStatus getHandshakeStatus() { 337 synchronized (stateLock) { 338 return getHandshakeStatusInternal(); 339 } 340 } 341 342 private HandshakeStatus getHandshakeStatusInternal() { 343 if (handshakeFinished) { 344 return HandshakeStatus.NOT_HANDSHAKING; 345 } 346 switch (engineState) { 347 case HANDSHAKE_STARTED: 348 return pendingStatus(pendingOutboundEncryptedBytes()); 349 case HANDSHAKE_COMPLETED: 350 return HandshakeStatus.NEED_WRAP; 351 case NEW: 352 case MODE_SET: 353 case CLOSED: 354 case CLOSED_INBOUND: 355 case CLOSED_OUTBOUND: 356 case READY: 357 case READY_HANDSHAKE_CUT_THROUGH: 358 return HandshakeStatus.NOT_HANDSHAKING; 359 default: 360 break; 361 } 362 throw new IllegalStateException("Unexpected engine state: " + engineState); 363 } 364 365 private int pendingOutboundEncryptedBytes() { 366 return NativeCrypto.SSL_pending_written_bytes_in_BIO(networkBio); 367 } 368 369 private int pendingInboundCleartextBytes() { 370 return NativeCrypto.SSL_pending_readable_bytes(sslNativePointer); 371 } 372 373 private int pendingInboundCleartextBytes(HandshakeStatus handshakeStatus) { 374 // There won't be any application data until we're done handshaking. 375 // We first check handshakeFinished to eliminate the overhead of extra JNI call if possible. 376 return handshakeStatus == HandshakeStatus.FINISHED ? pendingInboundCleartextBytes() : 0; 377 } 378 379 private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingOutboundBytes) { 380 // Depending on if there is something left in the BIO we need to WRAP or UNWRAP 381 return pendingOutboundBytes > 0 ? NEED_WRAP : NEED_UNWRAP; 382 } 383 384 @Override 385 public boolean getNeedClientAuth() { 386 return sslParameters.getNeedClientAuth(); 387 } 388 389 @Override 390 public SSLSession getSession() { 391 if (sslSession == null) { 392 return handshakeSession != null ? handshakeSession : SSLNullSession.getNullSession(); 393 } 394 return sslSession; 395 } 396 397 @Override 398 public String[] getSupportedCipherSuites() { 399 return NativeCrypto.getSupportedCipherSuites(); 400 } 401 402 @Override 403 public String[] getSupportedProtocols() { 404 return NativeCrypto.getSupportedProtocols(); 405 } 406 407 @Override 408 public boolean getUseClientMode() { 409 return sslParameters.getUseClientMode(); 410 } 411 412 @Override 413 public boolean getWantClientAuth() { 414 return sslParameters.getWantClientAuth(); 415 } 416 417 @Override 418 public boolean isInboundDone() { 419 if (sslNativePointer == 0) { 420 synchronized (stateLock) { 421 return engineState == EngineState.CLOSED 422 || engineState == EngineState.CLOSED_INBOUND; 423 } 424 } 425 return (NativeCrypto.SSL_get_shutdown(sslNativePointer) & SSL_RECEIVED_SHUTDOWN) != 0; 426 } 427 428 @Override 429 public boolean isOutboundDone() { 430 if (sslNativePointer == 0) { 431 synchronized (stateLock) { 432 return engineState == EngineState.CLOSED 433 || engineState == EngineState.CLOSED_OUTBOUND; 434 } 435 } 436 return (NativeCrypto.SSL_get_shutdown(sslNativePointer) & SSL_SENT_SHUTDOWN) != 0; 437 } 438 439 @Override 440 public void setEnabledCipherSuites(String[] suites) { 441 sslParameters.setEnabledCipherSuites(suites); 442 } 443 444 @Override 445 public void setEnabledProtocols(String[] protocols) { 446 sslParameters.setEnabledProtocols(protocols); 447 } 448 449 @Override 450 public void setEnableSessionCreation(boolean flag) { 451 sslParameters.setEnableSessionCreation(flag); 452 } 453 454 @Override 455 public void setNeedClientAuth(boolean need) { 456 sslParameters.setNeedClientAuth(need); 457 } 458 459 @Override 460 public void setUseClientMode(boolean mode) { 461 synchronized (stateLock) { 462 if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) { 463 throw new IllegalArgumentException( 464 "Can not change mode after handshake: engineState == " + engineState); 465 } 466 engineState = EngineState.MODE_SET; 467 } 468 sslParameters.setUseClientMode(mode); 469 } 470 471 @Override 472 public void setWantClientAuth(boolean want) { 473 sslParameters.setWantClientAuth(want); 474 } 475 476 @Override 477 public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException { 478 synchronized (stateLock) { 479 try { 480 return unwrap(singleSrcBuffer(src), singleDstBuffer(dst)); 481 } finally { 482 resetSingleSrcBuffer(); 483 resetSingleDstBuffer(); 484 } 485 } 486 } 487 488 @Override 489 public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException { 490 synchronized (stateLock) { 491 try { 492 return unwrap(singleSrcBuffer(src), dsts); 493 } finally { 494 resetSingleSrcBuffer(); 495 } 496 } 497 } 498 499 @Override 500 public SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, 501 final int length) throws SSLException { 502 synchronized (stateLock) { 503 try { 504 return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length); 505 } finally { 506 resetSingleSrcBuffer(); 507 } 508 } 509 } 510 511 public SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) 512 throws SSLException { 513 checkNotNull(srcs, "srcs"); 514 checkNotNull(dsts, "dsts"); 515 return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length); 516 } 517 518 public SSLEngineResult unwrap(final ByteBuffer[] srcs, int srcsOffset, final int srcsLength, 519 final ByteBuffer[] dsts, final int dstsOffset, final int dstsLength) 520 throws SSLException { 521 checkNotNull(srcs, "srcs"); 522 checkNotNull(dsts, "dsts"); 523 524 checkIndex(srcs.length, srcsOffset, srcsLength, "srcs"); 525 checkIndex(dsts.length, dstsOffset, dstsLength, "dsts"); 526 527 // Determine the output capacity. 528 int capacity = 0; 529 final int endOffset = dstsOffset + dstsLength; 530 for (int i = 0; i < dsts.length; i++) { 531 ByteBuffer dst = dsts[i]; 532 checkNotNull(dst, "one of the dst"); 533 if (dst.isReadOnly()) { 534 throw new ReadOnlyBufferException(); 535 } 536 if (i >= dstsOffset && i < dstsOffset + dstsLength) { 537 capacity += dst.remaining(); 538 } 539 } 540 541 final int srcsEndOffset = srcsOffset + srcsLength; 542 long len = 0; 543 for (int i = srcsOffset; i < srcsEndOffset; i++) { 544 ByteBuffer src = srcs[i]; 545 if (src == null) { 546 throw new IllegalArgumentException("srcs[" + i + "] is null"); 547 } 548 len += src.remaining(); 549 } 550 551 synchronized (stateLock) { 552 switch (engineState) { 553 case MODE_SET: 554 // Begin the handshake implicitly. 555 beginHandshakeInternal(); 556 break; 557 case CLOSED_INBOUND: 558 case CLOSED: 559 // If the inbound direction is closed. we can't send anymore. 560 return new SSLEngineResult(Status.CLOSED, getHandshakeStatusInternal(), 0, 0); 561 case NEW: 562 throw new IllegalStateException( 563 "Client/server mode must be set before calling unwrap"); 564 default: 565 break; 566 } 567 568 HandshakeStatus handshakeStatus = HandshakeStatus.NOT_HANDSHAKING; 569 if (!handshakeFinished) { 570 handshakeStatus = handshake(); 571 if (handshakeStatus == NEED_WRAP) { 572 return NEED_WRAP_OK; 573 } 574 if (engineState == EngineState.CLOSED) { 575 return NEED_WRAP_CLOSED; 576 } 577 // NEED_UNWRAP - just fall through to perform the unwrap. 578 } 579 580 if (len < SSL3_RT_HEADER_LENGTH) { 581 return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0); 582 } 583 584 int packetLength = SSLUtils.getEncryptedPacketLength(srcs, srcsOffset); 585 if (packetLength < 0) { 586 throw new SSLException("Unable to parse TLS packet header"); 587 } 588 589 if (len < packetLength) { 590 // We either have not enough data to read the packet header or not enough for 591 // reading the whole packet. 592 return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0); 593 } 594 595 // Write all of the source data to the networkBio 596 int bytesConsumed = 0; 597 if (srcsOffset < srcsEndOffset) { 598 int packetLengthRemaining = packetLength; 599 do { 600 ByteBuffer src = srcs[srcsOffset]; 601 int remaining = src.remaining(); 602 if (remaining == 0) { 603 // We must skip empty buffers as BIO_write will return 0 if asked to write 604 // something 605 // with length 0. 606 srcsOffset++; 607 continue; 608 } 609 // Write the source encrypted data to the networkBio. 610 int written = 611 writeEncryptedData(src, Math.min(packetLengthRemaining, remaining)); 612 if (written > 0) { 613 packetLengthRemaining -= written; 614 if (packetLengthRemaining == 0) { 615 // A whole packet has been consumed. 616 break; 617 } 618 619 if (written == remaining) { 620 srcsOffset++; 621 } else { 622 // We were not able to write everything into the BIO so break the write 623 // loop as otherwise 624 // we will produce an error on the next write attempt, which will 625 // trigger a SSL.clearError() 626 // later. 627 break; 628 } 629 } else { 630 // BIO_write returned a negative or zero number, this means we could not 631 // complete the write 632 // operation and should retry later. 633 // We ignore BIO_* errors here as we use in memory BIO anyway and will do 634 // another SSL_* call 635 // later on in which we will produce an exception in case of an error 636 NativeCrypto.SSL_clear_error(); 637 break; 638 } 639 } while (srcsOffset < srcsEndOffset); 640 bytesConsumed = packetLength - packetLengthRemaining; 641 } 642 643 // Now read any available plaintext data. 644 int bytesProduced = 0; 645 if (capacity > 0) { 646 // Write decrypted data to dsts buffers 647 for (int idx = dstsOffset; idx < endOffset; ++idx) { 648 ByteBuffer dst = dsts[idx]; 649 if (!dst.hasRemaining()) { 650 continue; 651 } 652 653 int bytesRead = readPlaintextData(dst); 654 655 if (bytesRead > 0) { 656 bytesProduced += bytesRead; 657 if (!dst.hasRemaining()) { 658 continue; 659 } 660 661 // We read everything return now. 662 return newResult(bytesConsumed, bytesProduced, handshakeStatus); 663 } 664 665 // Return an appropriate result based on the error code. 666 int sslError = NativeCrypto.SSL_get_error(sslNativePointer, bytesRead); 667 switch (sslError) { 668 case SSL_ERROR_ZERO_RETURN: 669 // This means the connection was shutdown correctly, close inbound and 670 // outbound 671 closeAll(); 672 return newResult(bytesConsumed, bytesProduced, handshakeStatus); 673 case SSL_ERROR_WANT_READ: 674 case SSL_ERROR_WANT_WRITE: 675 return newResult(bytesConsumed, bytesProduced, handshakeStatus); 676 default: 677 return sslReadErrorResult(NativeCrypto.SSL_get_last_error_number(), 678 bytesConsumed, bytesProduced); 679 } 680 } 681 } else { 682 // If the capacity of all destination buffers is 0 we need to trigger a SSL_read 683 // anyway to ensure 684 // everything is flushed in the BIO pair and so we can detect it in the 685 // pendingInboundCleartextBytes() call. 686 try { 687 if (NativeCrypto.ENGINE_SSL_read_direct(sslNativePointer, EMPTY_ADDR, 0, this) 688 <= 0) { 689 // We do not check SSL_get_error as we are not interested in any error that 690 // is not fatal. 691 int err = NativeCrypto.SSL_get_last_error_number(); 692 if (err != SSL_ERROR_NONE) { 693 return sslReadErrorResult(err, bytesConsumed, bytesProduced); 694 } 695 } 696 } catch (IOException e) { 697 throw new SSLException(e); 698 } 699 } 700 if (pendingInboundCleartextBytes(handshakeStatus) > 0) { 701 // We filled all buffers but there is still some data pending in the BIO buffer, 702 // return BUFFER_OVERFLOW. 703 return new SSLEngineResult(BUFFER_OVERFLOW, 704 mayFinishHandshake(handshakeStatus == FINISHED 705 ? handshakeStatus 706 : getHandshakeStatusInternal()), 707 bytesConsumed, bytesProduced); 708 } 709 710 return newResult(bytesConsumed, bytesProduced, handshakeStatus); 711 } 712 } 713 714 private SSLEngineResult.HandshakeStatus handshake() throws SSLException { 715 long sslSessionCtx = 0L; 716 try { 717 // Only actually perform the handshake if we haven't already just completed it 718 // via BIO operations. 719 int code = NativeCrypto.ENGINE_SSL_do_handshake(sslNativePointer, this); 720 if (code <= 0) { 721 int sslError = NativeCrypto.SSL_get_error(sslNativePointer, code); 722 switch (sslError) { 723 case SSL_ERROR_WANT_READ: 724 case SSL_ERROR_WANT_WRITE: 725 return pendingStatus(pendingOutboundEncryptedBytes()); 726 default: 727 // Everything else is considered as error 728 throw shutdownWithError("SSL_do_handshake"); 729 } 730 } 731 732 // Handshake is finished! 733 sslSessionCtx = NativeCrypto.SSL_get1_session(sslNativePointer); 734 if (sslSessionCtx == 0) { 735 // TODO(nathanmittler): Should we throw here? 736 // return pendingStatus(pendingOutboundBytes()); 737 throw shutdownWithError("Failed to obtain session after handshake completed"); 738 } 739 sslSession = sslParameters.setupSession(sslSessionCtx, sslNativePointer, sslSession, 740 getPeerHost(), getPeerPort(), true); 741 if (sslSession != null && engineState == EngineState.HANDSHAKE_STARTED) { 742 engineState = EngineState.READY_HANDSHAKE_CUT_THROUGH; 743 } else { 744 engineState = EngineState.READY; 745 } 746 finishHandshake(); 747 return FINISHED; 748 } catch (Exception e) { 749 throw toSSLHandshakeException(e); 750 } finally { 751 if (sslSession == null && sslSessionCtx != 0) { 752 NativeCrypto.SSL_SESSION_free(sslSessionCtx); 753 } 754 } 755 } 756 757 private void finishHandshake() throws SSLException { 758 handshakeFinished = true; 759 // Notify the listener, if provided. 760 if (handshakeListener != null) { 761 handshakeListener.onHandshakeFinished(); 762 } 763 } 764 /** 765 * Write plaintext data to the OpenSSL internal BIO 766 * 767 * Calling this function with src.remaining == 0 is undefined. 768 */ 769 private int writePlaintextData(final ByteBuffer src, int len) throws SSLException { 770 try { 771 final int pos = src.position(); 772 final int sslWrote; 773 774 if (src.isDirect()) { 775 long addr = NativeCrypto.getDirectBufferAddress(src) + pos; 776 sslWrote = NativeCrypto.ENGINE_SSL_write_direct(sslNativePointer, addr, len, this); 777 } else { 778 ByteBuffer heapSrc = toHeapBuffer(src, len); 779 sslWrote = NativeCrypto.ENGINE_SSL_write_heap(sslNativePointer, heapSrc.array(), 780 heapSrc.arrayOffset() + heapSrc.position(), len, this); 781 } 782 if (sslWrote > 0) { 783 src.position(pos + sslWrote); 784 } 785 return sslWrote; 786 } catch (Exception e) { 787 throw convertException(e); 788 } 789 } 790 791 /** 792 * Read plaintext data from the OpenSSL internal BIO 793 */ 794 private int readPlaintextData(final ByteBuffer dst) throws SSLException { 795 try { 796 final int sslRead; 797 final int pos = dst.position(); 798 final int limit = dst.limit(); 799 final int len = Math.min(SSL3_RT_MAX_PACKET_SIZE, limit - pos); 800 if (dst.isDirect()) { 801 long addr = NativeCrypto.getDirectBufferAddress(dst) + pos; 802 sslRead = NativeCrypto.ENGINE_SSL_read_direct(sslNativePointer, addr, len, this); 803 if (sslRead > 0) { 804 dst.position(pos + sslRead); 805 } 806 } else if (dst.hasArray()) { 807 sslRead = NativeCrypto.ENGINE_SSL_read_heap( 808 sslNativePointer, dst.array(), dst.arrayOffset() + pos, len, this); 809 if (sslRead > 0) { 810 dst.position(pos + sslRead); 811 } 812 } else { 813 byte[] data = new byte[len]; 814 sslRead = NativeCrypto.ENGINE_SSL_read_heap(sslNativePointer, data, 0, len, this); 815 if (sslRead > 0) { 816 dst.put(data, 0, sslRead); 817 } 818 } 819 return sslRead; 820 } catch (Exception e) { 821 throw convertException(e); 822 } 823 } 824 825 private SSLException convertException(Throwable e) { 826 if (e instanceof SSLHandshakeException || !handshakeFinished) { 827 return SSLUtils.toSSLHandshakeException(e); 828 } 829 return SSLUtils.toSSLException(e); 830 } 831 832 /** 833 * Write encrypted data to the OpenSSL network BIO. 834 */ 835 private int writeEncryptedData(final ByteBuffer src, int len) throws SSLException { 836 try { 837 final int pos = src.position(); 838 final int netWrote; 839 if (src.isDirect()) { 840 long addr = NativeCrypto.getDirectBufferAddress(src) + pos; 841 netWrote = NativeCrypto.ENGINE_SSL_write_BIO_direct( 842 sslNativePointer, networkBio, addr, len, this); 843 } else { 844 ByteBuffer heapSrc = toHeapBuffer(src, len); 845 netWrote = NativeCrypto.ENGINE_SSL_write_BIO_heap(sslNativePointer, networkBio, 846 heapSrc.array(), heapSrc.arrayOffset() + heapSrc.position(), len, this); 847 } 848 849 if (netWrote >= 0) { 850 src.position(pos + netWrote); 851 } 852 853 return netWrote; 854 } catch (IOException e) { 855 throw new SSLException(e); 856 } 857 } 858 859 private SSLEngineResult readPendingBytesFromBIO(ByteBuffer dst, int bytesConsumed, 860 int bytesProduced, SSLEngineResult.HandshakeStatus status) throws SSLException { 861 try { 862 // Check to see if the engine wrote data into the network BIO 863 int pendingNet = pendingOutboundEncryptedBytes(); 864 if (pendingNet > 0) { 865 // Do we have enough room in dst to write encrypted data? 866 int capacity = dst.remaining(); 867 if (capacity < pendingNet) { 868 return new SSLEngineResult(BUFFER_OVERFLOW, 869 mayFinishHandshake( 870 status == FINISHED ? status : getHandshakeStatus(pendingNet)), 871 bytesConsumed, bytesProduced); 872 } 873 874 // Write the pending data from the network BIO into the dst buffer 875 int produced = readEncryptedData(dst, pendingNet); 876 877 if (produced <= 0) { 878 // We ignore BIO_* errors here as we use in memory BIO anyway and will do another 879 // SSL_* call later 880 // on in which we will produce an exception in case of an error 881 NativeCrypto.SSL_clear_error(); 882 } else { 883 bytesProduced += produced; 884 pendingNet -= produced; 885 } 886 887 return new SSLEngineResult(getEngineStatus(), 888 mayFinishHandshake( 889 status == FINISHED ? status : getHandshakeStatus(pendingNet)), 890 bytesConsumed, bytesProduced); 891 } 892 return null; 893 } catch (Exception e) { 894 throw convertException(e); 895 } 896 } 897 898 /** 899 * Read encrypted data from the OpenSSL network BIO 900 */ 901 private int readEncryptedData(final ByteBuffer dst, final int pending) throws SSLException { 902 try { 903 int bioRead = 0; 904 if (dst.remaining() >= pending) { 905 final int pos = dst.position(); 906 final int limit = dst.limit(); 907 final int len = Math.min(pending, limit - pos); 908 if (dst.isDirect()) { 909 long addr = NativeCrypto.getDirectBufferAddress(dst) + pos; 910 bioRead = NativeCrypto.ENGINE_SSL_read_BIO_direct( 911 sslNativePointer, networkBio, addr, len, this); 912 if (bioRead > 0) { 913 dst.position(pos + bioRead); 914 return bioRead; 915 } 916 } else if (dst.hasArray()) { 917 bioRead = NativeCrypto.ENGINE_SSL_read_BIO_heap(sslNativePointer, networkBio, 918 dst.array(), dst.arrayOffset() + pos, pending, this); 919 if (bioRead > 0) { 920 dst.position(pos + bioRead); 921 return bioRead; 922 } 923 } else { 924 byte[] data = new byte[len]; 925 bioRead = NativeCrypto.ENGINE_SSL_read_BIO_heap( 926 sslNativePointer, networkBio, data, 0, pending, this); 927 if (bioRead > 0) { 928 dst.put(data, 0, bioRead); 929 return bioRead; 930 } 931 } 932 } 933 return bioRead; 934 } catch (Exception e) { 935 throw convertException(e); 936 } 937 } 938 939 private SSLEngineResult.HandshakeStatus mayFinishHandshake( 940 SSLEngineResult.HandshakeStatus status) throws SSLException { 941 if (!handshakeFinished 942 && status 943 == NOT_HANDSHAKING /*|| engineState == EngineState.HANDSHAKE_COMPLETED)*/) { 944 // If the status was NOT_HANDSHAKING and we not finished the handshake we need to call 945 // SSL_do_handshake() again 946 return handshake(); 947 } 948 return status; 949 } 950 951 private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) { 952 // Check if we are in the initial handshake phase or shutdown phase 953 return !handshakeFinished ? pendingStatus(pending) : NOT_HANDSHAKING; 954 } 955 956 private SSLEngineResult.Status getEngineStatus() { 957 switch (engineState) { 958 case CLOSED_INBOUND: 959 case CLOSED_OUTBOUND: 960 case CLOSED: 961 return CLOSED; 962 default: 963 return OK; 964 } 965 } 966 967 private void closeAll() throws SSLException { 968 closeOutbound(); 969 closeInbound(); 970 } 971 972 private SSLEngineResult sslReadErrorResult(int err, int bytesConsumed, int bytesProduced) 973 throws SSLException { 974 if (!handshakeFinished && pendingOutboundEncryptedBytes() > 0) { 975 return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced); 976 } 977 throw shutdownWithError(NativeCrypto.SSL_get_error_string(err)); 978 } 979 980 private SSLException shutdownWithError(String err) { 981 // There was an internal error -- shutdown 982 shutdown(); 983 if (getHandshakeStatusInternal() == HandshakeStatus.FINISHED) { 984 return new SSLException(err); 985 } 986 return new SSLHandshakeException(err); 987 } 988 989 private SSLEngineResult newResult(int bytesConsumed, int bytesProduced, 990 SSLEngineResult.HandshakeStatus status) throws SSLException { 991 return new SSLEngineResult(getEngineStatus(), 992 mayFinishHandshake(status == FINISHED ? status : getHandshakeStatusInternal()), 993 bytesConsumed, bytesProduced); 994 } 995 996 @Override 997 public final SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException { 998 synchronized (stateLock) { 999 try { 1000 return wrap(singleSrcBuffer(src), dst); 1001 } finally { 1002 resetSingleSrcBuffer(); 1003 } 1004 } 1005 } 1006 1007 @Override 1008 public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst) 1009 throws SSLException { 1010 checkNotNull(srcs, "srcs"); 1011 checkNotNull(dst, "dst"); 1012 checkIndex(srcs.length, offset, length, "srcs"); 1013 if (dst.isReadOnly()) { 1014 throw new ReadOnlyBufferException(); 1015 } 1016 1017 synchronized (stateLock) { 1018 switch (engineState) { 1019 case MODE_SET: 1020 // Begin the handshake implicitly. 1021 beginHandshakeInternal(); 1022 break; 1023 case CLOSED_OUTBOUND: 1024 case CLOSED: 1025 return new SSLEngineResult(Status.CLOSED, getHandshakeStatusInternal(), 0, 0); 1026 case NEW: 1027 throw new IllegalStateException( 1028 "Client/server mode must be set before calling wrap"); 1029 } 1030 1031 // If we haven't completed the handshake yet, just let the caller know. 1032 HandshakeStatus handshakeStatus = HandshakeStatus.NOT_HANDSHAKING; 1033 // Prepare OpenSSL to work in server mode and receive handshake 1034 if (!handshakeFinished) { 1035 handshakeStatus = handshake(); 1036 if (handshakeStatus == NEED_UNWRAP) { 1037 return NEED_UNWRAP_OK; 1038 } 1039 1040 if (engineState == EngineState.CLOSED) { 1041 return NEED_UNWRAP_CLOSED; 1042 } 1043 // NEED_WRAP - just fall through to perform the wrap. 1044 } 1045 1046 int srcsLen = 0; 1047 final int endOffset = offset + length; 1048 for (int i = offset; i < endOffset; ++i) { 1049 final ByteBuffer src = srcs[i]; 1050 if (src == null) { 1051 throw new IllegalArgumentException("srcs[" + i + "] is null"); 1052 } 1053 if (srcsLen == SSL3_RT_MAX_PLAIN_LENGTH) { 1054 continue; 1055 } 1056 1057 srcsLen += src.remaining(); 1058 if (srcsLen > SSL3_RT_MAX_PLAIN_LENGTH || srcsLen < 0) { 1059 // If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to MAX_PLAINTEXT_LENGTH. 1060 // This also help us to guard against overflow. 1061 // We not break out here as we still need to check for null entries in srcs[]. 1062 srcsLen = SSL3_RT_MAX_PLAIN_LENGTH; 1063 } 1064 } 1065 1066 if (dst.remaining() < calculateOutNetBufSize(srcsLen)) { 1067 return new SSLEngineResult( 1068 Status.BUFFER_OVERFLOW, getHandshakeStatusInternal(), 0, 0); 1069 } 1070 1071 int bytesProduced = 0; 1072 int bytesConsumed = 0; 1073 loop: 1074 for (int i = offset; i < endOffset; ++i) { 1075 final ByteBuffer src = srcs[i]; 1076 checkNotNull(src, "srcs[%d] is null", i); 1077 while (src.hasRemaining()) { 1078 final SSLEngineResult pendingNetResult; 1079 // Write plaintext application data to the SSL engine 1080 int result = writePlaintextData(src, 1081 Math.min(src.remaining(), SSL3_RT_MAX_PLAIN_LENGTH - bytesConsumed)); 1082 if (result > 0) { 1083 bytesConsumed += result; 1084 1085 pendingNetResult = readPendingBytesFromBIO( 1086 dst, bytesConsumed, bytesProduced, handshakeStatus); 1087 if (pendingNetResult != null) { 1088 if (pendingNetResult.getStatus() != OK) { 1089 return pendingNetResult; 1090 } 1091 bytesProduced = pendingNetResult.bytesProduced(); 1092 } 1093 if (bytesConsumed == SSL3_RT_MAX_PLAIN_LENGTH) { 1094 // If we consumed the maximum amount of bytes for the plaintext length 1095 // break out of the loop and start to fill the dst buffer. 1096 break loop; 1097 } 1098 } else { 1099 int sslError = NativeCrypto.SSL_get_error(sslNativePointer, result); 1100 switch (sslError) { 1101 case SSL_ERROR_ZERO_RETURN: 1102 // This means the connection was shutdown correctly, close inbound 1103 // and outbound 1104 closeAll(); 1105 pendingNetResult = readPendingBytesFromBIO( 1106 dst, bytesConsumed, bytesProduced, handshakeStatus); 1107 return pendingNetResult != null ? pendingNetResult 1108 : CLOSED_NOT_HANDSHAKING; 1109 case SSL_ERROR_WANT_READ: 1110 // If there is no pending data to read from BIO we should go back to 1111 // event loop and try 1112 // to read more data [1]. It is also possible that event loop will 1113 // detect the socket 1114 // has been closed. [1] 1115 // https://www.openssl.org/docs/manmaster/ssl/SSL_write.html 1116 pendingNetResult = readPendingBytesFromBIO( 1117 dst, bytesConsumed, bytesProduced, handshakeStatus); 1118 return pendingNetResult != null 1119 ? pendingNetResult 1120 : new SSLEngineResult(getEngineStatus(), NEED_UNWRAP, 1121 bytesConsumed, bytesProduced); 1122 case SSL_ERROR_WANT_WRITE: 1123 // SSL_ERROR_WANT_WRITE typically means that the underlying 1124 // transport is not writable 1125 // and we should set the "want write" flag on the selector and try 1126 // again when the 1127 // underlying transport is writable [1]. However we are not directly 1128 // writing to the 1129 // underlying transport and instead writing to a BIO buffer. The 1130 // OpenSsl documentation 1131 // says we should do the following [1]: 1132 // 1133 // "When using a buffering BIO, like a BIO pair, data must be 1134 // written into or retrieved 1135 // out of the BIO before being able to continue." 1136 // 1137 // So we attempt to drain the BIO buffer below, but if there is no 1138 // data this condition 1139 // is undefined and we assume their is a fatal error with the 1140 // openssl engine and close. 1141 // [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html 1142 pendingNetResult = readPendingBytesFromBIO( 1143 dst, bytesConsumed, bytesProduced, handshakeStatus); 1144 return pendingNetResult != null ? pendingNetResult 1145 : NEED_WRAP_CLOSED; 1146 default: 1147 // Everything else is considered as error 1148 throw shutdownWithError("SSL_write"); 1149 } 1150 } 1151 } 1152 } 1153 // We need to check if pendingWrittenBytesInBIO was checked yet, as we may not checked 1154 // if the srcs was 1155 // empty, or only contained empty buffers. 1156 if (bytesConsumed == 0) { 1157 SSLEngineResult pendingNetResult = 1158 readPendingBytesFromBIO(dst, 0, bytesProduced, handshakeStatus); 1159 if (pendingNetResult != null) { 1160 return pendingNetResult; 1161 } 1162 } 1163 1164 // return new SSLEngineResult(OK, getHandshakeStatusInternal(), bytesConsumed, 1165 // bytesProduced); 1166 return newResult(bytesConsumed, bytesProduced, handshakeStatus); 1167 } 1168 } 1169 1170 @Override 1171 public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) { 1172 return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this); 1173 } 1174 1175 @Override 1176 public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) { 1177 return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this); 1178 } 1179 1180 @Override 1181 public void onSSLStateChange(int type, int val) { 1182 synchronized (stateLock) { 1183 switch (type) { 1184 case SSL_CB_HANDSHAKE_DONE: 1185 if (engineState != EngineState.HANDSHAKE_STARTED && 1186 engineState != EngineState.READY_HANDSHAKE_CUT_THROUGH) { 1187 throw new IllegalStateException( 1188 "Completed handshake while in mode " + engineState); 1189 } 1190 engineState = EngineState.HANDSHAKE_COMPLETED; 1191 break; 1192 case SSL_CB_HANDSHAKE_START: 1193 // For clients, this will allow the NEED_UNWRAP status to be 1194 // returned. 1195 engineState = EngineState.HANDSHAKE_STARTED; 1196 break; 1197 } 1198 } 1199 } 1200 1201 @Override 1202 public void verifyCertificateChain(long[] certRefs, String authMethod) 1203 throws CertificateException { 1204 try { 1205 X509TrustManager x509tm = sslParameters.getX509TrustManager(); 1206 if (x509tm == null) { 1207 throw new CertificateException("No X.509 TrustManager"); 1208 } 1209 if (certRefs == null || certRefs.length == 0) { 1210 throw new SSLException("Peer sent no certificate"); 1211 } 1212 OpenSSLX509Certificate[] peerCertChain = 1213 OpenSSLX509Certificate.createCertChain(certRefs); 1214 1215 byte[] ocspData = NativeCrypto.SSL_get_ocsp_response(sslNativePointer); 1216 byte[] tlsSctData = NativeCrypto.SSL_get_signed_cert_timestamp_list(sslNativePointer); 1217 1218 // Used for verifyCertificateChain callback 1219 handshakeSession = new OpenSSLSessionImpl( 1220 NativeCrypto.SSL_get1_session(sslNativePointer), null, peerCertChain, ocspData, 1221 tlsSctData, getPeerHost(), getPeerPort(), null); 1222 1223 boolean client = sslParameters.getUseClientMode(); 1224 if (client) { 1225 Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, this); 1226 } else { 1227 String authType = peerCertChain[0].getPublicKey().getAlgorithm(); 1228 Platform.checkClientTrusted(x509tm, peerCertChain, authType, this); 1229 } 1230 } catch (CertificateException e) { 1231 throw e; 1232 } catch (Exception e) { 1233 throw new CertificateException(e); 1234 } finally { 1235 handshakeSession = null; 1236 } 1237 } 1238 1239 @Override 1240 public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 1241 throws CertificateEncodingException, SSLException { 1242 sslParameters.chooseClientCertificate( 1243 keyTypeBytes, asn1DerEncodedPrincipals, sslNativePointer, this); 1244 } 1245 1246 private void shutdown() { 1247 try { 1248 NativeCrypto.ENGINE_SSL_shutdown(sslNativePointer, this); 1249 } catch (IOException ignored) { 1250 // TODO: The RI ignores close failures in SSLSocket, but need to 1251 // investigate whether it does for SSLEngine. 1252 } 1253 } 1254 1255 private void shutdownAndFreeSslNative() { 1256 try { 1257 shutdown(); 1258 } finally { 1259 free(); 1260 } 1261 } 1262 1263 private void free() { 1264 if (sslNativePointer == 0) { 1265 return; 1266 } 1267 NativeCrypto.SSL_free(sslNativePointer); 1268 NativeCrypto.BIO_free_all(networkBio); 1269 sslNativePointer = 0; 1270 networkBio = 0; 1271 } 1272 1273 @Override 1274 protected void finalize() throws Throwable { 1275 try { 1276 free(); 1277 } finally { 1278 super.finalize(); 1279 } 1280 } 1281 1282 /* @Override */ 1283 @SuppressWarnings("MissingOverride") // For compilation with Java 6. 1284 public SSLSession getHandshakeSession() { 1285 return handshakeSession; 1286 } 1287 1288 @Override 1289 public String chooseServerAlias(X509KeyManager keyManager, String keyType) { 1290 if (keyManager instanceof X509ExtendedKeyManager) { 1291 X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager; 1292 return ekm.chooseEngineServerAlias(keyType, null, this); 1293 } else { 1294 return keyManager.chooseServerAlias(keyType, null, null); 1295 } 1296 } 1297 1298 @Override 1299 public String chooseClientAlias( 1300 X509KeyManager keyManager, X500Principal[] issuers, String[] keyTypes) { 1301 if (keyManager instanceof X509ExtendedKeyManager) { 1302 X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager; 1303 return ekm.chooseEngineClientAlias(keyTypes, issuers, this); 1304 } else { 1305 return keyManager.chooseClientAlias(keyTypes, issuers, null); 1306 } 1307 } 1308 1309 @Override 1310 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 1311 public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) { 1312 return keyManager.chooseServerKeyIdentityHint(this); 1313 } 1314 1315 @Override 1316 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 1317 public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) { 1318 return keyManager.chooseClientKeyIdentity(identityHint, this); 1319 } 1320 1321 @Override 1322 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 1323 public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) { 1324 return keyManager.getKey(identityHint, identity, this); 1325 } 1326 1327 /** 1328 * This method enables session ticket support. 1329 * 1330 * @param useSessionTickets True to enable session tickets 1331 */ 1332 public void setUseSessionTickets(boolean useSessionTickets) { 1333 sslParameters.setUseSessionTickets(useSessionTickets); 1334 } 1335 1336 /** 1337 * This method does nothing and is kept for backward compatibility. 1338 */ 1339 public void setNpnProtocols(byte[] npnProtocols) {} 1340 1341 /** 1342 * Sets the list of ALPN protocols. This method internally converts the protocols to their 1343 * wire-format form. 1344 * 1345 * @param alpnProtocols the list of ALPN protocols 1346 * @see #setAlpnProtocols(byte[]) 1347 */ 1348 public void setAlpnProtocols(String[] alpnProtocols) { 1349 sslParameters.setAlpnProtocols(alpnProtocols); 1350 } 1351 1352 /** 1353 * Alternate version of {@link #setAlpnProtocols(String[])} that directly sets the list of 1354 * ALPN in the wire-format form used by BoringSSL (length-prefixed 8-bit strings). 1355 * Requires that all strings be encoded with US-ASCII. 1356 * 1357 * @param alpnProtocols the encoded form of the ALPN protocol list 1358 * @see #setAlpnProtocols(String[]) 1359 */ 1360 public void setAlpnProtocols(byte[] alpnProtocols) { 1361 sslParameters.setAlpnProtocols(alpnProtocols); 1362 } 1363 1364 /** 1365 * Returns null always for backward compatibility. 1366 */ 1367 public byte[] getNpnSelectedProtocol() { 1368 return null; 1369 } 1370 1371 /** 1372 * Returns the protocol agreed upon by client and server, or {@code null} if no protocol was 1373 * agreed upon. 1374 */ 1375 public byte[] getAlpnSelectedProtocol() { 1376 return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer); 1377 } 1378 1379 private ByteBuffer toHeapBuffer(ByteBuffer buffer, int len) { 1380 if (buffer.hasArray()) { 1381 return buffer; 1382 } 1383 1384 // Need to copy to a heap buffer. 1385 final ByteBuffer heapBuffer = ByteBuffer.allocate(len); 1386 final int pos = buffer.position(); 1387 final int limit = buffer.limit(); 1388 buffer.limit(pos + len); 1389 try { 1390 heapBuffer.put(buffer); 1391 heapBuffer.flip(); 1392 return heapBuffer; 1393 } finally { 1394 buffer.limit(limit); 1395 buffer.position(pos); 1396 } 1397 } 1398 1399 private ByteBuffer[] singleSrcBuffer(ByteBuffer src) { 1400 singleSrcBuffer[0] = src; 1401 return singleSrcBuffer; 1402 } 1403 1404 private void resetSingleSrcBuffer() { 1405 singleSrcBuffer[0] = null; 1406 } 1407 1408 private ByteBuffer[] singleDstBuffer(ByteBuffer src) { 1409 singleDstBuffer[0] = src; 1410 return singleDstBuffer; 1411 } 1412 1413 private void resetSingleDstBuffer() { 1414 singleDstBuffer[0] = null; 1415 } 1416 1417 private static void checkIndex(int arrayLength, int offset, int length, String arrayName) { 1418 if ((offset | length) < 0 || offset + length > arrayLength) { 1419 throw new IndexOutOfBoundsException("offset: " + offset + ", length: " + length 1420 + " (expected: offset <= offset + length <= " + arrayName + ".length (" 1421 + arrayLength + "))"); 1422 } 1423 } 1424 1425 private static <T> T checkNotNull(T obj, String fmt, Object... args) { 1426 if (obj == null) { 1427 throw new IllegalArgumentException(String.format(fmt, args)); 1428 } 1429 return obj; 1430 } 1431} 1432