1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 /* 3 * Copyright (C) 2017 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.org.conscrypt; 19 20 import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_CLOSED; 21 import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_HANDSHAKE_COMPLETED; 22 import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_HANDSHAKE_STARTED; 23 import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_NEW; 24 import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_READY; 25 import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_READY_HANDSHAKE_CUT_THROUGH; 26 27 import com.android.org.conscrypt.ExternalSession.Provider; 28 import com.android.org.conscrypt.NativeRef.SSL_SESSION; 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.io.OutputStream; 32 import java.net.InetAddress; 33 import java.net.Socket; 34 import java.net.SocketException; 35 import java.security.InvalidKeyException; 36 import java.security.PrivateKey; 37 import java.security.cert.CertificateEncodingException; 38 import java.security.cert.CertificateException; 39 import java.security.cert.X509Certificate; 40 import java.security.interfaces.ECKey; 41 import java.security.spec.ECParameterSpec; 42 import javax.crypto.SecretKey; 43 import javax.net.ssl.SSLException; 44 import javax.net.ssl.SSLHandshakeException; 45 import javax.net.ssl.SSLParameters; 46 import javax.net.ssl.SSLProtocolException; 47 import javax.net.ssl.SSLSession; 48 import javax.net.ssl.X509KeyManager; 49 import javax.net.ssl.X509TrustManager; 50 import javax.security.auth.x500.X500Principal; 51 52 /** 53 * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 54 * <p> 55 * Extensions to SSLSocket include: 56 * <ul> 57 * <li>handshake timeout 58 * <li>session tickets 59 * <li>Server Name Indication 60 * </ul> 61 */ 62 class ConscryptFileDescriptorSocket extends OpenSSLSocketImpl 63 implements NativeCrypto.SSLHandshakeCallbacks, SSLParametersImpl.PSKCallbacks, 64 SSLParametersImpl.AliasChooser { 65 private static final boolean DBG_STATE = false; 66 67 // @GuardedBy("ssl"); 68 private int state = STATE_NEW; 69 70 /** 71 * Wrapper around the underlying SSL object. 72 */ 73 private final NativeSsl ssl; 74 75 /** 76 * Protected by synchronizing on ssl. Starts as null, set by 77 * getInputStream. 78 */ 79 // @GuardedBy("ssl"); 80 private SSLInputStream is; 81 82 /** 83 * Protected by synchronizing on ssl. Starts as null, set by 84 * getInputStream. 85 */ 86 // @GuardedBy("ssl"); 87 private SSLOutputStream os; 88 89 private final SSLParametersImpl sslParameters; 90 91 /* 92 * A CloseGuard object on Android. On other platforms, this is nothing. 93 */ 94 private final Object guard = Platform.closeGuardGet(); 95 96 /** 97 * Private key for the TLS Channel ID extension. This field is client-side 98 * only. Set during startHandshake. 99 */ 100 private OpenSSLKey channelIdPrivateKey; 101 102 private final ActiveSession activeSession; 103 /** 104 * A snapshot of the active session when the engine was closed. 105 */ 106 private SessionSnapshot closedSession; 107 /** 108 * The session object exposed externally from this class. 109 */ 110 private final SSLSession externalSession = 111 Platform.wrapSSLSession(new ExternalSession(new ExternalSession.Provider() { 112 @Override 113 public ConscryptSession provideSession() { 114 return ConscryptFileDescriptorSocket.this.provideSession(); 115 } 116 })); 117 118 private int writeTimeoutMilliseconds = 0; 119 private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 120 121 private long handshakeStartedMillis = 0; 122 123 // The constructors should not be called except from the Platform class, because we may 124 // want to construct a subclass instead. ConscryptFileDescriptorSocket(SSLParametersImpl sslParameters)125 ConscryptFileDescriptorSocket(SSLParametersImpl sslParameters) throws IOException { 126 this.sslParameters = sslParameters; 127 this.ssl = newSsl(sslParameters, this); 128 activeSession = new ActiveSession(ssl, sslParameters.getSessionContext()); 129 } 130 ConscryptFileDescriptorSocket(String hostname, int port, SSLParametersImpl sslParameters)131 ConscryptFileDescriptorSocket(String hostname, int port, SSLParametersImpl sslParameters) 132 throws IOException { 133 super(hostname, port); 134 this.sslParameters = sslParameters; 135 this.ssl = newSsl(sslParameters, this); 136 activeSession = new ActiveSession(ssl, sslParameters.getSessionContext()); 137 } 138 ConscryptFileDescriptorSocket(InetAddress address, int port, SSLParametersImpl sslParameters)139 ConscryptFileDescriptorSocket(InetAddress address, int port, SSLParametersImpl sslParameters) 140 throws IOException { 141 super(address, port); 142 this.sslParameters = sslParameters; 143 this.ssl = newSsl(sslParameters, this); 144 activeSession = new ActiveSession(ssl, sslParameters.getSessionContext()); 145 } 146 ConscryptFileDescriptorSocket(String hostname, int port, InetAddress clientAddress, int clientPort, SSLParametersImpl sslParameters)147 ConscryptFileDescriptorSocket(String hostname, int port, InetAddress clientAddress, 148 int clientPort, SSLParametersImpl sslParameters) throws IOException { 149 super(hostname, port, clientAddress, clientPort); 150 this.sslParameters = sslParameters; 151 this.ssl = newSsl(sslParameters, this); 152 activeSession = new ActiveSession(ssl, sslParameters.getSessionContext()); 153 } 154 ConscryptFileDescriptorSocket(InetAddress address, int port, InetAddress clientAddress, int clientPort, SSLParametersImpl sslParameters)155 ConscryptFileDescriptorSocket(InetAddress address, int port, InetAddress clientAddress, 156 int clientPort, SSLParametersImpl sslParameters) throws IOException { 157 super(address, port, clientAddress, clientPort); 158 this.sslParameters = sslParameters; 159 this.ssl = newSsl(sslParameters, this); 160 activeSession = new ActiveSession(ssl, sslParameters.getSessionContext()); 161 } 162 ConscryptFileDescriptorSocket(Socket socket, String hostname, int port, boolean autoClose, SSLParametersImpl sslParameters)163 ConscryptFileDescriptorSocket(Socket socket, String hostname, int port, boolean autoClose, 164 SSLParametersImpl sslParameters) throws IOException { 165 super(socket, hostname, port, autoClose); 166 this.sslParameters = sslParameters; 167 this.ssl = newSsl(sslParameters, this); 168 activeSession = new ActiveSession(ssl, sslParameters.getSessionContext()); 169 } 170 newSsl(SSLParametersImpl sslParameters, ConscryptFileDescriptorSocket engine)171 private static NativeSsl newSsl(SSLParametersImpl sslParameters, 172 ConscryptFileDescriptorSocket engine) throws SSLException { 173 return NativeSsl.newInstance(sslParameters, engine, engine, engine); 174 } 175 176 /** 177 * Starts a TLS/SSL handshake on this connection using some native methods 178 * from the OpenSSL library. It can negotiate new encryption keys, change 179 * cipher suites, or initiate a new session. The certificate chain is 180 * verified if the correspondent property in java.Security is set. All 181 * listeners are notified at the end of the TLS/SSL handshake. 182 */ 183 @Override startHandshake()184 public final void startHandshake() throws IOException { 185 checkOpen(); 186 synchronized (ssl) { 187 if (state == STATE_NEW) { 188 transitionTo(STATE_HANDSHAKE_STARTED); 189 } else { 190 // We've either started the handshake already or have been closed. 191 // Do nothing in both cases. 192 return; 193 } 194 } 195 196 boolean releaseResources = true; 197 try { 198 Platform.closeGuardOpen(guard, "close"); 199 200 // Prepare the SSL object for the handshake. 201 ssl.initialize(getHostname(), channelIdPrivateKey); 202 203 // For clients, offer to resume a previously cached session to avoid the 204 // full TLS handshake. 205 if (getUseClientMode()) { 206 NativeSslSession cachedSession = clientSessionContext().getCachedSession( 207 getHostnameOrIP(), getPort(), sslParameters); 208 if (cachedSession != null) { 209 cachedSession.offerToResume(ssl); 210 } 211 } 212 213 // Temporarily use a different timeout for the handshake process 214 int savedReadTimeoutMilliseconds = getSoTimeout(); 215 int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 216 if (handshakeTimeoutMilliseconds >= 0) { 217 setSoTimeout(handshakeTimeoutMilliseconds); 218 setSoWriteTimeout(handshakeTimeoutMilliseconds); 219 } 220 221 synchronized (ssl) { 222 if (state == STATE_CLOSED) { 223 return; 224 } 225 } 226 227 try { 228 ssl.doHandshake(Platform.getFileDescriptor(socket), getSoTimeout()); 229 230 // Update the session from the current state of the SSL object. 231 activeSession.onPeerCertificateAvailable(getHostnameOrIP(), getPort()); 232 } catch (CertificateException e) { 233 SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 234 wrapper.initCause(e); 235 throw wrapper; 236 } catch (SSLException e) { 237 // Swallow this exception if it's thrown as the result of an interruption. 238 // 239 // TODO: SSL_read and SSL_write return -1 when interrupted, but SSL_do_handshake 240 // will throw the last sslError that it saw before sslSelect, usually SSL_WANT_READ 241 // (or WANT_WRITE). Catching that exception here doesn't seem much worse than 242 // changing the native code to return a "special" native pointer value when that 243 // happens. 244 synchronized (ssl) { 245 if (state == STATE_CLOSED) { 246 return; 247 } 248 } 249 throw e; 250 } 251 252 synchronized (ssl) { 253 if (state == STATE_CLOSED) { 254 return; 255 } 256 } 257 258 // Restore the original timeout now that the handshake is complete 259 if (handshakeTimeoutMilliseconds >= 0) { 260 setSoTimeout(savedReadTimeoutMilliseconds); 261 setSoWriteTimeout(savedWriteTimeoutMilliseconds); 262 } 263 264 synchronized (ssl) { 265 releaseResources = (state == STATE_CLOSED); 266 267 if (state == STATE_HANDSHAKE_STARTED) { 268 transitionTo(STATE_READY_HANDSHAKE_CUT_THROUGH); 269 } else { 270 transitionTo(STATE_READY); 271 } 272 273 if (!releaseResources) { 274 // Unblock threads that are waiting for our state to transition 275 // into STATE_READY or STATE_READY_HANDSHAKE_CUT_THROUGH. 276 ssl.notifyAll(); 277 } 278 } 279 } catch (SSLProtocolException e) { 280 throw(SSLHandshakeException) new SSLHandshakeException("Handshake failed").initCause(e); 281 } finally { 282 // on exceptional exit, treat the socket as closed 283 if (releaseResources) { 284 synchronized (ssl) { 285 // Mark the socket as closed since we might have reached this as 286 // a result on an exception thrown by the handshake process. 287 // 288 // The state will already be set to closed if we reach this as a result of 289 // an early return or an interruption due to a concurrent call to close(). 290 transitionTo(STATE_CLOSED); 291 ssl.notifyAll(); 292 } 293 294 try { 295 shutdownAndFreeSslNative(); 296 } catch (IOException ignored) { 297 // Ignored. 298 } 299 } 300 } 301 } 302 303 @Override 304 @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb clientCertificateRequested(byte[] keyTypeBytes, int[] signatureAlgs, byte[][] asn1DerEncodedPrincipals)305 public final void clientCertificateRequested(byte[] keyTypeBytes, int[] signatureAlgs, 306 byte[][] asn1DerEncodedPrincipals) 307 throws CertificateEncodingException, SSLException { 308 ssl.chooseClientCertificate(keyTypeBytes, signatureAlgs, asn1DerEncodedPrincipals); 309 } 310 311 @Override 312 @SuppressWarnings("unused") // used by native psk_client_callback clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key)313 public final int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) { 314 return ssl.clientPSKKeyRequested(identityHint, identity, key); 315 } 316 317 @Override 318 @SuppressWarnings("unused") // used by native psk_server_callback serverPSKKeyRequested(String identityHint, String identity, byte[] key)319 public final int serverPSKKeyRequested(String identityHint, String identity, byte[] key) { 320 return ssl.serverPSKKeyRequested(identityHint, identity, key); 321 } 322 323 @Override 324 @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback onSSLStateChange(int type, int val)325 public final void onSSLStateChange(int type, int val) { 326 if (type != NativeConstants.SSL_CB_HANDSHAKE_DONE) { 327 // We only care about successful completion. 328 return; 329 } 330 331 // First, update the state. 332 synchronized (ssl) { 333 if (state == STATE_CLOSED) { 334 // Someone called "close" but the handshake hasn't been interrupted yet. 335 return; 336 } 337 338 // Now that we've fixed up our state, we can tell waiting threads that 339 // we're ready. 340 transitionTo(STATE_READY); 341 } 342 343 // Let listeners know we are finally done 344 notifyHandshakeCompletedListeners(); 345 346 synchronized (ssl) { 347 // Notify all threads waiting for the handshake to complete. 348 ssl.notifyAll(); 349 } 350 } 351 352 @Override 353 @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / new_session_callback onNewSessionEstablished(long sslSessionNativePtr)354 public final void onNewSessionEstablished(long sslSessionNativePtr) { 355 try { 356 // Increment the reference count to "take ownership" of the session resource. 357 NativeCrypto.SSL_SESSION_up_ref(sslSessionNativePtr); 358 359 // Create a native reference which will release the SSL_SESSION in its finalizer. 360 // This constructor will only throw if the native pointer passed in is NULL, which 361 // BoringSSL guarantees will not happen. 362 NativeRef.SSL_SESSION ref = new SSL_SESSION(sslSessionNativePtr); 363 364 NativeSslSession nativeSession = NativeSslSession.newInstance(ref, activeSession); 365 366 // Cache the newly established session. 367 AbstractSessionContext ctx = sessionContext(); 368 ctx.cacheSession(nativeSession); 369 } catch (Exception ignored) { 370 // Ignore. 371 } 372 } 373 374 @Override serverSessionRequested(byte[] id)375 public final long serverSessionRequested(byte[] id) { 376 // TODO(nathanmittler): Implement server-side caching for TLS < 1.3 377 return 0; 378 } 379 380 @Override serverCertificateRequested()381 public final void serverCertificateRequested() throws IOException { 382 synchronized (ssl) { 383 ssl.configureServerCertificate(); 384 } 385 } 386 387 @Override verifyCertificateChain(byte[][] certChain, String authMethod)388 public final void verifyCertificateChain(byte[][] certChain, String authMethod) 389 throws CertificateException { 390 try { 391 if (certChain == null || certChain.length == 0) { 392 throw new CertificateException("Peer sent no certificate"); 393 } 394 X509Certificate[] peerCertChain = SSLUtils.decodeX509CertificateChain(certChain); 395 396 X509TrustManager x509tm = sslParameters.getX509TrustManager(); 397 if (x509tm == null) { 398 throw new CertificateException("No X.509 TrustManager"); 399 } 400 // Update the peer information on the session. 401 activeSession.onPeerCertificatesReceived(getHostnameOrIP(), getPort(), peerCertChain); 402 403 if (getUseClientMode()) { 404 Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, this); 405 } else { 406 String authType = peerCertChain[0].getPublicKey().getAlgorithm(); 407 Platform.checkClientTrusted(x509tm, peerCertChain, authType, this); 408 } 409 } catch (CertificateException e) { 410 throw e; 411 } catch (Exception e) { 412 throw new CertificateException(e); 413 } 414 } 415 416 @Override getInputStream()417 public final InputStream getInputStream() throws IOException { 418 checkOpen(); 419 420 InputStream returnVal; 421 synchronized (ssl) { 422 if (state == STATE_CLOSED) { 423 throw new SocketException("Socket is closed."); 424 } 425 426 if (is == null) { 427 is = new SSLInputStream(); 428 } 429 430 returnVal = is; 431 } 432 433 // Block waiting for a handshake without a lock held. It's possible that the socket 434 // is closed at this point. If that happens, we'll still return the input stream but 435 // all reads on it will throw. 436 waitForHandshake(); 437 return returnVal; 438 } 439 440 @Override getOutputStream()441 public final OutputStream getOutputStream() throws IOException { 442 checkOpen(); 443 444 OutputStream returnVal; 445 synchronized (ssl) { 446 if (state == STATE_CLOSED) { 447 throw new SocketException("Socket is closed."); 448 } 449 450 if (os == null) { 451 os = new SSLOutputStream(); 452 } 453 454 returnVal = os; 455 } 456 457 // Block waiting for a handshake without a lock held. It's possible that the socket 458 // is closed at this point. If that happens, we'll still return the output stream but 459 // all writes on it will throw. 460 waitForHandshake(); 461 return returnVal; 462 } 463 assertReadableOrWriteableState()464 private void assertReadableOrWriteableState() { 465 if (state == STATE_READY || state == STATE_READY_HANDSHAKE_CUT_THROUGH) { 466 return; 467 } 468 469 throw new AssertionError("Invalid state: " + state); 470 } 471 waitForHandshake()472 private void waitForHandshake() throws IOException { 473 startHandshake(); 474 475 synchronized (ssl) { 476 while (state != STATE_READY && 477 state != STATE_READY_HANDSHAKE_CUT_THROUGH && 478 state != STATE_CLOSED) { 479 try { 480 ssl.wait(); 481 } catch (InterruptedException e) { 482 Thread.currentThread().interrupt(); 483 throw new IOException("Interrupted waiting for handshake", e); 484 } 485 } 486 487 if (state == STATE_CLOSED) { 488 throw new SocketException("Socket is closed"); 489 } 490 } 491 } 492 493 /** 494 * This inner class provides input data stream functionality 495 * for the OpenSSL native implementation. It is used to 496 * read data received via SSL protocol. 497 */ 498 private class SSLInputStream extends InputStream { 499 /** 500 * OpenSSL only lets one thread read at a time, so this is used to 501 * make sure we serialize callers of SSL_read. Thread is already 502 * expected to have completed handshaking. 503 */ 504 private final Object readLock = new Object(); 505 SSLInputStream()506 SSLInputStream() { 507 } 508 509 /** 510 * Reads one byte. If there is no data in the underlying buffer, 511 * this operation can block until the data will be 512 * available. 513 */ 514 @Override read()515 public int read() throws IOException { 516 byte[] buffer = new byte[1]; 517 int result = read(buffer, 0, 1); 518 return (result != -1) ? buffer[0] & 0xff : -1; 519 } 520 521 /** 522 * Method acts as described in spec for superclass. 523 * @see java.io.InputStream#read(byte[],int,int) 524 */ 525 @Override read(byte[] buf, int offset, int byteCount)526 public int read(byte[] buf, int offset, int byteCount) throws IOException { 527 Platform.blockGuardOnNetwork(); 528 529 checkOpen(); 530 ArrayUtils.checkOffsetAndCount(buf.length, offset, byteCount); 531 if (byteCount == 0) { 532 return 0; 533 } 534 535 synchronized (readLock) { 536 synchronized (ssl) { 537 if (state == STATE_CLOSED) { 538 throw new SocketException("socket is closed"); 539 } 540 541 if (DBG_STATE) { 542 assertReadableOrWriteableState(); 543 } 544 } 545 546 int ret = ssl.read( 547 Platform.getFileDescriptor(socket), buf, offset, byteCount, getSoTimeout()); 548 if (ret == -1) { 549 synchronized (ssl) { 550 if (state == STATE_CLOSED) { 551 throw new SocketException("socket is closed"); 552 } 553 } 554 } 555 return ret; 556 } 557 } 558 559 @Override available()560 public int available() { 561 return ssl.getPendingReadableBytes(); 562 } 563 awaitPendingOps()564 void awaitPendingOps() { 565 if (DBG_STATE) { 566 synchronized (ssl) { 567 if (state != STATE_CLOSED) { 568 throw new AssertionError("State is: " + state); 569 } 570 } 571 } 572 573 synchronized (readLock) {} 574 } 575 } 576 577 /** 578 * This inner class provides output data stream functionality 579 * for the OpenSSL native implementation. It is used to 580 * write data according to the encryption parameters given in SSL context. 581 */ 582 private class SSLOutputStream extends OutputStream { 583 /** 584 * OpenSSL only lets one thread write at a time, so this is used 585 * to make sure we serialize callers of SSL_write. Thread is 586 * already expected to have completed handshaking. 587 */ 588 private final Object writeLock = new Object(); 589 SSLOutputStream()590 SSLOutputStream() { 591 } 592 593 /** 594 * Method acts as described in spec for superclass. 595 * @see java.io.OutputStream#write(int) 596 */ 597 @Override write(int oneByte)598 public void write(int oneByte) throws IOException { 599 byte[] buffer = new byte[1]; 600 buffer[0] = (byte) (oneByte & 0xff); 601 write(buffer); 602 } 603 604 /** 605 * Method acts as described in spec for superclass. 606 * @see java.io.OutputStream#write(byte[],int,int) 607 */ 608 @Override write(byte[] buf, int offset, int byteCount)609 public void write(byte[] buf, int offset, int byteCount) throws IOException { 610 Platform.blockGuardOnNetwork(); 611 checkOpen(); 612 ArrayUtils.checkOffsetAndCount(buf.length, offset, byteCount); 613 if (byteCount == 0) { 614 return; 615 } 616 617 synchronized (writeLock) { 618 synchronized (ssl) { 619 if (state == STATE_CLOSED) { 620 throw new SocketException("socket is closed"); 621 } 622 623 if (DBG_STATE) { 624 assertReadableOrWriteableState(); 625 } 626 } 627 628 ssl.write(Platform.getFileDescriptor(socket), buf, offset, byteCount, 629 writeTimeoutMilliseconds); 630 631 synchronized (ssl) { 632 if (state == STATE_CLOSED) { 633 throw new SocketException("socket is closed"); 634 } 635 } 636 } 637 } 638 awaitPendingOps()639 void awaitPendingOps() { 640 if (DBG_STATE) { 641 synchronized (ssl) { 642 if (state != STATE_CLOSED) { 643 throw new AssertionError("State is: " + state); 644 } 645 } 646 } 647 648 synchronized (writeLock) {} 649 } 650 } 651 652 @Override getSession()653 public final SSLSession getSession() { 654 return externalSession; 655 } 656 provideSession()657 private ConscryptSession provideSession() { 658 boolean handshakeCompleted = false; 659 synchronized (ssl) { 660 if (state == STATE_CLOSED) { 661 return closedSession != null ? closedSession : SSLNullSession.getNullSession(); 662 } 663 664 try { 665 handshakeCompleted = state >= STATE_READY; 666 if (!handshakeCompleted && isConnected()) { 667 waitForHandshake(); 668 handshakeCompleted = true; 669 } 670 } catch (IOException e) { 671 // Fall through. 672 } 673 } 674 675 if (!handshakeCompleted) { 676 // return an invalid session with 677 // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 678 return SSLNullSession.getNullSession(); 679 } 680 681 return activeSession; 682 } 683 684 // After handshake has started, provide active session otherwise a null session, 685 // for code which needs to read session attributes without triggering the handshake. provideAfterHandshakeSession()686 private ConscryptSession provideAfterHandshakeSession() { 687 return (state < STATE_HANDSHAKE_STARTED) ? SSLNullSession.getNullSession() 688 : provideSession(); 689 } 690 691 // If handshake is in progress, provide active session otherwise a null session. provideHandshakeSession()692 private ConscryptSession provideHandshakeSession() { 693 synchronized (ssl) { 694 return state >= STATE_HANDSHAKE_STARTED && state < STATE_READY ? activeSession 695 : SSLNullSession.getNullSession(); 696 } 697 } 698 699 @Override getActiveSession()700 final SSLSession getActiveSession() { 701 return activeSession; 702 } 703 704 @Override getHandshakeSession()705 public final SSLSession getHandshakeSession() { 706 synchronized (ssl) { 707 if (state >= STATE_HANDSHAKE_STARTED && state < STATE_READY) { 708 return Platform.wrapSSLSession(new ExternalSession(new ExternalSession.Provider() { 709 @Override 710 public ConscryptSession provideSession() { 711 return ConscryptFileDescriptorSocket.this.provideHandshakeSession(); 712 } 713 })); 714 } 715 return null; 716 } 717 } 718 719 @Override 720 public final boolean getEnableSessionCreation() { 721 return sslParameters.getEnableSessionCreation(); 722 } 723 724 @Override 725 public final void setEnableSessionCreation(boolean flag) { 726 sslParameters.setEnableSessionCreation(flag); 727 } 728 729 @Override 730 public final String[] getSupportedCipherSuites() { 731 return NativeCrypto.getSupportedCipherSuites(); 732 } 733 734 @Override 735 public final String[] getEnabledCipherSuites() { 736 return sslParameters.getEnabledCipherSuites(); 737 } 738 739 @Override 740 public final void setEnabledCipherSuites(String[] suites) { 741 sslParameters.setEnabledCipherSuites(suites); 742 } 743 744 @Override 745 public final String[] getSupportedProtocols() { 746 return NativeCrypto.getSupportedProtocols(); 747 } 748 749 @Override 750 public final String[] getEnabledProtocols() { 751 return sslParameters.getEnabledProtocols(); 752 } 753 754 @Override 755 public final void setEnabledProtocols(String[] protocols) { 756 sslParameters.setEnabledProtocols(protocols); 757 } 758 759 /** 760 * This method enables session ticket support. 761 * 762 * @param useSessionTickets True to enable session tickets 763 */ 764 @android.compat.annotation. 765 UnsupportedAppUsage(maxTargetSdk = dalvik.annotation.compat.VersionCodes.Q, 766 publicAlternatives = "Use {@link android.net.ssl.SSLSockets#setUseSessionTickets}.") 767 @Override 768 public final void 769 setUseSessionTickets(boolean useSessionTickets) { 770 sslParameters.setUseSessionTickets(useSessionTickets); 771 } 772 773 /** 774 * This method enables Server Name Indication. If the hostname is not a valid SNI hostname, 775 * the SNI extension will be omitted from the handshake. 776 * 777 * @param hostname the desired SNI hostname, or null to disable 778 */ 779 @android.compat.annotation. 780 UnsupportedAppUsage(maxTargetSdk = dalvik.annotation.compat.VersionCodes.Q, 781 publicAlternatives = "Use {@code javax.net.ssl.SSLParameters#setServerNames}.") 782 @Override 783 public final void 784 setHostname(String hostname) { 785 sslParameters.setUseSni(hostname != null); 786 super.setHostname(hostname); 787 } 788 789 /** 790 * Enables/disables TLS Channel ID for this server socket. 791 * 792 * <p>This method needs to be invoked before the handshake starts. 793 * 794 * @throws IllegalStateException if this is a client socket or if the handshake has already 795 * started. 796 */ 797 @Override 798 public final void setChannelIdEnabled(boolean enabled) { 799 if (getUseClientMode()) { 800 throw new IllegalStateException("Client mode"); 801 } 802 803 synchronized (ssl) { 804 if (state != STATE_NEW) { 805 throw new IllegalStateException( 806 "Could not enable/disable Channel ID after the initial handshake has" 807 + " begun."); 808 } 809 } 810 sslParameters.channelIdEnabled = enabled; 811 } 812 813 /** 814 * Gets the TLS Channel ID for this server socket. Channel ID is only available once the 815 * handshake completes. 816 * 817 * @return channel ID or {@code null} if not available. 818 * 819 * @throws IllegalStateException if this is a client socket or if the handshake has not yet 820 * completed. 821 * @throws SSLException if channel ID is available but could not be obtained. 822 */ 823 @Override 824 public final byte[] getChannelId() throws SSLException { 825 if (getUseClientMode()) { 826 throw new IllegalStateException("Client mode"); 827 } 828 829 synchronized (ssl) { 830 if (state != STATE_READY) { 831 throw new IllegalStateException( 832 "Channel ID is only available after handshake completes"); 833 } 834 } 835 return ssl.getTlsChannelId(); 836 } 837 838 /** 839 * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 840 * 841 * <p>This method needs to be invoked before the handshake starts. 842 * 843 * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 844 * TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST 845 * P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 846 * 847 * @throws IllegalStateException if this is a server socket or if the handshake has already 848 * started. 849 */ 850 @Override 851 public final void setChannelIdPrivateKey(PrivateKey privateKey) { 852 if (!getUseClientMode()) { 853 throw new IllegalStateException("Server mode"); 854 } 855 856 synchronized (ssl) { 857 if (state != STATE_NEW) { 858 throw new IllegalStateException( 859 "Could not change Channel ID private key after the initial handshake has" 860 + " begun."); 861 } 862 } 863 864 if (privateKey == null) { 865 sslParameters.channelIdEnabled = false; 866 channelIdPrivateKey = null; 867 } else { 868 sslParameters.channelIdEnabled = true; 869 try { 870 ECParameterSpec ecParams = null; 871 if (privateKey instanceof ECKey) { 872 ecParams = ((ECKey) privateKey).getParams(); 873 } 874 if (ecParams == null) { 875 // Assume this is a P-256 key, as specified in the contract of this method. 876 ecParams = 877 OpenSSLECGroupContext.getCurveByName("prime256v1").getECParameterSpec(); 878 } 879 channelIdPrivateKey = 880 OpenSSLKey.fromECPrivateKeyForTLSStackOnly(privateKey, ecParams); 881 } catch (InvalidKeyException e) { 882 // Will have error in startHandshake 883 } 884 } 885 } 886 887 @Override 888 byte[] getTlsUnique() { 889 return ssl.getTlsUnique(); 890 } 891 892 @Override 893 byte[] exportKeyingMaterial(String label, byte[] context, int length) throws SSLException { 894 synchronized (ssl) { 895 if (state < STATE_HANDSHAKE_COMPLETED || state == STATE_CLOSED) { 896 return null; 897 } 898 } 899 return ssl.exportKeyingMaterial(label, context, length); 900 } 901 902 @Override 903 public final boolean getUseClientMode() { 904 return sslParameters.getUseClientMode(); 905 } 906 907 @Override 908 public final void setUseClientMode(boolean mode) { 909 synchronized (ssl) { 910 if (state != STATE_NEW) { 911 throw new IllegalArgumentException( 912 "Could not change the mode after the initial handshake has begun."); 913 } 914 } 915 sslParameters.setUseClientMode(mode); 916 } 917 918 @Override 919 public final boolean getWantClientAuth() { 920 return sslParameters.getWantClientAuth(); 921 } 922 923 @Override 924 public final boolean getNeedClientAuth() { 925 return sslParameters.getNeedClientAuth(); 926 } 927 928 @Override 929 public final void setNeedClientAuth(boolean need) { 930 sslParameters.setNeedClientAuth(need); 931 } 932 933 @Override 934 public final void setWantClientAuth(boolean want) { 935 sslParameters.setWantClientAuth(want); 936 } 937 938 /** 939 * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 940 */ 941 @Override 942 public final void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 943 this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 944 945 Platform.setSocketWriteTimeout(this, writeTimeoutMilliseconds); 946 } 947 948 /** 949 * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 950 */ 951 @Override 952 public final int getSoWriteTimeout() { 953 return writeTimeoutMilliseconds; 954 } 955 956 /** 957 * Set the handshake timeout on this socket. This timeout is specified in 958 * milliseconds and will be used only during the handshake process. 959 */ 960 @Override 961 public final void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 962 this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 963 } 964 965 @Override 966 @SuppressWarnings("UnsynchronizedOverridesSynchronized") 967 public final void close() throws IOException { 968 // TODO: Close SSL sockets using a background thread so they close gracefully. 969 970 SSLInputStream sslInputStream; 971 SSLOutputStream sslOutputStream; 972 973 if (ssl == null) { 974 // close() has been called before we've initialized the socket, so just 975 // return. 976 return; 977 } 978 979 synchronized (ssl) { 980 if (state == STATE_CLOSED) { 981 // close() has already been called, so do nothing and return. 982 return; 983 } 984 985 int oldState = state; 986 transitionTo(STATE_CLOSED); 987 988 if (oldState == STATE_NEW) { 989 // The handshake hasn't been started yet, so there's no OpenSSL related 990 // state to clean up. We still need to close the underlying socket if 991 // we're wrapping it and were asked to autoClose. 992 free(); 993 closeUnderlyingSocket(); 994 995 ssl.notifyAll(); 996 return; 997 } 998 999 if (oldState != STATE_READY && oldState != STATE_READY_HANDSHAKE_CUT_THROUGH) { 1000 // If we're in these states, we still haven't returned from startHandshake. 1001 // We call SSL_interrupt so that we can interrupt SSL_do_handshake and then 1002 // set the state to STATE_CLOSED. startHandshake will handle all cleanup 1003 // after SSL_do_handshake returns, so we don't have anything to do here. 1004 ssl.interrupt(); 1005 1006 ssl.notifyAll(); 1007 return; 1008 } 1009 1010 ssl.notifyAll(); 1011 // We've already returned from startHandshake, so we potentially have 1012 // input and output streams to clean up. 1013 sslInputStream = is; 1014 sslOutputStream = os; 1015 } 1016 1017 // Don't bother interrupting unless we have something to interrupt. 1018 if (sslInputStream != null || sslOutputStream != null) { 1019 ssl.interrupt(); 1020 } 1021 1022 // Wait for the input and output streams to finish any reads they have in 1023 // progress. If there are no reads in progress at this point, future reads will 1024 // throw because state == STATE_CLOSED 1025 if (sslInputStream != null) { 1026 sslInputStream.awaitPendingOps(); 1027 } 1028 if (sslOutputStream != null) { 1029 sslOutputStream.awaitPendingOps(); 1030 } 1031 1032 shutdownAndFreeSslNative(); 1033 } 1034 1035 private void shutdownAndFreeSslNative() throws IOException { 1036 try { 1037 Platform.blockGuardOnNetwork(); 1038 ssl.shutdown(Platform.getFileDescriptor(socket)); 1039 } catch (IOException ignored) { 1040 /* 1041 * Note that although close() can throw 1042 * IOException, the RI does not throw if there 1043 * is problem sending a "close notify" which 1044 * can happen if the underlying socket is closed. 1045 */ 1046 } finally { 1047 free(); 1048 closeUnderlyingSocket(); 1049 } 1050 } 1051 1052 private void closeUnderlyingSocket() throws IOException { 1053 super.close(); 1054 } 1055 1056 private void free() { 1057 if (!ssl.isClosed()) { 1058 ssl.close(); 1059 Platform.closeGuardClose(guard); 1060 } 1061 } 1062 1063 @Override 1064 @SuppressWarnings("deprecation") 1065 protected final void finalize() throws Throwable { 1066 try { 1067 /* 1068 * Just worry about our own state. Notably we do not try and 1069 * close anything. The SocketImpl, either our own 1070 * PlainSocketImpl, or the Socket we are wrapping, will do 1071 * that. This might mean we do not properly SSL_shutdown, but 1072 * if you want to do that, properly close the socket yourself. 1073 * 1074 * The reason why we don't try to SSL_shutdown, is that there 1075 * can be a race between finalizers where the PlainSocketImpl 1076 * finalizer runs first and closes the socket. However, in the 1077 * meanwhile, the underlying file descriptor could be reused 1078 * for another purpose. If we call SSL_shutdown, the 1079 * underlying socket BIOs still have the old file descriptor 1080 * and will write the close notify to some unsuspecting 1081 * reader. 1082 */ 1083 if (guard != null) { 1084 Platform.closeGuardWarnIfOpen(guard); 1085 } 1086 if (ssl != null) { 1087 synchronized (ssl) { 1088 transitionTo(STATE_CLOSED); 1089 } 1090 } 1091 } finally { 1092 super.finalize(); 1093 } 1094 } 1095 1096 @Override 1097 public final void setApplicationProtocolSelector(ApplicationProtocolSelector selector) { 1098 setApplicationProtocolSelector( 1099 selector == null ? null : new ApplicationProtocolSelectorAdapter(this, selector)); 1100 } 1101 1102 @Override 1103 final void setApplicationProtocolSelector(ApplicationProtocolSelectorAdapter selector) { 1104 sslParameters.setApplicationProtocolSelector(selector); 1105 } 1106 1107 @Override 1108 public int selectApplicationProtocol(byte[] protocols) { 1109 ApplicationProtocolSelectorAdapter adapter = sslParameters.getApplicationProtocolSelector(); 1110 if (adapter == null) { 1111 return NativeConstants.SSL_TLSEXT_ERR_NOACK; 1112 } 1113 return adapter.selectApplicationProtocol(protocols); 1114 } 1115 1116 @Override 1117 final void setApplicationProtocols(String[] protocols) { 1118 sslParameters.setApplicationProtocols(protocols); 1119 } 1120 1121 @Override 1122 final String[] getApplicationProtocols() { 1123 return sslParameters.getApplicationProtocols(); 1124 } 1125 1126 @Override 1127 public final String getApplicationProtocol() { 1128 return provideAfterHandshakeSession().getApplicationProtocol(); 1129 } 1130 1131 @Override 1132 public final String getHandshakeApplicationProtocol() { 1133 synchronized (ssl) { 1134 return state >= STATE_HANDSHAKE_STARTED && state < STATE_READY 1135 ? getApplicationProtocol() : null; 1136 } 1137 } 1138 1139 @Override 1140 public final SSLParameters getSSLParameters() { 1141 SSLParameters params = super.getSSLParameters(); 1142 Platform.getSSLParameters(params, sslParameters, this); 1143 return params; 1144 } 1145 1146 @Override 1147 public final void setSSLParameters(SSLParameters p) { 1148 super.setSSLParameters(p); 1149 Platform.setSSLParameters(p, sslParameters, this); 1150 } 1151 1152 @Override 1153 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 1154 public final String chooseServerPSKIdentityHint(PSKKeyManager keyManager) { 1155 return keyManager.chooseServerKeyIdentityHint(this); 1156 } 1157 1158 @Override 1159 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 1160 public final String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) { 1161 return keyManager.chooseClientKeyIdentity(identityHint, this); 1162 } 1163 1164 @Override 1165 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 1166 public final SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) { 1167 return keyManager.getKey(identityHint, identity, this); 1168 } 1169 1170 @Override 1171 public final String chooseServerAlias(X509KeyManager keyManager, String keyType) { 1172 return keyManager.chooseServerAlias(keyType, null, this); 1173 } 1174 1175 @Override 1176 public final String chooseClientAlias( 1177 X509KeyManager keyManager, X500Principal[] issuers, String[] keyTypes) { 1178 return keyManager.chooseClientAlias(keyTypes, issuers, this); 1179 } 1180 1181 private ClientSessionContext clientSessionContext() { 1182 return sslParameters.getClientSessionContext(); 1183 } 1184 1185 private AbstractSessionContext sessionContext() { 1186 return sslParameters.getSessionContext(); 1187 } 1188 1189 // All calls synchronized on this.ssl. 1190 private void transitionTo(int newState) { 1191 if (state == newState) { 1192 return; 1193 } 1194 1195 switch (newState) { 1196 case STATE_HANDSHAKE_STARTED: 1197 handshakeStartedMillis = Platform.getMillisSinceBoot(); 1198 break; 1199 1200 case STATE_READY: 1201 if (handshakeStartedMillis != 0) { 1202 Platform.countTlsHandshake(true, activeSession.getProtocol(), 1203 activeSession.getCipherSuite(), 1204 Platform.getMillisSinceBoot() - handshakeStartedMillis); 1205 handshakeStartedMillis = 0; 1206 } 1207 break; 1208 1209 case STATE_CLOSED: { 1210 if (handshakeStartedMillis != 0) { 1211 // Handshake was in progress so must have failed. 1212 Platform.countTlsHandshake(false, "TLS_PROTO_FAILED", "TLS_CIPHER_FAILED", 1213 Platform.getMillisSinceBoot() - handshakeStartedMillis); 1214 handshakeStartedMillis = 0; 1215 } 1216 if (!ssl.isClosed() && state >= STATE_HANDSHAKE_STARTED && state < STATE_CLOSED) { 1217 closedSession = new SessionSnapshot(activeSession); 1218 } 1219 break; 1220 } 1221 default: { 1222 break; 1223 } 1224 } 1225 1226 // Update the state 1227 this.state = newState; 1228 } 1229 } 1230