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