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