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 17package org.conscrypt; 18 19import java.io.IOException; 20import java.nio.ByteBuffer; 21import java.nio.ReadOnlyBufferException; 22import java.security.cert.CertificateEncodingException; 23import java.security.cert.CertificateException; 24 25import javax.crypto.SecretKey; 26import javax.net.ssl.SSLEngine; 27import javax.net.ssl.SSLEngineResult; 28import javax.net.ssl.SSLEngineResult.HandshakeStatus; 29import javax.net.ssl.SSLEngineResult.Status; 30import javax.net.ssl.SSLException; 31import javax.net.ssl.SSLHandshakeException; 32import javax.net.ssl.SSLSession; 33import javax.net.ssl.X509ExtendedKeyManager; 34import javax.net.ssl.X509KeyManager; 35import javax.net.ssl.X509TrustManager; 36import javax.security.auth.x500.X500Principal; 37 38/** 39 * Implements the {@link SSLEngine} API using OpenSSL's non-blocking interfaces. 40 */ 41public class OpenSSLEngineImpl extends SSLEngine implements NativeCrypto.SSLHandshakeCallbacks, 42 SSLParametersImpl.AliasChooser, SSLParametersImpl.PSKCallbacks { 43 private final SSLParametersImpl sslParameters; 44 45 /** 46 * Protects handshakeStarted and handshakeCompleted. 47 */ 48 private final Object stateLock = new Object(); 49 50 private static enum EngineState { 51 /** 52 * The {@link OpenSSLSocketImpl} object is constructed, but {@link #beginHandshake()} 53 * has not yet been called. 54 */ 55 NEW, 56 /** 57 * {@link #setUseClientMode(boolean)} has been called at least once. 58 */ 59 MODE_SET, 60 /** 61 * {@link #beginHandshake()} has been called at least once. 62 */ 63 HANDSHAKE_WANTED, 64 /** 65 * Handshake task has been started. 66 */ 67 HANDSHAKE_STARTED, 68 /** 69 * Handshake has been completed, but {@link #beginHandshake()} hasn't returned yet. 70 */ 71 HANDSHAKE_COMPLETED, 72 /** 73 * {@link #beginHandshake()} has completed but the task hasn't 74 * been called. This is expected behaviour in cut-through mode, where SSL_do_handshake 75 * returns before the handshake is complete. We can now start writing data to the socket. 76 */ 77 READY_HANDSHAKE_CUT_THROUGH, 78 /** 79 * {@link #beginHandshake()} has completed and socket is ready to go. 80 */ 81 READY, 82 CLOSED_INBOUND, 83 CLOSED_OUTBOUND, 84 /** 85 * Inbound and outbound has been called. 86 */ 87 CLOSED, 88 } 89 90 // @GuardedBy("stateLock"); 91 private EngineState engineState = EngineState.NEW; 92 93 /** 94 * Protected by synchronizing on stateLock. Starts as 0, set by 95 * startHandshake, reset to 0 on close. 96 */ 97 // @GuardedBy("stateLock"); 98 private long sslNativePointer; 99 100 /** Used during handshake when {@link #wrap(ByteBuffer, ByteBuffer)} is called. */ 101 // TODO: make this use something similar to BIO_s_null() in native code 102 private static OpenSSLBIOSource nullSource = OpenSSLBIOSource.wrap(ByteBuffer.allocate(0)); 103 104 /** A BIO sink written to only during handshakes. */ 105 private OpenSSLBIOSink handshakeSink; 106 107 /** A BIO sink written to during regular operation. */ 108 private final OpenSSLBIOSink localToRemoteSink = OpenSSLBIOSink.create(); 109 110 /** Set during startHandshake. */ 111 private OpenSSLSessionImpl sslSession; 112 113 /** Used during handshake callbacks. */ 114 private OpenSSLSessionImpl handshakeSession; 115 116 /** 117 * Private key for the TLS Channel ID extension. This field is client-side 118 * only. Set during startHandshake. 119 */ 120 OpenSSLKey channelIdPrivateKey; 121 122 public OpenSSLEngineImpl(SSLParametersImpl sslParameters) { 123 this.sslParameters = sslParameters; 124 } 125 126 public OpenSSLEngineImpl(String host, int port, SSLParametersImpl sslParameters) { 127 super(host, port); 128 this.sslParameters = sslParameters; 129 } 130 131 @Override 132 public void beginHandshake() throws SSLException { 133 synchronized (stateLock) { 134 if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND 135 || engineState == EngineState.CLOSED_INBOUND) { 136 throw new IllegalStateException("Engine has already been closed"); 137 } 138 if (engineState == EngineState.HANDSHAKE_STARTED) { 139 throw new IllegalStateException("Handshake has already been started"); 140 } 141 if (engineState != EngineState.MODE_SET) { 142 throw new IllegalStateException("Client/server mode must be set before handshake"); 143 } 144 if (getUseClientMode()) { 145 engineState = EngineState.HANDSHAKE_WANTED; 146 } else { 147 engineState = EngineState.HANDSHAKE_STARTED; 148 } 149 } 150 151 boolean releaseResources = true; 152 try { 153 final AbstractSessionContext sessionContext = sslParameters.getSessionContext(); 154 final long sslCtxNativePointer = sessionContext.sslCtxNativePointer; 155 sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 156 sslSession = sslParameters.getSessionToReuse( 157 sslNativePointer, getPeerHost(), getPeerPort()); 158 sslParameters.setSSLParameters(sslCtxNativePointer, sslNativePointer, this, this, 159 getPeerHost()); 160 sslParameters.setCertificateValidation(sslNativePointer); 161 sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey); 162 if (getUseClientMode()) { 163 NativeCrypto.SSL_set_connect_state(sslNativePointer); 164 } else { 165 NativeCrypto.SSL_set_accept_state(sslNativePointer); 166 } 167 handshakeSink = OpenSSLBIOSink.create(); 168 releaseResources = false; 169 } catch (IOException e) { 170 // Write CCS errors to EventLog 171 String message = e.getMessage(); 172 // Must match error reason string of SSL_R_UNEXPECTED_CCS (in ssl/ssl_err.c) 173 if (message.contains("unexpected CCS")) { 174 String logMessage = String.format("ssl_unexpected_ccs: host=%s", getPeerHost()); 175 Platform.logEvent(logMessage); 176 } 177 throw new SSLException(e); 178 } finally { 179 if (releaseResources) { 180 synchronized (stateLock) { 181 engineState = EngineState.CLOSED; 182 } 183 shutdownAndFreeSslNative(); 184 } 185 } 186 } 187 188 @Override 189 public void closeInbound() throws SSLException { 190 synchronized (stateLock) { 191 if (engineState == EngineState.CLOSED) { 192 return; 193 } 194 if (engineState == EngineState.CLOSED_OUTBOUND) { 195 engineState = EngineState.CLOSED; 196 } else { 197 engineState = EngineState.CLOSED_INBOUND; 198 } 199 } 200 // TODO anything else to notify OpenSSL layer? 201 } 202 203 @Override 204 public void closeOutbound() { 205 synchronized (stateLock) { 206 if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND) { 207 return; 208 } 209 if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) { 210 shutdownAndFreeSslNative(); 211 } 212 if (engineState == EngineState.CLOSED_INBOUND) { 213 engineState = EngineState.CLOSED; 214 } else { 215 engineState = EngineState.CLOSED_OUTBOUND; 216 } 217 } 218 shutdown(); 219 } 220 221 @Override 222 public Runnable getDelegatedTask() { 223 /* This implementation doesn't use any delegated tasks. */ 224 return null; 225 } 226 227 @Override 228 public String[] getEnabledCipherSuites() { 229 return sslParameters.getEnabledCipherSuites(); 230 } 231 232 @Override 233 public String[] getEnabledProtocols() { 234 return sslParameters.getEnabledProtocols(); 235 } 236 237 @Override 238 public boolean getEnableSessionCreation() { 239 return sslParameters.getEnableSessionCreation(); 240 } 241 242 @Override 243 public HandshakeStatus getHandshakeStatus() { 244 synchronized (stateLock) { 245 switch (engineState) { 246 case HANDSHAKE_WANTED: 247 if (getUseClientMode()) { 248 return HandshakeStatus.NEED_WRAP; 249 } else { 250 return HandshakeStatus.NEED_UNWRAP; 251 } 252 case HANDSHAKE_STARTED: 253 if (handshakeSink.available() > 0) { 254 return HandshakeStatus.NEED_WRAP; 255 } else { 256 return HandshakeStatus.NEED_UNWRAP; 257 } 258 case HANDSHAKE_COMPLETED: 259 if (handshakeSink.available() == 0) { 260 handshakeSink = null; 261 engineState = EngineState.READY; 262 return HandshakeStatus.FINISHED; 263 } else { 264 return HandshakeStatus.NEED_WRAP; 265 } 266 case NEW: 267 case MODE_SET: 268 case CLOSED: 269 case CLOSED_INBOUND: 270 case CLOSED_OUTBOUND: 271 case READY: 272 case READY_HANDSHAKE_CUT_THROUGH: 273 return HandshakeStatus.NOT_HANDSHAKING; 274 default: 275 break; 276 } 277 throw new IllegalStateException("Unexpected engine state: " + engineState); 278 } 279 } 280 281 @Override 282 public boolean getNeedClientAuth() { 283 return sslParameters.getNeedClientAuth(); 284 } 285 286 @Override 287 public SSLSession getSession() { 288 if (sslSession == null) { 289 return SSLNullSession.getNullSession(); 290 } 291 return sslSession; 292 } 293 294 @Override 295 public String[] getSupportedCipherSuites() { 296 return NativeCrypto.getSupportedCipherSuites(); 297 } 298 299 @Override 300 public String[] getSupportedProtocols() { 301 return NativeCrypto.getSupportedProtocols(); 302 } 303 304 @Override 305 public boolean getUseClientMode() { 306 return sslParameters.getUseClientMode(); 307 } 308 309 @Override 310 public boolean getWantClientAuth() { 311 return sslParameters.getWantClientAuth(); 312 } 313 314 @Override 315 public boolean isInboundDone() { 316 if (sslNativePointer == 0) { 317 synchronized (stateLock) { 318 return engineState == EngineState.CLOSED 319 || engineState == EngineState.CLOSED_INBOUND; 320 } 321 } 322 return (NativeCrypto.SSL_get_shutdown(sslNativePointer) 323 & NativeConstants.SSL_RECEIVED_SHUTDOWN) != 0; 324 } 325 326 @Override 327 public boolean isOutboundDone() { 328 if (sslNativePointer == 0) { 329 synchronized (stateLock) { 330 return engineState == EngineState.CLOSED 331 || engineState == EngineState.CLOSED_OUTBOUND; 332 } 333 } 334 return (NativeCrypto.SSL_get_shutdown(sslNativePointer) 335 & NativeConstants.SSL_SENT_SHUTDOWN) != 0; 336 } 337 338 @Override 339 public void setEnabledCipherSuites(String[] suites) { 340 sslParameters.setEnabledCipherSuites(suites); 341 } 342 343 @Override 344 public void setEnabledProtocols(String[] protocols) { 345 sslParameters.setEnabledProtocols(protocols); 346 } 347 348 @Override 349 public void setEnableSessionCreation(boolean flag) { 350 sslParameters.setEnableSessionCreation(flag); 351 } 352 353 @Override 354 public void setNeedClientAuth(boolean need) { 355 sslParameters.setNeedClientAuth(need); 356 } 357 358 @Override 359 public void setUseClientMode(boolean mode) { 360 synchronized (stateLock) { 361 if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) { 362 throw new IllegalArgumentException( 363 "Can not change mode after handshake: engineState == " + engineState); 364 } 365 engineState = EngineState.MODE_SET; 366 } 367 sslParameters.setUseClientMode(mode); 368 } 369 370 @Override 371 public void setWantClientAuth(boolean want) { 372 sslParameters.setWantClientAuth(want); 373 } 374 375 private static void checkIndex(int length, int offset, int count) { 376 if (offset < 0) { 377 throw new IndexOutOfBoundsException("offset < 0"); 378 } else if (count < 0) { 379 throw new IndexOutOfBoundsException("count < 0"); 380 } else if (offset > length) { 381 throw new IndexOutOfBoundsException("offset > length"); 382 } else if (offset > length - count) { 383 throw new IndexOutOfBoundsException("offset + count > length"); 384 } 385 } 386 387 @Override 388 public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts, int offset, int length) 389 throws SSLException { 390 if (src == null) { 391 throw new IllegalArgumentException("src == null"); 392 } else if (dsts == null) { 393 throw new IllegalArgumentException("dsts == null"); 394 } 395 checkIndex(dsts.length, offset, length); 396 int dstRemaining = 0; 397 for (int i = 0; i < dsts.length; i++) { 398 ByteBuffer dst = dsts[i]; 399 if (dst == null) { 400 throw new IllegalArgumentException("one of the dst == null"); 401 } else if (dst.isReadOnly()) { 402 throw new ReadOnlyBufferException(); 403 } 404 if (i >= offset && i < offset + length) { 405 dstRemaining += dst.remaining(); 406 } 407 } 408 409 synchronized (stateLock) { 410 // If the inbound direction is closed. we can't send anymore. 411 if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_INBOUND) { 412 return new SSLEngineResult(Status.CLOSED, getHandshakeStatus(), 0, 0); 413 } 414 if (engineState == EngineState.NEW || engineState == EngineState.MODE_SET) { 415 beginHandshake(); 416 } 417 } 418 419 // If we haven't completed the handshake yet, just let the caller know. 420 HandshakeStatus handshakeStatus = getHandshakeStatus(); 421 if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) { 422 int positionBeforeHandshake = src.position(); 423 OpenSSLBIOSource source = OpenSSLBIOSource.wrap(src); 424 long sslSessionCtx = 0L; 425 try { 426 sslSessionCtx = NativeCrypto.SSL_do_handshake_bio(sslNativePointer, 427 source.getContext(), handshakeSink.getContext(), this, getUseClientMode(), 428 sslParameters.npnProtocols, sslParameters.alpnProtocols); 429 if (sslSessionCtx != 0) { 430 if (sslSession != null && engineState == EngineState.HANDSHAKE_STARTED) { 431 engineState = EngineState.READY_HANDSHAKE_CUT_THROUGH; 432 } 433 sslSession = sslParameters.setupSession(sslSessionCtx, sslNativePointer, sslSession, 434 getPeerHost(), getPeerPort(), true); 435 } 436 int bytesWritten = handshakeSink.position(); 437 int bytesConsumed = (src.position() - positionBeforeHandshake); 438 return new SSLEngineResult((bytesConsumed > 0) ? Status.OK : Status.BUFFER_UNDERFLOW, 439 getHandshakeStatus(), bytesConsumed, bytesWritten); 440 } catch (Exception e) { 441 throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed") 442 .initCause(e); 443 } finally { 444 if (sslSession == null && sslSessionCtx != 0) { 445 NativeCrypto.SSL_SESSION_free(sslSessionCtx); 446 } 447 source.release(); 448 } 449 } else if (handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) { 450 return new SSLEngineResult(Status.OK, handshakeStatus, 0, 0); 451 } 452 453 if (dstRemaining == 0) { 454 return new SSLEngineResult(Status.BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0); 455 } 456 457 ByteBuffer srcDuplicate = src.duplicate(); 458 OpenSSLBIOSource source = OpenSSLBIOSource.wrap(srcDuplicate); 459 try { 460 int positionBeforeRead = srcDuplicate.position(); 461 int produced = 0; 462 boolean shouldStop = false; 463 464 while (!shouldStop) { 465 ByteBuffer dst = getNextAvailableByteBuffer(dsts, offset, length); 466 if (dst == null) { 467 shouldStop = true; 468 continue; 469 } 470 ByteBuffer arrayDst = dst; 471 if (dst.isDirect()) { 472 arrayDst = ByteBuffer.allocate(dst.remaining()); 473 } 474 475 int dstOffset = arrayDst.arrayOffset() + arrayDst.position(); 476 477 int internalProduced = NativeCrypto.SSL_read_BIO(sslNativePointer, 478 arrayDst.array(), dstOffset, dst.remaining(), source.getContext(), 479 localToRemoteSink.getContext(), this); 480 if (internalProduced <= 0) { 481 shouldStop = true; 482 continue; 483 } 484 arrayDst.position(arrayDst.position() + internalProduced); 485 produced += internalProduced; 486 if (dst != arrayDst) { 487 arrayDst.flip(); 488 dst.put(arrayDst); 489 } 490 } 491 492 int consumed = srcDuplicate.position() - positionBeforeRead; 493 src.position(srcDuplicate.position()); 494 return new SSLEngineResult((consumed > 0) ? Status.OK : Status.BUFFER_UNDERFLOW, 495 getHandshakeStatus(), consumed, produced); 496 } catch (IOException e) { 497 throw new SSLException(e); 498 } finally { 499 source.release(); 500 } 501 } 502 503 /** Returns the next non-empty ByteBuffer. */ 504 private ByteBuffer getNextAvailableByteBuffer(ByteBuffer[] buffers, int offset, int length) { 505 for (int i = offset; i < length; ++i) { 506 if (buffers[i].remaining() > 0) { 507 return buffers[i]; 508 } 509 } 510 return null; 511 } 512 513 @Override 514 public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst) 515 throws SSLException { 516 if (srcs == null) { 517 throw new IllegalArgumentException("srcs == null"); 518 } else if (dst == null) { 519 throw new IllegalArgumentException("dst == null"); 520 } else if (dst.isReadOnly()) { 521 throw new ReadOnlyBufferException(); 522 } 523 for (ByteBuffer src : srcs) { 524 if (src == null) { 525 throw new IllegalArgumentException("one of the src == null"); 526 } 527 } 528 checkIndex(srcs.length, offset, length); 529 530 if (dst.remaining() < NativeConstants.SSL3_RT_MAX_PACKET_SIZE) { 531 return new SSLEngineResult(Status.BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0); 532 } 533 534 synchronized (stateLock) { 535 // If the outbound direction is closed. we can't send anymore. 536 if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND) { 537 return new SSLEngineResult(Status.CLOSED, getHandshakeStatus(), 0, 0); 538 } 539 if (engineState == EngineState.NEW || engineState == EngineState.MODE_SET) { 540 beginHandshake(); 541 } 542 } 543 544 // If we haven't completed the handshake yet, just let the caller know. 545 HandshakeStatus handshakeStatus = getHandshakeStatus(); 546 if (handshakeStatus == HandshakeStatus.NEED_WRAP) { 547 if (handshakeSink.available() == 0) { 548 long sslSessionCtx = 0L; 549 try { 550 sslSessionCtx = NativeCrypto.SSL_do_handshake_bio(sslNativePointer, 551 nullSource.getContext(), handshakeSink.getContext(), this, 552 getUseClientMode(), sslParameters.npnProtocols, 553 sslParameters.alpnProtocols); 554 if (sslSessionCtx != 0) { 555 if (sslSession != null && engineState == EngineState.HANDSHAKE_STARTED) { 556 engineState = EngineState.READY_HANDSHAKE_CUT_THROUGH; 557 } 558 sslSession = sslParameters.setupSession(sslSessionCtx, sslNativePointer, sslSession, 559 getPeerHost(), getPeerPort(), true); 560 } 561 } catch (Exception e) { 562 throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed") 563 .initCause(e); 564 } finally { 565 if (sslSession == null && sslSessionCtx != 0) { 566 NativeCrypto.SSL_SESSION_free(sslSessionCtx); 567 } 568 } 569 } 570 int bytesWritten = writeSinkToByteBuffer(handshakeSink, dst); 571 return new SSLEngineResult(Status.OK, getHandshakeStatus(), 0, bytesWritten); 572 } else if (handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) { 573 return new SSLEngineResult(Status.OK, handshakeStatus, 0, 0); 574 } 575 576 try { 577 int totalRead = 0; 578 byte[] buffer = null; 579 580 for (ByteBuffer src : srcs) { 581 int toRead = src.remaining(); 582 if (buffer == null || toRead > buffer.length) { 583 buffer = new byte[toRead]; 584 } 585 /* 586 * We can't just use .mark() here because the caller might be 587 * using it. 588 */ 589 src.duplicate().get(buffer, 0, toRead); 590 int numRead = NativeCrypto.SSL_write_BIO(sslNativePointer, buffer, toRead, 591 localToRemoteSink.getContext(), this); 592 if (numRead > 0) { 593 src.position(src.position() + numRead); 594 totalRead += numRead; 595 } 596 } 597 598 return new SSLEngineResult(Status.OK, getHandshakeStatus(), totalRead, 599 writeSinkToByteBuffer(localToRemoteSink, dst)); 600 } catch (IOException e) { 601 throw new SSLException(e); 602 } 603 } 604 605 /** Writes data available in a BIO sink to a ByteBuffer. */ 606 private static int writeSinkToByteBuffer(OpenSSLBIOSink sink, ByteBuffer dst) { 607 int toWrite = Math.min(sink.available(), dst.remaining()); 608 dst.put(sink.toByteArray(), sink.position(), toWrite); 609 sink.skip(toWrite); 610 return toWrite; 611 } 612 613 @Override 614 public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) { 615 return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this); 616 } 617 618 @Override 619 public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) { 620 return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this); 621 } 622 623 @Override 624 public void onSSLStateChange(long sslSessionNativePtr, int type, int val) { 625 synchronized (stateLock) { 626 switch (type) { 627 case NativeConstants.SSL_CB_HANDSHAKE_DONE: 628 if (engineState != EngineState.HANDSHAKE_STARTED && 629 engineState != EngineState.READY_HANDSHAKE_CUT_THROUGH) { 630 throw new IllegalStateException("Completed handshake while in mode " 631 + engineState); 632 } 633 engineState = EngineState.HANDSHAKE_COMPLETED; 634 break; 635 case NativeConstants.SSL_CB_HANDSHAKE_START: 636 // For clients, this will allow the NEED_UNWRAP status to be 637 // returned. 638 engineState = EngineState.HANDSHAKE_STARTED; 639 break; 640 } 641 } 642 } 643 644 @Override 645 public void verifyCertificateChain(long sslSessionNativePtr, long[] certRefs, 646 String authMethod) throws CertificateException { 647 try { 648 X509TrustManager x509tm = sslParameters.getX509TrustManager(); 649 if (x509tm == null) { 650 throw new CertificateException("No X.509 TrustManager"); 651 } 652 if (certRefs == null || certRefs.length == 0) { 653 throw new SSLException("Peer sent no certificate"); 654 } 655 OpenSSLX509Certificate[] peerCertChain = new OpenSSLX509Certificate[certRefs.length]; 656 for (int i = 0; i < certRefs.length; i++) { 657 peerCertChain[i] = new OpenSSLX509Certificate(certRefs[i]); 658 } 659 660 // Used for verifyCertificateChain callback 661 handshakeSession = new OpenSSLSessionImpl(sslSessionNativePtr, null, peerCertChain, 662 getPeerHost(), getPeerPort(), null); 663 664 boolean client = sslParameters.getUseClientMode(); 665 if (client) { 666 Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, this); 667 } else { 668 String authType = peerCertChain[0].getPublicKey().getAlgorithm(); 669 Platform.checkClientTrusted(x509tm, peerCertChain, authType, this); 670 } 671 } catch (CertificateException e) { 672 throw e; 673 } catch (Exception e) { 674 throw new CertificateException(e); 675 } finally { 676 // Clear this before notifying handshake completed listeners 677 handshakeSession = null; 678 } 679 } 680 681 @Override 682 public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 683 throws CertificateEncodingException, SSLException { 684 sslParameters.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals, 685 sslNativePointer, this); 686 } 687 688 private void shutdown() { 689 try { 690 NativeCrypto.SSL_shutdown_BIO(sslNativePointer, nullSource.getContext(), 691 localToRemoteSink.getContext(), this); 692 } catch (IOException ignored) { 693 /* 694 * TODO: The RI ignores close failures in SSLSocket, but need to 695 * investigate whether it does for SSLEngine. 696 */ 697 } 698 } 699 700 private void shutdownAndFreeSslNative() { 701 try { 702 shutdown(); 703 } finally { 704 free(); 705 } 706 } 707 708 private void free() { 709 if (sslNativePointer == 0) { 710 return; 711 } 712 NativeCrypto.SSL_free(sslNativePointer); 713 sslNativePointer = 0; 714 } 715 716 @Override 717 protected void finalize() throws Throwable { 718 try { 719 free(); 720 } finally { 721 super.finalize(); 722 } 723 } 724 725 // Comment annotation to compile Conscrypt unbundled with Java 6. 726 /* @Override */ 727 public SSLSession getHandshakeSession() { 728 return handshakeSession; 729 } 730 731 @Override 732 public String chooseServerAlias(X509KeyManager keyManager, String keyType) { 733 if (keyManager instanceof X509ExtendedKeyManager) { 734 X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager; 735 return ekm.chooseEngineServerAlias(keyType, null, this); 736 } else { 737 return keyManager.chooseServerAlias(keyType, null, null); 738 } 739 } 740 741 @Override 742 public String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 743 String[] keyTypes) { 744 if (keyManager instanceof X509ExtendedKeyManager) { 745 X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager; 746 return ekm.chooseEngineClientAlias(keyTypes, issuers, this); 747 } else { 748 return keyManager.chooseClientAlias(keyTypes, issuers, null); 749 } 750 } 751 752 @Override 753 public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) { 754 return keyManager.chooseServerKeyIdentityHint(this); 755 } 756 757 @Override 758 public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) { 759 return keyManager.chooseClientKeyIdentity(identityHint, this); 760 } 761 762 @Override 763 public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) { 764 return keyManager.getKey(identityHint, identity, this); 765 } 766} 767